]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Fix shutdown regression with buggy qemu
authorJiri Denemark <jdenemar@redhat.com>
Wed, 21 Sep 2011 08:25:29 +0000 (10:25 +0200)
committerJiri Denemark <jdenemar@redhat.com>
Wed, 21 Sep 2011 14:53:06 +0000 (16:53 +0200)
The commit that prevents disk corruption on domain shutdown
(96fc4784177ecb70357518fa863442455e45ad0e) causes regression with QEMU
0.14.* and 0.15.* because of a regression bug in QEMU that was fixed
only recently in QEMU git. The affected versions of QEMU do not quit on
SIGTERM if started with -no-shutdown, which we use to implement fake
reboot. Since -no-shutdown tells QEMU not to quit automatically on guest
shutdown, domains started using the affected QEMU cannot be shutdown
properly and stay in a paused state.

This patch disables fake reboot feature on such QEMU by not using
-no-shutdown, which makes shutdown work as expected. However,
virDomainReboot will not work in this case and it will report "Requested
operation is not valid: Reboot is not supported with this QEMU binary".

src/qemu/qemu_capabilities.c
src/qemu/qemu_capabilities.h
src/qemu/qemu_command.c
src/qemu/qemu_driver.c
tests/qemuhelptest.c
tests/qemuxml2argvdata/qemuxml2argv-monitor-json.args
tests/qemuxml2argvdata/qemuxml2argv-no-shutdown.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-no-shutdown.xml [new file with mode: 0644]
tests/qemuxml2argvtest.c

index 36f47a9a66e53279176c00f1b17dd0fc77b0805c..850d46e7665e094aae42e105f9a35e36bea9ec2e 100644 (file)
@@ -136,6 +136,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
               "pci-ohci",
               "usb-redir",
               "usb-hub",
+              "no-shutdown",
     );
 
 struct qemu_feature_flags {
@@ -1008,6 +1009,13 @@ qemuCapsComputeCmdFlags(const char *help,
         qemuCapsSet(flags, QEMU_CAPS_VHOST_NET);
     }
 
+    /* Do not use -no-shutdown if qemu doesn't support it or SIGTERM handling
+     * is most likely buggy when used with -no-shutdown (which applies for qemu
+     * 0.14.* and 0.15.*)
+     */
+    if (strstr(help, "-no-shutdown") && (version < 14000 || version > 15999))
+        qemuCapsSet(flags, QEMU_CAPS_NO_SHUTDOWN);
+
     /*
      * Handling of -incoming arg with varying features
      *  -incoming tcp    (kvm >= 79, qemu >= 0.10.0)
index 96b7a3b18b8b4d22abce42f88cc96e85ee4247a7..74d3ab24226fbb088e15e5752a58d372ddb4ffdb 100644 (file)
@@ -110,6 +110,7 @@ enum qemuCapsFlags {
     QEMU_CAPS_PCI_OHCI          = 71, /* -device pci-ohci */
     QEMU_CAPS_USB_REDIR         = 72, /* -device usb-redir */
     QEMU_CAPS_USB_HUB           = 73, /* -device usb-hub */
+    QEMU_CAPS_NO_SHUTDOWN       = 74, /* usable -no-shutdown */
 
     QEMU_CAPS_LAST,                   /* this must always be the last item */
 };
index ee4b52beb95ff5333e842c91295fad2728af78f5..0adc56a5f94f75480559c6267a6c0e0879765d16 100644 (file)
@@ -3574,7 +3574,7 @@ qemuBuildCommandLine(virConnectPtr conn,
      * when QEMU stops. If we use no-shutdown, then we can
      * watch for this event and do a soft/warm reboot.
      */
-    if (monitor_json)
+    if (monitor_json && qemuCapsGet(qemuCaps, QEMU_CAPS_NO_SHUTDOWN))
         virCommandAddArg(cmd, "-no-shutdown");
 
     if (!(def->features & (1 << VIR_DOMAIN_FEATURE_ACPI)))
index f4ee4c3f8f9e8bc907049a5264ed80d65d83bd39..67c43ab203ced2c2b1eb91cb875a413a5386108c 100644 (file)
@@ -1557,6 +1557,12 @@ static int qemuDomainReboot(virDomainPtr dom, unsigned int flags) {
     priv = vm->privateData;
 
     if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_MONITOR_JSON)) {
+        if (!qemuCapsGet(priv->qemuCaps, QEMU_CAPS_NO_SHUTDOWN)) {
+            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                            _("Reboot is not supported with this QEMU binary"));
+            goto cleanup;
+        }
+
         if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
             goto cleanup;
 
index ffd30e29357cc5798188c3a4c6b3510476b13805..4a4070a154dd0512e189094d22ade75545401306 100644 (file)
@@ -152,7 +152,8 @@ mymain(void)
             QEMU_CAPS_KVM,
             QEMU_CAPS_DRIVE_FORMAT,
             QEMU_CAPS_MEM_PATH,
-            QEMU_CAPS_TDF);
+            QEMU_CAPS_TDF,
+            QEMU_CAPS_NO_SHUTDOWN);
     DO_TEST("kvm-83-rhel56", 9001, 1, 83,
             QEMU_CAPS_VNC_COLON,
             QEMU_CAPS_NO_REBOOT,
@@ -177,7 +178,8 @@ mymain(void)
             QEMU_CAPS_TDF,
             QEMU_CAPS_DRIVE_READONLY,
             QEMU_CAPS_SMBIOS_TYPE,
-            QEMU_CAPS_SPICE);
+            QEMU_CAPS_SPICE,
+            QEMU_CAPS_NO_SHUTDOWN);
     DO_TEST("qemu-0.10.5", 10005, 0, 0,
             QEMU_CAPS_KQEMU,
             QEMU_CAPS_VNC_COLON,
@@ -196,7 +198,8 @@ mymain(void)
             QEMU_CAPS_SDL,
             QEMU_CAPS_RTC_TD_HACK,
             QEMU_CAPS_NO_HPET,
-            QEMU_CAPS_VGA_NONE);
+            QEMU_CAPS_VGA_NONE,
+            QEMU_CAPS_NO_SHUTDOWN);
     DO_TEST("qemu-kvm-0.10.5", 10005, 1, 0,
             QEMU_CAPS_VNC_COLON,
             QEMU_CAPS_NO_REBOOT,
@@ -221,7 +224,8 @@ mymain(void)
             QEMU_CAPS_NO_KVM_PIT,
             QEMU_CAPS_TDF,
             QEMU_CAPS_NESTING,
-            QEMU_CAPS_VGA_NONE);
+            QEMU_CAPS_VGA_NONE,
+            QEMU_CAPS_NO_SHUTDOWN);
     DO_TEST("kvm-86", 10050, 1, 0,
             QEMU_CAPS_VNC_COLON,
             QEMU_CAPS_NO_REBOOT,
@@ -246,7 +250,8 @@ mymain(void)
             QEMU_CAPS_TDF,
             QEMU_CAPS_NESTING,
             QEMU_CAPS_SMBIOS_TYPE,
-            QEMU_CAPS_VGA_NONE);
+            QEMU_CAPS_VGA_NONE,
+            QEMU_CAPS_NO_SHUTDOWN);
     DO_TEST("qemu-kvm-0.11.0-rc2", 10092, 1, 0,
             QEMU_CAPS_VNC_COLON,
             QEMU_CAPS_NO_REBOOT,
@@ -276,7 +281,8 @@ mymain(void)
             QEMU_CAPS_NESTING,
             QEMU_CAPS_NAME_PROCESS,
             QEMU_CAPS_SMBIOS_TYPE,
-            QEMU_CAPS_VGA_NONE);
+            QEMU_CAPS_VGA_NONE,
+            QEMU_CAPS_NO_SHUTDOWN);
     DO_TEST("qemu-0.12.1", 12001, 0, 0,
             QEMU_CAPS_VNC_COLON,
             QEMU_CAPS_NO_REBOOT,
@@ -306,7 +312,8 @@ mymain(void)
             QEMU_CAPS_SMBIOS_TYPE,
             QEMU_CAPS_VGA_NONE,
             QEMU_CAPS_MIGRATE_QEMU_FD,
-            QEMU_CAPS_DRIVE_AIO);
+            QEMU_CAPS_DRIVE_AIO,
+            QEMU_CAPS_NO_SHUTDOWN);
     DO_TEST("qemu-kvm-0.12.1.2-rhel60", 12001, 1, 0,
             QEMU_CAPS_VNC_COLON,
             QEMU_CAPS_NO_REBOOT,
@@ -350,7 +357,8 @@ mymain(void)
             QEMU_CAPS_DEVICE_SPICEVMC,
             QEMU_CAPS_PIIX3_USB_UHCI,
             QEMU_CAPS_PIIX4_USB_UHCI,
-            QEMU_CAPS_USB_HUB);
+            QEMU_CAPS_USB_HUB,
+            QEMU_CAPS_NO_SHUTDOWN);
     DO_TEST("qemu-kvm-0.12.3", 12003, 1, 0,
             QEMU_CAPS_VNC_COLON,
             QEMU_CAPS_NO_REBOOT,
@@ -387,7 +395,8 @@ mymain(void)
             QEMU_CAPS_SMBIOS_TYPE,
             QEMU_CAPS_VGA_NONE,
             QEMU_CAPS_MIGRATE_QEMU_FD,
-            QEMU_CAPS_DRIVE_AIO);
+            QEMU_CAPS_DRIVE_AIO,
+            QEMU_CAPS_NO_SHUTDOWN);
     DO_TEST("qemu-kvm-0.13.0", 13000, 1, 0,
             QEMU_CAPS_VNC_COLON,
             QEMU_CAPS_NO_REBOOT,
@@ -439,7 +448,8 @@ mymain(void)
             QEMU_CAPS_PIIX4_USB_UHCI,
             QEMU_CAPS_VT82C686B_USB_UHCI,
             QEMU_CAPS_PCI_OHCI,
-            QEMU_CAPS_USB_HUB);
+            QEMU_CAPS_USB_HUB,
+            QEMU_CAPS_NO_SHUTDOWN);
     DO_TEST("qemu-kvm-0.12.1.2-rhel61", 12001, 1, 0,
             QEMU_CAPS_VNC_COLON,
             QEMU_CAPS_NO_REBOOT,
@@ -487,7 +497,8 @@ mymain(void)
             QEMU_CAPS_VIRTIO_IOEVENTFD,
             QEMU_CAPS_PIIX3_USB_UHCI,
             QEMU_CAPS_PIIX4_USB_UHCI,
-            QEMU_CAPS_USB_HUB);
+            QEMU_CAPS_USB_HUB,
+            QEMU_CAPS_NO_SHUTDOWN);
 
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
index 8d8e43ebd1203f98dbcd3849d2ece33513eb4745..e04cdec8f3a9b02056a76226815f42c6c2750b69 100644 (file)
@@ -1,5 +1,5 @@
 LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
 pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,\
 id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,\
-id=monitor,mode=control -no-shutdown -no-acpi -boot c -hda /dev/hda1 -usb -device \
+id=monitor,mode=control -no-acpi -boot c -hda /dev/hda1 -usb -device \
 virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-no-shutdown.args b/tests/qemuxml2argvdata/qemuxml2argv-no-shutdown.args
new file mode 100644 (file)
index 0000000..1464d09
--- /dev/null
@@ -0,0 +1,21 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+/usr/bin/qemu \
+-S \
+-M pc \
+-m 214 \
+-smp 1 \
+-nographic \
+-nodefconfig \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-no-shutdown \
+-no-acpi \
+-boot c \
+-hda /dev/hda1 \
+-usb \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-no-shutdown.xml b/tests/qemuxml2argvdata/qemuxml2argv-no-shutdown.xml
new file mode 100644 (file)
index 0000000..1901715
--- /dev/null
@@ -0,0 +1,24 @@
+<domain type='qemu'>
+  <name>encryptdisk</name>
+  <uuid>496898a6-e6ff-f7c8-5dc2-3cf410945ee9</uuid>
+  <memory>219100</memory>
+  <currentMemory>219100</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</emulator>
+    <disk type='file' device='disk'>
+      <driver name='qemu' type='qcow2'/>
+      <source file='/dev/hda1'/>
+      <target dev='hda'/>
+    </disk>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
index fcb20bbd623f36b325a951f5529a53cd6ced59e0..1dc6a017597dc4f466d62af14274d3b2af289a94 100644 (file)
@@ -578,6 +578,9 @@ mymain(void)
     json = true;
     DO_TEST("monitor-json", false, QEMU_CAPS_DEVICE,
             QEMU_CAPS_CHARDEV, QEMU_CAPS_MONITOR_JSON, QEMU_CAPS_NODEFCONFIG);
+    DO_TEST("no-shutdown", false, QEMU_CAPS_DEVICE,
+            QEMU_CAPS_CHARDEV, QEMU_CAPS_MONITOR_JSON, QEMU_CAPS_NODEFCONFIG,
+            QEMU_CAPS_NO_SHUTDOWN);
     json = false;
 
     free(driver.stateDir);