From: yvinter <yves.vinter(a)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