[libvirt] [PATCH 05/16] hyperv: implement vcpu functions

Jason Miesionczek jmiesionczek at datto.com
Tue Aug 9 12:39:13 UTC 2016


---
 src/hyperv/hyperv_driver.c | 176 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 176 insertions(+)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index b2d1abf..7d956d3 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -1401,6 +1401,178 @@ hypervConnectGetVersion(virConnectPtr conn, unsigned long *version)
     return result;
 }
 
+static int
+hypervConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED)
+{
+    int result = -1;
+    hypervPrivate *priv = conn->privateData;
+    virBuffer query = VIR_BUFFER_INITIALIZER;
+    Msvm_ProcessorSettingData *processorSettingData = NULL;
+
+    /* Get Msvm_ProcessorSettingData maximum definition */
+    virBufferAddLit(&query, "SELECT * FROM Msvm_ProcessorSettingData "
+                    "WHERE InstanceID LIKE 'Microsoft:Definition%Maximum'");
+
+    if (hypervGetMsvmProcessorSettingDataList(priv, &query, &processorSettingData) < 0) {
+        goto cleanup;
+    }
+
+    if (processorSettingData == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Could not get maximum definition of Msvm_ProcessorSettingData"));
+        goto cleanup;
+    }
+
+    result = processorSettingData->data->SocketCount * processorSettingData->data->ProcessorsPerSocket;
+
+ cleanup:
+    hypervFreeObject(priv, (hypervObject *) processorSettingData);
+    virBufferFreeAndReset(&query);
+
+    return result;
+}
+
+static int
+hypervDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags)
+{
+    int result = -1;
+    char uuid_string[VIR_UUID_STRING_BUFLEN];
+    hypervPrivate *priv = domain->conn->privateData;
+    Msvm_ComputerSystem *computerSystem = NULL;
+    Msvm_ProcessorSettingData *processorSettingData = NULL;
+    Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+    virBuffer query = VIR_BUFFER_INITIALIZER;
+
+    virCheckFlags(VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG | VIR_DOMAIN_VCPU_MAXIMUM, -1);
+
+    virUUIDFormat(domain->uuid, uuid_string);
+
+    /* Get Msvm_ComputerSystem */
+    if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
+        goto cleanup;
+    }
+
+    /* If @flags includes VIR_DOMAIN_VCPU_LIVE,
+       this will query a running domain (which will fail if domain is not active) */
+    if (flags & VIR_DOMAIN_VCPU_LIVE) {
+        if (computerSystem->data->EnabledState != MSVM_COMPUTERSYSTEM_ENABLEDSTATE_ENABLED) {
+            virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not active"));
+            goto cleanup;
+        }
+    }
+
+    /* If @flags includes VIR_DOMAIN_VCPU_MAXIMUM, then the maximum virtual CPU limit is queried */
+    if (flags & VIR_DOMAIN_VCPU_MAXIMUM) {
+        result = hypervConnectGetMaxVcpus(domain->conn, NULL);
+        goto cleanup;
+    }
+
+    /* Get Msvm_VirtualSystemSettingData */
+    virBufferAsprintf(&query,
+                      "associators of "
+                      "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+                      "Name=\"%s\"} "
+                      "where AssocClass = Msvm_SettingsDefineState "
+                      "ResultClass = Msvm_VirtualSystemSettingData",
+                      uuid_string);
+    if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query, &virtualSystemSettingData) < 0) {
+        goto cleanup;
+    }
+    if (virtualSystemSettingData == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain %s"),
+                       "Msvm_VirtualSystemSettingData", computerSystem->data->ElementName);
+        goto cleanup;
+    }
+
+    /* Get Msvm_ProcessorSettingData */
+    virBufferFreeAndReset(&query);
+    virBufferAsprintf(&query,
+                      "associators of "
+                      "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
+                      "where AssocClass = Msvm_VirtualSystemSettingDataComponent "
+                      "ResultClass = Msvm_ProcessorSettingData",
+                      virtualSystemSettingData->data->InstanceID);
+    if (hypervGetMsvmProcessorSettingDataList(priv, &query, &processorSettingData) < 0) {
+        goto cleanup;
+    }
+    if (processorSettingData == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not lookup %s for domain %s"),
+                       "Msvm_ProcessorSettingData", computerSystem->data->ElementName);
+        goto cleanup;
+    }
+
+    result = processorSettingData->data->VirtualQuantity;
+
+ cleanup:
+    hypervFreeObject(priv, (hypervObject *)computerSystem);
+    hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+    hypervFreeObject(priv, (hypervObject *)processorSettingData);
+    virBufferFreeAndReset(&query);
+
+    return result;
+}
+
+static int
+hypervDomainGetMaxVcpus(virDomainPtr dom)
+{
+    /* If the guest is inactive, this is basically the same as virConnectGetMaxVcpus() */
+    return (hypervDomainIsActive(dom)) ?
+        hypervDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM))
+        : hypervConnectGetMaxVcpus(dom->conn, NULL);
+}
+
+static int
+hypervDomainGetVcpus(virDomainPtr domain, virVcpuInfoPtr info, int maxinfo,
+                     unsigned char *cpumaps, int maplen)
+{
+    int count = 0, i;
+    hypervPrivate *priv = domain->conn->privateData;
+    virBuffer query = VIR_BUFFER_INITIALIZER;
+    Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor *hypervVirtualProcessor = NULL;
+
+    /* FIXME: no information stored in cpumaps */
+    if ((cpumaps != NULL) && (maplen > 0))
+        memset(cpumaps, 0, maxinfo * maplen);
+
+    /* Loop for each vCPU */
+    for (i = 0; i < maxinfo; i++) {
+
+        /* Get vCPU stats */
+        hypervFreeObject(priv, (hypervObject *)hypervVirtualProcessor);
+        hypervVirtualProcessor = NULL;
+        virBufferFreeAndReset(&query);
+        virBufferAddLit(&query, WIN32_PERFRAWDATA_HVSTATS_HYPERVHYPERVISORVIRTUALPROCESSOR_WQL_SELECT);
+        /* Attribute Name format : <domain_name>:Hv VP <vCPU_number> */
+        virBufferAsprintf(&query, "where Name = \"%s:Hv VP %d\"", domain->name, i);
+
+        if (hypervGetWin32PerfRawDataHvStatsHyperVHypervisorVirtualProcessorList(
+                priv, &query, &hypervVirtualProcessor) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Could not get stats on vCPU #%d"), i);
+            continue;
+        }
+
+        /* Fill structure info */
+        info[i].number = i;
+        if (hypervVirtualProcessor == NULL) {
+            info[i].state = VIR_VCPU_OFFLINE;
+            info[i].cpuTime = 0LLU;
+            info[i].cpu = -1;
+        } else {
+            info[i].state = VIR_VCPU_RUNNING;
+            info[i].cpuTime = hypervVirtualProcessor->data->PercentTotalRunTime;
+            info[i].cpu = i;
+        }
+
+        count++;
+    }
+
+    hypervFreeObject(priv, (hypervObject *)hypervVirtualProcessor);
+    virBufferFreeAndReset(&query);
+
+    return count;
+}
+
 static virHypervisorDriver hypervHypervisorDriver = {
     .name = "Hyper-V",
     .connectOpen = hypervConnectOpen, /* 0.9.5 */
@@ -1437,6 +1609,10 @@ static virHypervisorDriver hypervHypervisorDriver = {
     .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */
     .connectGetCapabilities = hypervConnectGetCapabilities, /* 1.2.10 */
     .connectGetVersion = hypervConnectGetVersion, /* 1.2.10 */
+    .connectGetMaxVcpus = hypervConnectGetMaxVcpus, /* 1.2.10 */
+    .domainGetMaxVcpus = hypervDomainGetMaxVcpus, /* 1.2.10 */
+    .domainGetVcpusFlags = hypervDomainGetVcpusFlags, /* 1.2.10 */
+    .domainGetVcpus = hypervDomainGetVcpus, /* 1.2.10 */
 };
 
 /* Retrieves host system UUID  */
-- 
2.7.4




More information about the libvir-list mailing list