]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: implement QEMU NBD source reconnect delay attribute
authorChristian Nautze <christian.nautze@exoscale.ch>
Mon, 27 Feb 2023 11:15:33 +0000 (12:15 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Fri, 10 Mar 2023 08:38:05 +0000 (09:38 +0100)
Currently it's only possible to set this parameter during domain
creation via QEMU commandline passthrough feature.
With the new delay attribute it's also possible to set this
parameter if you want to attach a new NBD disk
using "virsh attach-device domain device.xml" e.g.:

  <disk type='network' device='disk'>
    <driver name='qemu' type='raw'/>
    <source protocol='nbd' name='foo'>
      <host name='example.org' port='6000'/>
      <reconnect delay='10'/>
    </source>
    <target dev='vdb' bus='virtio'/>
  </disk>

Signed-off-by: Christian Nautze <christian.nautze@exoscale.ch>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
docs/formatdomain.rst
src/conf/domain_conf.c
src/conf/schemas/domaincommon.rng
src/conf/schemas/storagecommon.rng
src/conf/storage_source_conf.c
src/conf/storage_source_conf.h
src/qemu/qemu_block.c
src/qemu/qemu_domain.c
tests/qemuxml2argvdata/disk-network-nbd.x86_64-latest.args
tests/qemuxml2argvdata/disk-network-nbd.xml
tests/qemuxml2xmloutdata/disk-network-nbd.xml

index 80612382caef09e73efbb7fb1bd7cf58fd7eaedf..4f4874eba272037611876a4cd1fbbad7f9ec442a 100644 (file)
@@ -2956,13 +2956,20 @@ paravirtualized driver is specified via the ``disk`` element.
       are intended to be default, then the entire element may be omitted.
    ``reconnect``
       For disk type ``vhostuser`` configures reconnect timeout if the connection
-      is lost. It has two mandatory attributes:
+      is lost. This is set with the two mandatory attributes ``enabled`` and
+      ``timeout``.
+      For disk type ``network`` and protocol ``nbd`` the QEMU NBD reconnect delay
+      can be set via attribute ``delay``:
 
       ``enabled``
          If the reconnect feature is enabled, accepts ``yes`` and ``no``
       ``timeout``
          The amount of seconds after which hypervisor tries to reconnect.
-
+      ``delay``
+         Only for NBD hosts. The amount of seconds during which all requests are
+         paused and will be rerun after a successful reconnect. After that time, any
+         delayed requests and all future requests before a successful reconnect
+         will immediately fail. If not set the default QEMU value is 0.
 
    For a "file" or "volume" disk type which represents a cdrom or floppy (the
    ``device`` attribute), it is possible to define policy what to do with the
index be1ce1cc53d716c9598c39b38b473a2946cbd330..783d3a5fff8189e68646b7cc27d978fe91ea0c45 100644 (file)
@@ -7166,6 +7166,15 @@ virDomainDiskSourceNetworkParse(xmlNodePtr node,
         src->tlsFromConfig = !!value;
     }
 
+    if (src->protocol == VIR_STORAGE_NET_PROTOCOL_NBD) {
+        xmlNodePtr cur;
+        if ((cur = virXPathNode("./reconnect", ctxt))) {
+            if (virXMLPropUInt(cur, "delay", 10, VIR_XML_PROP_NONE,
+                               &src->reconnectDelay) < 0)
+                return -1;
+        }
+    }
+
     /* for historical reasons we store the volume and image name in one XML
      * element although it complicates thing when attempting to access them. */
     if (src->path &&
@@ -22146,6 +22155,9 @@ virDomainDiskSourceFormatNetwork(virBuffer *attrBuf,
         virBufferAddLit(childBuf, "/>\n");
     }
 
+    if (src->reconnectDelay) {
+        virBufferAsprintf(childBuf, "<reconnect delay='%u'/>\n", src->reconnectDelay);
+    }
 
     virBufferEscapeString(childBuf, "<snapshot name='%s'/>\n", src->snapshot);
     virBufferEscapeString(childBuf, "<config file='%s'/>\n", src->configFile);
index d9373977a8b1dbd8e42d69ecd7ece92da8530675..6158ed79ac1096211c516dc42bfc415fec0164bd 100644 (file)
         </optional>
         <ref name="diskSourceCommon"/>
         <ref name="diskSourceNetworkHost"/>
+        <optional>
+          <ref name="reconnect"/>
+        </optional>
         <optional>
           <ref name="encryption"/>
         </optional>
index 4d6e646c9a00425cb1917fc886ca50db12e7ed72..23eff9ecb1c1f2fa48db2157a8279658b754a5ba 100644 (file)
 
   <define name="reconnect">
     <element name="reconnect">
-      <attribute name="enabled">
-        <ref name="virYesNo"/>
-      </attribute>
-      <optional>
-        <attribute name="timeout">
+      <choice>
+        <group>
+          <attribute name="enabled">
+            <ref name="virYesNo"/>
+          </attribute>
+          <optional>
+            <attribute name="timeout">
+              <ref name="unsignedInt"/>
+            </attribute>
+          </optional>
+        </group>
+        <attribute name="delay">
           <ref name="unsignedInt"/>
         </attribute>
-      </optional>
+      </choice>
     </element>
   </define>
 
index cecd7e811ef7a471a98675c1db0455fa7f40f62c..58009fd06e7871ee496fedc910052aaeeef3d688 100644 (file)
@@ -811,6 +811,7 @@ virStorageSourceCopy(const virStorageSource *src,
     def->sslverify = src->sslverify;
     def->readahead = src->readahead;
     def->timeout = src->timeout;
+    def->reconnectDelay = src->reconnectDelay;
     def->metadataCacheMaxSize = src->metadataCacheMaxSize;
 
     /* storage driver metadata are not copied */
index 14a6825d54cb2732acf5156579f925cf36f8c81f..c6187dda597174da1cd3b66b7468d3bec48288ae 100644 (file)
@@ -312,6 +312,10 @@ struct _virStorageSource {
     unsigned long long readahead; /* size of the readahead buffer in bytes */
     unsigned long long timeout; /* connection timeout in seconds */
 
+    /* NBD QEMU reconnect-delay option,
+     * 0 as default value */
+    unsigned int reconnectDelay;
+
     virStorageSourceNVMeDef *nvme; /* type == VIR_STORAGE_TYPE_NVME */
 
     virDomainChrSourceDef *vhostuser; /* type == VIR_STORAGE_TYPE_VHOST_USER */
index 5e700eff9976ccbb55f6b38b2ff07d812dab98c8..8fcebd89920fe151e0d17abec15f885276988e70 100644 (file)
@@ -529,6 +529,7 @@ qemuBlockStorageSourceGetNBDProps(virStorageSource *src,
                               "S:export", src->path,
                               "S:tls-creds", tlsAlias,
                               "S:tls-hostname", tlsHostname,
+                              "p:reconnect-delay", src->reconnectDelay,
                               NULL) < 0)
         return NULL;
 
@@ -1848,7 +1849,8 @@ qemuBlockGetBackingStoreString(virStorageSource *src,
             src->ncookies == 0 &&
             src->sslverify == VIR_TRISTATE_BOOL_ABSENT &&
             src->timeout == 0 &&
-            src->readahead == 0) {
+            src->readahead == 0 &&
+            src->reconnectDelay == 0) {
 
             switch ((virStorageNetProtocol) src->protocol) {
             case VIR_STORAGE_NET_PROTOCOL_NBD:
index aa567f652af555a24aa32b2957226b8643ececed..0feab09bee831e2fd1ed19fc2f2c773d1b68ab2f 100644 (file)
@@ -5063,6 +5063,15 @@ qemuDomainValidateStorageSource(virStorageSource *src,
         }
     }
 
+    if (src->reconnectDelay > 0) {
+        if (actualType != VIR_STORAGE_TYPE_NETWORK ||
+            src->protocol != VIR_STORAGE_NET_PROTOCOL_NBD) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("reconnect delay is supported only with NBD protocol"));
+            return -1;
+        }
+    }
+
     if (src->query &&
         (actualType != VIR_STORAGE_TYPE_NETWORK ||
          (src->protocol != VIR_STORAGE_NET_PROTOCOL_HTTPS &&
index 20a388f414d93a56dac69fcadb9ace19d2cdfc63..8b5a0bfb9b9288a5f111b0330a9c4e8a71e6aaa7 100644 (file)
@@ -27,21 +27,24 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
 -no-shutdown \
 -boot strict=on \
 -device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
--blockdev '{"driver":"nbd","server":{"type":"inet","host":"example.org","port":"6000"},"node-name":"libvirt-5-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"driver":"nbd","server":{"type":"inet","host":"example.org","port":"6000"},"node-name":"libvirt-6-storage","auto-read-only":true,"discard":"unmap"}' \
+-blockdev '{"node-name":"libvirt-6-format","read-only":false,"driver":"raw","file":"libvirt-6-storage"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-6-format","id":"virtio-disk0","bootindex":1}' \
+-blockdev '{"driver":"nbd","server":{"type":"inet","host":"example.org","port":"6000"},"export":"bar","node-name":"libvirt-5-storage","auto-read-only":true,"discard":"unmap"}' \
 -blockdev '{"node-name":"libvirt-5-format","read-only":false,"driver":"raw","file":"libvirt-5-storage"}' \
--device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x2","drive":"libvirt-5-format","id":"virtio-disk0","bootindex":1}' \
--blockdev '{"driver":"nbd","server":{"type":"inet","host":"example.org","port":"6000"},"export":"bar","node-name":"libvirt-4-storage","auto-read-only":true,"discard":"unmap"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x3","drive":"libvirt-5-format","id":"virtio-disk1"}' \
+-blockdev '{"driver":"nbd","server":{"type":"inet","host":"::1","port":"6000"},"node-name":"libvirt-4-storage","auto-read-only":true,"discard":"unmap"}' \
 -blockdev '{"node-name":"libvirt-4-format","read-only":false,"driver":"raw","file":"libvirt-4-storage"}' \
--device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x3","drive":"libvirt-4-format","id":"virtio-disk1"}' \
--blockdev '{"driver":"nbd","server":{"type":"inet","host":"::1","port":"6000"},"node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x4","drive":"libvirt-4-format","id":"virtio-disk2"}' \
+-blockdev '{"driver":"nbd","server":{"type":"inet","host":"::1","port":"6000"},"export":"bar","node-name":"libvirt-3-storage","auto-read-only":true,"discard":"unmap"}' \
 -blockdev '{"node-name":"libvirt-3-format","read-only":false,"driver":"raw","file":"libvirt-3-storage"}' \
--device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x4","drive":"libvirt-3-format","id":"virtio-disk2"}' \
--blockdev '{"driver":"nbd","server":{"type":"inet","host":"::1","port":"6000"},"export":"bar","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x5","drive":"libvirt-3-format","id":"virtio-disk3"}' \
+-blockdev '{"driver":"nbd","server":{"type":"unix","path":"/var/run/nbdsock"},"export":"bar","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"}' \
 -blockdev '{"node-name":"libvirt-2-format","read-only":false,"driver":"raw","file":"libvirt-2-storage"}' \
--device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x5","drive":"libvirt-2-format","id":"virtio-disk3"}' \
--blockdev '{"driver":"nbd","server":{"type":"unix","path":"/var/run/nbdsock"},"export":"bar","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x6","drive":"libvirt-2-format","id":"virtio-disk4"}' \
+-blockdev '{"driver":"nbd","server":{"type":"inet","host":"example.org","port":"6000"},"export":"foo","reconnect-delay":10,"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
 -blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \
--device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x6","drive":"libvirt-1-format","id":"virtio-disk4"}' \
+-device '{"driver":"virtio-blk-pci","bus":"pci.0","addr":"0x7","drive":"libvirt-1-format","id":"virtio-disk5"}' \
 -audiodev '{"id":"audio1","driver":"none"}' \
 -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
 -msg timestamp=on
index 8ac6cc3b7b518f0152f31a8aa41287b941a83ad0..4e8b1e5b0380f5566a599bf2d28a300b90088544 100644 (file)
       </source>
       <target dev='vde' bus='virtio'/>
     </disk>
+    <disk type='network' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source protocol='nbd' name='foo'>
+        <host name='example.org' port='6000'/>
+        <reconnect delay='10'/>
+      </source>
+      <target dev='vdf' bus='virtio'/>
+    </disk>
     <controller type='usb' index='0'/>
     <controller type='ide' index='0'/>
     <controller type='pci' index='0' model='pci-root'/>
index f8dcca4bab698c0d70e222d6f64541fc329e8b00..38d1f290c84c26f9daaff43431d024ed3cbe103b 100644 (file)
       <target dev='vde' bus='virtio'/>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
     </disk>
+    <disk type='network' device='disk'>
+      <driver name='qemu' type='raw'/>
+      <source protocol='nbd' name='foo'>
+        <host name='example.org' port='6000'/>
+        <reconnect delay='10'/>
+      </source>
+      <target dev='vdf' bus='virtio'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
+    </disk>
     <controller type='usb' index='0'>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
     </controller>