[libvirt] [PATCH 11/16] hyperv: add set memory functions
John Ferlan
jferlan at redhat.com
Thu Sep 15 14:20:29 UTC 2016
On 08/09/2016 08:39 AM, Jason Miesionczek wrote:
> ---
> src/hyperv/hyperv_driver.c | 232 ++++++++++++++++++++++++++++++++++++++++++++
> src/hyperv/hyperv_private.h | 2 +
> 2 files changed, 234 insertions(+)
>
> diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
> index 348b39c..daae371 100644
> --- a/src/hyperv/hyperv_driver.c
> +++ b/src/hyperv/hyperv_driver.c
> @@ -56,6 +56,9 @@ hypervFreePrivate(hypervPrivate **priv)
> if ((*priv)->caps != NULL)
> virObjectUnref((*priv)->caps);
>
> + if ((*priv)->xmlopt != NULL)
> + virObjectUnref((*priv)->xmlopt);
> +
> hypervFreeParsedUri(&(*priv)->parsedUri);
> VIR_FREE(*priv);
> }
> @@ -195,6 +198,9 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth,
> goto cleanup;
> }
>
> + /* Init xmlopt to parse Domain XML */
> + priv->xmlopt = virDomainXMLOptionNew(NULL, NULL, NULL);
> +
Strange to see NULL, NULL, NULL
No MAC prefix needs?
No desire/need to have post parse callbacks? IOW: Things to check after
all the parsing is done so that you can verify things work together?
Guess I'm unclear why this is being done here.
Looking forward - I see patch 14 makes use of it, so that's where it
should be moved to.
> conn->privateData = priv;
> priv = NULL;
> result = VIR_DRV_OPEN_SUCCESS;
> @@ -1860,6 +1866,229 @@ hypervDomainGetSchedulerType(virDomainPtr domain ATTRIBUTE_UNUSED, int *nparams)
> return type;
> }
>
> +/* Format a number as a string value */
> +static char *num2str(unsigned long value)
> +{
> + int sz;
> + char *result;
> +
> + sz = snprintf (NULL, 0, "%lu", value);
> + if (VIR_ALLOC_N(result, sz + 1) < 0) {
> + return NULL;
> + }
> +
> + sprintf(result, "%lu", value);
> + return result;
open coding virAsprintf() I think...
> +}
> +
> +
> +
> +static int
> +hypervDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
> +{
> + int result = -1;
> + invokeXmlParam *params = NULL;
> + char uuid_string[VIR_UUID_STRING_BUFLEN];
> + hypervPrivate *priv = domain->conn->privateData;
> + properties_t *tab_props = NULL;
> + virBuffer query = VIR_BUFFER_INITIALIZER;
> + virBuffer query2 = VIR_BUFFER_INITIALIZER;
> + Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
> + Msvm_MemorySettingData *memorySettingData = NULL;
> + eprParam eprparam;
> + embeddedParam embeddedparam;
> + int nb_params;
> + const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService";
> + unsigned long memory_mb = memory/1024;
> + char *memory_str = NULL;
> +
> + /* Memory value must be a multiple of 2 MB; round up it accordingly if necessary */
> + if (memory_mb % 2) memory_mb++;
There's VIR_ROUND_UP or VIR_ROUND_UP_POWER_OF_TWO
Not sure if you meant power of 2 instead multiple of 2MB
> +
> + /* Convert the memory value as a string */
> + memory_str = num2str(memory_mb);
> + if (memory_str == NULL)
> + goto cleanup;
if (virAsprintf(memory_str, "%lu", memory_mb) < 0)
goto cleanup;
> +
> + virUUIDFormat(domain->uuid, uuid_string);
> +
> + VIR_DEBUG("memory=%sMb, uuid=%s", memory_str, uuid_string);
> +
> + /* Prepare EPR param */
> + virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
> + virBufferAsprintf(&query, "where Name = \"%s\"",uuid_string);
> + eprparam.query = &query;
> + eprparam.wmiProviderURI = ROOT_VIRTUALIZATION;
> +
> + /* Prepare EMBEDDED param 1 */
> + /* Get Msvm_VirtualSystemSettingData */
> + virBufferAsprintf(&query2,
> + "associators of "
> + "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
> + "Name=\"%s\"} "
> + "where AssocClass = Msvm_SettingsDefineState "
> + "ResultClass = Msvm_VirtualSystemSettingData",
> + uuid_string);
> +
> + if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query2, &virtualSystemSettingData) < 0)
> + goto cleanup;
> +
> + /* Get Msvm_MemorySettingData */
> + virBufferFreeAndReset(&query2);
> + virBufferAsprintf(&query2,
> + "associators of "
> + "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
> + "where AssocClass = Msvm_VirtualSystemSettingDataComponent "
> + "ResultClass = Msvm_MemorySettingData",
> + virtualSystemSettingData->data->InstanceID);
> +
> + if (hypervGetMsvmMemorySettingDataList(priv, &query2, &memorySettingData) < 0)
> + goto cleanup;
> +
> + embeddedparam.nbProps = 2;
> + if (VIR_ALLOC_N(tab_props, embeddedparam.nbProps) < 0)
> + goto cleanup;
> + (*tab_props).name = "Limit";
> + (*tab_props).val = memory_str;
> + (*(tab_props+1)).name = "InstanceID";
> + (*(tab_props+1)).val = memorySettingData->data->InstanceID;
> + embeddedparam.instanceName = "Msvm_MemorySettingData";
> + embeddedparam.prop_t = tab_props;
> + embeddedparam.nbProps = 2;
> +
> + /* Create invokeXmlParam */
> + nb_params = 2;
> + if (VIR_ALLOC_N(params, nb_params) < 0)
> + goto cleanup;
> + (*params).name = "ComputerSystem";
> + (*params).type = EPR_PARAM;
> + (*params).param = &eprparam;
> + (*(params+1)).name = "ResourceSettingData";
> + (*(params+1)).type = EMBEDDED_PARAM;
> + (*(params+1)).param = &embeddedparam;
> +
More of these strange constructs *tab_props, *params... consider
tab_props[0]->
tab_props[1]->
params[0]->
params[1]->
> + result = hypervInvokeMethod(priv, params, nb_params, "ModifyVirtualSystemResources",
> + MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector);
> +
> + cleanup:
> + VIR_FREE(tab_props);
> + VIR_FREE(params);
> + VIR_FREE(memory_str);
> + hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
> + hypervFreeObject(priv, (hypervObject *)memorySettingData);
> + virBufferFreeAndReset(&query);
> + virBufferFreeAndReset(&query2);
> +
> + return result;
> +}
> +
Since these two are so similar - check out what the qemu driver code does:
static int qemuDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
{
return qemuDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
}
Then in qemuDomainSetMemoryFlags, there's a check:
if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
} else {
}
Of course there's also an extra flags check for VIR_DOMAIN_MEM_MAXIMUM
in qemuDomainSetMemoryFlags
It's up to you though to determine how similar and whether any merging
of the two could be done...
> +static int
> +hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
> + unsigned int flags ATTRIBUTE_UNUSED)
> +{
> + int result = -1, nb_params;
> + const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService";
> + char uuid_string[VIR_UUID_STRING_BUFLEN];
> + hypervPrivate *priv = domain->conn->privateData;
> + invokeXmlParam *params = NULL;
> + properties_t *tab_props = NULL;
> + eprParam eprparam;
> + embeddedParam embeddedparam;
> + virBuffer query = VIR_BUFFER_INITIALIZER;
> + Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
> + Msvm_MemorySettingData *memorySettingData = NULL;
> + unsigned long memory_mb = memory / 1024; /* Memory converted in MB */
> + char *memory_str = NULL;
> +
> + /* Memory value must be a multiple of 2 MB; round up it accordingly if necessary */
> + if (memory_mb % 2) memory_mb++;
> +
> + /* Convert the memory value as a string */
> + memory_str = num2str(memory_mb);
> + if (memory_str == NULL)
> + goto cleanup;
Simi
> +
> + virUUIDFormat(domain->uuid, uuid_string);
> +
> + VIR_DEBUG("memory=%sMb, uuid=%s", memory_str, uuid_string);
> +
> + /* 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;
> +
> + /* Get Msvm_MemorySettingData */
> + virBufferFreeAndReset(&query);
> + virBufferAsprintf(&query,
> + "associators of "
> + "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
> + "where AssocClass = Msvm_VirtualSystemSettingDataComponent "
> + "ResultClass = Msvm_MemorySettingData",
> + virtualSystemSettingData->data->InstanceID);
> + if (hypervGetMsvmMemorySettingDataList(priv, &query, &memorySettingData) < 0)
> + goto cleanup;
> +
> + /* Prepare EPR param */
> + virBufferFreeAndReset(&query);
> + virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
> + virBufferAsprintf(&query, "where Name = \"%s\"",uuid_string);
> + eprparam.query = &query;
> + eprparam.wmiProviderURI = ROOT_VIRTUALIZATION;
> +
> + /* Prepare EMBEDDED param */
> + embeddedparam.nbProps = 2;
> + if (VIR_ALLOC_N(tab_props, embeddedparam.nbProps) < 0)
> + goto cleanup;
> + (*tab_props).name = "VirtualQuantity";
> + (*tab_props).val = memory_str;
> + (*(tab_props+1)).name = "InstanceID";
> + (*(tab_props+1)).val = memorySettingData->data->InstanceID;
> + embeddedparam.instanceName = "Msvm_MemorySettingData";
> + embeddedparam.prop_t = tab_props;
> +
> + /* Create invokeXmlParam */
> + nb_params = 2;
> + if (VIR_ALLOC_N(params, nb_params) < 0)
> + goto cleanup;
> + (*params).name = "ComputerSystem";
> + (*params).type = EPR_PARAM;
> + (*params).param = &eprparam;
> + (*(params+1)).name = "ResourceSettingData";
> + (*(params+1)).type = EMBEDDED_PARAM;
> + (*(params+1)).param = &embeddedparam;
> +
> + if (hypervInvokeMethod(priv, params, nb_params, "ModifyVirtualSystemResources",
> + MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not set domain memory"));
> + goto cleanup;
> + }
> +
> + result = 0;
> +
> + cleanup:
> + VIR_FREE(tab_props);
> + VIR_FREE(params);
> + VIR_FREE(memory_str);
> + hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
> + hypervFreeObject(priv, (hypervObject *)memorySettingData);
> + virBufferFreeAndReset(&query);
> +
> + return result;
> +}
> +
> +
> +
> +static int
> +hypervDomainSetMemory(virDomainPtr domain, unsigned long memory)
> +{
> + return hypervDomainSetMemoryFlags(domain, memory, 0);
> +}
>
> static virHypervisorDriver hypervHypervisorDriver = {
> .name = "Hyper-V",
> @@ -1909,6 +2138,9 @@ static virHypervisorDriver hypervHypervisorDriver = {
> .domainGetSchedulerParametersFlags = hypervDomainGetSchedulerParametersFlags, /* 1.2.10 */
> .domainGetSchedulerParameters = hypervDomainGetSchedulerParameters, /* 1.2.10 */
> .domainGetSchedulerType = hypervDomainGetSchedulerType, /* 1.2.10 */
> + .domainSetMaxMemory = hypervDomainSetMaxMemory, /* 1.2.10 */
> + .domainSetMemory = hypervDomainSetMemory, /* 1.2.10 */
> + .domainSetMemoryFlags = hypervDomainSetMemoryFlags, /* 1.2.10 */
2.3.0 at the earliest
> };
>
> /* Retrieves host system UUID */
> diff --git a/src/hyperv/hyperv_private.h b/src/hyperv/hyperv_private.h
> index d9aa0bd..2dfce6e 100644
> --- a/src/hyperv/hyperv_private.h
> +++ b/src/hyperv/hyperv_private.h
> @@ -27,6 +27,7 @@
> # include "virerror.h"
> # include "hyperv_util.h"
> # include "capabilities.h"
> +# include "domain_conf.h"
Will this also need to move to patch 14?
> # include "openwsman.h"
>
> typedef struct _hypervPrivate hypervPrivate;
> @@ -35,6 +36,7 @@ struct _hypervPrivate {
> hypervParsedUri *parsedUri;
> WsManClient *client;
> virCapsPtr caps;
> + virDomainXMLOptionPtr xmlopt;
Move to patch 14
John
> };
>
> #endif /* __HYPERV_PRIVATE_H__ */
>
More information about the libvir-list
mailing list