In qemu-0.11 there is a 'pc-0.10' machine type which allows you to run
guests with a machine which is compatible with the pc machine in
qemu-0.10 - e.g. using the original PCI class for virtio-blk and
virtio-console and disabling MSI support in virtio-net. The idea here
is that we don't want to suprise guests by changing the hardware when
qemu is updated.
I've just posted some patches for qemu-0.11 which allows libvirt to
canonicalize the 'pc' machine alias to the latest machine version.
This patches makes us use that so that when a guest is configured to
use the 'pc' machine type, we resolve that to 'pc-0.11' machine and
save that in the guest XML.
See also:
https://fedoraproject.org/wiki/Features/KVM_Stable_Guest_ABI
* src/qemu_conf.c: add qemudCanonicalizeMachine() to canonicalize
the machine type according to the machine aliases in capabilities
* src/qemu_driver.c: parse aliases in qemudParseMachineTypesStr()
---
src/qemu_conf.c | 11 +++++++-
src/qemu_driver.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 84 insertions(+), 1 deletions(-)
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index 022a7a9..6f89f33 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -271,7 +271,7 @@ static const struct qemu_arch_info const arch_info_xen[] = {
/* Format is:
- * <machine> <desc> [(default)]
+ * <machine> <desc> [(default)|(alias of <canonical>)]
*/
static int
qemudParseMachineTypesStr(const char *output,
@@ -319,6 +319,15 @@ qemudParseMachineTypesStr(const char *output,
list[0] = machine;
nitems++;
}
+
+ if ((t = strstr(p, "(alias of ")) && (!next || t < next)) {
+ p = t + strlen("(alias of ");
+ if (!(t = strchr(p, ')')) || (next && t >= next))
+ continue;
+
+ if (!(machine->canonical = strndup(p, t - p)))
+ goto error;
+ }
} while ((p = next));
*machines = list;
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 3b56092..e2fa4d4 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -4056,6 +4056,77 @@ cleanup:
return ret;
}
+static int
+qemudCanonicalizeMachineFromInfo(virDomainDefPtr def,
+ virCapsGuestDomainInfoPtr info,
+ char **canonical)
+{
+ int i;
+
+ *canonical = NULL;
+
+ for (i = 0; i < info->nmachines; i++) {
+ virCapsGuestMachinePtr machine = info->machines[i];
+
+ if (!machine->canonical)
+ continue;
+
+ if (strcmp(def->os.machine, machine->name) != 0)
+ continue;
+
+ if (!(*canonical = strdup(machine->canonical)))
+ return -1;
+
+ break;
+ }
+
+ return 0;
+}
+
+static int
+qemudCanonicalizeMachine(virConnectPtr conn, virDomainDefPtr def)
+{
+ struct qemud_driver *driver = conn->privateData;
+ char *canonical = NULL;
+ int i;
+
+ for (i = 0; i < driver->caps->nguests; i++) {
+ virCapsGuestPtr guest = driver->caps->guests[i];
+ int j;
+
+ for (j = 0; j < guest->arch.ndomains; j++) {
+ virCapsGuestDomainPtr dom = guest->arch.domains[j];
+
+ if (dom->info.emulator &&
+ STREQ(dom->info.emulator, def->emulator)) {
+ if (qemudCanonicalizeMachineFromInfo(def, &dom->info,
+ &canonical) < 0)
+ return -1;
+ if (canonical)
+ goto out;
+ break;
+ }
+ }
+
+ /* if we matched one of the domain's emulators, or if
+ * we match the default emulator
+ */
+ if (j < guest->arch.ndomains ||
+ (guest->arch.defaultInfo.emulator &&
+ STREQ(guest->arch.defaultInfo.emulator, def->emulator))) {
+ if (qemudCanonicalizeMachineFromInfo(def, &guest->arch.defaultInfo,
+ &canonical) < 0)
+ return -1;
+ goto out;
+ }
+ }
+out:
+ if (canonical) {
+ VIR_FREE(def->os.machine);
+ def->os.machine = canonical;
+ }
+ return 0;
+}
static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
struct qemud_driver *driver = conn->privateData;
@@ -4102,6 +4173,9 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char
*xml) {
}
}
+ if (qemudCanonicalizeMachine(conn, def) < 0)
+ goto cleanup;
+
if (!(vm = virDomainAssignDef(conn,
&driver->domains,
def))) {
--
1.6.2.5