--- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list