Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
---
src/hyperv/hyperv_driver.c | 88 ++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 841d9ccaa5..5417c8593f 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -4163,6 +4163,93 @@ hypervDomainSnapshotLookupByName(virDomainPtr domain,
}
+static virDomainSnapshotPtr
+hypervDomainSnapshotCreateXML(virDomainPtr domain,
+ const char *xmlDesc,
+ unsigned int flags)
+{
+ hypervPrivate *priv = domain->conn->privateData;
+ g_autoptr(Msvm_ComputerSystem) computerSystem = NULL;
+ g_autoptr(hypervInvokeParamsList) params = NULL;
+ g_autoptr(virDomainSnapshotDef) def = NULL;
+ g_autoptr(GHashTable) snapshotSettings = NULL;
+ g_auto(virBuffer) eprQuery = VIR_BUFFER_INITIALIZER;
+ g_auto(virBuffer) query = VIR_BUFFER_INITIALIZER;
+ g_autoptr(Msvm_VirtualSystemSettingData) snapshot = NULL;
+ g_auto(WsXmlDocH) response = NULL;
+ char uuid_string[VIR_UUID_STRING_BUFLEN];
+
+ virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE, NULL);
+
+ def = virDomainSnapshotDefParseString(xmlDesc, priv->xmlopt, NULL, NULL, 0);
+ if (!def)
+ return NULL;
+
+ if (def->ndisks) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("configuring specific disks is not yet supported for hyperv"));
+ return NULL;
+ }
+
+ if (def->memory) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("configuring snapshot memory is not yet supported for hyperv"));
+ return NULL;
+ }
+
+ virUUIDFormat(domain->uuid, uuid_string);
+
+ if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0)
+ return NULL;
+
+ virBufferEscapeSQL(&eprQuery,
+ MSVM_COMPUTERSYSTEM_WQL_SELECT "WHERE Name = '%s'",
+ uuid_string);
+
+ params = hypervCreateInvokeParamsList("CreateSnapshot",
+ MSVM_VIRTUALSYSTEMSNAPSHOTSERVICE_SELECTOR,
+ Msvm_VirtualSystemSnapshotService_WmiInfo);
+ if (!params)
+ return NULL;
+
+ if (hypervAddEprParam(params, "AffectedSystem", &eprQuery,
+ Msvm_ComputerSystem_WmiInfo) < 0)
+ return NULL;
+
+ snapshotSettings = hypervCreateEmbeddedParam(Msvm_VirtualSystemSnapshotSettingData_WmiInfo);
+ if (!snapshotSettings)
+ return NULL;
+
+ if (hypervSetEmbeddedProperty(snapshotSettings, "ConsistencyLevel",
+ (flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) ?
+ HYPERV_SNAPSHOT_CONSISTENCY_APP_CONSISTENT :
+ HYPERV_SNAPSHOT_CONSISTENCY_CRASH_CONSISTENT) < 0)
+ return NULL;
+
+ if (hypervAddEmbeddedParam(params, "SnapshotSettings", &snapshotSettings,
+ Msvm_VirtualSystemSnapshotSettingData_WmiInfo) < 0)
+ return NULL;
+
+ hypervAddSimpleParam(params, "SnapshotType", HYPERV_SNAPSHOT_TYPE_FULL);
+
+ if (hypervInvokeMethod(priv, ¶ms, &response) < 0)
+ return NULL;
+
+ /* The CreateSnapshot method will generally return an async job rather
+ * than returning the 'ResultingSnapshot' output parameter directly
+ * in the response. Although hypervInvokeMethod() polls the async job to
+ * completion when this occurs, the response will not include the output
+ * parameters. So we use this helper function to build a query to fetch the
+ * resulting object from the async job associations. */
+ if (hypervResponseGetOutputParam(priv, response, "ResultingSnapshot",
+ Msvm_VirtualSystemSettingData_WmiInfo,
+ (hypervObject**) &snapshot) < 0)
+ return NULL;
+
+ return virGetDomainSnapshot(domain, snapshot->data->InstanceID);
+}
+
+
static int
hypervDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
unsigned int flags)
@@ -4493,6 +4580,7 @@ static virHypervisorDriver hypervHypervisorDriver = {
.domainSnapshotCurrent = hypervDomainSnapshotCurrent, /* 12.2.0 */
.domainSnapshotGetParent = hypervDomainSnapshotGetParent, /* 12.2.0 */
.domainSnapshotDelete = hypervDomainSnapshotDelete, /* 12.2.0 */
+ .domainSnapshotCreateXML = hypervDomainSnapshotCreateXML, /* 12.2.0 */
};
--
2.53.0
© 2016 - 2026 Red Hat, Inc.