提交 8c952908 编写于 作者: M Martin Kletzander

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).
上级 a5e8beef
......@@ -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;
......
......@@ -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");
}
}
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"))
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 \
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册