[libvirt] [PATCH 04/21] Added implementation for virDomainGetVcpus and virConnectGetMaxVcpus (required Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor class)

Yves Vinter yves.vinter at bull.net
Wed Oct 8 12:33:49 UTC 2014


From: yvinter <yves.vinter at bull.net>

---
 src/hyperv/hyperv_driver.c            | 184 ++++++++++++++++++++++++++++++++++
 src/hyperv/hyperv_wmi_generator.input | 109 ++++++++++++++++++++
 2 files changed, 293 insertions(+)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index dd56fb0..f734c09 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -1532,6 +1532,186 @@ hypervConnectGetCapabilities(virConnectPtr conn)
 
 
 
+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 virDriver hypervDriver = {
     .no = VIR_DRV_HYPERV,
     .name = "Hyper-V",
@@ -1569,6 +1749,10 @@ static virDriver hypervDriver = {
     .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */
     .connectGetVersion = hypervConnectGetVersion, /* 1.2.10 */
     .connectGetCapabilities = hypervConnectGetCapabilities, /* 1.2.10 */
+    .connectGetMaxVcpus = hypervConnectGetMaxVcpus, /* 1.2.10 */
+    .domainGetMaxVcpus = hypervDomainGetMaxVcpus, /* 1.2.10 */
+    .domainGetVcpusFlags = hypervDomainGetVcpusFlags, /* 1.2.10 */
+    .domainGetVcpus = hypervDomainGetVcpus, /* 1.2.10 */
 };
 
 
diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input
index f1e0c81..8fb34e4 100644
--- a/src/hyperv/hyperv_wmi_generator.input
+++ b/src/hyperv/hyperv_wmi_generator.input
@@ -345,3 +345,112 @@ class Win32_ComputerSystemProduct
 	string 	Vendor
 	string 	Version
 end
+
+
+class Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor
+	uint64   AddressDomainFlushesPersec
+	uint64   AddressSpaceEvictionsPersec
+	uint64   AddressSpaceFlushesPersec
+	uint64   AddressSpaceSwitchesPersec
+	uint64   APICEOIAccessesPersec
+	uint64   APICIPIsSentPersec
+	uint64   APICMMIOAccessesPersec
+	uint64   APICSelfIPIsSentPersec
+	uint64   APICTPRAccessesPersec
+	string   Caption
+	uint64   ControlRegisterAccessesCost
+	uint64   ControlRegisterAccessesCost_Base
+	uint64   ControlRegisterAccessesPersec
+	uint64   CPUIDInstructionsCost
+	uint64   CPUIDInstructionsCost_Base
+	uint64   CPUIDInstructionsPersec
+	uint64   CPUWaitTimePerDispatch
+	uint64   CPUWaitTimePerDispatch_Base
+	uint64   DebugRegisterAccessesCost
+	uint64   DebugRegisterAccessesCost_Base
+	uint64   DebugRegisterAccessesPersec
+	string   Description
+	uint64   EmulatedInstructionsCost
+	uint64   EmulatedInstructionsCost_Base
+	uint64   EmulatedInstructionsPersec
+	uint64   ExternalInterruptsCost
+	uint64   ExternalInterruptsCost_Base
+	uint64   ExternalInterruptsPersec
+	uint64   Frequency_Object
+	uint64   Frequency_PerfTime
+	uint64   Frequency_Sys100NS
+	uint64   GlobalGVARangeFlushesPersec
+	uint64   GPASpaceHypercallsPersec
+	uint64   GuestPageTableMapsPersec
+	uint64   HardwareInterruptsPersec
+	uint64   HLTInstructionsCost
+	uint64   HLTInstructionsCost_Base
+	uint64   HLTInstructionsPersec
+	uint64   HypercallsCost
+	uint64   HypercallsCost_Base
+	uint64   HypercallsPersec
+	uint64   IOInstructionsCost
+	uint64   IOInstructionsCost_Base
+	uint64   IOInstructionsPersec
+	uint64   IOInterceptMessagesPersec
+	uint64   LargePageTLBFillsPersec
+	uint64   LocalFlushedGVARangesPersec
+	uint64   LogicalProcessorDispatchesPersec
+	uint64   LogicalProcessorHypercallsPersec
+	uint64   LogicalProcessorMigrationsPersec
+	uint64   LongSpinWaitHypercallsPersec
+	uint64   MemoryInterceptMessagesPersec
+	uint64   MSRAccessesCost
+	uint64   MSRAccessesCost_Base
+	uint64   MSRAccessesPersec
+	uint64   MWAITInstructionsCost
+	uint64   MWAITInstructionsCost_Base
+	uint64   MWAITInstructionsPersec
+	string   Name
+	uint64   NestedPageFaultInterceptsCost
+	uint64   NestedPageFaultInterceptsCost_Base
+	uint64   NestedPageFaultInterceptsPersec
+	uint64   OtherHypercallsPersec
+	uint64   OtherInterceptsCost
+	uint64   OtherInterceptsCost_Base
+	uint64   OtherInterceptsPersec
+	uint64   OtherMessagesPersec
+	uint64   PageFaultInterceptsCost
+	uint64   PageFaultInterceptsCost_Base
+	uint64   PageFaultInterceptsPersec
+	uint64   PageInvalidationsCost
+	uint64   PageInvalidationsCost_Base
+	uint64   PageInvalidationsPersec
+	uint64   PageTableAllocationsPersec
+	uint64   PageTableEvictionsPersec
+	uint64   PageTableReclamationsPersec
+	uint64   PageTableResetsPersec
+	uint64   PageTableValidationsPersec
+	uint64   PageTableWriteInterceptsPersec
+	uint64   PendingInterruptsCost
+	uint64   PendingInterruptsCost_Base
+	uint64   PendingInterruptsPersec
+	uint64   PercentGuestRunTime
+	uint64   PercentGuestRunTime_Base
+	uint64   PercentHypervisorRunTime
+	uint64   PercentHypervisorRunTime_Base
+	uint64   PercentRemoteRunTime
+	uint64   PercentRemoteRunTime_Base
+	uint64   PercentTotalRunTime
+	uint64   PercentTotalRunTime_Base
+	uint64   ReflectedGuestPageFaultsPersec
+	uint64   SmallPageTLBFillsPersec
+	uint64   SyntheticInterruptHypercallsPersec
+	uint64   SyntheticInterruptsPersec
+	uint64   Timestamp_Object
+	uint64   Timestamp_PerfTime
+	uint64   Timestamp_Sys100NS
+	uint64   TotalInterceptsCost
+	uint64   TotalInterceptsCost_Base
+	uint64   TotalInterceptsPersec
+	uint64   TotalMessagesPersec
+	uint64   VirtualInterruptHypercallsPersec
+	uint64   VirtualInterruptsPersec
+	uint64   VirtualMMUHypercallsPersec
+	uint64   VirtualProcessorHypercallsPersec
+end
-- 
1.9.1




More information about the libvir-list mailing list