[libvirt] [PATCH] qemu: Allow setting boot menu on/off

Cole Robinson crobinso at redhat.com
Mon Jul 26 20:31:23 UTC 2010


Add a new element to the <os> block:

  <bootmenu enable="yes|no"/>

Which maps to -boot,menu=on|off on the QEMU command line.

I decided to use an explicit 'enable' attribute rather than just make the
bootmenu element boolean. This allows us to treat lack of a bootmenu element
as 'use hypervisor default'.

Signed-off-by: Cole Robinson <crobinso at redhat.com>
---
 docs/formatdomain.html.in                          |    8 +++++
 docs/schemas/domain.rng                            |   10 ++++++
 src/conf/domain_conf.c                             |   18 ++++++++++++
 src/conf/domain_conf.h                             |    8 ++++-
 src/qemu/qemu_conf.c                               |   27 ++++++++++++++++-
 src/qemu/qemu_conf.h                               |    1 +
 tests/qemuhelptest.c                               |    9 ++++--
 .../qemuxml2argv-boot-menu-disable.args            |    1 +
 .../qemuxml2argv-boot-menu-disable.xml             |   27 ++++++++++++++++++
 .../qemuxml2argvdata/qemuxml2argv-boot-multi.args  |    1 +
 tests/qemuxml2argvdata/qemuxml2argv-boot-multi.xml |   30 ++++++++++++++++++++
 tests/qemuxml2argvtest.c                           |    2 +
 tests/qemuxml2xmltest.c                            |    2 +
 13 files changed, 138 insertions(+), 6 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable.xml
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-multi.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-multi.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 3e80312..c79b606 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -79,6 +79,8 @@
     <type>hvm</type>
     <loader>/usr/lib/xen/boot/hvmloader</loader>
     <boot dev='hd'/>
+    <boot dev='cdrom'/>
+    <bootmenu enable='yes'/>
   </os>
   ...</pre>
 
@@ -104,6 +106,12 @@
         times to setup a priority list of boot devices to try in turn.
         <span class="since">Since 0.1.3</span>
       </dd>
+      <dt><code>bootmenu</code></dt>
+      <dd> Whether or not to enable an interactive boot menu prompt on guest
+      startup. The <code>enable</code> attribute can be either "yes" or "no".
+      If not specified, the hypervisor default is used. <span class="since">
+      Since 0.8.3</span>
+      </dd>
     </dl>
 
     <h4><a name="elementsOSBootloader">Host bootloader</a></h4>
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 2d22ce4..f36bb1f 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -122,6 +122,16 @@
             <ref name="osbootdev"/>
           </oneOrMore>
         </choice>
+        <optional>
+          <element name="bootmenu">
+            <attribute name="enable">
+              <choice>
+                <value>yes</value>
+                <value>no</value>
+              </choice>
+            </attribute>
+          </element>
+        </optional>
       </interleave>
     </element>
   </define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5b59c01..dc775e8 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4300,6 +4300,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
     }
 
     if (STREQ(def->os.type, "hvm")) {
+        char *bootstr;
+
         /* analysis of the boot devices */
         if ((n = virXPathNodeSet("./os/boot", ctxt, &nodes)) < 0) {
             virDomainReportError(VIR_ERR_INTERNAL_ERROR,
@@ -4329,6 +4331,15 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
             def->os.bootDevs[0] = VIR_DOMAIN_BOOT_DISK;
         }
         VIR_FREE(nodes);
+
+        bootstr = virXPathString("string(./os/bootmenu[1]/@enable)", ctxt);
+        if (bootstr) {
+            if (STREQ(bootstr, "yes"))
+                def->os.bootmenu = VIR_DOMAIN_BOOT_MENU_ENABLED;
+            else
+                def->os.bootmenu = VIR_DOMAIN_BOOT_MENU_DISABLED;
+            VIR_FREE(bootstr);
+        }
     }
 
     def->emulator = virXPathString("string(./devices/emulator[1])", ctxt);
@@ -6275,6 +6286,13 @@ char *virDomainDefFormat(virDomainDefPtr def,
             }
             virBufferVSprintf(&buf, "    <boot dev='%s'/>\n", boottype);
         }
+
+        if (def->os.bootmenu != VIR_DOMAIN_BOOT_MENU_DEFAULT) {
+            const char *enabled = (def->os.bootmenu ==
+                                   VIR_DOMAIN_BOOT_MENU_ENABLED ? "yes"
+                                                                : "no");
+            virBufferVSprintf(&buf, "    <bootmenu enable='%s'/>\n", enabled);
+        }
     }
 
     virBufferAddLit(&buf, "  </os>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 9ef687b..afd172f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -615,7 +615,6 @@ struct _virDomainDeviceDef {
 
 # define VIR_DOMAIN_MAX_BOOT_DEVS 4
 
-/* 3 possible boot devices */
 enum virDomainBootOrder {
     VIR_DOMAIN_BOOT_FLOPPY,
     VIR_DOMAIN_BOOT_CDROM,
@@ -625,6 +624,12 @@ enum virDomainBootOrder {
     VIR_DOMAIN_BOOT_LAST,
 };
 
+enum virDomainBootMenu {
+    VIR_DOMAIN_BOOT_MENU_DEFAULT = 0,
+    VIR_DOMAIN_BOOT_MENU_ENABLED,
+    VIR_DOMAIN_BOOT_MENU_DISABLED,
+};
+
 enum virDomainFeature {
     VIR_DOMAIN_FEATURE_ACPI,
     VIR_DOMAIN_FEATURE_APIC,
@@ -651,6 +656,7 @@ struct _virDomainOSDef {
     char *machine;
     int nBootDevs;
     int bootDevs[VIR_DOMAIN_BOOT_LAST];
+    int bootmenu;
     char *init;
     char *kernel;
     char *initrd;
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 05ad67d..1db504d 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1205,6 +1205,8 @@ static unsigned long long qemudComputeCmdFlags(const char *help,
         flags |= QEMUD_CMD_FLAG_NO_KVM_PIT;
     if (strstr(help, "-tdf"))
         flags |= QEMUD_CMD_FLAG_TDF;
+    if (strstr(help, ",menu=on"))
+        flags |= QEMUD_CMD_FLAG_BOOT_MENU;
 
     /* Keep disabled till we're actually ready to turn on netdev mode
      * The plan is todo it in 0.13.0 QEMU, but lets wait & see... */
@@ -4078,9 +4080,25 @@ int qemudBuildCommandLine(virConnectPtr conn,
             }
         }
         if (def->os.nBootDevs) {
+            virBuffer boot_buf = VIR_BUFFER_INITIALIZER;
+
             boot[def->os.nBootDevs] = '\0';
-            ADD_ARG_LIT("-boot");
-            ADD_ARG_LIT(boot);
+            virBufferVSprintf(&boot_buf, "-boot %s", boot);
+
+            if (qemuCmdFlags & QEMUD_CMD_FLAG_BOOT_MENU &&
+                def->os.bootmenu != VIR_DOMAIN_BOOT_MENU_DEFAULT) {
+                if (def->os.bootmenu == VIR_DOMAIN_BOOT_MENU_ENABLED)
+                    virBufferAddLit(&boot_buf, ",menu=on");
+                else if (def->os.bootmenu == VIR_DOMAIN_BOOT_MENU_DISABLED)
+                    virBufferAddLit(&boot_buf, ",menu=off");
+            }
+
+            if (virBufferError(&boot_buf)) {
+                virReportOOMError();
+                goto error;
+            }
+
+            ADD_ARG_LIT(virBufferContentAndReset(&boot_buf));
         }
 
         if (def->os.kernel) {
@@ -6207,8 +6225,13 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
                     def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_CDROM;
                 else if (val[n] == 'n')
                     def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_NET;
+                else if (val[n] == ',')
+                    break;
             }
             def->os.nBootDevs = b;
+
+            if (strstr(val, "menu=on"))
+                def->os.bootmenu = 1;
         } else if (STREQ(arg, "-name")) {
             WANT_VALUE();
             if (!(def->name = strdup(val)))
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 8c17e26..1aa9d2e 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -91,6 +91,7 @@ enum qemud_cmd_flags {
     QEMUD_CMD_FLAG_TDF           = (1LL << 35), /* -tdf flag (user-mode pit catchup) */
     QEMUD_CMD_FLAG_PCI_CONFIGFD  = (1LL << 36), /* pci-assign.configfd */
     QEMUD_CMD_FLAG_NODEFCONFIG   = (1LL << 37), /* -nodefconfig */
+    QEMUD_CMD_FLAG_BOOT_MENU     = (1LL << 38), /* -boot menu=on support */
 };
 
 /* Main driver state */
diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c
index 517a8fe..56a49fd 100644
--- a/tests/qemuhelptest.c
+++ b/tests/qemuhelptest.c
@@ -220,7 +220,8 @@ mymain(int argc, char **argv)
             QEMUD_CMD_FLAG_RTC_TD_HACK |
             QEMUD_CMD_FLAG_NO_HPET |
             QEMUD_CMD_FLAG_NO_KVM_PIT |
-            QEMUD_CMD_FLAG_TDF,
+            QEMUD_CMD_FLAG_TDF |
+            QEMUD_CMD_FLAG_BOOT_MENU,
             10092, 1,  0);
     DO_TEST("qemu-0.12.1",
             QEMUD_CMD_FLAG_VNC_COLON |
@@ -244,7 +245,8 @@ mymain(int argc, char **argv)
             QEMUD_CMD_FLAG_DEVICE |
             QEMUD_CMD_FLAG_SMP_TOPOLOGY |
             QEMUD_CMD_FLAG_RTC |
-            QEMUD_CMD_FLAG_NO_HPET,
+            QEMUD_CMD_FLAG_NO_HPET |
+            QEMUD_CMD_FLAG_BOOT_MENU,
             12001, 0,  0);
     DO_TEST("qemu-kvm-0.12.3",
             QEMUD_CMD_FLAG_VNC_COLON |
@@ -274,7 +276,8 @@ mymain(int argc, char **argv)
             QEMUD_CMD_FLAG_VNET_HOST |
             QEMUD_CMD_FLAG_NO_HPET |
             QEMUD_CMD_FLAG_NO_KVM_PIT |
-            QEMUD_CMD_FLAG_TDF,
+            QEMUD_CMD_FLAG_TDF |
+            QEMUD_CMD_FLAG_BOOT_MENU,
             12003, 1,  0);
 
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable.args b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable.args
new file mode 100644
index 0000000..1c773fd
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable.args
@@ -0,0 +1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot d,menu=off -cdrom /dev/cdrom -net none -serial none -parallel none -usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable.xml b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable.xml
new file mode 100644
index 0000000..ceb109c
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable.xml
@@ -0,0 +1,27 @@
+<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='cdrom'/>
+    <bootmenu enable='no'/>
+  </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='block' device='cdrom'>
+      <source dev='/dev/cdrom'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-multi.args b/tests/qemuxml2argvdata/qemuxml2argv-boot-multi.args
new file mode 100644
index 0000000..85b74d1
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-multi.args
@@ -0,0 +1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot dcna,menu=on -cdrom /dev/cdrom -net none -serial none -parallel none -usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-multi.xml b/tests/qemuxml2argvdata/qemuxml2argv-boot-multi.xml
new file mode 100644
index 0000000..48f27aa
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-multi.xml
@@ -0,0 +1,30 @@
+<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='cdrom'/>
+    <boot dev='hd'/>
+    <boot dev='network'/>
+    <boot dev='fd'/>
+    <bootmenu enable='yes'/>
+  </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='block' device='cdrom'>
+      <source dev='/dev/cdrom'/>
+      <target dev='hdc' bus='ide'/>
+      <readonly/>
+      <address type='drive' controller='0' bus='1' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 3d6c583..0ca9804 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -223,6 +223,8 @@ mymain(int argc, char **argv)
     DO_TEST("boot-cdrom", 0);
     DO_TEST("boot-network", 0);
     DO_TEST("boot-floppy", 0);
+    DO_TEST("boot-multi", QEMUD_CMD_FLAG_BOOT_MENU);
+    DO_TEST("boot-menu-disable", QEMUD_CMD_FLAG_BOOT_MENU);
     DO_TEST("bootloader", QEMUD_CMD_FLAG_DOMID);
     DO_TEST("clock-utc", 0);
     DO_TEST("clock-localtime", 0);
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 69829b1..00b3a1b 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -89,6 +89,8 @@ mymain(int argc, char **argv)
     DO_TEST("boot-cdrom");
     DO_TEST("boot-network");
     DO_TEST("boot-floppy");
+    DO_TEST("boot-multi");
+    DO_TEST("boot-menu-disable");
     DO_TEST("bootloader");
     DO_TEST("clock-utc");
     DO_TEST("clock-localtime");
-- 
1.7.1.1




More information about the libvir-list mailing list