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