From e721e9e6bd8467e92d6f86c8d3124b0cf27cd92c Mon Sep 17 00:00:00 2001 From: Alexander Burluka Date: Thu, 5 Jun 2014 09:50:04 +0400 Subject: [PATCH] Parallels: add domainGetVcpus() OpenStack Nova requires this function to start VM instance. Cpumask info is obtained via prlctl utility. Unlike KVM, Parallels Cloud Server is unable to set cpu affinity mask for every VCpu. Mask is unique for all VCpu. You can set it using 'prlctl set --cpumask <{n[,n,n1-n2]|all}>' command. For example, 'prlctl set SomeDomain --cpumask 0,1,5-7' would set this mask to yy---yyy. Signed-off-by: Eric Blake --- src/parallels/parallels_driver.c | 93 ++++++++++++++++++++++++++++++-- src/parallels/parallels_utils.h | 1 + 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c index ab595999ba..f6e701dba3 100644 --- a/src/parallels/parallels_driver.c +++ b/src/parallels/parallels_driver.c @@ -108,6 +108,7 @@ parallelsDomObjFreePrivate(void *p) if (!pdom) return; + virBitmapFree(pdom->cpumask); VIR_FREE(pdom->uuid); VIR_FREE(pdom->home); VIR_FREE(p); @@ -650,10 +651,14 @@ parallelsLoadDomain(parallelsConnPtr privconn, virJSONValuePtr jobj) unsigned int x; const char *autostart; const char *state; + int hostcpus; if (VIR_ALLOC(def) < 0) goto cleanup; + if (VIR_ALLOC(pdom) < 0) + goto cleanup; + def->virtType = VIR_DOMAIN_VIRT_PARALLELS; def->id = -1; @@ -716,6 +721,19 @@ parallelsLoadDomain(parallelsConnPtr privconn, virJSONValuePtr jobj) goto cleanup; } + if ((hostcpus = nodeGetCPUCount()) < 0) + goto cleanup; + + if (!(tmp = virJSONValueObjectGetString(jobj3, "mask"))) { + /* Absence of this field means that all domains cpus are available */ + if (!(pdom->cpumask = virBitmapNew(hostcpus))) + goto cleanup; + virBitmapSetAll(pdom->cpumask); + } else { + if (virBitmapParse(tmp, 0, &pdom->cpumask, hostcpus) < 0) + goto cleanup; + } + if (!(jobj3 = virJSONValueObjectGet(jobj2, "memory"))) { parallelsParseError(); goto cleanup; @@ -757,9 +775,6 @@ parallelsLoadDomain(parallelsConnPtr privconn, virJSONValuePtr jobj) def->os.arch = VIR_ARCH_X86_64; - if (VIR_ALLOC(pdom) < 0) - goto cleanup; - if (virJSONValueObjectGetNumberUint(jobj, "EnvID", &x) < 0) goto cleanup; pdom->id = x; @@ -2300,6 +2315,77 @@ static int parallelsConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED) } +static int +parallelsDomainGetVcpus(virDomainPtr domain, + virVcpuInfoPtr info, + int maxinfo, + unsigned char *cpumaps, + int maplen) +{ + parallelsConnPtr privconn = domain->conn->privateData; + parallelsDomObjPtr privdomdata = NULL; + virDomainObjPtr privdom = NULL; + size_t i; + int v, maxcpu, hostcpus; + int ret = -1; + + parallelsDriverLock(privconn); + privdom = virDomainObjListFindByUUID(privconn->domains, domain->uuid); + parallelsDriverUnlock(privconn); + + if (privdom == NULL) { + parallelsDomNotFoundError(domain); + goto cleanup; + } + + if (!virDomainObjIsActive(privdom)) { + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", + _("cannot list vcpu pinning for an inactive domain")); + goto cleanup; + } + + privdomdata = privdom->privateData; + if ((hostcpus = nodeGetCPUCount()) < 0) + goto cleanup; + + maxcpu = maplen * 8; + if (maxcpu > hostcpus) + maxcpu = hostcpus; + + if (maxinfo >= 1) { + if (info != NULL) { + memset(info, 0, sizeof(*info) * maxinfo); + for (i = 0; i < maxinfo; i++) { + info[i].number = i; + info[i].state = VIR_VCPU_RUNNING; + } + } + if (cpumaps != NULL) { + unsigned char *tmpmap = NULL; + int tmpmapLen = 0; + + memset(cpumaps, 0, maplen * maxinfo); + virBitmapToData(privdomdata->cpumask, &tmpmap, &tmpmapLen); + if (tmpmapLen > maplen) + tmpmapLen = maplen; + + for (v = 0; v < maxinfo; v++) { + unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, v); + memcpy(cpumap, tmpmap, tmpmapLen); + } + VIR_FREE(tmpmap); + } + } + ret = maxinfo; + + cleanup: + if (privdom) + virObjectUnlock(privdom); + return ret; +} + + static virDriver parallelsDriver = { .no = VIR_DRV_PARALLELS, .name = "Parallels", @@ -2323,6 +2409,7 @@ static virDriver parallelsDriver = { .domainGetXMLDesc = parallelsDomainGetXMLDesc, /* 0.10.0 */ .domainIsPersistent = parallelsDomainIsPersistent, /* 0.10.0 */ .domainGetAutostart = parallelsDomainGetAutostart, /* 0.10.0 */ + .domainGetVcpus = parallelsDomainGetVcpus, /* 1.2.6 */ .domainSuspend = parallelsDomainSuspend, /* 0.10.0 */ .domainResume = parallelsDomainResume, /* 0.10.0 */ .domainDestroy = parallelsDomainDestroy, /* 0.10.0 */ diff --git a/src/parallels/parallels_utils.h b/src/parallels/parallels_utils.h index 62155530be..599e2c5258 100644 --- a/src/parallels/parallels_utils.h +++ b/src/parallels/parallels_utils.h @@ -54,6 +54,7 @@ struct parallelsDomObj { int id; char *uuid; char *home; + virBitmapPtr cpumask; }; typedef struct parallelsDomObj *parallelsDomObjPtr;