virBufferAddLit(&xml, " <machine");
if (machine->canonical)
virBufferAsprintf(&xml, " canonical='%s'", machine->canonical);
+ if (machine->maxCpus > 0)
+ virBufferAsprintf(&xml, " maxCpus='%d'", machine->maxCpus);
virBufferAsprintf(&xml, ">%s</machine>\n", machine->name);
}
virBufferAddLit(&xml, " <machine");
if (machine->canonical)
virBufferAsprintf(&xml, " canonical='%s'", machine->canonical);
+ if (machine->maxCpus > 0)
+ virBufferAsprintf(&xml, " maxCpus='%d'", machine->maxCpus);
virBufferAsprintf(&xml, ">%s</machine>\n", machine->name);
}
virBufferAddLit(&xml, " </domain>\n");
size_t nmachineTypes;
char **machineTypes;
char **machineAliases;
+ unsigned int *machineMaxCpus;
};
struct _virQEMUCapsCache {
{
char *name = qemuCaps->machineTypes[defIdx];
char *alias = qemuCaps->machineAliases[defIdx];
+ unsigned int maxCpus = qemuCaps->machineMaxCpus[defIdx];
memmove(qemuCaps->machineTypes + 1,
qemuCaps->machineTypes,
memmove(qemuCaps->machineAliases + 1,
qemuCaps->machineAliases,
sizeof(qemuCaps->machineAliases[0]) * defIdx);
+ memmove(qemuCaps->machineMaxCpus + 1,
+ qemuCaps->machineMaxCpus,
+ sizeof(qemuCaps->machineMaxCpus[0]) * defIdx);
qemuCaps->machineTypes[0] = name;
qemuCaps->machineAliases[0] = alias;
+ qemuCaps->machineMaxCpus[0] = maxCpus;
}
/* Format is:
}
if (VIR_REALLOC_N(qemuCaps->machineTypes, qemuCaps->nmachineTypes + 1) < 0 ||
- VIR_REALLOC_N(qemuCaps->machineAliases, qemuCaps->nmachineTypes + 1) < 0) {
+ VIR_REALLOC_N(qemuCaps->machineAliases, qemuCaps->nmachineTypes + 1) < 0 ||
+ VIR_REALLOC_N(qemuCaps->machineMaxCpus, qemuCaps->nmachineTypes + 1) < 0) {
VIR_FREE(name);
VIR_FREE(canonical);
virReportOOMError();
qemuCaps->machineTypes[qemuCaps->nmachineTypes-1] = name;
qemuCaps->machineAliases[qemuCaps->nmachineTypes-1] = NULL;
}
+ /* When parsing from command line we don't have information about maxCpus */
+ qemuCaps->machineMaxCpus[qemuCaps->nmachineTypes-1] = 0;
} while ((p = next));
goto no_memory;
if (VIR_ALLOC_N(ret->machineAliases, qemuCaps->nmachineTypes) < 0)
goto no_memory;
+ if (VIR_ALLOC_N(ret->machineMaxCpus, qemuCaps->nmachineTypes) < 0)
+ goto no_memory;
ret->nmachineTypes = qemuCaps->nmachineTypes;
for (i = 0; i < qemuCaps->nmachineTypes; i++) {
if (VIR_STRDUP(ret->machineTypes[i], qemuCaps->machineTypes[i]) < 0 ||
VIR_STRDUP(ret->machineAliases[i], qemuCaps->machineAliases[i]) < 0)
goto error;
+ ret->machineMaxCpus[i] = qemuCaps->machineMaxCpus[i];
}
return ret;
}
VIR_FREE(qemuCaps->machineTypes);
VIR_FREE(qemuCaps->machineAliases);
+ VIR_FREE(qemuCaps->machineMaxCpus);
for (i = 0; i < qemuCaps->ncpuDefinitions; i++) {
VIR_FREE(qemuCaps->cpuDefinitions[i]);
if (VIR_STRDUP(mach->name, qemuCaps->machineTypes[i]) < 0)
goto error;
}
+ mach->maxCpus = qemuCaps->machineMaxCpus[i];
(*machines)[i] = mach;
}
}
+int virQEMUCapsGetMachineMaxCpus(virQEMUCapsPtr qemuCaps,
+ const char *name)
+{
+ size_t i;
+
+ if (!name)
+ return 0;
+
+ for (i = 0; i < qemuCaps->nmachineTypes; i++) {
+ if (!qemuCaps->machineMaxCpus[i])
+ continue;
+ if (STREQ(qemuCaps->machineTypes[i], name))
+ return qemuCaps->machineMaxCpus[i];
+ }
+
+ return 0;
+}
+
+
static int
virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
qemuMonitorPtr mon)
virReportOOMError();
goto cleanup;
}
+ if (VIR_ALLOC_N(qemuCaps->machineMaxCpus, nmachines) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
for (i = 0; i < nmachines; i++) {
if (VIR_STRDUP(qemuCaps->machineAliases[i], machines[i]->alias) < 0 ||
goto cleanup;
if (machines[i]->isDefault)
defIdx = i;
+ qemuCaps->machineMaxCpus[i] = machines[i]->maxCpus;
}
qemuCaps->nmachineTypes = nmachines;
}
+static bool
+qemuValidateCpuMax(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
+{
+ unsigned int maxCpus;
+
+ maxCpus = virQEMUCapsGetMachineMaxCpus(qemuCaps, def->os.machine);
+ if (!maxCpus)
+ return true;
+
+ if (def->maxvcpus > maxCpus) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ "%s", _("Maximum CPUs greater than specified machine type limit"));
+ return false;
+ }
+
+ return true;
+}
+
int qemuProcessStart(virConnectPtr conn,
virQEMUDriverPtr driver,
virDomainObjPtr vm,
vm->def->emulator)))
goto cleanup;
+ if (!qemuValidateCpuMax(vm->def, priv->qemuCaps))
+ goto cleanup;
+
if (qemuAssignDeviceAliases(vm->def, priv->qemuCaps) < 0)
goto cleanup;
<arch name='i686'>
<wordsize>32</wordsize>
<emulator>/usr/bin/qemu</emulator>
- <machine>pc-0.11</machine>
- <machine canonical='pc-0.11'>pc</machine>
- <machine>pc-0.10</machine>
- <machine>isapc</machine>
+ <machine maxCpus='255'>pc-0.11</machine>
+ <machine canonical='pc-0.11' maxCpus='255'>pc</machine>
+ <machine maxCpus='255'>pc-0.10</machine>
+ <machine maxCpus='1'>isapc</machine>
<domain type='qemu'>
</domain>
<domain type='kvm'>
<emulator>/usr/bin/qemu-kvm</emulator>
- <machine>pc-0.11</machine>
- <machine canonical='pc-0.11'>pc</machine>
- <machine>pc-0.10</machine>
- <machine>isapc</machine>
+ <machine maxCpus='255'>pc-0.11</machine>
+ <machine canonical='pc-0.11' maxCpus='255'>pc</machine>
+ <machine maxCpus='255'>pc-0.10</machine>
+ <machine maxCpus='1'>isapc</machine>
</domain>
</arch>
<features>