[PATCH 03/11] hyperv: implement domainCreateXML and domainDefineXML

Matt Coleman mcoleman at datto.com
Tue Nov 24 19:48:32 UTC 2020


Co-authored-by: Sri Ramanujam <sramanujam at datto.com>
Signed-off-by: Matt Coleman <matt at datto.com>
---
 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, &params, 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





More information about the libvir-list mailing list