[libvirt] [PATCH v2] virsh: add keepalive protocol in virsh

Guannan Ren gren at redhat.com
Tue Jun 5 08:36:55 UTC 2012


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




More information about the libvir-list mailing list