]> xenbits.xensource.com Git - libvirt.git/commitdiff
Parallels: add domainGetVcpus()
authorAlexander Burluka <aburluka@parallels.com>
Thu, 5 Jun 2014 05:50:04 +0000 (09:50 +0400)
committerEric Blake <eblake@redhat.com>
Fri, 6 Jun 2014 12:29:52 +0000 (06:29 -0600)
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 <vm_id|vm_name> --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 <eblake@redhat.com>
src/parallels/parallels_driver.c
src/parallels/parallels_utils.h

index ab595999ba65b6b1050f91c99b47dddd98d405b2..f6e701dba30316763e8229046a7e753e99445b28 100644 (file)
@@ -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 */
index 62155530be6817cf0a2a175ef27f4b2262d003b0..599e2c52580f4d774a3e011f7a05ea6963896980 100644 (file)
@@ -54,6 +54,7 @@ struct parallelsDomObj {
     int id;
     char *uuid;
     char *home;
+    virBitmapPtr cpumask;
 };
 
 typedef struct parallelsDomObj *parallelsDomObjPtr;