diff --git a/src/qemu_conf.c b/src/qemu_conf.c index 1efd9e9..d845d18 100644 --- a/src/qemu_conf.c +++ b/src/qemu_conf.c @@ -554,6 +554,21 @@ int qemudExtractVersion(virConnectPtr conn, return 0; } +/* Converts def->virtType to applicable string type + * @param type integer virt type + * @return string type on success, NULL on fail + */ +const char * qemudVirtTypeToString(int type) { + switch (type) { + case QEMUD_VIRT_QEMU: + return "qemu"; + case QEMUD_VIRT_KQEMU: + return "kqemu"; + case QEMUD_VIRT_KVM: + return "kvm"; + } + return NULL; +} /* Parse the XML definition for a disk * @param disk pre-allocated & zero'd disk record @@ -1699,9 +1714,12 @@ static struct qemud_vm_def *qemudParseXML(virConnectPtr conn, obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt); if ((obj == NULL) || (obj->type != XPATH_STRING) || (obj->stringval == NULL) || (obj->stringval[0] == 0)) { - const char *type = (def->virtType == QEMUD_VIRT_QEMU ? "qemu" : - def->virtType == QEMUD_VIRT_KQEMU ? "kqemu": - "kvm"); + const char *type = qemudVirtTypeToString(def->virtType); + if (!type) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + "%s", _("unknown virt type")); + goto error; + } const char *emulator = virCapabilitiesDefaultGuestEmulator(driver->caps, def->os.type, def->os.arch, @@ -3479,18 +3497,7 @@ char *qemudGenerateXML(virConnectPtr conn, const char *type = NULL; int n; - switch (def->virtType) { - case QEMUD_VIRT_QEMU: - type = "qemu"; - break; - case QEMUD_VIRT_KQEMU: - type = "kqemu"; - break; - case QEMUD_VIRT_KVM: - type = "kvm"; - break; - } - if (!type) { + if (!(type = qemudVirtTypeToString(def->virtType))) { qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, _("unexpected domain type %d"), def->virtType); goto cleanup; diff --git a/src/qemu_conf.h b/src/qemu_conf.h index bd8d8b2..81e4aea 100644 --- a/src/qemu_conf.h +++ b/src/qemu_conf.h @@ -486,6 +486,7 @@ char * qemudGenerateNetworkXML (virConnectPtr conn, struct qemud_network *network, struct qemud_network_def *def); +const char *qemudVirtTypeToString (int type); #endif /* WITH_QEMU */ diff --git a/src/qemu_driver.c b/src/qemu_driver.c index e924633..cf52a07 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -113,6 +113,8 @@ static int qemudShutdownNetworkDaemon(virConnectPtr conn, struct qemud_driver *driver, struct qemud_network *network); +static int qemudDomainGetMaxVcpus(virDomainPtr dom); + static struct qemud_driver *qemu_driver = NULL; @@ -1563,21 +1565,23 @@ static const char *qemudGetType(virConnectPtr conn ATTRIBUTE_UNUSED) { return "QEMU"; } -static int qemudGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED, - const char *type) { +static int qemudGetMaxVCPUs(virConnectPtr conn, const char *type) { if (!type) return 16; - if (!strcmp(type, "qemu")) + if (STRCASEEQ(type, "qemu")) return 16; /* XXX future KVM will support SMP. Need to probe kernel to figure out KVM module version i guess */ - if (!strcmp(type, "kvm")) + if (STRCASEEQ(type, "kvm")) return 1; - if (!strcmp(type, "kqemu")) + if (STRCASEEQ(type, "kqemu")) return 1; + + qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_ARG, + _("unknown type '%s'"), type); return -1; } @@ -2161,6 +2165,67 @@ static int qemudDomainSave(virDomainPtr dom, } +static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) { + const struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; + struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + int max; + + if (!vm) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, + _("no domain with matching uuid '%s'"), dom->uuid); + return -1; + } + + if (qemudIsActiveVM(vm)) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot change vcpu count of an active domain")); + return -1; + } + + if ((max = qemudDomainGetMaxVcpus(dom)) < 0) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("could not determine max vcpus for the domain")); + return -1; + } + + if (nvcpus > max) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, + _("requested vcpus is greater than max allowable" + " vcpus for the domain: %d > %d"), nvcpus, max); + return -1; + } + + vm->def->vcpus = nvcpus; + return 0; +} + +static int qemudDomainGetMaxVcpus(virDomainPtr dom) { + struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; + struct qemud_vm *vm = qemudFindVMByUUID(driver, dom->uuid); + const char *type; + int ret; + + if (!vm) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, + _("no domain with matching uuid '%s'"), dom->uuid); + return -1; + } + + if (!(type = qemudVirtTypeToString(vm->def->virtType))) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, + _("unknown virt type in domain definition '%d'"), + vm->def->virtType); + return -1; + } + + if ((ret = qemudGetMaxVCPUs(dom->conn, type)) < 0) { + return -1; + } + + return ret; +} + + static int qemudDomainRestore(virConnectPtr conn, const char *path) { struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; @@ -3081,10 +3146,10 @@ static virDriver qemuDriver = { qemudDomainSave, /* domainSave */ qemudDomainRestore, /* domainRestore */ NULL, /* domainCoreDump */ - NULL, /* domainSetVcpus */ + qemudDomainSetVcpus, /* domainSetVcpus */ NULL, /* domainPinVcpu */ NULL, /* domainGetVcpus */ - NULL, /* domainGetMaxVcpus */ + qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */ qemudDomainDumpXML, /* domainDumpXML */ qemudListDefinedDomains, /* listDomains */ qemudNumDefinedDomains, /* numOfDomains */