This function is required for `virsh snapshot-list` to work.

Signed-off-by: Jonathon Jongsma <[email protected]>
---
 src/hyperv/hyperv_driver.c | 67 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 8a1cc4b453..4a4db0e76b 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -41,6 +41,7 @@
 #include "virstring.h"
 #include "virkeycode.h"
 #include "domain_conf.h"
+#include "snapshot_conf.h"
 #include "virfdstream.h"
 #include "virfile.h"
 
@@ -4209,6 +4210,71 @@ hypervDomainSnapshotNum(virDomainPtr domain,
 }
 
 
+/* A snapshot's parent is specified as an object path like 'InstanceID="$ID"'.
+ * This function extracts the id portion. */
+static char *
+hypervParseInstanceIdFromParentPath(const char *obj_path)
+{
+    const char *const instance_prefix = "InstanceID=\"";
+    const char *id_start = NULL;
+    if (!obj_path)
+        return NULL;
+
+    id_start = strstr(obj_path, instance_prefix);
+    if (id_start) {
+        const char *id_end;
+        id_start += strlen(instance_prefix);
+        id_end = strchr(id_start, '"');
+        if (id_end) {
+            g_autofree char* parent_id_escaped = g_strndup(id_start, id_end - 
id_start);
+            char* parent_id = virStringReplace(parent_id_escaped, "\\\\", 
"\\");
+            return parent_id;
+        }
+    }
+    return NULL;
+}
+
+
+static char *
+hypervDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
+                               unsigned int flags)
+{
+    hypervPrivate *priv = snapshot->domain->conn->privateData;
+    g_autoptr(Msvm_VirtualSystemSettingData) vssd = NULL;
+    g_autoptr(virDomainSnapshotDef) def = NULL;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+    virCheckFlags(VIR_DOMAIN_SNAPSHOT_XML_SECURE, NULL);
+
+    vssd = hypervDomainLookupSnapshotSD(snapshot->domain, snapshot->name);
+    if (!vssd)
+        return NULL;
+
+    if (!(def = virDomainSnapshotDefNew()))
+        return NULL;
+
+    def->parent.name = g_strdup(vssd->data->InstanceID);
+    def->parent.description = g_strdup(vssd->data->ElementName);
+    def->parent.parent_name = 
hypervParseInstanceIdFromParentPath(vssd->data->Parent);
+    /* IsSaved indicates the snapshot configuration references a saved memory
+     * state file, meaning the snapshot was taken from a running VM and 
includes
+     * full machine state. Otherwise it's either a 'production' checkpoint or 
an
+     * offline snapshot, which are both disk-only. */
+    def->state = vssd->data->IsSaved ? VIR_DOMAIN_SNAPSHOT_RUNNING : 
VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT;
+
+    if (vssd->data->CreationTime) {
+        g_autoptr(GDateTime) dt = 
g_date_time_new_from_iso8601(vssd->data->CreationTime, NULL);
+        if (dt)
+            def->parent.creationTime = g_date_time_to_unix(dt);
+    }
+
+    virUUIDFormat(snapshot->domain->uuid, uuidstr);
+
+    return virDomainSnapshotDefFormat(uuidstr, def, priv->xmlopt,
+                                      
virDomainSnapshotFormatConvertXMLFlags(flags));
+}
+
+
 static virHypervisorDriver hypervHypervisorDriver = {
     .name = "Hyper-V",
     .connectOpen = hypervConnectOpen, /* 0.9.5 */
@@ -4278,6 +4344,7 @@ static virHypervisorDriver hypervHypervisorDriver = {
     .domainSnapshotLookupByName = hypervDomainSnapshotLookupByName, /* 12.2.0 
*/
     .domainListAllSnapshots = hypervDomainListAllSnapshots, /* 12.2.0 */
     .domainSnapshotNum = hypervDomainSnapshotNum, /* 12.2.0 */
+    .domainSnapshotGetXMLDesc = hypervDomainSnapshotGetXMLDesc, /* 12.2.0 */
 };
 
 
-- 
2.53.0

Reply via email to