In case a hypervisor doesn't support the exact CPU model requested by a domain XML, we automatically fallback to a closest CPU model the hypervisor supports (and make sure we add/remove any additional features if needed). This patch adds 'fallback' attribute to model element, which can be used to disable this automatic fallback. --- Notes: Version 2: - grammar docs/formatdomain.html.in | 12 +++- docs/schemas/domaincommon.rng | 8 ++ src/conf/cpu_conf.c | 38 ++++++++- src/conf/cpu_conf.h | 10 +++ src/cpu/cpu_x86.c | 17 ++++- src/qemu/qemu_command.c | 1 + tests/cputest.c | 2 + tests/cputestdata/x86-baseline-1-result.xml | 2 +- tests/cputestdata/x86-baseline-2-result.xml | 2 +- .../cputestdata/x86-baseline-no-vendor-result.xml | 2 +- .../x86-baseline-some-vendors-result.xml | 2 +- tests/cputestdata/x86-guest-nofallback.xml | 18 ++++ .../cputestdata/x86-host+guest,model486-result.xml | 2 +- .../x86-host+guest,models,Penryn-result.xml | 2 +- .../x86-host+guest,models,qemu64-result.xml | 2 +- tests/cputestdata/x86-host+guest,models-result.xml | 2 +- tests/cputestdata/x86-host+guest-result.xml | 2 +- tests/cputestdata/x86-host+guest.xml | 2 +- tests/cputestdata/x86-host+min.xml | 2 +- .../cputestdata/x86-host+nehalem-force-result.xml | 2 +- tests/cputestdata/x86-host+pentium3.xml | 2 +- .../x86-host+strict-force-extra-result.xml | 2 +- .../x86-host-better+pentium3,core2duo-result.xml | 2 +- .../x86-host-better+pentium3,pentium3-result.xml | 2 +- .../x86-host-better+pentium3-result.xml | 2 +- tests/cputestdata/x86-host-worse+guest-result.xml | 2 +- tests/qemuxml2argvdata/qemuxml2argv-cpu-exact1.xml | 2 +- .../qemuxml2argv-cpu-exact2-nofallback.args | 4 + .../qemuxml2argv-cpu-exact2-nofallback.xml | 35 ++++++++ .../qemuxml2argv-cpu-fallback.args | 19 +++++ .../qemuxml2argvdata/qemuxml2argv-cpu-fallback.xml | 25 ++++++ .../qemuxml2argv-cpu-nofallback.xml | 25 ++++++ tests/qemuxml2argvtest.c | 84 ++++++++++++------- .../qemuxml2xmlout-graphics-spice-timeout.xml | 86 ++++++++++++++++++++ tests/qemuxml2xmltest.c | 2 +- tests/testutilsqemu.c | 1 + 36 files changed, 367 insertions(+), 58 deletions(-) create mode 100644 tests/cputestdata/x86-guest-nofallback.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-exact2-nofallback.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-exact2-nofallback.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-fallback.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-fallback.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cpu-nofallback.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-graphics-spice-timeout.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 42e23a1..8961fed 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -559,7 +559,7 @@ <pre> ... <cpu match='exact'> - <model>core2duo</model> + <model fallback='allow'>core2duo</model> <vendor>Intel</vendor> <topology sockets='1' cores='2' threads='1'/> <feature policy='disable' name='lahf_lm'/> @@ -609,7 +609,15 @@ <dd>The content of the <code>model</code> element specifies CPU model requested by the guest. The list of available CPU models and their definition can be found in <code>cpu_map.xml</code> file installed - in libvirt's data directory.</dd> + in libvirt's data directory. If a hypervisor is not able to use the + exact CPU model, libvirt automatically falls back to a closest model + supported by the hypervisor while maintaining the list of CPU + features. <span class="since">Since 0.9.10</span>, an optional + <code>fallback</code> attribute can be used to forbid this behavior, + in which case an attempt to start a domain requesting unsupported + CPU model will fail. Supported values for <code>fallback</code> + attribute are: <code>allow</code> (this is the default), and + <code>forbid</code>.</dd> <dt><code>vendor</code></dt> <dd><span class="since">Since 0.8.3</span> the content of the diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index e93ae77..a3ad3d3 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2459,6 +2459,14 @@ <define name="cpuModel"> <element name="model"> + <optional> + <attribute name="fallback"> + <choice> + <value>allow</value> + <value>forbid</value> + </choice> + </attribute> + </optional> <text/> </element> </define> diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index 348299b..c8e29e4 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -44,6 +44,10 @@ VIR_ENUM_IMPL(virCPUMatch, VIR_CPU_MATCH_LAST, "exact", "strict") +VIR_ENUM_IMPL(virCPUFallback, VIR_CPU_FALLBACK_LAST, + "allow", + "forbid") + VIR_ENUM_IMPL(virCPUFeaturePolicy, VIR_CPU_FEATURE_LAST, "force", "require", @@ -97,6 +101,7 @@ virCPUDefCopy(const virCPUDefPtr cpu) copy->type = cpu->type; copy->match = cpu->match; + copy->fallback = cpu->fallback; copy->sockets = cpu->sockets; copy->cores = cpu->cores; copy->threads = cpu->threads; @@ -209,6 +214,21 @@ virCPUDefParseXML(const xmlNodePtr node, goto error; } + if (def->model && def->type == VIR_CPU_TYPE_GUEST) { + const char *fallback; + + fallback = virXPathString("string(./model[1]/@fallback)", ctxt); + if (fallback) { + def->fallback = virCPUFallbackTypeFromString(fallback); + VIR_FREE(fallback); + if (def->fallback < 0) { + virCPUReportError(VIR_ERR_XML_ERROR, "%s", + _("Invalid fallback attribute")); + goto error; + } + } + } + def->vendor = virXPathString("string(./vendor[1])", ctxt); if (def->vendor && !def->model) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, @@ -455,8 +475,22 @@ virCPUDefFormatBuf(virBufferPtr buf, return -1; } - if (def->model) - virBufferAsprintf(buf, "<model>%s</model>\n", def->model); + if (def->model) { + virBufferAddLit(buf, "<model"); + if (def->type == VIR_CPU_TYPE_GUEST) { + const char *fallback; + + fallback = virCPUFallbackTypeToString(def->fallback); + if (!fallback) { + virCPUReportError(VIR_ERR_INTERNAL_ERROR, + _("Unexpected CPU fallback value: %d"), + def->fallback); + return -1; + } + virBufferAsprintf(buf, " fallback='%s'", fallback); + } + virBufferAsprintf(buf, ">%s</model>\n", def->model); + } if (def->vendor) { virBufferAsprintf(buf, "<vendor>%s</vendor>\n", def->vendor); diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h index efff473..0c50f90 100644 --- a/src/conf/cpu_conf.h +++ b/src/conf/cpu_conf.h @@ -48,6 +48,15 @@ enum virCPUMatch { VIR_ENUM_DECL(virCPUMatch) +enum virCPUFallback { + VIR_CPU_FALLBACK_ALLOW, + VIR_CPU_FALLBACK_FORBID, + + VIR_CPU_FALLBACK_LAST +}; + +VIR_ENUM_DECL(virCPUFallback) + enum virCPUFeaturePolicy { VIR_CPU_FEATURE_FORCE, VIR_CPU_FEATURE_REQUIRE, @@ -83,6 +92,7 @@ struct _virCPUDef { int match; /* enum virCPUMatch */ char *arch; char *model; + int fallback; /* enum virCPUFallback */ char *vendor; unsigned int sockets; unsigned int cores; diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 4a4272e..ad2d5cd 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -1294,8 +1294,21 @@ x86Decode(virCPUDefPtr cpu, } if (!allowed) { - VIR_DEBUG("CPU model %s not allowed by hypervisor; ignoring", - candidate->name); + if (preferred && STREQ(candidate->name, preferred)) { + if (cpu->fallback != VIR_CPU_FALLBACK_ALLOW) { + virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("CPU model %s is not supported by hypervisor"), + preferred); + goto out; + } else { + VIR_WARN("Preferred CPU model %s not allowed by" + " hypervisor; closest supported model will be" + " used", preferred); + } + } else { + VIR_DEBUG("CPU model %s not allowed by hypervisor; ignoring", + candidate->name); + } goto next; } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index d051305..4d7842e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3481,6 +3481,7 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver, preferred = def->cpu->model; guest->type = VIR_CPU_TYPE_GUEST; + guest->fallback = def->cpu->fallback; if (cpuDecode(guest, data, cpus, ncpus, preferred) < 0) goto cleanup; diff --git a/tests/cputest.c b/tests/cputest.c index 5b7b951..2dd89f2 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -287,6 +287,7 @@ cpuTestGuestData(const void *arg) guest->type = VIR_CPU_TYPE_GUEST; guest->match = VIR_CPU_MATCH_EXACT; + guest->fallback = cpu->fallback; if (cpuDecode(guest, guestData, data->models, data->nmodels, data->preferred) < 0) { if (data->result < 0) { @@ -620,6 +621,7 @@ mymain(void) DO_TEST_GUESTDATA("x86", "host", "guest", models, "Penryn", 0); DO_TEST_GUESTDATA("x86", "host", "guest", models, "qemu64", 0); DO_TEST_GUESTDATA("x86", "host", "guest", nomodel, NULL, -1); + DO_TEST_GUESTDATA("x86", "host", "guest-nofallback", models, "Penryn", -1); free(map); return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE); diff --git a/tests/cputestdata/x86-baseline-1-result.xml b/tests/cputestdata/x86-baseline-1-result.xml index e376f74..99e43d0 100644 --- a/tests/cputestdata/x86-baseline-1-result.xml +++ b/tests/cputestdata/x86-baseline-1-result.xml @@ -1,5 +1,5 @@ <cpu match='exact'> - <model>Conroe</model> + <model fallback='allow'>Conroe</model> <vendor>Intel</vendor> <feature policy='disable' name='lahf_lm'/> </cpu> diff --git a/tests/cputestdata/x86-baseline-2-result.xml b/tests/cputestdata/x86-baseline-2-result.xml index 3fd0551..76c13aa 100644 --- a/tests/cputestdata/x86-baseline-2-result.xml +++ b/tests/cputestdata/x86-baseline-2-result.xml @@ -1,4 +1,4 @@ <cpu match='exact'> - <model>core2duo</model> + <model fallback='allow'>core2duo</model> <feature policy='disable' name='nx'/> </cpu> diff --git a/tests/cputestdata/x86-baseline-no-vendor-result.xml b/tests/cputestdata/x86-baseline-no-vendor-result.xml index 0fc0892..8b97d2c 100644 --- a/tests/cputestdata/x86-baseline-no-vendor-result.xml +++ b/tests/cputestdata/x86-baseline-no-vendor-result.xml @@ -1,5 +1,5 @@ <cpu match='exact'> - <model>Opteron_G2</model> + <model fallback='allow'>Opteron_G2</model> <feature policy='disable' name='svm'/> <feature policy='disable' name='rdtscp'/> </cpu> diff --git a/tests/cputestdata/x86-baseline-some-vendors-result.xml b/tests/cputestdata/x86-baseline-some-vendors-result.xml index 2ddfcc5..bac0e5d 100644 --- a/tests/cputestdata/x86-baseline-some-vendors-result.xml +++ b/tests/cputestdata/x86-baseline-some-vendors-result.xml @@ -1,3 +1,3 @@ <cpu match='exact'> - <model>Opteron_G1</model> + <model fallback='allow'>Opteron_G1</model> </cpu> diff --git a/tests/cputestdata/x86-guest-nofallback.xml b/tests/cputestdata/x86-guest-nofallback.xml new file mode 100644 index 0000000..babe47d --- /dev/null +++ b/tests/cputestdata/x86-guest-nofallback.xml @@ -0,0 +1,18 @@ +<cpu match='exact'> + <model fallback='forbid'>Penryn</model> + <topology sockets='2' cores='4' threads='1'/> + <!--feature name='sse4.1' policy='optional'/--> + <feature name='dca' policy='optional'/> + <feature name='xtpr' policy='optional'/> + <feature name='sse4.2' policy='optional'/> + <feature name='3dnow' policy='optional'/> + <feature name='ssse3' policy='optional'/> + <feature name='vmx' policy='disable'/> + <feature name='ds_cpl' policy='disable'/> + <feature name='sse' policy='disable'/> + <feature name='monitor' policy='force'/> + <feature name='pbe' policy='force'/> + <feature name='3dnowext' policy='force'/> + <feature name='svm' policy='force'/> + <feature name='popcnt' policy='forbid'/> +</cpu> diff --git a/tests/cputestdata/x86-host+guest,model486-result.xml b/tests/cputestdata/x86-host+guest,model486-result.xml index fb1bb4b..9fd67eb 100644 --- a/tests/cputestdata/x86-host+guest,model486-result.xml +++ b/tests/cputestdata/x86-host+guest,model486-result.xml @@ -1,6 +1,6 @@ <cpu match='exact'> <arch>x86_64</arch> - <model>486</model> + <model fallback='allow'>486</model> <feature policy='require' name='svm'/> <feature policy='require' name='lahf_lm'/> <feature policy='require' name='3dnowext'/> diff --git a/tests/cputestdata/x86-host+guest,models,Penryn-result.xml b/tests/cputestdata/x86-host+guest,models,Penryn-result.xml index 9559465..9ae11c9 100644 --- a/tests/cputestdata/x86-host+guest,models,Penryn-result.xml +++ b/tests/cputestdata/x86-host+guest,models,Penryn-result.xml @@ -1,6 +1,6 @@ <cpu match='exact'> <arch>x86_64</arch> - <model>Nehalem</model> + <model fallback='allow'>Nehalem</model> <feature policy='require' name='svm'/> <feature policy='require' name='3dnowext'/> <feature policy='require' name='dca'/> diff --git a/tests/cputestdata/x86-host+guest,models,qemu64-result.xml b/tests/cputestdata/x86-host+guest,models,qemu64-result.xml index b41863e..7582ddc 100644 --- a/tests/cputestdata/x86-host+guest,models,qemu64-result.xml +++ b/tests/cputestdata/x86-host+guest,models,qemu64-result.xml @@ -1,6 +1,6 @@ <cpu match='exact'> <arch>x86_64</arch> - <model>qemu64</model> + <model fallback='allow'>qemu64</model> <feature policy='require' name='lahf_lm'/> <feature policy='require' name='3dnowext'/> <feature policy='require' name='sse4.1'/> diff --git a/tests/cputestdata/x86-host+guest,models-result.xml b/tests/cputestdata/x86-host+guest,models-result.xml index 9559465..9ae11c9 100644 --- a/tests/cputestdata/x86-host+guest,models-result.xml +++ b/tests/cputestdata/x86-host+guest,models-result.xml @@ -1,6 +1,6 @@ <cpu match='exact'> <arch>x86_64</arch> - <model>Nehalem</model> + <model fallback='allow'>Nehalem</model> <feature policy='require' name='svm'/> <feature policy='require' name='3dnowext'/> <feature policy='require' name='dca'/> diff --git a/tests/cputestdata/x86-host+guest-result.xml b/tests/cputestdata/x86-host+guest-result.xml index 544a388..e596c43 100644 --- a/tests/cputestdata/x86-host+guest-result.xml +++ b/tests/cputestdata/x86-host+guest-result.xml @@ -1,6 +1,6 @@ <cpu match='exact'> <arch>x86_64</arch> - <model>Penryn</model> + <model fallback='allow'>Penryn</model> <feature policy='require' name='svm'/> <feature policy='require' name='3dnowext'/> <feature policy='require' name='dca'/> diff --git a/tests/cputestdata/x86-host+guest.xml b/tests/cputestdata/x86-host+guest.xml index c3fca87..2a786fd 100644 --- a/tests/cputestdata/x86-host+guest.xml +++ b/tests/cputestdata/x86-host+guest.xml @@ -1,5 +1,5 @@ <cpu match='exact'> - <model>Penryn</model> + <model fallback='allow'>Penryn</model> <topology sockets='2' cores='4' threads='1'/> <feature policy='require' name='dca'/> <feature policy='require' name='xtpr'/> diff --git a/tests/cputestdata/x86-host+min.xml b/tests/cputestdata/x86-host+min.xml index d22c7b6..fe55058 100644 --- a/tests/cputestdata/x86-host+min.xml +++ b/tests/cputestdata/x86-host+min.xml @@ -1,5 +1,5 @@ <cpu match='exact'> - <model>Penryn</model> + <model fallback='allow'>Penryn</model> <feature policy='require' name='dca'/> <feature policy='require' name='xtpr'/> <feature policy='require' name='tm2'/> diff --git a/tests/cputestdata/x86-host+nehalem-force-result.xml b/tests/cputestdata/x86-host+nehalem-force-result.xml index 162685f..41e7356 100644 --- a/tests/cputestdata/x86-host+nehalem-force-result.xml +++ b/tests/cputestdata/x86-host+nehalem-force-result.xml @@ -1,4 +1,4 @@ <cpu match='exact'> <arch>x86_64</arch> - <model>Nehalem</model> + <model fallback='allow'>Nehalem</model> </cpu> diff --git a/tests/cputestdata/x86-host+pentium3.xml b/tests/cputestdata/x86-host+pentium3.xml index d141d9e..e122ba5 100644 --- a/tests/cputestdata/x86-host+pentium3.xml +++ b/tests/cputestdata/x86-host+pentium3.xml @@ -1,5 +1,5 @@ <cpu match='exact'> - <model>pentium3</model> + <model fallback='allow'>pentium3</model> <feature policy='require' name='lahf_lm'/> <feature policy='require' name='lm'/> <feature policy='require' name='nx'/> diff --git a/tests/cputestdata/x86-host+strict-force-extra-result.xml b/tests/cputestdata/x86-host+strict-force-extra-result.xml index e47933c..f3d52a1 100644 --- a/tests/cputestdata/x86-host+strict-force-extra-result.xml +++ b/tests/cputestdata/x86-host+strict-force-extra-result.xml @@ -1,6 +1,6 @@ <cpu match='exact'> <arch>x86_64</arch> - <model>Penryn</model> + <model fallback='allow'>Penryn</model> <feature policy='require' name='3dnow'/> <feature policy='require' name='dca'/> <feature policy='require' name='xtpr'/> diff --git a/tests/cputestdata/x86-host-better+pentium3,core2duo-result.xml b/tests/cputestdata/x86-host-better+pentium3,core2duo-result.xml index c2d8ddd..5d4528b 100644 --- a/tests/cputestdata/x86-host-better+pentium3,core2duo-result.xml +++ b/tests/cputestdata/x86-host-better+pentium3,core2duo-result.xml @@ -1,6 +1,6 @@ <cpu match='exact'> <arch>x86_64</arch> - <model>core2duo</model> + <model fallback='allow'>core2duo</model> <feature policy='require' name='lahf_lm'/> <feature policy='require' name='popcnt'/> <feature policy='require' name='sse4.2'/> diff --git a/tests/cputestdata/x86-host-better+pentium3,pentium3-result.xml b/tests/cputestdata/x86-host-better+pentium3,pentium3-result.xml index 6e246a8..1530a07 100644 --- a/tests/cputestdata/x86-host-better+pentium3,pentium3-result.xml +++ b/tests/cputestdata/x86-host-better+pentium3,pentium3-result.xml @@ -1,6 +1,6 @@ <cpu match='exact'> <arch>x86_64</arch> - <model>pentium3</model> + <model fallback='allow'>pentium3</model> <feature policy='require' name='lahf_lm'/> <feature policy='require' name='lm'/> <feature policy='require' name='nx'/> diff --git a/tests/cputestdata/x86-host-better+pentium3-result.xml b/tests/cputestdata/x86-host-better+pentium3-result.xml index b918363..917d63f 100644 --- a/tests/cputestdata/x86-host-better+pentium3-result.xml +++ b/tests/cputestdata/x86-host-better+pentium3-result.xml @@ -1,6 +1,6 @@ <cpu match='exact'> <arch>x86_64</arch> - <model>Nehalem</model> + <model fallback='allow'>Nehalem</model> <feature policy='require' name='dca'/> <feature policy='require' name='xtpr'/> <feature policy='require' name='tm2'/> diff --git a/tests/cputestdata/x86-host-worse+guest-result.xml b/tests/cputestdata/x86-host-worse+guest-result.xml index 036177a..78e170a 100644 --- a/tests/cputestdata/x86-host-worse+guest-result.xml +++ b/tests/cputestdata/x86-host-worse+guest-result.xml @@ -1,6 +1,6 @@ <cpu match='exact'> <arch>x86_64</arch> - <model>Penryn</model> + <model fallback='allow'>Penryn</model> <feature policy='require' name='svm'/> <feature policy='require' name='3dnowext'/> <feature policy='require' name='monitor'/> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-exact1.xml b/tests/qemuxml2argvdata/qemuxml2argv-cpu-exact1.xml index d6db442..b5fd49c 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-cpu-exact1.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-exact1.xml @@ -9,7 +9,7 @@ <boot dev='network'/> </os> <cpu match='exact'> - <model>qemu64</model> + <model fallback='allow'>qemu64</model> <feature policy='disable' name='svm'/> <feature policy='disable' name='lm'/> <feature policy='disable' name='nx'/> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-exact2-nofallback.args b/tests/qemuxml2argvdata/qemuxml2argv-cpu-exact2-nofallback.args new file mode 100644 index 0000000..198d0d8 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-exact2-nofallback.args @@ -0,0 +1,4 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test ./qemu.sh -S -M pc \ +-cpu core2duo,+lahf_lm,+3dnowext,+xtpr,+ds_cpl,+tm,+ht,+ds,-nx -m 214 -smp 6 \ +-nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot n -net \ +none -serial none -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-exact2-nofallback.xml b/tests/qemuxml2argvdata/qemuxml2argv-cpu-exact2-nofallback.xml new file mode 100644 index 0000000..11de634 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-exact2-nofallback.xml @@ -0,0 +1,35 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219100</memory> + <currentMemory>219100</currentMemory> + <vcpu>6</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='network'/> + </os> + <cpu match='exact'> + <model fallback='forbid'>core2duo</model> + <feature name='lahf_lm' policy='require'/> + <feature name='xtpr' policy='require'/> + <feature name='cx16' policy='disable'/> + <feature name='tm2' policy='disable'/> + <feature name='ds_cpl' policy='require'/> + <feature name='pbe' policy='disable'/> + <feature name='tm' policy='optional'/> + <feature name='ht' policy='require'/> + <feature name='ss' policy='disable'/> + <feature name='ds' policy='require'/> + <feature name='nx' policy='disable'/> + <feature name='3dnowext' policy='force'/> + <feature name='sse4a' policy='optional'/> + <feature name='wdt' policy='forbid'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/./qemu.sh</emulator> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-fallback.args b/tests/qemuxml2argvdata/qemuxml2argv-cpu-fallback.args new file mode 100644 index 0000000..658f141 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-fallback.args @@ -0,0 +1,19 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +./qemu.sh \ +-S \ +-M pc \ +-cpu Penryn,-sse4.1 \ +-m 214 \ +-smp 6 \ +-nographic \ +-monitor unix:/tmp/test-monitor,server,nowait \ +-no-acpi \ +-boot n \ +-net none \ +-serial none \ +-parallel none \ +-usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-fallback.xml b/tests/qemuxml2argvdata/qemuxml2argv-cpu-fallback.xml new file mode 100644 index 0000000..7bd28a8 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-fallback.xml @@ -0,0 +1,25 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219100</memory> + <currentMemory>219100</currentMemory> + <vcpu>6</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='network'/> + </os> + <cpu match='exact'> + <model>Westmere</model> + <feature policy='disable' name='sse4.1'/> + <feature policy='disable' name='sse4.2'/> + <feature policy='disable' name='popcnt'/> + <feature policy='disable' name='aes'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/./qemu.sh</emulator> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-nofallback.xml b/tests/qemuxml2argvdata/qemuxml2argv-cpu-nofallback.xml new file mode 100644 index 0000000..7f1f09a --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-nofallback.xml @@ -0,0 +1,25 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219100</memory> + <currentMemory>219100</currentMemory> + <vcpu>6</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='network'/> + </os> + <cpu match='exact'> + <model fallback='forbid'>Westmere</model> + <feature policy='disable' name='sse4.1'/> + <feature policy='disable' name='sse4.2'/> + <feature policy='disable' name='popcnt'/> + <feature policy='disable' name='aes'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/./qemu.sh</emulator> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index d87654c..f944d82 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -84,7 +84,8 @@ static int testCompareXMLToArgvFiles(const char *xml, const char *migrateFrom, int migrateFd, bool json, - bool expectError) + bool expectError, + bool expectFailure) { char *expectargv = NULL; int len; @@ -98,19 +99,13 @@ static int testCompareXMLToArgvFiles(const char *xml, virCommandPtr cmd = NULL; if (!(conn = virGetConnect())) - goto fail; + goto out; conn->secretDriver = &fakeSecretDriver; - len = virtTestLoadFile(cmdline, &expectargv); - if (len < 0) - goto fail; - if (len && expectargv[len - 1] == '\n') - expectargv[len - 1] = '\0'; - if (!(vmdef = virDomainDefParseFile(driver.caps, xml, QEMU_EXPECTED_VIRT_TYPES, VIR_DOMAIN_XML_INACTIVE))) - goto fail; + goto out; /* * For test purposes, we may want to fake emulator's output by providing @@ -124,12 +119,12 @@ static int testCompareXMLToArgvFiles(const char *xml, */ if (vmdef->emulator && STRPREFIX(vmdef->emulator, "/.")) { if (!(emulator = strdup(vmdef->emulator + 1))) - goto fail; + goto out; free(vmdef->emulator); vmdef->emulator = NULL; if (virAsprintf(&vmdef->emulator, "%s/qemuxml2argvdata/%s", abs_srcdir, emulator) < 0) - goto fail; + goto out; } if (qemuCapsGet(extraFlags, QEMU_CAPS_DOMID)) @@ -149,15 +144,15 @@ static int testCompareXMLToArgvFiles(const char *xml, QEMU_CAPS_LAST); if (qemudCanonicalizeMachine(&driver, vmdef) < 0) - goto fail; + goto out; if (qemuCapsGet(extraFlags, QEMU_CAPS_DEVICE)) { qemuDomainPCIAddressSetPtr pciaddrs; if (!(pciaddrs = qemuDomainPCIAddressSetCreate(vmdef))) - goto fail; + goto out; if (qemuAssignDevicePCISlots(vmdef, pciaddrs) < 0) - goto fail; + goto out; qemuDomainPCIAddressSetFree(pciaddrs); } @@ -176,18 +171,27 @@ static int testCompareXMLToArgvFiles(const char *xml, } if (qemuAssignDeviceAliases(vmdef, extraFlags) < 0) - goto fail; + goto out; if (!(cmd = qemuBuildCommandLine(conn, &driver, vmdef, &monitor_chr, json, extraFlags, migrateFrom, migrateFd, NULL, - VIR_NETDEV_VPORT_PROFILE_OP_NO_OP))) - goto fail; + VIR_NETDEV_VPORT_PROFILE_OP_NO_OP))) { + if (expectFailure) { + ret = 0; + virResetLastError(); + } + goto out; + } else if (expectFailure) { + if (virTestGetDebug()) + fprintf(stderr, "qemuBuildCommandLine should have failed\n"); + goto out; + } if (!!virGetLastError() != expectError) { if (virTestGetDebug() && (log = virtTestLogContentAndReset())) fprintf(stderr, "\n%s", log); - goto fail; + goto out; } if (expectError) { @@ -196,25 +200,31 @@ static int testCompareXMLToArgvFiles(const char *xml, } if (!(actualargv = virCommandToString(cmd))) - goto fail; + goto out; if (emulator) { /* Skip the abs_srcdir portion of replacement emulator. */ char *start_skip = strstr(actualargv, abs_srcdir); char *end_skip = strstr(actualargv, emulator); if (!start_skip || !end_skip) - goto fail; + goto out; memmove(start_skip, end_skip, strlen(end_skip) + 1); } + len = virtTestLoadFile(cmdline, &expectargv); + if (len < 0) + goto out; + if (len && expectargv[len - 1] == '\n') + expectargv[len - 1] = '\0'; + if (STRNEQ(expectargv, actualargv)) { virtTestDifference(stderr, expectargv, actualargv); - goto fail; + goto out; } ret = 0; - fail: +out: free(log); free(emulator); free(expectargv); @@ -232,6 +242,7 @@ struct testInfo { const char *migrateFrom; int migrateFd; bool expectError; + bool expectFailure; }; static int @@ -252,7 +263,8 @@ testCompareXMLToArgvHelper(const void *data) info->migrateFrom, info->migrateFd, qemuCapsGet(info->extraFlags, QEMU_CAPS_MONITOR_JSON), - info->expectError); + info->expectError, + info->expectFailure); cleanup: free(xml); @@ -291,10 +303,12 @@ mymain(void) return EXIT_FAILURE; } -# define DO_TEST_FULL(name, migrateFrom, migrateFd, expectError, ...) \ +# define DO_TEST_FULL(name, migrateFrom, migrateFd, \ + expectError, expectFailure, ...) \ do { \ struct testInfo info = { \ - name, NULL, migrateFrom, migrateFd, expectError \ + name, NULL, migrateFrom, migrateFd, \ + expectError, expectFailure \ }; \ if (!(info.extraFlags = qemuCapsNew())) \ return EXIT_FAILURE; \ @@ -306,7 +320,10 @@ mymain(void) } while (0) # define DO_TEST(name, expectError, ...) \ - DO_TEST_FULL(name, NULL, -1, expectError, __VA_ARGS__) + DO_TEST_FULL(name, NULL, -1, expectError, false, __VA_ARGS__) + +# define DO_TEST_FAILURE(name, ...) \ + DO_TEST_FULL(name, NULL, -1, false, true, __VA_ARGS__) # define NONE QEMU_CAPS_LAST @@ -624,17 +641,17 @@ mymain(void) DO_TEST("hostdev-pci-address-device", false, QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); - DO_TEST_FULL("restore-v1", "stdio", 7, false, + DO_TEST_FULL("restore-v1", "stdio", 7, false, false, QEMU_CAPS_MIGRATE_KVM_STDIO); - DO_TEST_FULL("restore-v2", "stdio", 7, false, + DO_TEST_FULL("restore-v2", "stdio", 7, false, false, QEMU_CAPS_MIGRATE_QEMU_EXEC); - DO_TEST_FULL("restore-v2", "exec:cat", 7, false, + DO_TEST_FULL("restore-v2", "exec:cat", 7, false, false, QEMU_CAPS_MIGRATE_QEMU_EXEC); - DO_TEST_FULL("restore-v2-fd", "stdio", 7, false, + DO_TEST_FULL("restore-v2-fd", "stdio", 7, false, false, QEMU_CAPS_MIGRATE_QEMU_FD); - DO_TEST_FULL("restore-v2-fd", "fd:7", 7, false, + DO_TEST_FULL("restore-v2-fd", "fd:7", 7, false, false, QEMU_CAPS_MIGRATE_QEMU_FD); - DO_TEST_FULL("migrate", "tcp:10.0.0.1:5000", -1, false, + DO_TEST_FULL("migrate", "tcp:10.0.0.1:5000", -1, false, false, QEMU_CAPS_MIGRATE_QEMU_TCP); DO_TEST("qemu-ns", false, NONE); @@ -648,6 +665,9 @@ mymain(void) DO_TEST("cpu-minimum2", false, NONE); DO_TEST("cpu-exact1", false, NONE); DO_TEST("cpu-exact2", false, NONE); + DO_TEST("cpu-exact2-nofallback", false, NONE); + DO_TEST("cpu-fallback", false, NONE); + DO_TEST_FAILURE("cpu-nofallback", NONE); DO_TEST("cpu-strict1", false, NONE); DO_TEST("cpu-numa1", false, NONE); DO_TEST("cpu-numa2", false, QEMU_CAPS_SMP_TOPOLOGY); diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-graphics-spice-timeout.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-graphics-spice-timeout.xml new file mode 100644 index 0000000..caa5f0a --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-graphics-spice-timeout.xml @@ -0,0 +1,86 @@ +<domain type='qemu'> + <name>f14</name> + <uuid>553effab-b5e1-2d80-dfe3-da4344826c43</uuid> + <memory>1048576</memory> + <currentMemory>1048576</currentMemory> + <vcpu>2</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='cdrom'/> + <boot dev='hd'/> + <bootmenu enable='yes'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <cpu match='exact'> + <model fallback='allow'>core2duo</model> + <vendor>Intel</vendor> + <topology sockets='1' cores='2' threads='1'/> + <feature policy='require' name='lahf_lm'/> + <feature policy='require' name='xtpr'/> + <feature policy='require' name='cx16'/> + <feature policy='require' name='tm2'/> + <feature policy='require' name='est'/> + <feature policy='require' name='vmx'/> + <feature policy='require' name='ds_cpl'/> + <feature policy='require' name='pbe'/> + <feature policy='require' name='tm'/> + <feature policy='require' name='ht'/> + <feature policy='require' name='ss'/> + <feature policy='require' name='acpi'/> + <feature policy='require' name='ds'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/./qemu.sh</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2'/> + <source file='/var/lib/libvirt/images/f14.img'/> + <target dev='vda' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/var/lib/libvirt/Fedora-14-x86_64-Live-KDE.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + <address type='drive' controller='0' bus='1' unit='0'/> + </disk> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='virtio-serial' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </controller> + <interface type='ethernet'> + <mac address='52:54:00:71:70:89'/> + <script path='/etc/qemu-ifup'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> + </interface> + <serial type='pty'> + <target port='0'/> + </serial> + <console type='pty'> + <target type='serial' port='0'/> + </console> + <input type='tablet' bus='usb'/> + <input type='mouse' bus='ps2'/> + <graphics type='spice' port='5900' autoport='no' passwd='sercet' passwdValidTo='2011-05-31T16:11:22' connected='disconnect'/> + <sound model='ac97'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </sound> + <video> + <model type='vga' vram='9216' heads='1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </video> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 2cc1f7d..3c85c2f 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -147,7 +147,6 @@ mymain(void) DO_TEST("graphics-sdl-fullscreen"); DO_TEST("graphics-spice"); DO_TEST("graphics-spice-compression"); - DO_TEST("graphics-spice-timeout"); DO_TEST("graphics-spice-qxl-vga"); DO_TEST("input-usbmouse"); DO_TEST("input-usbtablet"); @@ -207,6 +206,7 @@ mymain(void) DO_TEST_DIFFERENT("console-virtio"); DO_TEST_DIFFERENT("serial-target-port-auto"); DO_TEST_DIFFERENT("graphics-listen-network2"); + DO_TEST_DIFFERENT("graphics-spice-timeout"); virCapabilitiesFree(driver.caps); diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c index fa6422a..c6adec9 100644 --- a/tests/testutilsqemu.c +++ b/tests/testutilsqemu.c @@ -115,6 +115,7 @@ virCapsPtr testQemuCapsInit(void) { 0, /* match */ (char *) "x86_64", /* arch */ (char *) "core2duo", /* model */ + 0, /* fallback */ (char *) "Intel", /* vendor */ 1, /* sockets */ 2, /* cores */ -- 1.7.8.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list