Parse the -M (or -machine) command line option before starting processing in earnest and have a fallback ready in case it's not present, so that while parsing other options we can rely on def->os.machine being initialized. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1379218 Signed-off-by: Andrea Bolognani <abologna@xxxxxxxxxx> --- Changes from [v1]: * rework command line parsing instead of adding checks to qemuDomainMachineIs*() functions [v1] https://www.redhat.com/archives/libvir-list/2017-October/msg00406.html src/qemu/qemu_parse_command.c | 174 ++++++++++++--------- .../qemuargv2xml-nomachine-aarch64.args | 11 ++ .../qemuargv2xml-nomachine-aarch64.xml | 39 +++++ .../qemuargv2xml-nomachine-ppc64.args | 11 ++ .../qemuargv2xml-nomachine-ppc64.xml | 49 ++++++ .../qemuargv2xml-nomachine-x86_64.args | 11 ++ .../qemuargv2xml-nomachine-x86_64.xml | 48 ++++++ tests/qemuargv2xmltest.c | 4 + 8 files changed, 270 insertions(+), 77 deletions(-) create mode 100644 tests/qemuargv2xmldata/qemuargv2xml-nomachine-aarch64.args create mode 100644 tests/qemuargv2xmldata/qemuargv2xml-nomachine-aarch64.xml create mode 100644 tests/qemuargv2xmldata/qemuargv2xml-nomachine-ppc64.args create mode 100644 tests/qemuargv2xmldata/qemuargv2xml-nomachine-ppc64.xml create mode 100644 tests/qemuargv2xmldata/qemuargv2xml-nomachine-x86_64.args create mode 100644 tests/qemuargv2xmldata/qemuargv2xml-nomachine-x86_64.xml diff --git a/src/qemu/qemu_parse_command.c b/src/qemu/qemu_parse_command.c index 7c409b03a..aaa4d3703 100644 --- a/src/qemu/qemu_parse_command.c +++ b/src/qemu/qemu_parse_command.c @@ -1884,6 +1884,98 @@ qemuParseCommandLine(virCapsPtr caps, } } + /* Detect machine type before processing any other arguments, + * because they might depend on it */ + for (i = 1; progargv[i]; i++) { + const char *arg = progargv[i]; + + /* Make sure we have a single - for all options to + simplify next logic */ + if (STRPREFIX(arg, "--")) + arg++; + + if (STREQ(arg, "-M") || + STREQ(arg, "-machine")) { + char *param; + size_t j = 0; + + /* -machine [type=]name[,prop[=value][,...]] + * Set os.machine only if first parameter lacks '=' or + * contains explicit type='...' */ + WANT_VALUE(); + if (!(list = virStringSplit(val, ",", 0))) + goto error; + param = list[0]; + + if (STRPREFIX(param, "type=")) + param += strlen("type="); + if (!strchr(param, '=')) { + if (VIR_STRDUP(def->os.machine, param) < 0) + goto error; + j++; + } + + /* handle all remaining "-machine" parameters */ + while ((param = list[j++])) { + if (STRPREFIX(param, "dump-guest-core=")) { + param += strlen("dump-guest-core="); + def->mem.dump_core = virTristateSwitchTypeFromString(param); + if (def->mem.dump_core <= 0) + def->mem.dump_core = VIR_TRISTATE_SWITCH_ABSENT; + } else if (STRPREFIX(param, "mem-merge=off")) { + def->mem.nosharepages = true; + } else if (STRPREFIX(param, "accel=kvm")) { + def->virtType = VIR_DOMAIN_VIRT_KVM; + def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_TRISTATE_SWITCH_ON; + } else if (STRPREFIX(param, "aes-key-wrap=")) { + if (STREQ(arg, "-M")) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("aes-key-wrap is not supported with " + "this QEMU binary")); + goto error; + } + param += strlen("aes-key-wrap="); + if (!def->keywrap && VIR_ALLOC(def->keywrap) < 0) + goto error; + def->keywrap->aes = virTristateSwitchTypeFromString(param); + if (def->keywrap->aes < 0) + def->keywrap->aes = VIR_TRISTATE_SWITCH_ABSENT; + } else if (STRPREFIX(param, "dea-key-wrap=")) { + if (STREQ(arg, "-M")) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("dea-key-wrap is not supported with " + "this QEMU binary")); + goto error; + } + param += strlen("dea-key-wrap="); + if (!def->keywrap && VIR_ALLOC(def->keywrap) < 0) + goto error; + def->keywrap->dea = virTristateSwitchTypeFromString(param); + if (def->keywrap->dea < 0) + def->keywrap->dea = VIR_TRISTATE_SWITCH_ABSENT; + } + } + virStringListFree(list); + list = NULL; + } + } + + /* If no machine type has been found among the arguments, then figure + * out a reasonable value by using capabilities */ + if (!def->os.machine) { + virCapsDomainDataPtr capsdata; + + if (!(capsdata = virCapabilitiesDomainDataLookup(caps, def->os.type, + def->os.arch, def->virtType, NULL, NULL))) + goto error; + + if (VIR_STRDUP(def->os.machine, capsdata->machinetype) < 0) { + VIR_FREE(capsdata); + goto error; + } + VIR_FREE(capsdata); + } + /* Now the real processing loop */ for (i = 1; progargv[i]; i++) { const char *arg = progargv[i]; @@ -2137,69 +2229,6 @@ qemuParseCommandLine(virCapsPtr caps, } if (STREQ(def->name, "")) VIR_FREE(def->name); - } else if (STREQ(arg, "-M") || - STREQ(arg, "-machine")) { - char *param; - size_t j = 0; - - /* -machine [type=]name[,prop[=value][,...]] - * Set os.machine only if first parameter lacks '=' or - * contains explicit type='...' */ - WANT_VALUE(); - if (!(list = virStringSplit(val, ",", 0))) - goto error; - param = list[0]; - - if (STRPREFIX(param, "type=")) - param += strlen("type="); - if (!strchr(param, '=')) { - if (VIR_STRDUP(def->os.machine, param) < 0) - goto error; - j++; - } - - /* handle all remaining "-machine" parameters */ - while ((param = list[j++])) { - if (STRPREFIX(param, "dump-guest-core=")) { - param += strlen("dump-guest-core="); - def->mem.dump_core = virTristateSwitchTypeFromString(param); - if (def->mem.dump_core <= 0) - def->mem.dump_core = VIR_TRISTATE_SWITCH_ABSENT; - } else if (STRPREFIX(param, "mem-merge=off")) { - def->mem.nosharepages = true; - } else if (STRPREFIX(param, "accel=kvm")) { - def->virtType = VIR_DOMAIN_VIRT_KVM; - def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_TRISTATE_SWITCH_ON; - } else if (STRPREFIX(param, "aes-key-wrap=")) { - if (STREQ(arg, "-M")) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("aes-key-wrap is not supported with " - "this QEMU binary")); - goto error; - } - param += strlen("aes-key-wrap="); - if (!def->keywrap && VIR_ALLOC(def->keywrap) < 0) - goto error; - def->keywrap->aes = virTristateSwitchTypeFromString(param); - if (def->keywrap->aes < 0) - def->keywrap->aes = VIR_TRISTATE_SWITCH_ABSENT; - } else if (STRPREFIX(param, "dea-key-wrap=")) { - if (STREQ(arg, "-M")) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("dea-key-wrap is not supported with " - "this QEMU binary")); - goto error; - } - param += strlen("dea-key-wrap="); - if (!def->keywrap && VIR_ALLOC(def->keywrap) < 0) - goto error; - def->keywrap->dea = virTristateSwitchTypeFromString(param); - if (def->keywrap->dea < 0) - def->keywrap->dea = VIR_TRISTATE_SWITCH_ABSENT; - } - } - virStringListFree(list); - list = NULL; } else if (STREQ(arg, "-serial")) { WANT_VALUE(); if (STRNEQ(val, "none")) { @@ -2489,6 +2518,11 @@ qemuParseCommandLine(virCapsPtr caps, argRecognized = false; } + } else if (STREQ(arg, "-M") || + STREQ(arg, "-machine")) { + // This option has already been processed before entering this + // loop, so we just need to skip its argument and move along + WANT_VALUE(); } else { argRecognized = false; } @@ -2571,20 +2605,6 @@ qemuParseCommandLine(virCapsPtr caps, } } - if (!def->os.machine) { - virCapsDomainDataPtr capsdata; - - if (!(capsdata = virCapabilitiesDomainDataLookup(caps, def->os.type, - def->os.arch, def->virtType, NULL, NULL))) - goto error; - - if (VIR_STRDUP(def->os.machine, capsdata->machinetype) < 0) { - VIR_FREE(capsdata); - goto error; - } - VIR_FREE(capsdata); - } - if (!nographics && (def->ngraphics == 0 || have_sdl)) { virDomainGraphicsDefPtr sdl; const char *display = qemuFindEnv(progenv, "DISPLAY"); diff --git a/tests/qemuargv2xmldata/qemuargv2xml-nomachine-aarch64.args b/tests/qemuargv2xmldata/qemuargv2xml-nomachine-aarch64.args new file mode 100644 index 000000000..b17c0d0c2 --- /dev/null +++ b/tests/qemuargv2xmldata/qemuargv2xml-nomachine-aarch64.args @@ -0,0 +1,11 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-aarch64 \ +-name QEMUGuest1 \ +-m 512 \ +-hda /dev/HostVG/QEMUGuest1 \ +-cdrom /root/boot.iso diff --git a/tests/qemuargv2xmldata/qemuargv2xml-nomachine-aarch64.xml b/tests/qemuargv2xmldata/qemuargv2xml-nomachine-aarch64.xml new file mode 100644 index 000000000..eb8f9db80 --- /dev/null +++ b/tests/qemuargv2xmldata/qemuargv2xml-nomachine-aarch64.xml @@ -0,0 +1,39 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='aarch64' machine='virt'>hvm</type> + </os> + <features> + <gic version='2'/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/root/boot.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + <address type='drive' controller='0' bus='1' target='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <graphics type='sdl'/> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + </video> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuargv2xmldata/qemuargv2xml-nomachine-ppc64.args b/tests/qemuargv2xmldata/qemuargv2xml-nomachine-ppc64.args new file mode 100644 index 000000000..ac618775e --- /dev/null +++ b/tests/qemuargv2xmldata/qemuargv2xml-nomachine-ppc64.args @@ -0,0 +1,11 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-ppc64 \ +-name QEMUGuest1 \ +-m 512 \ +-hda /dev/HostVG/QEMUGuest1 \ +-cdrom /root/boot.iso diff --git a/tests/qemuargv2xmldata/qemuargv2xml-nomachine-ppc64.xml b/tests/qemuargv2xmldata/qemuargv2xml-nomachine-ppc64.xml new file mode 100644 index 000000000..fa41070cb --- /dev/null +++ b/tests/qemuargv2xmldata/qemuargv2xml-nomachine-ppc64.xml @@ -0,0 +1,49 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='ppc64' machine='pseries'>hvm</type> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-ppc64</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='scsi'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/root/boot.iso'/> + <target dev='hdc' bus='scsi'/> + <readonly/> + <address type='drive' controller='0' bus='0' target='0' unit='2'/> + </disk> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <model name='spapr-pci-host-bridge'/> + <target index='0'/> + </controller> + <controller type='scsi' index='0'> + <address type='spapr-vio' reg='0x2000'/> + </controller> + <input type='keyboard' bus='usb'/> + <input type='mouse' bus='usb'/> + <graphics type='sdl'/> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='none'/> + <panic model='pseries'/> + </devices> +</domain> diff --git a/tests/qemuargv2xmldata/qemuargv2xml-nomachine-x86_64.args b/tests/qemuargv2xmldata/qemuargv2xml-nomachine-x86_64.args new file mode 100644 index 000000000..22bc4fb1c --- /dev/null +++ b/tests/qemuargv2xmldata/qemuargv2xml-nomachine-x86_64.args @@ -0,0 +1,11 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name QEMUGuest1 \ +-m 512 \ +-hda /dev/HostVG/QEMUGuest1 \ +-cdrom /root/boot.iso diff --git a/tests/qemuargv2xmldata/qemuargv2xml-nomachine-x86_64.xml b/tests/qemuargv2xmldata/qemuargv2xml-nomachine-x86_64.xml new file mode 100644 index 000000000..71a36f083 --- /dev/null +++ b/tests/qemuargv2xmldata/qemuargv2xml-nomachine-x86_64.xml @@ -0,0 +1,48 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-0.11'>hvm</type> + </os> + <features> + <acpi/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/root/boot.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + <address type='drive' controller='0' bus='1' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <graphics type='sdl'/> + <video> + <model type='cirrus' vram='16384' heads='1' primary='yes'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c index 1adbcfef6..5d261afa6 100644 --- a/tests/qemuargv2xmltest.c +++ b/tests/qemuargv2xmltest.c @@ -288,6 +288,10 @@ mymain(void) DO_TEST("machine-deakeywrap-off-argv"); DO_TEST("machine-keywrap-none-argv"); + DO_TEST("nomachine-x86_64"); + DO_TEST("nomachine-aarch64"); + DO_TEST("nomachine-ppc64"); + qemuTestDriverFree(&driver); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; -- 2.13.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list