Signed-off-by: Simon Kobyda <skobyda(a)redhat.com>
---
data/Makefile.am | 1 +
data/org.libvirt.DomainSnapshot.xml | 7 +++
src/Makefile.am | 2 +
src/connect.c | 6 +++
src/connect.h | 1 +
src/domainsnapshot.c | 79 +++++++++++++++++++++++++++++
src/domainsnapshot.h | 9 ++++
src/util.c | 47 +++++++++++++++++
src/util.h | 16 ++++++
9 files changed, 168 insertions(+)
create mode 100644 data/org.libvirt.DomainSnapshot.xml
create mode 100644 src/domainsnapshot.c
create mode 100644 src/domainsnapshot.h
diff --git a/data/Makefile.am b/data/Makefile.am
index f8311bd..5617c78 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -33,6 +33,7 @@ polkit_DATA = \
interfaces_files = \
org.libvirt.Connect.xml \
org.libvirt.Domain.xml \
+ org.libvirt.DomainSnapshot.xml \
org.libvirt.Interface.xml \
org.libvirt.Network.xml \
org.libvirt.NodeDevice.xml \
diff --git a/data/org.libvirt.DomainSnapshot.xml b/data/org.libvirt.DomainSnapshot.xml
new file mode 100644
index 0000000..80f61c6
--- /dev/null
+++ b/data/org.libvirt.DomainSnapshot.xml
@@ -0,0 +1,7 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection
1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<node name="/org/libvirt/snapshot">
+ <interface name="org.libvirt.DomainSnapshot">
+ </interface>
+</node>
diff --git a/src/Makefile.am b/src/Makefile.am
index 845696e..a78bac8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -37,6 +37,8 @@ libvirt_dbus_SOURCES = \
connect.h \
domain.c \
domain.h \
+ domainsnapshot.c \
+ domainsnapshot.h \
events.c \
events.h \
gdbus.c \
diff --git a/src/connect.c b/src/connect.c
index f8f76a2..b40b0ba 100644
--- a/src/connect.c
+++ b/src/connect.c
@@ -1,5 +1,6 @@
#include "connect.h"
#include "domain.h"
+#include "domainsnapshot.h"
#include "events.h"
#include "interface.h"
#include "network.h"
@@ -2002,6 +2003,7 @@ virtDBusConnectFree(virtDBusConnect *connect)
virtDBusConnectClose(connect, TRUE);
g_free(connect->domainPath);
+ g_free(connect->domainSnapshotPath);
g_free(connect->interfacePath);
g_free(connect->networkPath);
g_free(connect->nodeDevPath);
@@ -2062,6 +2064,10 @@ virtDBusConnectNew(virtDBusConnect **connectp,
if (error && *error)
return;
+ virtDBusDomainSnapshotRegister(connect, error);
+ if (error && *error)
+ return;
+
virtDBusInterfaceRegister(connect, error);
if (error && *error)
return;
diff --git a/src/connect.h b/src/connect.h
index 829bd57..74c89cf 100644
--- a/src/connect.h
+++ b/src/connect.h
@@ -13,6 +13,7 @@ struct virtDBusConnect {
const gchar *uri;
const gchar *connectPath;
gchar *domainPath;
+ gchar *domainSnapshotPath;
gchar *interfacePath;
gchar *networkPath;
gchar *nodeDevPath;
diff --git a/src/domainsnapshot.c b/src/domainsnapshot.c
new file mode 100644
index 0000000..590cbef
--- /dev/null
+++ b/src/domainsnapshot.c
@@ -0,0 +1,79 @@
+#include "domainsnapshot.h"
+#include "util.h"
+
+#include <libvirt/libvirt.h>
+
+static virtDBusGDBusPropertyTable virtDBusDomainSnapshotPropertyTable[] = {
+ { 0 }
+};
+
+static virtDBusGDBusMethodTable virtDBusDomainSnapshotMethodTable[] = {
+ { 0 }
+};
+
+static gchar **
+virtDBusDomainSnapshotEnumerate(gpointer userData)
+{
+ virtDBusConnect *connect = userData;
+ g_autoptr(virDomainPtr) domains = NULL;
+ gint numDoms = 0;
+ GPtrArray *list = NULL;
+
+ if (!virtDBusConnectOpen(connect, NULL))
+ return NULL;
+
+ numDoms = virConnectListAllDomains(connect->connection, &domains, 0);
+ if (numDoms <= 0)
+ return NULL;
+
+ list = g_ptr_array_new();
+
+ for (gint i = 0; i < numDoms; i++) {
+ g_autoptr(virDomainSnapshotPtr) domainSnapshots = NULL;
+ gint numSnaps;
+
+ numSnaps = virDomainListAllSnapshots(domains[i], &domainSnapshots, 0);
+ if (numSnaps <= 0)
+ continue;
+
+ for (gint j = 0; j < numSnaps; j++) {
+ gchar *snapPath = virtDBusUtilBusPathForVirDomainSnapshot(domains[i],
+
domainSnapshots[j],
+
connect->domainSnapshotPath);
+ g_ptr_array_add(list, snapPath);
+ }
+ }
+
+ gchar **ret = g_new0(gchar *, numDoms + 1);
+
+ for (gint i = 0; i < numDoms; i++) {
+ ret[i] = virtDBusUtilBusPathForVirDomain(domains[i],
+ connect->domainPath);
+ }
+
+ return ret;
+}
+
+static GDBusInterfaceInfo *interfaceInfo = NULL;
+
+void
+virtDBusDomainSnapshotRegister(virtDBusConnect *connect,
+ GError **error)
+{
+ connect->domainSnapshotPath = g_strdup_printf("%s/snapshot",
connect->connectPath);
+
+ if (!interfaceInfo) {
+ interfaceInfo =
virtDBusGDBusLoadIntrospectData(VIRT_DBUS_DOMAIN_SNAPSHOT_INTERFACE,
+ error);
+ if (!interfaceInfo)
+ return;
+ }
+
+ virtDBusGDBusRegisterSubtree(connect->bus,
+ connect->domainSnapshotPath,
+ interfaceInfo,
+ virtDBusDomainSnapshotEnumerate,
+ virtDBusDomainSnapshotMethodTable,
+ virtDBusDomainSnapshotPropertyTable,
+ connect);
+}
diff --git a/src/domainsnapshot.h b/src/domainsnapshot.h
new file mode 100644
index 0000000..7d8a938
--- /dev/null
+++ b/src/domainsnapshot.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "connect.h"
+
+#define VIRT_DBUS_DOMAIN_SNAPSHOT_INTERFACE "org.libvirt.DomainSnapshot"
+
+void
+virtDBusDomainSnapshotRegister(virtDBusConnect *connect,
+ GError **error);
diff --git a/src/util.c b/src/util.c
index 103bb29..2be616c 100644
--- a/src/util.c
+++ b/src/util.c
@@ -279,6 +279,53 @@ virtDBusUtilVirDomainListFree(virDomainPtr *domains)
g_free(domains);
}
+virDomainSnapshotPtr
+virtDBusUtilVirDomainSnapshotFromBusPath(virConnectPtr connection,
+ const gchar *path,
+ const gchar *domainSnapshotPath)
+{
+ g_autofree gchar *domainName = NULL;
+ g_autofree gchar *snapshotName = NULL;
+ g_autoptr(virDomain) domain = NULL;
+ gsize prefixLen = strlen(domainSnapshotPath) + 1;
+ gchar** strings = g_strsplit(path + prefixLen, "_", 2);
+
+ domainName = virtDBusUtilDecodeStr(strings[0]);
+ snapshotName = virtDBusUtilDecodeStr(strings[1]);
+
+ domain = virDomainLookupByName(connection, domainName);
+
+ return virDomainSnapshotLookupByName(domain, snapshotName, 0); // TODO flags for
external?
+}
+
+gchar *
+virtDBusUtilBusPathForVirDomainSnapshot(virDomainPtr domain,
+ virDomainSnapshotPtr domainSnapshot,
+ const gchar *domainSnapshotPath)
+{
+ const gchar *snapshotName = NULL;
+ const gchar *domainName = NULL;
+ g_autofree const gchar *encodedDomainNameStr = NULL;
+ g_autofree const gchar *encodedSnapshotNameStr = NULL;
+
+ domainName = virDomainGetName(domain);
+ snapshotName = virDomainSnapshotGetName(domainSnapshot);
+ encodedDomainNameStr = virtDBusUtilEncodeStr(domainName);
+ encodedSnapshotNameStr = virtDBusUtilEncodeStr(snapshotName);
+
+ return g_strdup_printf("%s/%s_%s", domainSnapshotPath,
+ encodedDomainNameStr, encodedSnapshotNameStr);
+}
+
+void
+virtDBusUtilVirDomainSnapshotListFree(virDomainSnapshotPtr* domainSnapshots)
+{
+ for (gint i = 0; domainSnapshots[i] != NULL; i++)
+ virDomainSnapshotFree(domainSnapshots[i]);
+
+ g_free(domainSnapshots);
+}
+
virInterfacePtr
virtDBusUtilVirInterfaceFromBusPath(virConnectPtr connection,
const gchar *path,
diff --git a/src/util.h b/src/util.h
index b05c2fc..c0b314d 100644
--- a/src/util.h
+++ b/src/util.h
@@ -65,6 +65,22 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainPtr,
virtDBusUtilVirDomainListFree);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainStatsRecordPtr, virDomainStatsRecordListFree);
+virDomainSnapshotPtr
+virtDBusUtilVirDomainSnapshotFromBusPath(virConnectPtr connection,
+ const gchar *path,
+ const gchar *domainSnapshotPath);
+
+gchar *
+virtDBusUtilBusPathForVirDomainSnapshot(virDomainPtr domain,
+ virDomainSnapshotPtr domainSnapshot,
+ const gchar *domainSnapshotPath);
+
+void
+virtDBusUtilVirDomainSnapshotListFree(virDomainSnapshotPtr* domainSnapshots);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainSnapshot, virDomainSnapshotFree);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainSnapshotPtr,
virtDBusUtilVirDomainSnapshotListFree);
+
virInterfacePtr
virtDBusUtilVirInterfaceFromBusPath(virConnectPtr connection,
const gchar *path,
--
2.21.0