[libvirt] [PATCH 05/16] hyperv: implement vcpu functions
John Ferlan
jferlan at redhat.com
Wed Sep 14 22:33:43 UTC 2016
??
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 */
>
More information about the libvir-list
mailing list