Co-authored-by: Sri Ramanujam <sramanujam@xxxxxxxxx> Signed-off-by: Matt Coleman <matt@xxxxxxxxx> --- src/hyperv/hyperv_driver.c | 114 +++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 8e16ff529f..559b60d3df 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -703,6 +703,9 @@ hypervFreePrivate(hypervPrivate **priv) if ((*priv)->caps) virObjectUnref((*priv)->caps); + if ((*priv)->xmlopt) + virObjectUnref((*priv)->xmlopt); + hypervFreeParsedUri(&(*priv)->parsedUri); VIR_FREE(*priv); } @@ -735,6 +738,8 @@ hypervInitConnection(virConnectPtr conn, hypervPrivate *priv, } +virDomainDefParserConfig hypervDomainDefParserConfig; + static virDrvOpenStatus hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, virConfPtr conf G_GNUC_UNUSED, @@ -787,6 +792,9 @@ hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, if (!priv->caps) goto cleanup; + /* init xmlopt for domain XML */ + priv->xmlopt = virDomainXMLOptionNew(&hypervDomainDefParserConfig, NULL, NULL, NULL, NULL); + conn->privateData = priv; priv = NULL; result = VIR_DRV_OPEN_SUCCESS; @@ -1932,6 +1940,105 @@ hypervDomainUndefine(virDomainPtr domain) } +static virDomainPtr +hypervDomainDefineXML(virConnectPtr conn, const char *xml) +{ + hypervPrivate *priv = conn->privateData; + g_autoptr(virDomainDef) def = NULL; + virDomainPtr domain = NULL; + g_autoptr(hypervInvokeParamsList) params = NULL; + g_autoptr(GHashTable) defineSystemParam = NULL; + + /* parse xml */ + def = virDomainDefParseString(xml, priv->xmlopt, NULL, + 1 << VIR_DOMAIN_VIRT_HYPERV | VIR_DOMAIN_XML_INACTIVE); + + if (!def) + goto error; + + /* abort if a domain with this UUID already exists */ + if ((domain = hypervDomainLookupByUUID(conn, def->uuid))) { + char uuid_string[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(domain->uuid, uuid_string); + virReportError(VIR_ERR_DOM_EXIST, _("Domain already exists with UUID '%s'"), uuid_string); + + // Don't use the 'exit' label, since we don't want to delete the existing domain. + virObjectUnref(domain); + return NULL; + } + + /* prepare params: only set the VM's name for now */ + params = hypervCreateInvokeParamsList("DefineSystem", + MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR, + Msvm_VirtualSystemManagementService_WmiInfo); + + if (!params) + goto error; + + defineSystemParam = hypervCreateEmbeddedParam(Msvm_VirtualSystemSettingData_WmiInfo); + + if (hypervSetEmbeddedProperty(defineSystemParam, "ElementName", def->name) < 0) + goto error; + + if (hypervAddEmbeddedParam(params, "SystemSettings", + &defineSystemParam, Msvm_VirtualSystemSettingData_WmiInfo) < 0) + goto error; + + /* create the VM */ + if (hypervInvokeMethod(priv, ¶ms, NULL) < 0) + goto error; + + /* populate a domain ptr so that we can edit it */ + domain = hypervDomainLookupByName(conn, def->name); + + /* set domain vcpus */ + if (def->vcpus && hypervDomainSetVcpus(domain, def->maxvcpus) < 0) + goto error; + + /* set VM maximum memory */ + if (def->mem.max_memory > 0 && hypervDomainSetMaxMemory(domain, def->mem.max_memory) < 0) + goto error; + + /* set VM memory */ + if (def->mem.cur_balloon > 0 && hypervDomainSetMemory(domain, def->mem.cur_balloon) < 0) + goto error; + + return domain; + + error: + VIR_DEBUG("Domain creation failed, rolling back"); + if (domain) + hypervDomainUndefine(domain); + + return NULL; +} + + +static virDomainPtr +hypervDomainCreateXML(virConnectPtr conn, const char *xmlDesc, unsigned int flags) +{ + virDomainPtr domain; + + virCheckFlags(VIR_DOMAIN_START_PAUSED, NULL); + + /* create the new domain */ + domain = hypervDomainDefineXML(conn, xmlDesc); + if (!domain) + return NULL; + + /* start the domain */ + if (hypervInvokeMsvmComputerSystemRequestStateChange(domain, MSVM_COMPUTERSYSTEM_REQUESTEDSTATE_ENABLED) < 0) + return domain; + + /* If VIR_DOMAIN_START_PAUSED is set, the guest domain will be started, + * but its vCPUs will be paused. */ + if (flags & VIR_DOMAIN_START_PAUSED) + hypervDomainSuspend(domain); + + return domain; +} + + static int hypervDomainGetAutostart(virDomainPtr domain, int *autostart) { @@ -2515,6 +2622,7 @@ static virHypervisorDriver hypervHypervisorDriver = { .connectListDomains = hypervConnectListDomains, /* 0.9.5 */ .connectNumOfDomains = hypervConnectNumOfDomains, /* 0.9.5 */ .connectListAllDomains = hypervConnectListAllDomains, /* 0.10.2 */ + .domainCreateXML = hypervDomainCreateXML, /* 6.10.0 */ .domainLookupByID = hypervDomainLookupByID, /* 0.9.5 */ .domainLookupByUUID = hypervDomainLookupByUUID, /* 0.9.5 */ .domainLookupByName = hypervDomainLookupByName, /* 0.9.5 */ @@ -2543,6 +2651,7 @@ static virHypervisorDriver hypervHypervisorDriver = { .connectNumOfDefinedDomains = hypervConnectNumOfDefinedDomains, /* 0.9.5 */ .domainCreate = hypervDomainCreate, /* 0.9.5 */ .domainCreateWithFlags = hypervDomainCreateWithFlags, /* 0.9.5 */ + .domainDefineXML = hypervDomainDefineXML, /* 6.10.0 */ .domainUndefine = hypervDomainUndefine, /* 6.10.0 */ .domainUndefineFlags = hypervDomainUndefineFlags, /* 6.10.0 */ .domainGetAutostart = hypervDomainGetAutostart, /* 6.9.0 */ @@ -2564,6 +2673,11 @@ static virHypervisorDriver hypervHypervisorDriver = { }; +virDomainDefParserConfig hypervDomainDefParserConfig = { + .features = VIR_DOMAIN_DEF_FEATURE_MEMORY_HOTPLUG, +}; + + static void hypervDebugHandler(const char *message, debug_level_e level, void *user_data G_GNUC_UNUSED) -- 2.27.0