qemu: Allow setting boot menu on/off

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'.
This commit is contained in:
Cole Robinson 2010-07-26 10:28:58 -04:00
parent f8b76f419a
commit 4f24ca01e8
13 changed files with 140 additions and 6 deletions

View File

@ -79,6 +79,8 @@
&lt;type&gt;hvm&lt;/type&gt; &lt;type&gt;hvm&lt;/type&gt;
&lt;loader&gt;/usr/lib/xen/boot/hvmloader&lt;/loader&gt; &lt;loader&gt;/usr/lib/xen/boot/hvmloader&lt;/loader&gt;
&lt;boot dev='hd'/&gt; &lt;boot dev='hd'/&gt;
&lt;boot dev='cdrom'/&gt;
&lt;bootmenu enable='yes'/&gt;
&lt;/os&gt; &lt;/os&gt;
...</pre> ...</pre>
@ -104,6 +106,12 @@
times to setup a priority list of boot devices to try in turn. times to setup a priority list of boot devices to try in turn.
<span class="since">Since 0.1.3</span> <span class="since">Since 0.1.3</span>
</dd> </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> </dl>
<h4><a name="elementsOSBootloader">Host bootloader</a></h4> <h4><a name="elementsOSBootloader">Host bootloader</a></h4>

View File

@ -122,6 +122,16 @@
<ref name="osbootdev"/> <ref name="osbootdev"/>
</oneOrMore> </oneOrMore>
</choice> </choice>
<optional>
<element name="bootmenu">
<attribute name="enable">
<choice>
<value>yes</value>
<value>no</value>
</choice>
</attribute>
</element>
</optional>
</interleave> </interleave>
</element> </element>
</define> </define>

View File

@ -4300,6 +4300,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
} }
if (STREQ(def->os.type, "hvm")) { if (STREQ(def->os.type, "hvm")) {
char *bootstr;
/* analysis of the boot devices */ /* analysis of the boot devices */
if ((n = virXPathNodeSet("./os/boot", ctxt, &nodes)) < 0) { if ((n = virXPathNodeSet("./os/boot", ctxt, &nodes)) < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, virDomainReportError(VIR_ERR_INTERNAL_ERROR,
@ -4329,6 +4331,15 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
def->os.bootDevs[0] = VIR_DOMAIN_BOOT_DISK; def->os.bootDevs[0] = VIR_DOMAIN_BOOT_DISK;
} }
VIR_FREE(nodes); 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); def->emulator = virXPathString("string(./devices/emulator[1])", ctxt);
@ -6275,6 +6286,13 @@ char *virDomainDefFormat(virDomainDefPtr def,
} }
virBufferVSprintf(&buf, " <boot dev='%s'/>\n", boottype); 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"); virBufferAddLit(&buf, " </os>\n");

View File

@ -615,7 +615,6 @@ struct _virDomainDeviceDef {
# define VIR_DOMAIN_MAX_BOOT_DEVS 4 # define VIR_DOMAIN_MAX_BOOT_DEVS 4
/* 3 possible boot devices */
enum virDomainBootOrder { enum virDomainBootOrder {
VIR_DOMAIN_BOOT_FLOPPY, VIR_DOMAIN_BOOT_FLOPPY,
VIR_DOMAIN_BOOT_CDROM, VIR_DOMAIN_BOOT_CDROM,
@ -625,6 +624,12 @@ enum virDomainBootOrder {
VIR_DOMAIN_BOOT_LAST, VIR_DOMAIN_BOOT_LAST,
}; };
enum virDomainBootMenu {
VIR_DOMAIN_BOOT_MENU_DEFAULT = 0,
VIR_DOMAIN_BOOT_MENU_ENABLED,
VIR_DOMAIN_BOOT_MENU_DISABLED,
};
enum virDomainFeature { enum virDomainFeature {
VIR_DOMAIN_FEATURE_ACPI, VIR_DOMAIN_FEATURE_ACPI,
VIR_DOMAIN_FEATURE_APIC, VIR_DOMAIN_FEATURE_APIC,
@ -651,6 +656,7 @@ struct _virDomainOSDef {
char *machine; char *machine;
int nBootDevs; int nBootDevs;
int bootDevs[VIR_DOMAIN_BOOT_LAST]; int bootDevs[VIR_DOMAIN_BOOT_LAST];
int bootmenu;
char *init; char *init;
char *kernel; char *kernel;
char *initrd; char *initrd;

View File

@ -1205,6 +1205,8 @@ static unsigned long long qemudComputeCmdFlags(const char *help,
flags |= QEMUD_CMD_FLAG_NO_KVM_PIT; flags |= QEMUD_CMD_FLAG_NO_KVM_PIT;
if (strstr(help, "-tdf")) if (strstr(help, "-tdf"))
flags |= QEMUD_CMD_FLAG_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 /* 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... */ * 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) { if (def->os.nBootDevs) {
boot[def->os.nBootDevs] = '\0'; virBuffer boot_buf = VIR_BUFFER_INITIALIZER;
ADD_ARG_LIT("-boot"); 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) { if (def->os.kernel) {
@ -6207,8 +6227,13 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_CDROM; def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_CDROM;
else if (val[n] == 'n') else if (val[n] == 'n')
def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_NET; def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_NET;
else if (val[n] == ',')
break;
} }
def->os.nBootDevs = b; def->os.nBootDevs = b;
if (strstr(val, "menu=on"))
def->os.bootmenu = 1;
} else if (STREQ(arg, "-name")) { } else if (STREQ(arg, "-name")) {
WANT_VALUE(); WANT_VALUE();
if (!(def->name = strdup(val))) if (!(def->name = strdup(val)))

View File

@ -91,6 +91,7 @@ enum qemud_cmd_flags {
QEMUD_CMD_FLAG_TDF = (1LL << 35), /* -tdf flag (user-mode pit catchup) */ 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_PCI_CONFIGFD = (1LL << 36), /* pci-assign.configfd */
QEMUD_CMD_FLAG_NODEFCONFIG = (1LL << 37), /* -nodefconfig */ QEMUD_CMD_FLAG_NODEFCONFIG = (1LL << 37), /* -nodefconfig */
QEMUD_CMD_FLAG_BOOT_MENU = (1LL << 38), /* -boot menu=on support */
}; };
/* Main driver state */ /* Main driver state */

View File

@ -220,7 +220,8 @@ mymain(int argc, char **argv)
QEMUD_CMD_FLAG_RTC_TD_HACK | QEMUD_CMD_FLAG_RTC_TD_HACK |
QEMUD_CMD_FLAG_NO_HPET | QEMUD_CMD_FLAG_NO_HPET |
QEMUD_CMD_FLAG_NO_KVM_PIT | QEMUD_CMD_FLAG_NO_KVM_PIT |
QEMUD_CMD_FLAG_TDF, QEMUD_CMD_FLAG_TDF |
QEMUD_CMD_FLAG_BOOT_MENU,
10092, 1, 0); 10092, 1, 0);
DO_TEST("qemu-0.12.1", DO_TEST("qemu-0.12.1",
QEMUD_CMD_FLAG_VNC_COLON | QEMUD_CMD_FLAG_VNC_COLON |
@ -244,7 +245,8 @@ mymain(int argc, char **argv)
QEMUD_CMD_FLAG_DEVICE | QEMUD_CMD_FLAG_DEVICE |
QEMUD_CMD_FLAG_SMP_TOPOLOGY | QEMUD_CMD_FLAG_SMP_TOPOLOGY |
QEMUD_CMD_FLAG_RTC | QEMUD_CMD_FLAG_RTC |
QEMUD_CMD_FLAG_NO_HPET, QEMUD_CMD_FLAG_NO_HPET |
QEMUD_CMD_FLAG_BOOT_MENU,
12001, 0, 0); 12001, 0, 0);
DO_TEST("qemu-kvm-0.12.3", DO_TEST("qemu-kvm-0.12.3",
QEMUD_CMD_FLAG_VNC_COLON | QEMUD_CMD_FLAG_VNC_COLON |
@ -274,7 +276,8 @@ mymain(int argc, char **argv)
QEMUD_CMD_FLAG_VNET_HOST | QEMUD_CMD_FLAG_VNET_HOST |
QEMUD_CMD_FLAG_NO_HPET | QEMUD_CMD_FLAG_NO_HPET |
QEMUD_CMD_FLAG_NO_KVM_PIT | QEMUD_CMD_FLAG_NO_KVM_PIT |
QEMUD_CMD_FLAG_TDF, QEMUD_CMD_FLAG_TDF |
QEMUD_CMD_FLAG_BOOT_MENU,
12003, 1, 0); 12003, 1, 0);
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;

View File

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

View File

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

View File

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

View File

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

View File

@ -223,6 +223,8 @@ mymain(int argc, char **argv)
DO_TEST("boot-cdrom", 0); DO_TEST("boot-cdrom", 0);
DO_TEST("boot-network", 0); DO_TEST("boot-network", 0);
DO_TEST("boot-floppy", 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("bootloader", QEMUD_CMD_FLAG_DOMID);
DO_TEST("clock-utc", 0); DO_TEST("clock-utc", 0);
DO_TEST("clock-localtime", 0); DO_TEST("clock-localtime", 0);

View File

@ -89,6 +89,8 @@ mymain(int argc, char **argv)
DO_TEST("boot-cdrom"); DO_TEST("boot-cdrom");
DO_TEST("boot-network"); DO_TEST("boot-network");
DO_TEST("boot-floppy"); DO_TEST("boot-floppy");
DO_TEST("boot-multi");
DO_TEST("boot-menu-disable");
DO_TEST("bootloader"); DO_TEST("bootloader");
DO_TEST("clock-utc"); DO_TEST("clock-utc");
DO_TEST("clock-localtime"); DO_TEST("clock-localtime");