Signed-off-by: Simon Kobyda <skobyda@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list