[libvirt] [RFC PATCH 02/10] add driver based implementation of backup API

Nikolay Shirokovskiy nshirokovskiy at virtuozzo.com
Mon Nov 14 07:14:54 UTC 2016


---
 
I wonder should I better name virDomainBackupCreateXML 
virDomainBackupStartPush as operation is asynchronous.

 include/libvirt/virterror.h |   2 +
 src/Makefile.am             |   2 +
 src/datatypes.c             |  24 ++++++
 src/datatypes.h             |  27 ++++++
 src/driver-hypervisor.h     |   6 ++
 src/libvirt-domain-backup.c | 203 ++++++++++++++++++++++++++++++++++++++++++++
 src/libvirt_private.syms    |   1 +
 src/libvirt_public.syms     |  10 +++
 src/util/virerror.c         |   6 ++
 9 files changed, 281 insertions(+)
 create mode 100644 src/libvirt-domain-backup.c

diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index efe83aa..bcd54bc 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -131,6 +131,7 @@ typedef enum {
     VIR_FROM_XENXL = 64,        /* Error from Xen xl config code */
 
     VIR_FROM_PERF = 65,         /* Error from perf */
+    VIR_FROM_DOMAIN_BACKUP = 66,/* Error from domain backup */
 
 # ifdef VIR_ENUM_SENTINELS
     VIR_ERR_DOMAIN_LAST
@@ -317,6 +318,7 @@ typedef enum {
     VIR_ERR_NO_CLIENT = 96,             /* Client was not found */
     VIR_ERR_AGENT_UNSYNCED = 97,        /* guest agent replies with wrong id
                                            to guest-sync command */
+    VIR_ERR_INVALID_DOMAIN_BACKUP = 98, /* invalid domain backup */
 } virErrorNumber;
 
 /**
diff --git a/src/Makefile.am b/src/Makefile.am
index 8ee5567..eb68728 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -219,6 +219,7 @@ DRIVER_SOURCES =							\
 		libvirt.c libvirt_internal.h				\
 		libvirt-domain.c 					\
 		libvirt-domain-snapshot.c 				\
+		libvirt-domain-backup.c 				\
 		libvirt-host.c 						\
 		libvirt-interface.c	 				\
 		libvirt-network.c	 				\
@@ -2390,6 +2391,7 @@ libvirt_setuid_rpc_client_la_SOURCES = 		\
 		libvirt.c			\
 		libvirt-domain.c		\
 		libvirt-domain-snapshot.c	\
+		libvirt-domain-backup.c	\
 		libvirt-host.c			\
 		libvirt-interface.c		\
 		libvirt-network.c		\
diff --git a/src/datatypes.c b/src/datatypes.c
index ff0c46f..b090b12 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -37,6 +37,7 @@ virClassPtr virConnectClass;
 virClassPtr virConnectCloseCallbackDataClass;
 virClassPtr virDomainClass;
 virClassPtr virDomainSnapshotClass;
+virClassPtr virDomainBackupClass;
 virClassPtr virInterfaceClass;
 virClassPtr virNetworkClass;
 virClassPtr virNodeDeviceClass;
@@ -50,6 +51,7 @@ static void virConnectDispose(void *obj);
 static void virConnectCloseCallbackDataDispose(void *obj);
 static void virDomainDispose(void *obj);
 static void virDomainSnapshotDispose(void *obj);
+static void virDomainBackupDispose(void *obj);
 static void virInterfaceDispose(void *obj);
 static void virNetworkDispose(void *obj);
 static void virNodeDeviceDispose(void *obj);
@@ -88,6 +90,7 @@ virDataTypesOnceInit(void)
     DECLARE_CLASS_LOCKABLE(virConnectCloseCallbackData);
     DECLARE_CLASS(virDomain);
     DECLARE_CLASS(virDomainSnapshot);
+    DECLARE_CLASS(virDomainBackup);
     DECLARE_CLASS(virInterface);
     DECLARE_CLASS(virNetwork);
     DECLARE_CLASS(virNodeDevice);
@@ -889,6 +892,27 @@ virDomainSnapshotDispose(void *obj)
 }
 
 
+/**
+ * virDomainBackupDispose:
+ * @obj: the domain backup to release
+ *
+ * Unconditionally release all memory associated with a backup.
+ * The backup object must not be used once this method returns.
+ *
+ * It will also unreference the associated connection object,
+ * which may also be released if its ref count hits zero.
+ */
+static void
+virDomainBackupDispose(void *obj)
+{
+    virDomainBackupPtr backup = obj;
+    VIR_DEBUG("release backup %p %s", backup, backup->name);
+
+    VIR_FREE(backup->name);
+    virObjectUnref(backup->domain);
+}
+
+
 virAdmConnectPtr
 virAdmConnectNew(void)
 {
diff --git a/src/datatypes.h b/src/datatypes.h
index 2b6adb4..59edda8 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -32,6 +32,7 @@
 extern virClassPtr virConnectClass;
 extern virClassPtr virDomainClass;
 extern virClassPtr virDomainSnapshotClass;
+extern virClassPtr virDomainBackupClass;
 extern virClassPtr virInterfaceClass;
 extern virClassPtr virNetworkClass;
 extern virClassPtr virNodeDeviceClass;
@@ -278,6 +279,21 @@ extern virClassPtr virAdmClientClass;
         }                                                               \
     } while (0)
 
+# define virCheckDomainBackupReturn(obj, retval)                        \
+    do {                                                                \
+        virDomainBackupPtr _back = (obj);                               \
+        if (!virObjectIsClass(_back, virDomainBackupClass) ||           \
+            !virObjectIsClass(_back->domain, virDomainClass) ||         \
+            !virObjectIsClass(_back->domain->conn, virConnectClass)) {  \
+            virReportErrorHelper(VIR_FROM_DOMAIN_BACKUP,                \
+                                 VIR_ERR_INVALID_DOMAIN_BACKUP,         \
+                                 __FILE__, __FUNCTION__, __LINE__,      \
+                                 __FUNCTION__);                         \
+            virDispatchError(NULL);                                     \
+            return retval;                                              \
+        }                                                               \
+    } while (0)
+
 
 /* Helper macros to implement VIR_DOMAIN_DEBUG using just C99.  This
  * assumes you pass fewer than 15 arguments to VIR_DOMAIN_DEBUG, but
@@ -661,6 +677,17 @@ struct _virNWFilter {
     unsigned char uuid[VIR_UUID_BUFLEN]; /* the network filter unique identifier */
 };
 
+/**
+ * _virDomainBackup
+ *
+ * Internal structure associated with a domain backup
+ */
+struct _virDomainBackup {
+    virObject object;
+    char *name;
+    virDomainPtr domain;
+};
+
 
 /*
  * Helper APIs for allocating new object instances
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index 51af732..5ea1dfd 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1251,6 +1251,11 @@ typedef int
                              int state,
                              unsigned int flags);
 
+typedef virDomainBackupPtr
+(*virDrvDomainBackupCreateXML)(virDomainPtr domain,
+                               const char *xmlDesc,
+                               unsigned int flags);
+
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
 
@@ -1489,6 +1494,7 @@ struct _virHypervisorDriver {
     virDrvDomainMigrateStartPostCopy domainMigrateStartPostCopy;
     virDrvDomainGetGuestVcpus domainGetGuestVcpus;
     virDrvDomainSetGuestVcpus domainSetGuestVcpus;
+    virDrvDomainBackupCreateXML domainBackupCreateXML;
 };
 
 
diff --git a/src/libvirt-domain-backup.c b/src/libvirt-domain-backup.c
new file mode 100644
index 0000000..f07f9cd
--- /dev/null
+++ b/src/libvirt-domain-backup.c
@@ -0,0 +1,203 @@
+/*
+ * libvirt-domain-backup.c: entry points for virDomainBackupPtr APIs
+
+ * Copyright (C) 2016 Virtuozzo
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "datatypes.h"
+#include "virlog.h"
+
+VIR_LOG_INIT("libvirt.domain-backup");
+
+#define VIR_FROM_THIS VIR_FROM_DOMAIN_BACKUP
+
+/**
+ * virDomainBackupGetName:
+ * @backup: a backup object
+ *
+ * Get the public name for that backup
+ *
+ * Returns a pointer to the name or NULL, the string need not be deallocated
+ * as its lifetime will be the same as the backup object.
+ */
+const char *
+virDomainBackupGetName(virDomainBackupPtr backup)
+{
+    VIR_DEBUG("backup=%p", backup);
+
+    virResetLastError();
+
+    virCheckDomainBackupReturn(backup, NULL);
+
+    return backup->name;
+}
+
+
+/**
+ * virDomainBackupGetDomain:
+ * @backup: a backup object
+ *
+ * Provides the domain pointer associated with a backup.  The
+ * reference counter on the domain is not increased by this
+ * call.
+ *
+ * WARNING: When writing libvirt bindings in other languages, do not use this
+ * function.  Instead, store the domain and the backup object together.
+ *
+ * Returns the domain or NULL.
+ */
+virDomainPtr
+virDomainBackupGetDomain(virDomainBackupPtr backup)
+{
+    VIR_DEBUG("backup=%p", backup);
+
+    virResetLastError();
+
+    virCheckDomainBackupReturn(backup, NULL);
+
+    return backup->domain;
+}
+
+
+/**
+ * virDomainBackupGetConnect:
+ * @backup: a backup object
+ *
+ * Provides the connection pointer associated with a backup.  The
+ * reference counter on the connection is not increased by this
+ * call.
+ *
+ * WARNING: When writing libvirt bindings in other languages, do not use this
+ * function.  Instead, store the connection and the backup object together.
+ *
+ * Returns the connection or NULL.
+ */
+virConnectPtr
+virDomainBackupGetConnect(virDomainBackupPtr backup)
+{
+    VIR_DEBUG("backup=%p", backup);
+
+    virResetLastError();
+
+    virCheckDomainBackupReturn(backup, NULL);
+
+    return backup->domain->conn;
+}
+
+
+/**
+ * virDomainBackupCreateXML
+ * @domain: a domain object
+ * @xmlDesc: domain backup XML description
+ * @flags: reserved, must be 0
+ *
+ * Starts a new backup of a domain based on the xml
+ * description in xmlDesc.
+ *
+ * Starts backup blockjob on exactly that disks that specified
+ * in description. Backup is finished when all the mentioned blockjobs
+ * are finished.
+ *
+ * Returns an (opaque) virDomainBackupPtr on success, NULL on failure.
+ */
+virDomainBackupPtr
+virDomainBackupCreateXML(virDomainPtr domain,
+                         const char *xmlDesc,
+                         unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "xmlDesc=%s, flags=%x", xmlDesc, flags);
+
+    virResetLastError();
+
+    virCheckDomainReturn(domain, NULL);
+    conn = domain->conn;
+
+    virCheckNonNullArgGoto(xmlDesc, error);
+    virCheckReadOnlyGoto(conn->flags, error);
+
+    if (conn->driver->domainBackupCreateXML) {
+        virDomainBackupPtr ret;
+        ret = conn->driver->domainBackupCreateXML(domain, xmlDesc, flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virReportUnsupportedError();
+ error:
+    virDispatchError(conn);
+    return NULL;
+}
+
+
+/**
+ * virDomainBackupRef:
+ * @backup: the backup to hold a reference on
+ *
+ * Increment the reference count on the backup. For each
+ * additional call to this method, there shall be a corresponding
+ * call to virDomainBackupFree to release the reference count, once
+ * the caller no longer needs the reference to this object.
+ *
+ * This method is typically useful for applications where multiple
+ * threads are using a connection, and it is required that the
+ * connection and domain remain open until all threads have finished
+ * using the backup. ie, each new thread using a backup would
+ * increment the reference count.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virDomainBackupRef(virDomainBackupPtr backup)
+{
+    VIR_DEBUG("backup=%p, refs=%d", backup,
+              backup ? backup->object.u.s.refs : 0);
+
+    virResetLastError();
+
+    virCheckDomainBackupReturn(backup, -1);
+
+    virObjectRef(backup);
+    return 0;
+}
+
+
+/**
+ * virDomainBackupFree:
+ * @backup: a domain backup object
+ *
+ * Free the domain backup object.  The backup itself is not modified.
+ * The data structure is freed and should not be used thereafter.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+int
+virDomainBackupFree(virDomainBackupPtr backup)
+{
+    VIR_DEBUG("backup=%p", backup);
+
+    virResetLastError();
+
+    virCheckDomainBackupReturn(backup, -1);
+
+    virObjectUnref(backup);
+    return 0;
+}
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 74dd527..c85602c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1004,6 +1004,7 @@ virConnectCloseCallbackDataClass;
 virConnectCloseCallbackDataGetCallback;
 virConnectCloseCallbackDataRegister;
 virConnectCloseCallbackDataUnregister;
+virDomainBackupClass;
 virDomainClass;
 virDomainSnapshotClass;
 virGetConnect;
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index e01604c..b87d04f 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -746,4 +746,14 @@ LIBVIRT_2.2.0 {
         virConnectNodeDeviceEventDeregisterAny;
 } LIBVIRT_2.0.0;
 
+LIBVIRT_2.5.0 {
+    global:
+        virDomainBackupRef;
+        virDomainBackupFree;
+        virDomainBackupGetName;
+        virDomainBackupGetDomain;
+        virDomainBackupGetConnect;
+        virDomainBackupCreateXML;
+} LIBVIRT_2.2.0;
+
 # .... define new API here using predicted next version number ....
diff --git a/src/util/virerror.c b/src/util/virerror.c
index 2958308..448b4c5 100644
--- a/src/util/virerror.c
+++ b/src/util/virerror.c
@@ -138,6 +138,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST,
               "Xen XL Config",
 
               "Perf",
+              "Domain Backup",
     )
 
 
@@ -1399,6 +1400,11 @@ virErrorMsg(virErrorNumber error, const char *info)
                 errmsg = _("guest agent replied with wrong id to guest-sync command");
             else
                 errmsg = _("guest agent replied with wrong id to guest-sync command: %s");
+        case VIR_ERR_INVALID_DOMAIN_BACKUP:
+            if (info == NULL)
+                errmsg = _("Invalid backup");
+            else
+                errmsg = _("Invalid backup: %s");
             break;
     }
     return errmsg;
-- 
1.8.3.1




More information about the libvir-list mailing list