[PATCH 7/7] qemu: Implement support for VIR_DOMAIN_VCPU in qemuDomainSetVcpusFlags

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds support for agent-based cpu disabling and enabling to
qemuDomainSetVcpusFlags() API.
---
 src/qemu/qemu_driver.c | 121 +++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 108 insertions(+), 13 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e54d8b9..6f2d6ff 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3695,6 +3695,68 @@ unsupported:


 static int
+qemuDomainPrepareAgentVCPUs(unsigned int nvcpus,
+                            qemuAgentCPUInfoPtr cpuinfo,
+                            int ncpuinfo)
+{
+    int i;
+    int nonline = 0;
+    int nofflinable = 0;
+
+    /* count the active and offlinable cpus */
+    for (i = 0; i < ncpuinfo; i++) {
+        if (cpuinfo[i].online)
+            nonline++;
+
+        if (cpuinfo[i].offlinable && cpuinfo[i].online)
+            nofflinable++;
+
+        /* This shouldn't happen, but we can't trust the guest agent */
+        if (!cpuinfo[i].online && !cpuinfo[i].offlinable) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Invalid data provided by guest agent"));
+            return -1;
+        }
+    }
+
+    /* the guest agent reported less cpus than requested */
+    if (nvcpus > ncpuinfo) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("guest agent reports less cpu than requested"));
+        return -1;
+    }
+
+    /* not enough offlinable CPUs to support the request */
+    if (nvcpus < nonline - nofflinable) {
+        virReportError(VIR_ERR_INVALID_ARG, "%s",
+                       _("Cannot offline enough CPUs"));
+        return -1;
+    }
+
+    for (i = 0; i < ncpuinfo; i++) {
+        if (nvcpus < nonline) {
+            /* unplug */
+            if (cpuinfo[i].offlinable && cpuinfo[i].online) {
+                cpuinfo[i].online = false;
+                nonline--;
+            }
+        } else if (nvcpus > nonline) {
+            /* plug */
+            if (!cpuinfo[i].online) {
+                cpuinfo[i].online = true;
+                nonline++;
+            }
+        } else {
+            /* done */
+            break;
+        }
+    }
+
+    return 0;
+}
+
+
+static int
 qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                         unsigned int flags)
 {
@@ -3705,10 +3767,14 @@ qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
     bool maximum;
     virQEMUDriverConfigPtr cfg = NULL;
     virCapsPtr caps = NULL;
+    qemuAgentCPUInfoPtr cpuinfo = NULL;
+    int ncpuinfo;
+    qemuDomainObjPrivatePtr priv;

     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                   VIR_DOMAIN_AFFECT_CONFIG |
-                  VIR_DOMAIN_VCPU_MAXIMUM, -1);
+                  VIR_DOMAIN_VCPU_MAXIMUM |
+                  VIR_DOMAIN_VCPU_AGENT, -1);

     if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
         virReportError(VIR_ERR_INVALID_ARG,
@@ -3723,6 +3789,8 @@ qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
     if (!(vm = qemuDomObjFromDomain(dom)))
         goto cleanup;

+    priv = vm->privateData;
+
     if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
         goto cleanup;

@@ -3748,22 +3816,48 @@ qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
         goto endjob;
     }

-    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
-        if (qemuDomainHotplugVcpus(driver, vm, nvcpus) < 0)
+    if (flags & VIR_DOMAIN_VCPU_AGENT) {
+        if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+            virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                           _("chainging of maximum vCPU count isn't supported "
+                             "via guest agent"));
             goto endjob;
-    }
-
-    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
-        if (maximum) {
-            persistentDef->maxvcpus = nvcpus;
-            if (nvcpus < persistentDef->vcpus)
-                persistentDef->vcpus = nvcpus;
-        } else {
-            persistentDef->vcpus = nvcpus;
         }

-        if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
+        qemuDomainObjEnterAgent(vm);
+        ncpuinfo = qemuAgentGetVCPUs(priv->agent, &cpuinfo);
+        qemuDomainObjExitAgent(vm);
+
+        if (ncpuinfo < 0)
+            goto endjob;
+
+        if (qemuDomainPrepareAgentVCPUs(nvcpus, cpuinfo, ncpuinfo) < 0)
+            goto endjob;
+
+        qemuDomainObjEnterAgent(vm);
+        ncpuinfo = qemuAgentSetVCPUs(priv->agent, cpuinfo, ncpuinfo);
+        qemuDomainObjExitAgent(vm);
+
+        if (ncpuinfo < 0)
             goto endjob;
+    } else {
+        if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+            if (qemuDomainHotplugVcpus(driver, vm, nvcpus) < 0)
+                goto endjob;
+        }
+
+        if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+            if (maximum) {
+                persistentDef->maxvcpus = nvcpus;
+                if (nvcpus < persistentDef->vcpus)
+                    persistentDef->vcpus = nvcpus;
+            } else {
+                persistentDef->vcpus = nvcpus;
+            }
+
+            if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0)
+                goto endjob;
+        }
     }

     ret = 0;
@@ -3776,6 +3870,7 @@ cleanup:
     if (vm)
         virObjectUnlock(vm);
     virObjectUnref(caps);
+    VIR_FREE(cpuinfo);
     virObjectUnref(cfg);
     return ret;
 }
-- 
1.8.1.5

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]