From nobody Thu Dec 18 19:25:12 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571415143; cv=none; d=zoho.com; s=zohoarc; b=MEuJqGuJorYbDCnYb0Hxizgk5j6jf19Qq9BMMzmqvnBQx/YmeuZWG1ALij0Q4t5c9gZjP1mi+s2dXzRaHlWpYdTOIzEyZWcZUrTfcbTlNOllm1mNhpiRkOpe5mg8+OUsTvWEfDIScU5Zz1vga9K9ao8ffqOYrzmNrdsRLYEtMGw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571415143; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=odmh5QEvXb+y8UdtZbqflHgCHjuBhlBV95txd1hOToY=; b=jpvypLRy6LIG76OuhBEF2pMQ2ZzEq3W5yfhVinpNsnhqxaj9YB/kIgitZtHHtDlpf/6PX7bnoX/P7L1PvjDH28h/5Uv5gzr2VZJM0AavCLnZvMO4XddqyHUJIeu7bXQKDz9qa+s1EheGmZs357QsLfMNn9ns4PZj/CHlMLI1oh8= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1571415143889554.0680967861629; Fri, 18 Oct 2019 09:12:23 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 067FB307B19B; Fri, 18 Oct 2019 16:12:22 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id CEDA47E21; Fri, 18 Oct 2019 16:12:21 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 8F9071803B59; Fri, 18 Oct 2019 16:12:21 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x9IGCHlr005209 for ; Fri, 18 Oct 2019 12:12:17 -0400 Received: by smtp.corp.redhat.com (Postfix) id D310A60166; Fri, 18 Oct 2019 16:12:17 +0000 (UTC) Received: from angien.brq.redhat.com (unknown [10.43.2.229]) by smtp.corp.redhat.com (Postfix) with ESMTP id 35390600C1; Fri, 18 Oct 2019 16:12:17 +0000 (UTC) From: Peter Krempa To: libvir-list@redhat.com Date: Fri, 18 Oct 2019 18:11:15 +0200 Message-Id: <6564db7ba5795df306e3d61d8d50c7f08b6cd5fb.1571414890.git.pkrempa@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH RFC 30/40] backup: Introduce virDomainBackup APIs X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.45]); Fri, 18 Oct 2019 16:12:22 +0000 (UTC) From: Eric Blake Introduce a few new public APIs related to incremental backups. This builds on the previous notion of a checkpoint (without an existing checkpoint, the new API is a full backup, differing from virDomainBlockCopy in the point of time chosen and in operation on multiple disks at once); and also allows creation of a new checkpoint at the same time as starting the backup (after all, an incremental backup is only useful if it covers the state since the previous backup). A backup job also affects filtering a listing of domains, as well as adding event reporting for signaling when a push model backup completes (where the hypervisor creates the backup); note that the pull model does not have an event (starting the backup lets a third party access the data, and only the third party knows when it is finished). Since multiple backup jobs can be run in parallel in the future (well, qemu doesn't support it yet, but we don't want to preclude the idea), virDomainBackupBegin() returns a positive job id, and the id is also visible in the backup XML. But until a future libvirt release adds a bunch of APIs related to parallel job management where job ids will actually matter, the documentation is also clear that job id 0 means the 'currently running backup job' (provided one exists), for use in virDomainBackupGetXMLDesc() and virDomainBackupEnd(). The full list of new APIs: virDomainBackupBegin; virDomainBackupEnd; virDomainBackupGetXMLDesc; Signed-off-by: Eric Blake Reviewed-by: Daniel P. Berrang=C3=A9 --- include/libvirt/libvirt-domain.h | 26 ++++- src/driver-hypervisor.h | 20 ++++ src/libvirt-domain-checkpoint.c | 7 +- src/libvirt-domain.c | 191 +++++++++++++++++++++++++++++++ src/libvirt_public.syms | 8 ++ tools/virsh-domain.c | 4 +- 6 files changed, 252 insertions(+), 4 deletions(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-dom= ain.h index 22277b0a84..2d9f69f7d4 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -3267,6 +3267,7 @@ typedef enum { VIR_DOMAIN_JOB_OPERATION_SNAPSHOT =3D 6, VIR_DOMAIN_JOB_OPERATION_SNAPSHOT_REVERT =3D 7, VIR_DOMAIN_JOB_OPERATION_DUMP =3D 8, + VIR_DOMAIN_JOB_OPERATION_BACKUP =3D 9, # ifdef VIR_ENUM_SENTINELS VIR_DOMAIN_JOB_OPERATION_LAST @@ -3282,6 +3283,14 @@ typedef enum { */ # define VIR_DOMAIN_JOB_OPERATION "operation" +/** + * VIR_DOMAIN_JOB_ID: + * + * virDomainGetJobStats field: the id of the job (so far, only for jobs + * started by virDomainBackupBegin()), as VIR_TYPED_PARAM_INT. + */ +# define VIR_DOMAIN_JOB_ID "id" + /** * VIR_DOMAIN_JOB_TIME_ELAPSED: * @@ -4106,7 +4115,8 @@ typedef void (*virConnectDomainEventMigrationIteratio= nCallback)(virConnectPtr co * @nparams: size of the params array * @opaque: application specific data * - * This callback occurs when a job (such as migration) running on the doma= in + * This callback occurs when a job (such as migration or push-model + * virDomainBackupBegin()) running on the domain * is completed. The params array will contain statistics of the just comp= leted * job as virDomainGetJobStats would return. The callback must not free @p= arams * (the array will be freed once the callback finishes). @@ -4916,4 +4926,18 @@ int virDomainGetGuestInfo(virDomainPtr domain, int *nparams, unsigned int flags); + +int virDomainBackupBegin(virDomainPtr domain, + const char *backupXML, + const char *checkpointXML, + unsigned int flags); + +char *virDomainBackupGetXMLDesc(virDomainPtr domain, + int id, + unsigned int flags); + +int virDomainBackupEnd(virDomainPtr domain, + int id, + unsigned int flags); + #endif /* LIBVIRT_DOMAIN_H */ diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index 015b2cd01c..cf69cf528d 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -1372,6 +1372,23 @@ typedef int int *nparams, unsigned int flags); + +typedef int +(*virDrvDomainBackupBegin)(virDomainPtr domain, + const char *backupXML, + const char *checkpointXML, + unsigned int flags); + +typedef char * +(*virDrvDomainBackupGetXMLDesc)(virDomainPtr domain, + int id, + unsigned int flags); + +typedef int +(*virDrvDomainBackupEnd)(virDomainPtr domain, + int id, + unsigned int flags); + typedef struct _virHypervisorDriver virHypervisorDriver; typedef virHypervisorDriver *virHypervisorDriverPtr; @@ -1632,4 +1649,7 @@ struct _virHypervisorDriver { virDrvDomainCheckpointGetParent domainCheckpointGetParent; virDrvDomainCheckpointDelete domainCheckpointDelete; virDrvDomainGetGuestInfo domainGetGuestInfo; + virDrvDomainBackupBegin domainBackupBegin; + virDrvDomainBackupGetXMLDesc domainBackupGetXMLDesc; + virDrvDomainBackupEnd domainBackupEnd; }; diff --git a/src/libvirt-domain-checkpoint.c b/src/libvirt-domain-checkpoin= t.c index fa391f8a06..432c2d5a52 100644 --- a/src/libvirt-domain-checkpoint.c +++ b/src/libvirt-domain-checkpoint.c @@ -102,8 +102,11 @@ virDomainCheckpointGetConnect(virDomainCheckpointPtr c= heckpoint) * @flags: bitwise-OR of supported virDomainCheckpointCreateFlags * * Create a new checkpoint using @xmlDesc, with a top-level - * element, on a running @domain. Note that @xmlDesc - * must validate against the XML schema. + * element, on a running @domain. Note that + * @xmlDesc must validate against the XML schema. + * Typically, it is more common to create a new checkpoint as part of + * kicking off a backup job with virDomainBackupBegin(); however, it + * is also possible to start a checkpoint without a backup. * * See Checkpoint X= ML * for more details on @xmlDesc. In particular, some hypervisors may requi= re diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index dcab179e6e..7564c9eee1 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -12497,3 +12497,194 @@ int virDomainGetLaunchSecurityInfo(virDomainPtr d= omain, virDispatchError(domain->conn); return -1; } + + +/** + * virDomainBackupBegin: + * @domain: a domain object + * @backupXML: description of the requested backup + * @checkpointXML: description of a checkpoint to create or NULL + * @flags: unused; callers must pass 0 + * + * Start a point-in-time backup job for the specified disks of a + * running domain. + * + * A backup job is mutually exclusive with domain migration + * (particularly when the job sets up an NBD export, since it is not + * possible to tell any NBD clients about a server migrating between + * hosts). For now, backup jobs are also mutually exclusive with any + * other block job on the same device, although this restriction may + * be lifted in a future release. Progress of the backup job can be + * tracked via virDomainGetJobStats(). The job remains active until a + * subsequent call to virDomainBackupEnd(), even if it no longer has + * anything to copy. + * + * There are two fundamental backup approaches. The first, called a + * push model, instructs the hypervisor to copy the state of the guest + * disk to the designated storage destination (which may be on the + * local file system or a network device). In this mode, the + * hypervisor writes the content of the guest disk to the destination, + * then emits VIR_DOMAIN_EVENT_ID_JOB_COMPLETED when the backup is + * either complete or failed (the backup image is invalid if the job + * fails or virDomainBackupEnd() is used prior to the event being + * emitted). + * + * The second, called a pull model, instructs the hypervisor to expose + * the state of the guest disk over an NBD export. A third-party + * client can then connect to this export and read whichever portions + * of the disk it desires. In this mode, there is no event; libvirt + * has to be informed via virDomainBackupEnd() when the third-party + * NBD client is done and the backup resources can be released. + * + * The @backupXML parameter contains details about the backup in the top-l= evel + * element , including which backup mode to use, whether the + * backup is incremental from a previous checkpoint, which disks + * participate in the backup, the destination for a push model backup, + * and the temporary storage and NBD server details for a pull model + * backup. + * + * virDomainBackupGetXMLDesc() can be called to learn actual + * values selected. For more information, see + * formatcheckpoint.html#BackupAttributes. + * + * The @checkpointXML parameter is optional; if non-NULL, then libvirt + * behaves as if virDomainCheckpointCreateXML() were called to create + * a checkpoint atomically covering the same point in time as the + * backup. + * The creation of a new checkpoint allows for future incremental backups. + * Note that some hypervisors may require a particular disk format, such as + * qcow2, in order to take advantage of checkpoints, while allowing arbitr= ary + * formats if checkpoints are not involved. + * + * Returns a non-negative job id on success or negative on failure. + * This id is then passed to virDomainBackupGetXMLDesc() and + * virDomainBackupEnd(). + */ +int +virDomainBackupBegin(virDomainPtr domain, + const char *backupXML, + const char *checkpointXML, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "backupXML=3D%s, checkpointXML=3D%s, flags=3D= 0x%x", + NULLSTR(backupXML), NULLSTR(checkpointXML), flags); + + virResetLastError(); + + virCheckDomainReturn(domain, -1); + conn =3D domain->conn; + + virCheckNonNullArgGoto(backupXML, error); + virCheckReadOnlyGoto(conn->flags, error); + + if (conn->driver->domainBackupBegin) { + int ret; + ret =3D conn->driver->domainBackupBegin(domain, backupXML, checkpo= intXML, + flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + error: + virDispatchError(conn); + return -1; +} + + +/** + * virDomainBackupGetXMLDesc: + * @domain: a domain object + * @id: the id of an active backup job + * @flags: extra flags; not used yet, so callers should always pass 0 + * + * In some cases, a user can start a backup job without supplying all + * details and rely on libvirt to fill in the rest (for example, + * selecting the port used for an NBD export). This API can then be + * used to learn what default values were chosen. + * + * @id can either be the return value of a previous virDomainBackupBegin(). + * + * Returns a NUL-terminated UTF-8 encoded XML instance or NULL in + * case of error. The caller must free() the returned value. + */ +char * +virDomainBackupGetXMLDesc(virDomainPtr domain, + int id, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "id=3D%d, flags=3D0x%x", id, flags); + + virResetLastError(); + + virCheckDomainReturn(domain, NULL); + conn =3D domain->conn; + + virCheckNonNegativeArgGoto(id, error); + + if (conn->driver->domainBackupGetXMLDesc) { + char *ret; + ret =3D conn->driver->domainBackupGetXMLDesc(domain, id, flags); + if (!ret) + goto error; + return ret; + } + + virReportUnsupportedError(); + error: + virDispatchError(conn); + return NULL; +} + + +/** + * virDomainBackupEnd: + * @domain: a domain object + * @id: the id of an active backup job + * @flags: unused; callers must pass 0 + * + * Conclude a point-in-time backup job of the given domain. + * + * In case of a push model backup the backup is aborted and will be incomp= lete. + * + * This API is asynchronous thus a successful return does not indicate tha= t the + * job was concluded yet. + * + * Returns 0 if the backup job termination was requested successfully, or = -1 on + * failure. + */ +int +virDomainBackupEnd(virDomainPtr domain, + int id, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "id=3D%d, flags=3D0x%x", id, flags); + + virResetLastError(); + + virCheckDomainReturn(domain, -1); + conn =3D domain->conn; + + virCheckReadOnlyGoto(conn->flags, error); + virCheckNonNegativeArgGoto(id, error); + + if (conn->driver->domainBackupEnd) { + int ret; + ret =3D conn->driver->domainBackupEnd(domain, id, flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + error: + virDispatchError(conn); + return -1; +} diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 40655fbbf5..bf7ef80741 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -858,7 +858,15 @@ LIBVIRT_5.7.0 { } LIBVIRT_5.6.0; LIBVIRT_5.8.0 { + global: virConnectSetIdentity; } LIBVIRT_5.7.0; +LIBVIRT_5.9.0 { + global: + virDomainBackupBegin; + virDomainBackupEnd; + virDomainBackupGetXMLDesc; +} LIBVIRT_5.8.0; + # .... define new API here using predicted next version number .... diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 3ba8451470..5ecc8a229c 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -6080,7 +6080,9 @@ VIR_ENUM_IMPL(virshDomainJobOperation, N_("Outgoing migration"), N_("Snapshot"), N_("Snapshot revert"), - N_("Dump")); + N_("Dump"), + N_("Backup"), +); static const char * virshDomainJobOperationToString(int op) --=20 2.21.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list