Signed-off-by: Simon Kobyda <skobyda(a)redhat.com>
---
data/org.libvirt.Domain.xml | 26 ++++
data/org.libvirt.DomainSnapshot.xml | 34 +++++
src/domain.c | 158 +++++++++++++++++++++
src/domainsnapshot.c | 205 +++++++++++++++++++++++++++-
tests/libvirttest.py | 14 ++
tests/meson.build | 1 +
tests/test_domain.py | 8 ++
tests/test_snapshot.py | 43 ++++++
tests/xmldata.py | 6 +
9 files changed, 494 insertions(+), 1 deletion(-)
create mode 100755 tests/test_snapshot.py
diff --git a/data/org.libvirt.Domain.xml b/data/org.libvirt.Domain.xml
index b4ed495..f03faf8 100644
--- a/data/org.libvirt.Domain.xml
+++ b/data/org.libvirt.Domain.xml
@@ -350,6 +350,12 @@
<arg name="flags" type="u" direction="in"/>
<arg name="ifaces" type="a(ssa(isu))"
direction="out"/>
</method>
+ <method name="ListDomainSnapshots">
+ <annotation name="org.gtk.GDBus.DocString"
+ value="See
https://libvirt.org/html/libvirt-libvirt-domain-snapshot.html#virDomainLi...
+ <arg name="flags" type="u" direction="in"/>
+ <arg name="snaps" type="ao" direction="out"/>
+ </method>
<method name="ManagedSave">
<annotation name="org.gtk.GDBus.DocString"
value="See
https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainManagedSave...
@@ -589,6 +595,26 @@
value="See
https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainShutdownFla...
<arg name="flags" type="u" direction="in"/>
</method>
+ <method name="SnapshotCurrent">
+ <annotation name="org.gtk.GDBus.DocString"
+ value="See
https://libvirt.org/html/libvirt-libvirt-domain-snapshot.html#virDomainSn...
+ <arg name="flags" type="u" direction="in"/>
+ <arg name="domainSnapshot" type="o"
direction="out"/>
+ </method>
+ <method name="SnapshotCreateXML">
+ <annotation name="org.gtk.GDBus.DocString"
+ value="See
https://libvirt.org/html/libvirt-libvirt-domain-snapshot.html#virDomainSn...
+ <arg name="xml" type="s" direction="in"/>
+ <arg name="flags" type="u" direction="in"/>
+ <arg name="domainSnapshot" type="o"
direction="out"/>
+ </method>
+ <method name="SnapshotLookupByName">
+ <annotation name="org.gtk.GDBus.DocString"
+ value="See
https://libvirt.org/html/libvirt-libvirt-domain-snapshot.html#virDomainSn...
+ <arg name="name" type="s" direction="in"/>
+ <arg name="flags" type="u" direction="in"/>
+ <arg name="domainSnapshot" type="o"
direction="out"/>
+ </method>
<method name="Suspend">
<annotation name="org.gtk.GDBus.DocString"
value="See
https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainSuspend&quo...
diff --git a/data/org.libvirt.DomainSnapshot.xml b/data/org.libvirt.DomainSnapshot.xml
index 80f61c6..463654f 100644
--- a/data/org.libvirt.DomainSnapshot.xml
+++ b/data/org.libvirt.DomainSnapshot.xml
@@ -3,5 +3,39 @@
<node name="/org/libvirt/snapshot">
<interface name="org.libvirt.DomainSnapshot">
+ <method name="Delete">
+ <annotation name="org.gtk.GDBus.DocString"
+ value="See
https://libvirt.org/html/libvirt-libvirt-domain-snapshot.html#virDomainSn...
+ <arg name="flags" type="u" direction="in"/>
+ </method>
+ <method name="GetParent">
+ <annotation name="org.gtk.GDBus.DocString"
+ value="See
https://libvirt.org/html/libvirt-libvirt-domain-snapshot.html#virDomainSn...
+ <arg name="flags" type="u" direction="in"/>
+ <arg name="parent" type="o" direction="out"/>
+ </method>
+ <method name="GetXMLDesc">
+ <annotation name="org.gtk.GDBus.DocString"
+ value="See
https://libvirt.org/html/libvirt-libvirt-domain-snapshot.html#virDomainSn...
+ <arg name="flags" type="u" direction="in"/>
+ <arg name="xml" type="s" direction="out"/>
+ </method>
+ <method name="IsCurrent">
+ <annotation name="org.gtk.GDBus.DocString"
+ value="See
https://libvirt.org/html/libvirt-libvirt-domain-snapshot.html#virDomainSn...
+ <arg name="flags" type="u" direction="in"/>
+ <arg name="current" type="b" direction="out"/>
+ </method>
+ <method name="ListChildren">
+ <annotation name="org.gtk.GDBus.DocString"
+ value="See
https://libvirt.org/html/libvirt-libvirt-domain-snapshot.html#virDomainSn...
+ <arg name="flags" type="u" direction="in"/>
+ <arg name="snaps" type="ao" direction="out"/>
+ </method>
+ <method name="Revert">
+ <annotation name="org.gtk.GDBus.DocString"
+ value="See
https://libvirt.org/html/libvirt-libvirt-domain-snapshot.html#virDomainRe...
+ <arg name="flags" type="u" direction="in"/>
+ </method>
</interface>
</node>
diff --git a/src/domain.c b/src/domain.c
index 10fa8de..3fc5bab 100644
--- a/src/domain.c
+++ b/src/domain.c
@@ -1857,6 +1857,50 @@ virtDBusDomainInjectNMI(GVariant *inArgs,
virtDBusUtilSetLastVirtError(error);
}
+static void
+virtDBusDomainListDomainSnapshots(GVariant *inArgs,
+ GUnixFDList *inFDs G_GNUC_UNUSED,
+ const gchar *objectPath,
+ gpointer userData,
+ GVariant **outArgs G_GNUC_UNUSED,
+ GUnixFDList **outFDs G_GNUC_UNUSED,
+ GError **error)
+{
+ virtDBusConnect *connect = userData;
+ g_autoptr(virDomain) domain = NULL;
+ g_autoptr(virDomainSnapshotPtr) domainSnapshots = NULL;
+ guint flags;
+ GVariantBuilder builder;
+ GVariant *gdomainSnapshots;
+
+ g_variant_get(inArgs, "(u)", &flags);
+
+ domain = virtDBusDomainGetVirDomain(connect, objectPath,
+ error);
+ if (!domain)
+ return;
+
+ if (!virtDBusConnectOpen(connect, error))
+ return;
+
+ if (virDomainListAllSnapshots(domain, &domainSnapshots, flags) < 0)
+ return virtDBusUtilSetLastVirtError(error);
+
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("ao"));
+
+ for (gint i = 0; domainSnapshots[i]; i++) {
+ g_autofree gchar *path = NULL;
+ path = virtDBusUtilBusPathForVirDomainSnapshot(domain,
+ domainSnapshots[i],
+ connect->domainSnapshotPath);
+
+ g_variant_builder_add(&builder, "o", path);
+ }
+
+ gdomainSnapshots = g_variant_builder_end(&builder);
+ *outArgs = g_variant_new_tuple(&gdomainSnapshots, 1);
+}
+
static void
virtDBusDomainInterfaceAddresses(GVariant *inArgs,
GUnixFDList *inFDs G_GNUC_UNUSED,
@@ -2966,6 +3010,116 @@ virtDBusDomainShutdown(GVariant *inArgs,
virtDBusUtilSetLastVirtError(error);
}
+static void
+virtDBusDomainSnapshotCurrent(GVariant *inArgs,
+ GUnixFDList *inFDs G_GNUC_UNUSED,
+ const gchar *objectPath,
+ gpointer userData,
+ GVariant **outArgs G_GNUC_UNUSED,
+ GUnixFDList **outFDs G_GNUC_UNUSED,
+ GError **error)
+{
+ virtDBusConnect *connect = userData;
+ g_autofree gchar *path = NULL;
+ g_autoptr(virDomain) domain = NULL;
+ g_autoptr(virDomainSnapshot) snapshot = NULL;
+ guint flags;
+
+ g_variant_get(inArgs, "(u)", &flags);
+
+ domain = virtDBusDomainGetVirDomain(connect, objectPath,
+ error);
+ if (!domain)
+ return;
+
+ if (!virtDBusConnectOpen(connect, error))
+ return;
+
+ snapshot = virDomainSnapshotCurrent(domain, flags);
+ if (!snapshot)
+ return virtDBusUtilSetLastVirtError(error);
+
+ path = virtDBusUtilBusPathForVirDomainSnapshot(domain,
+ snapshot,
+ connect->domainSnapshotPath);
+
+ *outArgs = g_variant_new("(o)", path);
+}
+
+static void
+virtDBusDomainSnapshotCreateXML(GVariant *inArgs,
+ GUnixFDList *inFDs G_GNUC_UNUSED,
+ const gchar *objectPath,
+ gpointer userData,
+ GVariant **outArgs G_GNUC_UNUSED,
+ GUnixFDList **outFDs G_GNUC_UNUSED,
+ GError **error)
+{
+ virtDBusConnect *connect = userData;
+ g_autofree gchar *path = NULL;
+ g_autoptr(virDomain) domain = NULL;
+ g_autoptr(virDomainSnapshot) snapshot = NULL;
+ guint flags;
+ const gchar *xml;
+
+ g_variant_get(inArgs, "(su)", &xml, &flags);
+
+ domain = virtDBusDomainGetVirDomain(connect, objectPath,
+ error);
+ if (!domain)
+ return;
+
+ if (!virtDBusConnectOpen(connect, error))
+ return;
+
+ snapshot = virDomainSnapshotCreateXML(domain, xml, flags);
+ if (!snapshot)
+ return virtDBusUtilSetLastVirtError(error);
+
+ path = virtDBusUtilBusPathForVirDomainSnapshot(domain,
+ snapshot,
+ connect->domainSnapshotPath);
+
+ *outArgs = g_variant_new("(o)", path);
+}
+
+static void
+virtDBusDomainSnapshotLookupByName(GVariant *inArgs,
+ GUnixFDList *inFDs G_GNUC_UNUSED,
+ const gchar *objectPath,
+ gpointer userData,
+ GVariant **outArgs G_GNUC_UNUSED,
+ GUnixFDList **outFDs G_GNUC_UNUSED,
+ GError **error)
+{
+ virtDBusConnect *connect = userData;
+ g_autofree gchar *path = NULL;
+ g_autoptr(virDomain) domain = NULL;
+ g_autoptr(virDomainSnapshot) snapshot = NULL;
+ guint flags;
+ const gchar *name;
+
+ g_variant_get(inArgs, "(su)", &name, &flags);
+
+ domain = virtDBusDomainGetVirDomain(connect, objectPath,
+ error);
+ if (!domain)
+ return;
+
+ if (!virtDBusConnectOpen(connect, error))
+ return;
+
+ snapshot = virDomainSnapshotLookupByName(domain, name, flags);
+ if (!snapshot)
+ return virtDBusUtilSetLastVirtError(error);
+
+ path = virtDBusUtilBusPathForVirDomainSnapshot(domain,
+ snapshot,
+ connect->domainSnapshotPath);
+
+ *outArgs = g_variant_new("(o)", path);
+}
+
static void
virtDBusDomainSuspend(GVariant *inArgs G_GNUC_UNUSED,
GUnixFDList *inFDs G_GNUC_UNUSED,
@@ -3095,6 +3249,7 @@ static virtDBusGDBusMethodTable virtDBusDomainMethodTable[] = {
{ "HasManagedSaveImage", virtDBusDomainHasManagedSaveImage },
{ "InjectNMI", virtDBusDomainInjectNMI },
{ "InterfaceAddresses", virtDBusDomainInterfaceAddresses },
+ { "ListDomainSnapshots", virtDBusDomainListDomainSnapshots },
{ "ManagedSave", virtDBusDomainManagedSave },
{ "ManagedSaveRemove", virtDBusDomainManagedSaveRemove },
{ "MemoryPeek", virtDBusDomainMemoryPeek },
@@ -3132,6 +3287,9 @@ static virtDBusGDBusMethodTable virtDBusDomainMethodTable[] = {
{ "SetSchedulerParameters", virtDBusDomainSetSchedulerParameters },
{ "SetTime", virtDBusDomainSetTime },
{ "SetUserPassword", virtDBusDomainSetUserPassword },
+ { "SnapshotCurrent", virtDBusDomainSnapshotCurrent },
+ { "SnapshotCreateXML", virtDBusDomainSnapshotCreateXML },
+ { "SnapshotLookupByName", virtDBusDomainSnapshotLookupByName },
{ "Shutdown", virtDBusDomainShutdown },
{ "Suspend", virtDBusDomainSuspend },
{ "Undefine", virtDBusDomainUndefine },
diff --git a/src/domainsnapshot.c b/src/domainsnapshot.c
index 590cbef..3f5f5a3 100644
--- a/src/domainsnapshot.c
+++ b/src/domainsnapshot.c
@@ -1,14 +1,217 @@
#include "domainsnapshot.h"
+#include "domain.h"
#include "util.h"
#include <libvirt/libvirt.h>
+static void
+virtDBusDomainSnapshotDelete(GVariant *inArgs,
+ GUnixFDList *inFDs G_GNUC_UNUSED,
+ const gchar *objectPath,
+ gpointer userData,
+ GVariant **outArgs G_GNUC_UNUSED,
+ GUnixFDList **outFDs G_GNUC_UNUSED,
+ GError **error)
+{
+ virtDBusConnect *connect = userData;
+ g_autoptr(virDomainSnapshot) domainSnapshot = NULL;
+ guint flags;
+
+ g_variant_get(inArgs, "(u)", &flags);
+
+ domainSnapshot = virtDBusUtilVirDomainSnapshotFromBusPath(connect->connection,
+ objectPath,
+
connect->domainSnapshotPath);
+ if (!domainSnapshot)
+ return;
+
+ if (virDomainSnapshotDelete(domainSnapshot, flags) < 0)
+ return virtDBusUtilSetLastVirtError(error);
+}
+
+static void
+virtDBusDomainSnapshotGetParent(GVariant *inArgs,
+ GUnixFDList *inFDs G_GNUC_UNUSED,
+ const gchar *objectPath,
+ gpointer userData,
+ GVariant **outArgs G_GNUC_UNUSED,
+ GUnixFDList **outFDs G_GNUC_UNUSED,
+ GError **error)
+{
+ virtDBusConnect *connect = userData;
+ g_autoptr(virDomainSnapshot) domainSnapshot = NULL;
+ g_autoptr(virDomainSnapshot) parent = NULL;
+ guint flags;
+ g_autofree gchar *domainName = NULL;
+ g_autoptr(virDomain) domain = NULL;
+ gsize prefixLen = strlen(connect->domainSnapshotPath) + 1;
+ gchar** strings = g_strsplit(objectPath + prefixLen, "_", 2);
+ g_autofree gchar *parentPath = NULL;
+
+ g_variant_get(inArgs, "(u)", &flags);
+
+ domainSnapshot = virtDBusUtilVirDomainSnapshotFromBusPath(connect->connection,
+ objectPath,
+
connect->domainSnapshotPath);
+ if (!domainSnapshot)
+ return;
+
+ parent = virDomainSnapshotGetParent(domainSnapshot, flags);
+ if (!parent)
+ return virtDBusUtilSetLastVirtError(error);
+
+ domainName = virtDBusUtilDecodeStr(strings[0]);
+ domain = virDomainLookupByName(connect->connection, domainName);
+ parentPath = virtDBusUtilBusPathForVirDomainSnapshot(domain,
+ parent,
+
connect->domainSnapshotPath);
+
+ *outArgs = g_variant_new("(o)", parentPath);
+}
+
+static void
+virtDBusDomainSnapshotGetXMLDesc(GVariant *inArgs,
+ GUnixFDList *inFDs G_GNUC_UNUSED,
+ const gchar *objectPath,
+ gpointer userData,
+ GVariant **outArgs G_GNUC_UNUSED,
+ GUnixFDList **outFDs G_GNUC_UNUSED,
+ GError **error)
+{
+ virtDBusConnect *connect = userData;
+ g_autoptr(virDomainSnapshot) domainSnapshot = NULL;
+ guint flags;
+ g_autofree gchar *xml = NULL;
+
+ g_variant_get(inArgs, "(u)", &flags);
+
+ domainSnapshot = virtDBusUtilVirDomainSnapshotFromBusPath(connect->connection,
+ objectPath,
+
connect->domainSnapshotPath);
+ if (!domainSnapshot)
+ return;
+
+ xml = virDomainSnapshotGetXMLDesc(domainSnapshot, flags);
+ if (!xml)
+ return virtDBusUtilSetLastVirtError(error);
+
+ *outArgs = g_variant_new("(s)", xml);
+}
+
+static void
+virtDBusDomainSnapshotIsCurrent(GVariant *inArgs,
+ GUnixFDList *inFDs G_GNUC_UNUSED,
+ const gchar *objectPath,
+ gpointer userData,
+ GVariant **outArgs G_GNUC_UNUSED,
+ GUnixFDList **outFDs G_GNUC_UNUSED,
+ GError **error)
+{
+ virtDBusConnect *connect = userData;
+ g_autoptr(virDomainSnapshot) domainSnapshot = NULL;
+ guint flags;
+ gint isCurrent;
+
+ g_variant_get(inArgs, "(u)", &flags);
+
+ domainSnapshot = virtDBusUtilVirDomainSnapshotFromBusPath(connect->connection,
+ objectPath,
+
connect->domainSnapshotPath);
+ if (!domainSnapshot)
+ return;
+
+ isCurrent = virDomainSnapshotIsCurrent(domainSnapshot, flags);
+ if (isCurrent < 0)
+ return virtDBusUtilSetLastVirtError(error);
+
+ *outArgs = g_variant_new("(b)", !!isCurrent);
+}
+
+static void
+virtDBusDomainSnapshotListAllChildren(GVariant *inArgs,
+ GUnixFDList *inFDs G_GNUC_UNUSED,
+ const gchar *objectPath,
+ gpointer userData,
+ GVariant **outArgs G_GNUC_UNUSED,
+ GUnixFDList **outFDs G_GNUC_UNUSED,
+ GError **error)
+{
+ virtDBusConnect *connect = userData;
+ g_autoptr(virDomainSnapshot) domainSnapshot = NULL;
+ g_autoptr(virDomainSnapshotPtr) snaps = NULL;
+ guint flags;
+ GVariantBuilder builder;
+ GVariant *gdomainSnapshots;
+ g_autofree gchar *domainName = NULL;
+ g_autoptr(virDomain) domain = NULL;
+ gsize prefixLen = strlen(connect->domainSnapshotPath) + 1;
+ gchar** strings = g_strsplit(objectPath + prefixLen, "_", 2);
+
+ g_variant_get(inArgs, "(u)", &flags);
+
+ domainSnapshot = virtDBusUtilVirDomainSnapshotFromBusPath(connect->connection,
+ objectPath,
+
connect->domainSnapshotPath);
+ if (!domainSnapshot)
+ return;
+
+ if (virDomainSnapshotListAllChildren(domainSnapshot, &snaps, flags) < 0)
+ return virtDBusUtilSetLastVirtError(error);
+
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("ao"));
+
+ domainName = virtDBusUtilDecodeStr(strings[0]);
+ domain = virDomainLookupByName(connect->connection, domainName);
+ for (gint i = 0; snaps[i]; i++) {
+ g_autofree gchar *path = NULL;
+ path = virtDBusUtilBusPathForVirDomainSnapshot(domain,
+ snaps[i],
+ connect->domainSnapshotPath);
+
+ g_variant_builder_add(&builder, "o", path);
+ }
+
+ gdomainSnapshots = g_variant_builder_end(&builder);
+ *outArgs = g_variant_new_tuple(&gdomainSnapshots, 1);
+}
+
+static void
+virtDBusDomainSnapshotRevert(GVariant *inArgs,
+ GUnixFDList *inFDs G_GNUC_UNUSED,
+ const gchar *objectPath,
+ gpointer userData,
+ GVariant **outArgs G_GNUC_UNUSED,
+ GUnixFDList **outFDs G_GNUC_UNUSED,
+ GError **error)
+{
+ virtDBusConnect *connect = userData;
+ g_autoptr(virDomainSnapshot) domainSnapshot = NULL;
+ guint flags;
+
+ g_variant_get(inArgs, "(u)", &flags);
+
+ domainSnapshot = virtDBusUtilVirDomainSnapshotFromBusPath(connect->connection,
+ objectPath,
+
connect->domainSnapshotPath);
+ if (!domainSnapshot)
+ return;
+
+ if (virDomainRevertToSnapshot(domainSnapshot, flags) < 0)
+ return virtDBusUtilSetLastVirtError(error);
+}
+
static virtDBusGDBusPropertyTable virtDBusDomainSnapshotPropertyTable[] = {
{ 0 }
};
static virtDBusGDBusMethodTable virtDBusDomainSnapshotMethodTable[] = {
- { 0 }
+ { "Delete", virtDBusDomainSnapshotDelete },
+ { "GetParent", virtDBusDomainSnapshotGetParent },
+ { "GetXMLDesc", virtDBusDomainSnapshotGetXMLDesc },
+ /* Needs to be method since it takes 'flags' parameter */
+ { "IsCurrent", virtDBusDomainSnapshotIsCurrent },
+ { "ListChildren", virtDBusDomainSnapshotListAllChildren },
+ { "Revert", virtDBusDomainSnapshotRevert },
};
static gchar **
diff --git a/tests/libvirttest.py b/tests/libvirttest.py
index a442196..8462fc3 100644
--- a/tests/libvirttest.py
+++ b/tests/libvirttest.py
@@ -112,6 +112,20 @@ class BaseTestClass():
"""
return self.node_device_create()
+ @pytest.fixture
+ def snapshot_create(self):
+ """ Fixture to create simple snapshot the test driver
+
+ This fixture should be used in the setup of every test manipulating
+ with snaphots.
+ """
+ _, test_domain = self.get_test_domain()
+ interface_obj = dbus.Interface(test_domain, 'org.libvirt.Domain')
+ path = interface_obj.SnapshotCreateXML(xmldata.minimal_snapshot_xml, 0)
+ obj = self.bus.get_object('org.libvirt', path)
+ interface_obj = dbus.Interface(obj, 'org.libvirt.DomainSnapshot')
+ return interface_obj
+
@pytest.fixture
def storage_volume_create(self):
""" Fixture to create dummy storage volume on the test driver
diff --git a/tests/meson.build b/tests/meson.build
index b6d4bd5..0ad5cdb 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -22,6 +22,7 @@ test('test_util', test_exec, suite: 'unit')
python_tests = [
'test_connect.py',
'test_domain.py',
+ 'test_snapshot.py',
'test_interface.py',
'test_network.py',
'test_nodedev.py',
diff --git a/tests/test_domain.py b/tests/test_domain.py
index b5879b4..fdb5aa4 100755
--- a/tests/test_domain.py
+++ b/tests/test_domain.py
@@ -2,6 +2,7 @@
import dbus
import libvirttest
+import xmldata
DBUS_EXCEPTION_MISSING_FUNCTION = 'this function is not supported by the connection
driver'
@@ -160,6 +161,13 @@ class TestDomain(libvirttest.BaseTestClass):
pinInfo = domain.GetVcpuPinInfo(0)
assert pinInfo == pinInfo_expected
+ def test_snapshot(self):
+ obj, domain = self.get_test_domain()
+ domain.SnapshotCreateXML(xmldata.minimal_snapshot_xml, 0)
+ assert isinstance(domain.SnapshotCurrent(0), dbus.ObjectPath)
+ assert isinstance(domain.SnapshotLookupByName("my_snapshot", 0),
dbus.ObjectPath)
+ assert isinstance(domain.ListDomainSnapshots(0), dbus.Array)
if __name__ == '__main__':
libvirttest.run()
+
diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py
new file mode 100755
index 0000000..e9cc5b9
--- /dev/null
+++ b/tests/test_snapshot.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+
+import dbus
+import libvirttest
+import pytest
+
+EXCEPTION_NO_PARENT = 'does not have a parent'
+
+(a)pytest.mark.usefixtures("snapshot_create")
+class TestSnapshot(libvirttest.BaseTestClass):
+ """ Tests for methods and properties of the Snapshot snapshot
+ """
+
+ def test_snapshot_delete(self, snapshot_create):
+ snapshot_obj = snapshot_create
+ snapshot_obj.Delete(0)
+
+ def test_snapshot_get_parent(self, snapshot_create):
+ snapshot_obj = snapshot_create
+ try:
+ snapshot_obj.GetParent(0)
+ except dbus.exceptions.DBusException as e:
+ if not any(EXCEPTION_NO_PARENT in arg for arg in e.args):
+ raise e
+
+ def test_snapshot_get_xml(self, snapshot_create):
+ snapshot_obj = snapshot_create
+ assert isinstance(snapshot_obj.GetXMLDesc(0), dbus.String)
+
+ def test_snapshot_get_is_current(self, snapshot_create):
+ snapshot_obj = snapshot_create
+ assert isinstance(snapshot_obj.IsCurrent(0), dbus.Boolean)
+
+ def test_snapshot_list_children(self, snapshot_create):
+ snapshot_obj = snapshot_create
+ assert isinstance(snapshot_obj.ListChildren(0), dbus.Array)
+
+ def test_snapshot_revert(self, snapshot_create):
+ snapshot_obj = snapshot_create
+ snapshot_obj.Revert(0)
+
+if __name__ == '__main__':
+ libvirttest.run()
diff --git a/tests/xmldata.py b/tests/xmldata.py
index 8075052..0146ccf 100644
--- a/tests/xmldata.py
+++ b/tests/xmldata.py
@@ -54,6 +54,12 @@ minimal_node_device_xml = '''
</device>
'''
+minimal_snapshot_xml = '''
+<domainsnapshot>
+ <name>my_snapshot</name>
+</domainsnapshot>
+'''
+
minimal_storage_pool_xml = '''
<pool type='dir'>
<name>foo</name>
--
2.21.0