It is increasingly likely that some distro is going to change the default "x86" machine type in QEMU from "pc" to "q35". This will certainly break existing applications which write their XML on the assumption that it is using a "pc" machine by default. For example they'll lack a IDE CDROM and get PCIe instead of PCI which changes the topology radically. Libvirt promises to isolate applications from hypervisor changes that may cause incompatibilities, so we must ensure that we always use the "pc" machine type if it is available. Only use QEMU's own reported default machine type if "pc" does not exist. This issue is not x86-only, other arches are liable t change their default machine, while some arches don't report any default at all causing libvirt to pick the first machine in the list. Thus to guarantee stability to applications, declare a preferred default machine for all architectures we currently support with QEMU. Note this change assumes there will always be a "pc" alias as long as a versioned "pc-XXX" machine type exists. If QEMU were to ship a "pc-XXX" machine type but not provide the "pc" alias, it is too hard to decide which to default so. Versioned machine types are supposed to be considered opaque strings, so we can't apply any sensible ordering ourselves and QEMU isn't reporting the list of machines in any sensible ordering itself. Signed-off-by: Daniel P. Berrangé <berrange@xxxxxxxxxx> --- src/qemu/qemu_capabilities.c | 79 ++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 0fb800589a..045e2bd489 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2233,6 +2233,61 @@ virQEMUCapsProbeQMPDevices(virQEMUCapsPtr qemuCaps, } +/* Historically QEMU x86 targets defaulted to 'pc' machine type but + * in future x86_64 might switch 'q35'. Such a change is considered + * an ABI break from libvirt's POV. Other QEMU targets may not declare + * a default macine at all, causing libvirt to use the first reported + * machinbe in the list. + * + * Here we record a preferred default machine for all arches, so + * that we're not vulnerable to changes in QEMU defaults or machine + * list ordering. + */ +static const char *preferredMachines[VIR_ARCH_LAST] = +{ + [VIR_ARCH_ALPHA] = "clipper", + [VIR_ARCH_ARMV6L] = NULL, /* No QEMU impl */ + [VIR_ARCH_ARMV7L] = "integratorcp", + [VIR_ARCH_ARMV7B] = "integratorcp", + + [VIR_ARCH_AARCH64] = "integratorcp", + [VIR_ARCH_CRIS] = "axis-dev88", + [VIR_ARCH_I686] = "pc", + [VIR_ARCH_ITANIUM] = NULL, /* doesn't exist in QEMU any more */ + [VIR_ARCH_LM32] = "lm32-evr", + + [VIR_ARCH_M68K] = "mcf5208evb", + [VIR_ARCH_MICROBLAZE] = "petalogix-s3adsp1800", + [VIR_ARCH_MICROBLAZEEL] = "petalogix-s3adsp1800", + [VIR_ARCH_MIPS] = "malta", + [VIR_ARCH_MIPSEL] = "malta", + + [VIR_ARCH_MIPS64] = "malta", + [VIR_ARCH_MIPS64EL] = "malta", + [VIR_ARCH_OR32] = "or1k-sim", + [VIR_ARCH_PARISC] = NULL, /* No QEMU impl */ + [VIR_ARCH_PARISC64] = NULL, /* No QEMU impl */ + + [VIR_ARCH_PPC] = "g3beige", + [VIR_ARCH_PPCLE] = "g3beige", + [VIR_ARCH_PPC64] = "pseries", + [VIR_ARCH_PPC64LE] = "pseries", + [VIR_ARCH_PPCEMB] = "bamboo", + + [VIR_ARCH_S390] = NULL, /* No QEMU impl*/ + [VIR_ARCH_S390X] = "s390-ccw-virtio", + [VIR_ARCH_SH4] = "shix", + [VIR_ARCH_SH4EB] = "shix", + [VIR_ARCH_SPARC] = "SS-5", + + [VIR_ARCH_SPARC64] = "sun4u", + [VIR_ARCH_UNICORE32] = "puv3", + [VIR_ARCH_X86_64] = "pc", + [VIR_ARCH_XTENSA] = "sim", + [VIR_ARCH_XTENSAEB] = "sim", + +}; + static int virQEMUCapsProbeQMPMachineTypes(virQEMUCapsPtr qemuCaps, qemuMonitorPtr mon) @@ -2241,7 +2296,9 @@ virQEMUCapsProbeQMPMachineTypes(virQEMUCapsPtr qemuCaps, int nmachines = 0; int ret = -1; size_t i; - size_t defIdx = 0; + ssize_t defIdx = -1; + ssize_t preferredIdx = -1; + const char *preferredMachine = preferredMachines[qemuCaps->arch]; if ((nmachines = qemuMonitorGetMachines(mon, &machines)) < 0) return -1; @@ -2263,12 +2320,28 @@ virQEMUCapsProbeQMPMachineTypes(virQEMUCapsPtr qemuCaps, mach->maxCpus = machines[i]->maxCpus; mach->hotplugCpus = machines[i]->hotplugCpus; + if (preferredMachine && + (STREQ_NULLABLE(mach->alias, preferredMachine) || + STREQ(mach->name, preferredMachine))) + preferredIdx = qemuCaps->nmachineTypes - 1; + if (machines[i]->isDefault) defIdx = qemuCaps->nmachineTypes - 1; } - if (defIdx) - virQEMUCapsSetDefaultMachine(qemuCaps, defIdx); + /* + * We'll prefer to use our own historical default machine + * to avoid mgmt apps seeing semantics changes when QEMU + * alters it defaults. + * + * Our preferred pmachine might have been compiled out of + * QEMU at build time though, so we still fallback to honouring + * QEMU's reported default in that case + */ + if (preferredIdx == -1) + preferredIdx = defIdx; + if (preferredIdx != -1) + virQEMUCapsSetDefaultMachine(qemuCaps, preferredIdx); ret = 0; -- 2.17.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list