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 :|