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(a)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