[libvirt] [libvirt-dbus][PATCH v3 2/2] Implement snapshots APIs

Pavel Hrdina phrdina at redhat.com
Thu Oct 24 13:51:21 UTC 2019


On Wed, Oct 23, 2019 at 01:11:46PM +0200, Simon Kobyda wrote:
> Signed-off-by: Simon Kobyda <skobyda at redhat.com>
> ---
>  data/org.libvirt.Domain.xml         |  26 ++++
>  data/org.libvirt.DomainSnapshot.xml |  34 +++++
>  src/domain.c                        | 154 ++++++++++++++++++++++
>  src/domainsnapshot.c                | 196 +++++++++++++++++++++++++++-
>  tests/libvirttest.py                |  12 ++
>  tests/meson.build                   |   1 +
>  tests/test_domain.py                |   8 ++
>  tests/test_snapshot.py              |  43 ++++++
>  tests/xmldata.py                    |   6 +
>  9 files changed, 479 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..3f108e7 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#virDomainListAllSnapshots"/>
> +      <arg name="flags" type="u" direction="in"/>
> +      <arg name="domainSnapshots" 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#virDomainShutdownFlags"/>
>        <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#virDomainSnapshotCurrent"/>
> +      <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#virDomainSnapshotCreateXML"/>
> +      <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#virDomainSnapshotLookupByName"/>
> +      <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"/>
> diff --git a/data/org.libvirt.DomainSnapshot.xml b/data/org.libvirt.DomainSnapshot.xml
> index 8ba059f..9e9daac 100644
> --- a/data/org.libvirt.DomainSnapshot.xml
> +++ b/data/org.libvirt.DomainSnapshot.xml
> @@ -3,5 +3,39 @@
>  
>  <node name="/org/libvirt/domainsnapshot">
>    <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#virDomainSnapshotDelete"/>
> +      <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#virDomainSnapshotGetParent"/>
> +      <arg name="flags" type="u" direction="in"/>
> +      <arg name="domainSnapshot" 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#virDomainSnapshotGetXMLDesc"/>
> +      <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#virDomainSnapshotIsCurrent"/>
> +      <arg name="flags" type="u" direction="in"/>
> +      <arg name="domainSnapshot" 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#virDomainSnapshotListAllChildren"/>
> +      <arg name="flags" type="u" direction="in"/>
> +      <arg name="domainSnapshots" 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#virDomainRevertToSnapshot"/>
> +      <arg name="flags" type="u" direction="in"/>
> +    </method>
>    </interface>
>  </node>
> diff --git a/src/domain.c b/src/domain.c
> index 10fa8de..a656c6a 100644
> --- a/src/domain.c
> +++ b/src/domain.c
> @@ -1857,6 +1857,49 @@ 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 +3009,113 @@ 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 +3245,7 @@ static virtDBusGDBusMethodTable virtDBusDomainMethodTable[] = {
>      { "HasManagedSaveImage", virtDBusDomainHasManagedSaveImage },
>      { "InjectNMI", virtDBusDomainInjectNMI },
>      { "InterfaceAddresses", virtDBusDomainInterfaceAddresses },
> +    { "ListDomainSnapshots", virtDBusDomainListDomainSnapshots },
>      { "ManagedSave", virtDBusDomainManagedSave },
>      { "ManagedSaveRemove", virtDBusDomainManagedSaveRemove },
>      { "MemoryPeek", virtDBusDomainMemoryPeek },
> @@ -3132,6 +3283,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 c523c9e..8e2cce0 100644
> --- a/src/domainsnapshot.c
> +++ b/src/domainsnapshot.c
> @@ -1,14 +1,208 @@
>  #include "domainsnapshot.h"
> +#include "domain.h"
>  #include "util.h"
>  
>  #include <libvirt/libvirt.h>

Here you have to implement virtDBusDomainSpanshotGetVirDomainSnapshot()
the same way how it's done for other objects to make sure that we have
a valid libvirt connection and to return libvirt error if
virtDBusUtilVirDomainSnapshotFromBusPath() function fails.

Check virtDBusStorageVolGetVirStorageVol as an example.

> +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_autoptr(virDomain) domain = NULL;
> +    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);
> +
> +    domain = virDomainSnapshotGetDomain(domainSnapshot);
> +    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_autoptr(virDomain) domain = NULL;
> +
> +    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"));
> +
> +    domain = virDomainSnapshotGetDomain(domainSnapshot);
> +    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 }

This has to stay as the last element of the table, it servers as a
termination element for a loop that is looking for a function to use.

> +    { "Delete", virtDBusDomainSnapshotDelete },
> +    { "GetParent", virtDBusDomainSnapshotGetParent },
> +    { "GetXMLDesc", virtDBusDomainSnapshotGetXMLDesc },
> +    { "IsCurrent", virtDBusDomainSnapshotIsCurrent },
> +    { "ListChildren", virtDBusDomainSnapshotListAllChildren },
> +    { "Revert", virtDBusDomainSnapshotRevert },
>  };
>  
>  static gchar **
> diff --git a/tests/libvirttest.py b/tests/libvirttest.py
> index a442196..dd181c2 100644
> --- a/tests/libvirttest.py
> +++ b/tests/libvirttest.py
> @@ -112,6 +112,18 @@ class BaseTestClass():
>          """
>          return self.node_device_create()
>  
> +    @pytest.fixture
> +    def snapshot_create(self):
> +        """ Fixture to create simple domain snapshot on the test driver
> +
> +        This fixture should be used in the setup of every test manipulating
> +        with domain snaphots.
> +        """
> +        _, test_domain = self.get_test_domain()
> +        path = test_domain.SnapshotCreateXML(xmldata.minimal_snapshot_xml, 0)
> +        obj = self.bus.get_object('org.libvirt', path)
> +        return dbus.Interface(obj, 'org.libvirt.DomainSnapshot')
> +
>      @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)
>  

E305 expected 2 blank lines after class or function definition, found 1

>  if __name__ == '__main__':
>      libvirttest.run()
> +

W391 blank line at end of file

> 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'
> +

E302 expected 2 blank lines, found 1

> + at 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)
> +

E305 expected 2 blank lines after class or function definition, found 1

Please install flake8 and run ninja -C build test before posting
patches.

Pavel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20191024/c479d619/attachment-0001.sig>


More information about the libvir-list mailing list