From: "Dr. David Alan Gilbert" <[email protected]> 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 <[email protected]> --- 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
