mirror of
https://github.com/libvirt/libvirt.git
synced 2026-07-31 08:38:16 -05:00
qemu: Cleanup boot parameter building
This patch cleans up building the "-boot" parameter and while on that
fixes one inconsistency by modifying these things:
- I completed the unfinished virDomainBootMenu enum by specifying
LAST, declaring it and also declaring the TypeFromString and
TypeToString parameters.
- Previously mentioned TypeFromString and TypeToString are used when
parsing the XML.
- Last, but not least, visible change is that the "-boot" parameter
is built and parsed properly:
- The "order=" prefix is used only when additional parameters are
used (menu, etc.).
- It's rewritten in a way that other parameters can be added
easily in the future (used in following patch).
- The "order=" parameter is properly parsed regardless to where it
is placed in the string (e.g. "menu=on,order=nc").
- The "menu=" parameter (and others in the future) are created
when they should be (i.e. even when bootindex is supported and
used, but not when bootloader is selected).
This commit is contained in:
+13
-3
@@ -102,6 +102,11 @@ VIR_ENUM_IMPL(virDomainBoot, VIR_DOMAIN_BOOT_LAST,
|
||||
"hd",
|
||||
"network")
|
||||
|
||||
VIR_ENUM_IMPL(virDomainBootMenu, VIR_DOMAIN_BOOT_MENU_LAST,
|
||||
"default",
|
||||
"yes",
|
||||
"no")
|
||||
|
||||
VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
|
||||
"acpi",
|
||||
"apic",
|
||||
@@ -8181,10 +8186,15 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
|
||||
|
||||
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 = virDomainBootMenuTypeFromString(bootstr);
|
||||
if (def->os.bootmenu <= 0) {
|
||||
/* In order not to break misconfigured machines, this
|
||||
* should not emit an error, but rather set the bootmenu
|
||||
* to disabled */
|
||||
VIR_WARN("disabling bootmenu due to unknown option '%s'",
|
||||
bootstr);
|
||||
def->os.bootmenu = VIR_DOMAIN_BOOT_MENU_DISABLED;
|
||||
}
|
||||
VIR_FREE(bootstr);
|
||||
}
|
||||
|
||||
|
||||
@@ -1359,6 +1359,8 @@ enum virDomainBootMenu {
|
||||
VIR_DOMAIN_BOOT_MENU_DEFAULT = 0,
|
||||
VIR_DOMAIN_BOOT_MENU_ENABLED,
|
||||
VIR_DOMAIN_BOOT_MENU_DISABLED,
|
||||
|
||||
VIR_DOMAIN_BOOT_MENU_LAST
|
||||
};
|
||||
|
||||
enum virDomainFeature {
|
||||
@@ -1429,6 +1431,7 @@ struct _virDomainOSDef {
|
||||
char *machine;
|
||||
int nBootDevs;
|
||||
int bootDevs[VIR_DOMAIN_BOOT_LAST];
|
||||
/* enum virDomainBootMenu */
|
||||
int bootmenu;
|
||||
char *init;
|
||||
char **initargv;
|
||||
@@ -1440,6 +1443,7 @@ struct _virDomainOSDef {
|
||||
char *bootloader;
|
||||
char *bootloaderArgs;
|
||||
int smbios_mode;
|
||||
|
||||
virDomainBIOSDef bios;
|
||||
};
|
||||
|
||||
@@ -2129,6 +2133,7 @@ VIR_ENUM_DECL(virDomainTaint)
|
||||
|
||||
VIR_ENUM_DECL(virDomainVirt)
|
||||
VIR_ENUM_DECL(virDomainBoot)
|
||||
VIR_ENUM_DECL(virDomainBootMenu)
|
||||
VIR_ENUM_DECL(virDomainFeature)
|
||||
VIR_ENUM_DECL(virDomainApicEoi)
|
||||
VIR_ENUM_DECL(virDomainLifecycle)
|
||||
|
||||
@@ -280,6 +280,8 @@ virDomainApicEoiTypeToString;
|
||||
virDomainAssignDef;
|
||||
virDomainBlockedReasonTypeFromString;
|
||||
virDomainBlockedReasonTypeToString;
|
||||
virDomainBootMenuTypeFromString;
|
||||
virDomainBootMenuTypeToString;
|
||||
virDomainChrConsoleTargetTypeFromString;
|
||||
virDomainChrConsoleTargetTypeToString;
|
||||
virDomainChrDefForeach;
|
||||
|
||||
+68
-25
@@ -4879,6 +4879,8 @@ qemuBuildCommandLine(virConnectPtr conn,
|
||||
}
|
||||
|
||||
if (!def->os.bootloader) {
|
||||
int boot_nparams = 0;
|
||||
virBuffer boot_buf = VIR_BUFFER_INITIALIZER;
|
||||
/*
|
||||
* We prefer using explicit bootindex=N parameters for predictable
|
||||
* results even though domain XML doesn't use per device boot elements.
|
||||
@@ -4901,7 +4903,6 @@ qemuBuildCommandLine(virConnectPtr conn,
|
||||
}
|
||||
|
||||
if (!emitBootindex) {
|
||||
virBuffer boot_buf = VIR_BUFFER_INITIALIZER;
|
||||
char boot[VIR_DOMAIN_BOOT_LAST+1];
|
||||
|
||||
for (i = 0 ; i < def->os.nBootDevs ; i++) {
|
||||
@@ -4925,19 +4926,38 @@ qemuBuildCommandLine(virConnectPtr conn,
|
||||
}
|
||||
boot[def->os.nBootDevs] = '\0';
|
||||
|
||||
virCommandAddArg(cmd, "-boot");
|
||||
virBufferAsprintf(&boot_buf, "%s", boot);
|
||||
boot_nparams++;
|
||||
}
|
||||
|
||||
if (def->os.bootmenu) {
|
||||
if (qemuCapsGet(caps, QEMU_CAPS_BOOT_MENU)) {
|
||||
if (boot_nparams++)
|
||||
virBufferAddChar(&boot_buf, ',');
|
||||
|
||||
if (qemuCapsGet(caps, QEMU_CAPS_BOOT_MENU) &&
|
||||
def->os.bootmenu != VIR_DOMAIN_BOOT_MENU_DEFAULT) {
|
||||
if (def->os.bootmenu == VIR_DOMAIN_BOOT_MENU_ENABLED)
|
||||
virBufferAsprintf(&boot_buf, "order=%s,menu=on", boot);
|
||||
else if (def->os.bootmenu == VIR_DOMAIN_BOOT_MENU_DISABLED)
|
||||
virBufferAsprintf(&boot_buf, "order=%s,menu=off", boot);
|
||||
virBufferAsprintf(&boot_buf, "menu=on");
|
||||
else
|
||||
virBufferAsprintf(&boot_buf, "menu=off");
|
||||
} else {
|
||||
virBufferAdd(&boot_buf, boot, -1);
|
||||
/* We cannot emit an error when bootmenu is enabled but
|
||||
* unsupported because of backward compatibility */
|
||||
VIR_WARN("bootmenu is enabled but not "
|
||||
"supported by this QEMU binary");
|
||||
}
|
||||
|
||||
virCommandAddArgBuffer(cmd, &boot_buf);
|
||||
}
|
||||
|
||||
if (boot_nparams > 0) {
|
||||
virCommandAddArg(cmd, "-boot");
|
||||
|
||||
if (boot_nparams < 2 || emitBootindex) {
|
||||
virCommandAddArgBuffer(cmd, &boot_buf);
|
||||
} else {
|
||||
virCommandAddArgFormat(cmd,
|
||||
"order=%s",
|
||||
virBufferContentAndReset(&boot_buf));
|
||||
}
|
||||
}
|
||||
|
||||
if (def->os.kernel)
|
||||
@@ -7861,6 +7881,26 @@ error:
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
qemuParseCommandLineBootDevs(virDomainDefPtr def, const char *str) {
|
||||
int n, b = 0;
|
||||
|
||||
for (n = 0 ; str[n] && b < VIR_DOMAIN_BOOT_LAST ; n++) {
|
||||
if (str[n] == 'a')
|
||||
def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_FLOPPY;
|
||||
else if (str[n] == 'c')
|
||||
def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_DISK;
|
||||
else if (str[n] == 'd')
|
||||
def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_CDROM;
|
||||
else if (str[n] == 'n')
|
||||
def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_NET;
|
||||
else if (str[n] == ',')
|
||||
break;
|
||||
}
|
||||
def->os.nBootDevs = b;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Analyse the env and argv settings and reconstruct a
|
||||
* virDomainDefPtr representing these settings as closely
|
||||
@@ -8218,24 +8258,27 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
|
||||
if (!(def->os.cmdline = strdup(val)))
|
||||
goto no_memory;
|
||||
} else if (STREQ(arg, "-boot")) {
|
||||
int n, b = 0;
|
||||
const char *token = NULL;
|
||||
WANT_VALUE();
|
||||
for (n = 0 ; val[n] && b < VIR_DOMAIN_BOOT_LAST ; n++) {
|
||||
if (val[n] == 'a')
|
||||
def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_FLOPPY;
|
||||
else if (val[n] == 'c')
|
||||
def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_DISK;
|
||||
else if (val[n] == 'd')
|
||||
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;
|
||||
if (!strchr(val, ','))
|
||||
qemuParseCommandLineBootDevs(def, val);
|
||||
else {
|
||||
token = val;
|
||||
while (token && *token) {
|
||||
if (STRPREFIX(token, "order=")) {
|
||||
token += strlen("order=");
|
||||
qemuParseCommandLineBootDevs(def, token);
|
||||
} else if (STRPREFIX(token, "menu=on")) {
|
||||
def->os.bootmenu = 1;
|
||||
}
|
||||
token = strchr(token, ',');
|
||||
/* This incrementation has to be done here in order to make it
|
||||
* possible to pass the token pointer properly into the loop */
|
||||
if (token)
|
||||
token++;
|
||||
}
|
||||
}
|
||||
} else if (STREQ(arg, "-name")) {
|
||||
char *process;
|
||||
WANT_VALUE();
|
||||
|
||||
@@ -7,6 +7,7 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu \
|
||||
-nodefaults \
|
||||
-monitor unix:/tmp/test-monitor,server,nowait \
|
||||
-no-acpi \
|
||||
-boot menu=off \
|
||||
-drive file=/dev/cdrom,if=none,media=cdrom,id=drive-ide0-1-0 \
|
||||
-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0,bootindex=1 \
|
||||
-usb \
|
||||
|
||||
Reference in New Issue
Block a user