diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 3e80312570..c79b606578 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>
...
@@ -104,6 +106,12 @@
times to setup a priority list of boot devices to try in turn.
Since 0.1.3
+
bootmenu
+ Whether or not to enable an interactive boot menu prompt on guest
+ startup. The enable
attribute can be either "yes" or "no".
+ If not specified, the hypervisor default is used.
+ Since 0.8.3
+
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 2d22ce4028..f36bb1fa9f 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -122,6 +122,16 @@
+
+
+
+
+ yes
+ no
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5b59c0143a..dc775e8b59 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, " \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, " \n", enabled);
+ }
}
virBufferAddLit(&buf, " \n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 9ef687b4c3..afd172f041 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 05ad67de6d..84f4e6f6c0 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,27 @@ int qemudBuildCommandLine(virConnectPtr conn,
}
}
if (def->os.nBootDevs) {
- boot[def->os.nBootDevs] = '\0';
+ virBuffer boot_buf = VIR_BUFFER_INITIALIZER;
ADD_ARG_LIT("-boot");
- ADD_ARG_LIT(boot);
+
+ boot[def->os.nBootDevs] = '\0';
+
+ if (qemuCmdFlags & QEMUD_CMD_FLAG_BOOT_MENU &&
+ def->os.bootmenu != VIR_DOMAIN_BOOT_MENU_DEFAULT) {
+ if (def->os.bootmenu == VIR_DOMAIN_BOOT_MENU_ENABLED)
+ virBufferVSprintf(&boot_buf, "order=%s,menu=on", boot);
+ else if (def->os.bootmenu == VIR_DOMAIN_BOOT_MENU_DISABLED)
+ virBufferVSprintf(&boot_buf, "order=%s,menu=off", boot);
+ } else {
+ virBufferVSprintf(&boot_buf, "%s", boot);
+ }
+
+ if (virBufferError(&boot_buf)) {
+ virReportOOMError();
+ goto error;
+ }
+
+ ADD_ARG_LIT(virBufferContentAndReset(&boot_buf));
}
if (def->os.kernel) {
@@ -6207,8 +6227,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 8c17e26c4b..1aa9d2e6dc 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 517a8fe001..56a49fd130 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 0000000000..ec472812f3
--- /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 order=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 0000000000..ceb109cfbd
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable.xml
@@ -0,0 +1,27 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219200
+ 219200
+ 1
+
+ hvm
+
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-multi.args b/tests/qemuxml2argvdata/qemuxml2argv-boot-multi.args
new file mode 100644
index 0000000000..e67f2a19b2
--- /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 order=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 0000000000..48f27aa481
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-multi.xml
@@ -0,0 +1,30 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219200
+ 219200
+ 1
+
+ hvm
+
+
+
+
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 3d6c583029..0ca98042c2 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 69829b1b72..00b3a1b188 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");