From: yvinter <yves.vinter@xxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list