[libvirt] RE: Re: kvm-81: save / restore does not work - missing incoming stdio feature

Daniel P. Berrange berrange at redhat.com
Thu Jan 22 12:10:51 UTC 2009


On Mon, Jan 19, 2009 at 01:01:15PM +0000, Daniel P. Berrange wrote:
> On Mon, Jan 19, 2009 at 01:53:48PM +0100, Daniel Schwager wrote:
> > Hi Daniel,
> > 
> > Charles Duffy (thanks Charles !) told me how to fix libvirt for using
> > the
> > new "-incoming" API - yust replace "stdio" with "exec:cat" ..
> > 
> > Works like a charm,  tested with FC9, libvirt.0.5.1-2 and KVM-83
> 
> Unfortunately things are not that simple. This will work for new KVM, but
> break for older KVM which only supports 'stdio:', 'file://' and 'tcp://'
> for incoming migration. There needs to be some kind of version / support
> check here to decide which syntax to use.

The version check is quite tricky due to soo many combinations. So I've
created some test scripts to check we're doing it right. This patch should
make restore work again,  by detecting if 'exec' is supported and then
doing an automatic conversion from 'stdio' to 'exec:cat' in this case.
It also prints clear error messages if it finds a QEMU which doesn't
have the neccessary support - likewise detecting old KVM where the
TCP migration wouldn't work correctly, just hanging on startup.

 b/tests/qemuxml2argvdata/qemuxml2argv-migrate.args    |    1 
 b/tests/qemuxml2argvdata/qemuxml2argv-migrate.xml     |   22 +++++++++
 b/tests/qemuxml2argvdata/qemuxml2argv-restore-v1.args |    1 
 b/tests/qemuxml2argvdata/qemuxml2argv-restore-v1.xml  |   22 +++++++++
 b/tests/qemuxml2argvdata/qemuxml2argv-restore-v2.args |    1 
 b/tests/qemuxml2argvdata/qemuxml2argv-restore-v2.xml  |   22 +++++++++
 src/qemu_conf.c                                       |   44 ++++++++++++++++++
 src/qemu_conf.h                                       |   20 ++++----
 tests/qemuxml2argvtest.c                              |   23 +++++++--
 9 files changed, 144 insertions(+), 12 deletions(-)


Daniel


diff -r 1643740ed71c src/qemu_conf.c
--- a/src/qemu_conf.c	Wed Jan 21 16:28:43 2009 +0000
+++ b/src/qemu_conf.c	Thu Jan 22 12:06:47 2009 +0000
@@ -355,6 +355,7 @@ int qemudExtractVersionInfo(const char *
     unsigned int major, minor, micro;
     unsigned int version;
     unsigned int flags = 0;
+    unsigned int kvmver = 0;
 
     if (retflags)
         *retflags = 0;
@@ -378,6 +379,22 @@ int qemudExtractVersionInfo(const char *
 
     version = (major * 1000 * 1000) + (minor * 1000) + micro;
 
+    /* Optional KVM version */
+    if (sscanf(help, "QEMU PC emulator version %*u.%*u.%*u (kvm-%u)",
+               &kvmver) == 1) {
+        if (kvmver >= 79) {
+            /*
+             * In kvm-79, KVM pulled in new migration code from
+             * QEMU which really messes things up for us
+             */
+            flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP;
+            if (kvmver >= 80)
+                flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC;
+        } else {
+            flags |= QEMUD_CMD_FLAG_MIGRATE_KVM_STDIO;
+        }
+    }
+
     if (strstr(help, "-no-kqemu"))
         flags |= QEMUD_CMD_FLAG_KQEMU;
     if (strstr(help, "-no-reboot"))
@@ -674,6 +691,33 @@ int qemudBuildCommandLine(virConnectPtr 
 
     virUUIDFormat(vm->def->uuid, uuid);
 
+    /* Migration is very annoying due to wildly varying syntax & capabilities
+     * over time of KVM / QEMU codebases
+     */
+    if (migrateFrom) {
+        if (STRPREFIX(migrateFrom, "tcp")) {
+            if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP)) {
+                qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
+                                 "%s", _("TCP migration is not supported with this QEMU binary"));
+                return -1;
+            }
+        } else if (STREQ(migrateFrom, "stdio")) {
+            if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC) {
+                migrateFrom = "exec:cat";
+            } else if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_KVM_STDIO)) {
+                qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
+                                 "%s", _("STDIO migration is not supported with this QEMU binary"));
+                return -1;
+            }
+        } else if (STRPREFIX(migrateFrom, "exec")) {
+            if (!(qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC)) {
+                qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
+                                 "%s", _("STDIO migration is not supported with this QEMU binary"));
+                return -1;
+            }
+        }
+    }
+
     /* Need to explicitly disable KQEMU if
      * 1. Arch matches host arch
      * 2. Guest is 'qemu'
diff -r 1643740ed71c src/qemu_conf.h
--- a/src/qemu_conf.h	Wed Jan 21 16:28:43 2009 +0000
+++ b/src/qemu_conf.h	Thu Jan 22 12:06:47 2009 +0000
@@ -40,14 +40,18 @@
 
 /* Internal flags to keep track of qemu command line capabilities */
 enum qemud_cmd_flags {
-    QEMUD_CMD_FLAG_KQEMU          = (1 << 0),
-    QEMUD_CMD_FLAG_VNC_COLON      = (1 << 1),
-    QEMUD_CMD_FLAG_NO_REBOOT      = (1 << 2),
-    QEMUD_CMD_FLAG_DRIVE          = (1 << 3),
-    QEMUD_CMD_FLAG_DRIVE_BOOT     = (1 << 4),
-    QEMUD_CMD_FLAG_NAME           = (1 << 5),
-    QEMUD_CMD_FLAG_UUID           = (1 << 6),
-    QEMUD_CMD_FLAG_DOMID          = (1 << 7), /* Xenner only */
+    QEMUD_CMD_FLAG_KQEMU          = (1 << 0), /* Whether KQEMU is compiled in */
+    QEMUD_CMD_FLAG_VNC_COLON      = (1 << 1), /* Does the VNC take just port, or address + display */
+    QEMUD_CMD_FLAG_NO_REBOOT      = (1 << 2), /* Is the -no-reboot flag available */
+    QEMUD_CMD_FLAG_DRIVE          = (1 << 3), /* Is the new -drive arg available */
+    QEMUD_CMD_FLAG_DRIVE_BOOT     = (1 << 4), /* Does -drive support boot=on */
+    QEMUD_CMD_FLAG_NAME           = (1 << 5), /* Is the -name flag available */
+    QEMUD_CMD_FLAG_UUID           = (1 << 6), /* Is the -uuid flag available */
+    QEMUD_CMD_FLAG_DOMID          = (1 << 7), /* Xenner only, special -domid flag available */
+    QEMUD_CMD_FLAG_MIGRATE_KVM_STDIO = (1 << 8),  /* Original migration code from KVM. Also had tcp, but we can't use that
+                                                   * since it had a design bug blocking the entire monitor console */
+    QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP  = (1 << 9),  /* New migration syntax after merge to QEMU with TCP transport */
+    QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC = (1 << 10), /* New migration syntax after merge to QEMU with EXEC transport */
 };
 
 /* Main driver state */
diff -r 1643740ed71c tests/qemuxml2argvdata/qemuxml2argv-migrate.args
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/qemuxml2argvdata/qemuxml2argv-migrate.args	Thu Jan 22 12:06:47 2009 +0000
@@ -0,0 +1,1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu-kvm -S -M pc -m 214 -smp 1 -nographic -monitor pty -pidfile /nowhere/QEMUGuest1.pid -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb -incoming tcp:10.0.0.1:5000
diff -r 1643740ed71c tests/qemuxml2argvdata/qemuxml2argv-migrate.xml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/qemuxml2argvdata/qemuxml2argv-migrate.xml	Thu Jan 22 12:06:47 2009 +0000
@@ -0,0 +1,22 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219200</memory>
+  <currentMemory>219200</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-kvm</emulator>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+    </disk>
+  </devices>
+</domain>
diff -r 1643740ed71c tests/qemuxml2argvdata/qemuxml2argv-restore-v1.args
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/qemuxml2argvdata/qemuxml2argv-restore-v1.args	Thu Jan 22 12:06:47 2009 +0000
@@ -0,0 +1,1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu-kvm -S -M pc -m 214 -smp 1 -nographic -monitor pty -pidfile /nowhere/QEMUGuest1.pid -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb -incoming stdio
diff -r 1643740ed71c tests/qemuxml2argvdata/qemuxml2argv-restore-v1.xml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/qemuxml2argvdata/qemuxml2argv-restore-v1.xml	Thu Jan 22 12:06:47 2009 +0000
@@ -0,0 +1,22 @@
+<domain type='kvm'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219200</memory>
+  <currentMemory>219200</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-kvm</emulator>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+    </disk>
+  </devices>
+</domain>
diff -r 1643740ed71c tests/qemuxml2argvdata/qemuxml2argv-restore-v2.args
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/qemuxml2argvdata/qemuxml2argv-restore-v2.args	Thu Jan 22 12:06:47 2009 +0000
@@ -0,0 +1,1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu-kvm -S -M pc -m 214 -smp 1 -nographic -monitor pty -pidfile /nowhere/QEMUGuest1.pid -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb -incoming exec:cat
diff -r 1643740ed71c tests/qemuxml2argvdata/qemuxml2argv-restore-v2.xml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/qemuxml2argvdata/qemuxml2argv-restore-v2.xml	Thu Jan 22 12:06:47 2009 +0000
@@ -0,0 +1,22 @@
+<domain type='kvm'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219200</memory>
+  <currentMemory>219200</currentMemory>
+  <vcpu>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-kvm</emulator>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+    </disk>
+  </devices>
+</domain>
diff -r 1643740ed71c tests/qemuxml2argvtest.c
--- a/tests/qemuxml2argvtest.c	Wed Jan 21 16:28:43 2009 +0000
+++ b/tests/qemuxml2argvtest.c	Thu Jan 22 12:06:47 2009 +0000
@@ -24,7 +24,8 @@ static struct qemud_driver driver;
 
 static int testCompareXMLToArgvFiles(const char *xml,
                                      const char *cmd,
-                                     int extraFlags) {
+                                     int extraFlags,
+                                     const char *migrateFrom) {
     char argvData[MAX_FILE];
     char *expectargv = &(argvData[0]);
     char *actualargv = NULL;
@@ -56,7 +57,7 @@ static int testCompareXMLToArgvFiles(con
 
     if (qemudBuildCommandLine(NULL, &driver,
                               &vm, flags, &argv, &qenv,
-                              NULL, NULL, NULL) < 0)
+                              NULL, NULL, migrateFrom) < 0)
         goto fail;
 
     len = 1; /* for trailing newline */
@@ -122,6 +123,7 @@ static int testCompareXMLToArgvFiles(con
 struct testInfo {
     const char *name;
     int extraFlags;
+    const char *migrateFrom;
 };
 
 static int testCompareXMLToArgvHelper(const void *data) {
@@ -132,7 +134,7 @@ static int testCompareXMLToArgvHelper(co
              abs_srcdir, info->name);
     snprintf(args, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.args",
              abs_srcdir, info->name);
-    return testCompareXMLToArgvFiles(xml, args, info->extraFlags);
+    return testCompareXMLToArgvFiles(xml, args, info->extraFlags, info->migrateFrom);
 }
 
 
@@ -161,7 +163,15 @@ mymain(int argc, char **argv)
 
 #define DO_TEST(name, extraFlags)                                       \
     do {                                                                \
-        struct testInfo info = { name, extraFlags };                    \
+        struct testInfo info = { name, extraFlags, NULL };              \
+        if (virtTestRun("QEMU XML-2-ARGV " name,                        \
+                        1, testCompareXMLToArgvHelper, &info) < 0)      \
+            ret = -1;                                                   \
+    } while (0)
+
+#define DO_TEST_MIGRATE(name, extraFlags, migrateFrom)                  \
+    do {                                                                \
+        struct testInfo info = { name, extraFlags, migrateFrom };       \
         if (virtTestRun("QEMU XML-2-ARGV " name,                        \
                         1, testCompareXMLToArgvHelper, &info) < 0)      \
             ret = -1;                                                   \
@@ -228,6 +238,11 @@ mymain(int argc, char **argv)
 
     DO_TEST("hostdev-pci-address", 0);
 
+    DO_TEST_MIGRATE("restore-v1", QEMUD_CMD_FLAG_MIGRATE_KVM_STDIO, "stdio");
+    DO_TEST_MIGRATE("restore-v2", QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC, "stdio");
+    DO_TEST_MIGRATE("restore-v2", QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC, "exec:cat");
+    DO_TEST_MIGRATE("migrate", QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP, "tcp:10.0.0.1:5000");
+
     virCapabilitiesFree(driver.caps);
 
     return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);

-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list