Bugzilla:https://bugzilla.redhat.com/show_bug.cgi?id=822839
add two general virsh options to support keepalive message protocol
-i | --keepalive_interval interval time value (default 5 seconds)
-n | --keepalive_count number of heartbeats (default 5 times)
For non-p2p migration, start keepalive for remote driver to
determine the status of network connection, aborting migrating job
after defined amount of interval time.
---
tools/virsh.c | 88 +++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 70 insertions(+), 18 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 0e41d00..602e5a5 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -251,6 +251,8 @@ typedef struct __vshControl {
bool readonly; /* connect readonly (first time only, not
* during explicit connect command)
*/
+ int keepalive_interval; /* interval time value */
+ int keepalive_count; /* keepalive_count value */
char *logfile; /* log file name */
int log_fd; /* log file descriptor */
char *historydir; /* readline history directory name */
@@ -415,13 +417,14 @@ typedef struct __vshCtrlData {
vshControl *ctl;
const vshCmd *cmd;
int writefd;
+ virConnectPtr dconn;
} vshCtrlData;
typedef void (*jobWatchTimeoutFunc) (vshControl *ctl, virDomainPtr dom,
void *opaque);
static bool
-vshWatchJob(vshControl *ctl,
+vshWatchJob(vshCtrlData *data,
virDomainPtr dom,
bool verbose,
int pipe_fd,
@@ -3334,6 +3337,7 @@ cmdSave(vshControl *ctl, const vshCmd *cmd)
data.ctl = ctl;
data.cmd = cmd;
data.writefd = p[1];
+ data.dconn = NULL;
if (virThreadCreate(&workerThread,
true,
@@ -3341,7 +3345,7 @@ cmdSave(vshControl *ctl, const vshCmd *cmd)
&data) < 0)
goto cleanup;
- ret = vshWatchJob(ctl, dom, verbose, p[0], 0, NULL, NULL, _("Save"));
+ ret = vshWatchJob(&data, dom, verbose, p[0], 0, NULL, NULL,
_("Save"));
virThreadJoin(&workerThread);
@@ -3608,6 +3612,7 @@ cmdManagedSave(vshControl *ctl, const vshCmd *cmd)
data.ctl = ctl;
data.cmd = cmd;
data.writefd = p[1];
+ data.dconn = NULL;
if (virThreadCreate(&workerThread,
true,
@@ -3615,7 +3620,7 @@ cmdManagedSave(vshControl *ctl, const vshCmd *cmd)
&data) < 0)
goto cleanup;
- ret = vshWatchJob(ctl, dom, verbose, p[0], 0,
+ ret = vshWatchJob(&data, dom, verbose, p[0], 0,
NULL, NULL, _("Managedsave"));
virThreadJoin(&workerThread);
@@ -4086,6 +4091,7 @@ cmdDump(vshControl *ctl, const vshCmd *cmd)
data.ctl = ctl;
data.cmd = cmd;
data.writefd = p[1];
+ data.dconn = NULL;
if (virThreadCreate(&workerThread,
true,
@@ -4093,7 +4099,7 @@ cmdDump(vshControl *ctl, const vshCmd *cmd)
&data) < 0)
goto cleanup;
- ret = vshWatchJob(ctl, dom, verbose, p[0], 0, NULL, NULL, _("Dump"));
+ ret = vshWatchJob(&data, dom, verbose, p[0], 0, NULL, NULL,
_("Dump"));
virThreadJoin(&workerThread);
@@ -7213,6 +7219,12 @@ doMigrate (void *opaque)
dconn = virConnectOpenAuth (desturi, virConnectAuthPtrDefault, 0);
if (!dconn) goto out;
+ data->dconn = dconn;
+ if (virConnectSetKeepAlive(dconn,
+ ctl->keepalive_interval,
+ ctl->keepalive_count) < 0)
+ vshDebug(ctl, VSH_ERR_WARNING, "migrate: Failed to start
keepalive\n");
+
ddom = virDomainMigrate2(dom, dconn, xml, flags, dname, migrateuri, 0);
if (ddom) {
virDomainFree(ddom);
@@ -7268,7 +7280,7 @@ vshMigrationTimeout(vshControl *ctl,
}
static bool
-vshWatchJob(vshControl *ctl,
+vshWatchJob(vshCtrlData *data,
virDomainPtr dom,
bool verbose,
int pipe_fd,
@@ -7286,6 +7298,7 @@ vshWatchJob(vshControl *ctl,
char retchar;
bool functionReturn = false;
sigset_t sigmask, oldsigmask;
+ vshControl *ctl = data->ctl;
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGINT);
@@ -7329,6 +7342,13 @@ repoll:
goto cleanup;
}
+ if (data->dconn && virConnectIsAlive(data->dconn) <= 0) {
+ virDomainAbortJob(dom);
+ vshError(ctl, "%s",
+ _("Lost connection to destination host"));
+ goto cleanup;
+ }
+
GETTIMEOFDAY(&curr);
if (timeout && (((int)(curr.tv_sec - start.tv_sec) * 1000 +
(int)(curr.tv_usec - start.tv_usec) / 1000) >
@@ -7402,13 +7422,14 @@ cmdMigrate(vshControl *ctl, const vshCmd *cmd)
data.ctl = ctl;
data.cmd = cmd;
data.writefd = p[1];
+ data.dconn = NULL;
if (virThreadCreate(&workerThread,
true,
doMigrate,
&data) < 0)
goto cleanup;
- functionReturn = vshWatchJob(ctl, dom, verbose, p[0], timeout,
+ functionReturn = vshWatchJob(&data, dom, verbose, p[0], timeout,
vshMigrationTimeout, NULL, _("Migration"));
virThreadJoin(&workerThread);
@@ -18673,6 +18694,7 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd)
while (cmd) {
struct timeval before, after;
bool enable_timing = ctl->timing;
+ const char *driver = NULL;
if ((ctl->conn == NULL || disconnected) &&
!(cmd->def->flags & VSH_CMD_FLAG_NOCONNECT))
@@ -18681,6 +18703,18 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd)
if (enable_timing)
GETTIMEOFDAY(&before);
+ /* start keepalive for remote driver */
+ driver = virConnectGetType(ctl->conn);
+ if (STREQ_NULLABLE(driver, "QEMU") ||
+ STREQ_NULLABLE(driver, "xenlight") ||
+ STREQ_NULLABLE(driver, "UML") ||
+ STREQ_NULLABLE(driver, "LXC") ||
+ STREQ_NULLABLE(driver, "remote"))
+ if (virConnectSetKeepAlive(ctl->conn,
+ ctl->keepalive_interval,
+ ctl->keepalive_count) < 0)
+ vshDebug(ctl, VSH_ERR_WARNING, "migrate: Failed to start
keepalive\n");
+
ret = cmd->def->handler(ctl, cmd);
if (enable_timing)
@@ -19959,17 +19993,19 @@ vshUsage(void)
fprintf(stdout, _("\n%s [options]... [<command_string>]"
"\n%s [options]... <command> [args...]\n\n"
" options:\n"
- " -c | --connect=URI hypervisor connection
URI\n"
- " -r | --readonly connect readonly\n"
- " -d | --debug=NUM debug level [0-4]\n"
- " -h | --help this help\n"
- " -q | --quiet quiet mode\n"
- " -t | --timing print timing information\n"
- " -l | --log=FILE output logging to file\n"
- " -v short version\n"
- " -V long version\n"
- " --version[=TYPE] version, TYPE is short or long
(default short)\n"
- " -e | --escape <char> set escape sequence for
console\n\n"
+ " -c | --connect=URI hypervisor connection
URI\n"
+ " -r | --readonly connect readonly\n"
+ " -d | --debug=NUM debug level [0-4]\n"
+ " -h | --help this help\n"
+ " -q | --quiet quiet mode\n"
+ " -t | --timing print timing
information\n"
+ " -l | --log=FILE output logging to
file\n"
+ " -v short version\n"
+ " -V long version\n"
+ " --version[=TYPE] version, TYPE is short or
long (default short)\n"
+ " -e | --escape <char> set escape sequence for
console\n"
+ " -i | --keepalive_interval interval time value (default
5 seconds)\n"
+ " -n | --keepalive_count number of heartbeats (default
5 times)\n\n"
" commands (non interactive mode):\n\n"), progname,
progname);
for (grp = cmdGroups; grp->name; grp++) {
@@ -20146,13 +20182,15 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
{"readonly", no_argument, NULL, 'r'},
{"log", required_argument, NULL, 'l'},
{"escape", required_argument, NULL, 'e'},
+ {"keepalive_interval", required_argument, NULL, 'i'},
+ {"keepalive_count", required_argument, NULL, 'n'},
{NULL, 0, NULL, 0}
};
/* Standard (non-command) options. The leading + ensures that no
* argument reordering takes place, so that command options are
* not confused with top-level virsh options. */
- while ((arg = getopt_long(argc, argv, "+d:hqtc:vVrl:e:", opt, NULL)) != -1)
{
+ while ((arg = getopt_long(argc, argv, "+d:hqtc:vVrl:e:i:n:", opt, NULL)) !=
-1) {
switch (arg) {
case 'd':
if (virStrToLong_i(optarg, NULL, 10, &ctl->debug) < 0) {
@@ -20201,6 +20239,18 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
exit(EXIT_FAILURE);
}
break;
+ case 'i':
+ if (virStrToLong_i(optarg, NULL, 10, &ctl->keepalive_interval) < 0)
{
+ vshError(ctl, "%s", _("option -i takes a numeric
argument"));
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'n':
+ if (virStrToLong_i(optarg, NULL, 10, &ctl->keepalive_count) < 0) {
+ vshError(ctl, "%s", _("option -n takes a numeric
argument"));
+ exit(EXIT_FAILURE);
+ }
+ break;
default:
vshError(ctl, _("unsupported option '-%c'. See --help."),
arg);
exit(EXIT_FAILURE);
@@ -20232,6 +20282,8 @@ main(int argc, char **argv)
ctl->log_fd = -1; /* Initialize log file descriptor */
ctl->debug = VSH_DEBUG_DEFAULT;
ctl->escapeChar = CTRL_CLOSE_BRACKET;
+ ctl->keepalive_interval = 5;
+ ctl->keepalive_count = 5;
if (!setlocale(LC_ALL, "")) {
--
1.7.7.5