qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 3/3] Add optional migrate version to hmp migrate com


From: Dr. David Alan Gilbert (git)
Subject: [Qemu-devel] [PATCH 3/3] Add optional migrate version to hmp migrate command
Date: Wed, 28 May 2014 12:20:34 +0100

From: "Dr. David Alan Gilbert" <address@hidden>

Uses the new 'optional parameter with string' parameter type

e.g.
migrate -v "2.0.0 (foo)" "exec: whatever"

Signed-off-by: Dr. David Alan Gilbert <address@hidden>
---
 hmp-commands.hx |   7 ++--
 hmp.c           | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 109 insertions(+), 4 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 4cbceda..a3732f2 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -887,13 +887,14 @@ ETEXI
 
     {
         .name       = "migrate",
-        .args_type  = "detach:-d,blk:-b,inc:-i,uri:s",
-        .params     = "[-d] [-b] [-i] uri",
+        .args_type  = "detach:-d,blk:-b,inc:-i,dest-version:+v,uri:s",
+        .params     = "[-d] [-b] [-i] [-v version] uri",
         .help       = "migrate to URI (using -d to not wait for completion)"
                      "\n\t\t\t -b for migration without shared storage with"
                      " full copy of disk\n\t\t\t -i for migration without "
                      "shared storage with incremental copy of disk "
-                     "(base image shared between src and destination)",
+                     "(base image shared between src and destination)"
+                      "\n\t\t\t -v to specify destination QEMU version",
         .mhandler.cmd = hmp_migrate,
     },
 
diff --git a/hmp.c b/hmp.c
index 411e4bc..e06d8c9 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1272,18 +1272,122 @@ static void hmp_migrate_status_cb(void *opaque)
     qapi_free_MigrationInfo(info);
 }
 
+/* Parse a string into a VersionInfo structure
+ * if the input string is NULL, return NULL.
+ * The input is the same as that output by 'info version'
+ * example input:
+ *    3.1.4 (arbitrary-package-name-3.1.4-stuff)
+ *    2.0.0
+ */
+static VersionInfo *parse_version_info(Monitor *mon, const char *s)
+{
+    char *tmps;
+    VersionInfo *vi = NULL;
+    const char *err_text;
+
+    if (!s) {
+        return NULL;
+    }
+
+    if (!*s) {
+        err_text = "Empty version string";
+        goto badstring;
+    }
+
+    /*
+     * There must be an easier way; but scanf's %n is apparently not
+     * portable to check if we hit the end of the string after the numeric
+     * part.
+     */
+    vi = g_malloc(sizeof(VersionInfo));
+    errno = 0;
+    if (!isdigit(*s)) {
+        err_text = "Parsing major version";
+        goto badstring;
+    }
+    vi->qemu.major = (int)strtol(s, &tmps, 10);
+    if (errno || (*tmps != '.')) {
+        err_text = "Parsing major version";
+        goto badstring;
+    }
+    if (!isdigit(*(++tmps))) {
+        err_text = "Parsing minor version";
+        goto badstring;
+    }
+    vi->qemu.minor = (int)strtol(tmps, &tmps, 10);
+    if (errno || (*tmps != '.')) {
+        err_text = "Parsing minor version";
+        goto badstring;
+    }
+    if (!isdigit(*(++tmps))) {
+        err_text = "Parsing micro version";
+        goto badstring;
+    }
+    vi->qemu.micro = (int)strtol(tmps, &tmps, 10);
+    if (errno) {
+        err_text = "Parsing micro version";
+        goto badstring;
+    }
+
+    /*
+     * At this point we're either at the end (fine) or we should have a
+     * version in brackets
+     */
+    if (*tmps) {
+        /* Expect a (package version) */
+        char *open_bracket = strchr(tmps, '(');
+        if (!open_bracket) {
+            err_text = "Finding open bracket";
+            goto badstring;
+        }
+        char *close_bracket = strchr(open_bracket+1, ')');
+        if (!close_bracket) {
+            err_text = "Finding close bracket";
+            goto badstring;
+        }
+
+        tmps = g_strdup(open_bracket+1);
+        *strchr(tmps, ')') = '\0';
+        vi->package = tmps;
+    } else {
+        /* Just makes everything consistent later */
+        vi->package = g_malloc(1);
+        vi->package[0] = '\0';
+    }
+
+    return vi;
+
+badstring:
+    monitor_printf(mon, "Failed to parse version (%s)\n", err_text);
+    if (vi) {
+        g_free(vi);
+    }
+    return NULL;
+}
+
 void hmp_migrate(Monitor *mon, const QDict *qdict)
 {
     int detach = qdict_get_try_bool(qdict, "detach", 0);
     int blk = qdict_get_try_bool(qdict, "blk", 0);
     int inc = qdict_get_try_bool(qdict, "inc", 0);
     const char *uri = qdict_get_str(qdict, "uri");
+    const char *dest_ver_s = qdict_get_try_str(qdict, "dest-version");
+    VersionInfo *vi = parse_version_info(mon, dest_ver_s);
     Error *err = NULL;
 
+    if (dest_ver_s && !vi) {
+        /* There's a version string but we couldn't parse it */
+        return;
+    }
+
     qmp_migrate(uri, !!blk, blk, !!inc, inc,
                 false, false,  /* detach */
-                false, NULL, /* dest_version */
+                !!vi, vi,      /* dest_version */
                 &err);
+    if (vi) {
+        qapi_free_VersionInfo(vi);
+    }
+
     if (err) {
         monitor_printf(mon, "migrate: %s\n", error_get_pretty(err));
         error_free(err);
-- 
1.9.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]