??
On 08/09/2016 08:39 AM, Jason Miesionczek wrote:
---
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'");
I see this is going to be a theme - I guess that's how it works.
Maybe all these strings should be part of some #define GET_MAX_VCPU_STR
"..."
+
+ if (hypervGetMsvmProcessorSettingDataList(priv, &query,
&processorSettingData) < 0) {
Long line - > 80 chars
+ goto cleanup;
+ }
+
+ if (processorSettingData == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
You'll need a "%s", here too
+ _("Could not get maximum definition of
Msvm_ProcessorSettingData"));
really long line consider
"text.... text "
"more text"
+ goto cleanup;
+ }
+
+ result = processorSettingData->data->SocketCount *
processorSettingData->data->ProcessorsPerSocket;
Long line
+
+ 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);
Long line - typically one flag per line - makes it easier to insert more
flags.
+
+ 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);
syntax-check complained here - just make 4 lines out of this...
+ 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);
syntax-check complained here - just make 4 lines out of this...
+ 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);
There's a few examples out there that you should be able to use...
+
+ /* 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);
Since you're continuing, perhaps a VIR_WARN or VIR_INFO is more
appropriate?
However, when the caller/client returns you could then get more than one
"info[0].number = 0, .state = 0, cpuTime = 0, .cpu = 0"
So the question becomes - should this fail instead.
+ 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 */
2.3.0 at the earliest
John
[I need to run for the evening - it's after 630P where I'm at - will
pick up again tomorrow]
};
/* Retrieves host system UUID */