]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
backup: Add support for passing server socket file descriptor to backup NBD server
authorPeter Krempa <pkrempa@redhat.com>
Tue, 25 Mar 2025 16:46:45 +0000 (17:46 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Tue, 1 Apr 2025 14:18:30 +0000 (16:18 +0200)
In deployments where libvirt is containerized together with the VM it
may be hard for the management application to access listening sockets
inside the container from the outside.

This patch implements "transport='fd'" for the NBD server definition for
backups which allows to use the existing "virDomainFDAssociate()" to
pass FD to a pre-opened server socket to qemu instead of trying to
create it by qemu.

Add schema, enable the parser, add formatter and implement the actual
passing for the qemu backup code.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Spellchecked-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
docs/formatbackup.rst
src/conf/backup_conf.c
src/conf/schemas/domainbackup.rng
src/qemu/qemu_backup.c

index 02847fd5d49c975bd7443cf9d651c1649e2ff520..155a45a22fcbe3327c2530723f4659c9f5a1f5b6 100644 (file)
@@ -1,3 +1,5 @@
+ .. role:: since
+
 Backup XML format
 =================
 
@@ -42,6 +44,25 @@ were supplied). The following child elements and attributes are supported:
    necessary to set up an NBD server that exposes the content of each disk at
    the time the backup is started.
 
+   In addition to the above the NBD server used for backups allows using
+   ``transport='fd' fdgroup='NAME'`` where ``NAME`` is the name used with
+   ``virDomainFDAssociate()`` to pass a pre-opened server socket file descriptor
+   to qemu. :since:`Since 11.3.0`
+
+   Example code to pass a socket with libvirt-python bindings::
+
+     import socket
+     import libvirt
+
+     s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+     s.bind("/path/to/socket")
+
+     fdlist = [ s.fileno() ]
+
+     conn = libvirt.open()
+     dom = conn.lookupByName("VMNAME")
+     dom.FDAssociate("NAME", fdlist)
+
    Note that for the QEMU hypervisor the TLS environment in controlled using
    ``backup_tls_x509_cert_dir``, ``backup_tls_x509_verify``, and
    ``backup_tls_x509_secret_uuid`` properties in ``/etc/libvirt/qemu.conf``.
index 1bdfbfa3d6731e3b9d3b70db8abb77806466aa94..b20292af3d8aa9e0aeccb8e7c98b6412fd554c4c 100644 (file)
@@ -228,7 +228,7 @@ virDomainBackupDefParseXML(xmlXPathContextPtr ctxt,
 
         def->server = g_new0(virStorageNetHostDef, 1);
 
-        if (virDomainStorageNetworkParseHost(node, def->server, false) < 0)
+        if (virDomainStorageNetworkParseHost(node, def->server, true) < 0)
             return NULL;
 
         if (def->server->transport == VIR_STORAGE_NET_HOST_TRANS_RDMA) {
@@ -388,6 +388,7 @@ virDomainBackupDefFormat(virBuffer *buf,
         if (def->server->port)
             virBufferAsprintf(&serverAttrBuf, " port='%u'", def->server->port);
         virBufferEscapeString(&serverAttrBuf, " socket='%s'", def->server->socket);
+        virBufferEscapeString(&serverAttrBuf, " fdgroup='%s'", def->server->fdgroup);
     }
 
     virXMLFormatElement(&childBuf, "server", &serverAttrBuf, NULL);
index 80ba155aad356f520253fe55fc9c9c182ad379dc..91cf2a7bbd461ba58e8e5a4e034905bc8326ab24 100644 (file)
                       <ref name="absFilePath"/>
                     </attribute>
                   </group>
+                  <group>
+                    <attribute name="transport">
+                      <value>fd</value>
+                    </attribute>
+                    <attribute name="fdgroup"/>
+                  </group>
                 </choice>
               </element>
               <ref name="backupDisksPull"/>
index 2935153cdffc202bb469a93997bfe4fd33763596..f6ee31dc2a4098e37c10e8eb417f335de048b212 100644 (file)
@@ -761,6 +761,7 @@ qemuBackupBegin(virDomainObj *vm,
     bool reuse = (flags & VIR_DOMAIN_BACKUP_BEGIN_REUSE_EXTERNAL);
     int rc = 0;
     int ret = -1;
+    g_autoptr(qemuFDPassDirect) fdpass = NULL;
 
     virCheckFlags(VIR_DOMAIN_BACKUP_BEGIN_REUSE_EXTERNAL, -1);
 
@@ -847,6 +848,29 @@ qemuBackupBegin(virDomainObj *vm,
 
     priv->backup = g_steal_pointer(&def);
 
+    if (pull && priv->backup->server->fdgroup) {
+        virStorageSourceFDTuple *fdt = NULL;
+        VIR_AUTOCLOSE fdcopy = -1;
+
+        if (!(fdt = virHashLookup(priv->fds, priv->backup->server->fdgroup))) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("file descriptor group '%1$s' was not associated with the domain"),
+                           priv->backup->server->fdgroup);
+            goto endjob;
+        }
+
+        if (fdt->nfds != 1) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("file descriptor group '%1$s' must contain only 1 file descriptor for NBD server"),
+                           priv->backup->server->fdgroup);
+            goto endjob;
+        }
+
+        priv->backup->server->qemu_fdname = g_strdup("libvirt-backup-nbd");
+        fdcopy = dup(fdt->fds[0]);
+        fdpass = qemuFDPassDirectNew(priv->backup->server->qemu_fdname, &fdcopy);
+    }
+
     if (qemuDomainObjEnterMonitorAsync(vm, VIR_ASYNC_JOB_BACKUP) < 0)
         goto endjob;
 
@@ -857,6 +881,9 @@ qemuBackupBegin(virDomainObj *vm,
         if (rc == 0 && tlsProps)
             rc = qemuMonitorAddObject(priv->mon, &tlsProps, &tlsAlias);
 
+        if (rc == 0 && fdpass)
+            rc = qemuFDPassDirectTransferMonitor(fdpass, priv->mon);
+
         if (rc == 0) {
             if ((rc = qemuMonitorNBDServerStart(priv->mon, priv->backup->server, tlsAlias)) == 0)
                 nbd_running = true;