From a9a4421ba825474008e04d602365e7bbbf75bfd2 Mon Sep 17 00:00:00 2001 From: Christian Nautze Date: Mon, 27 Feb 2023 12:15:33 +0100 Subject: [PATCH] qemu: implement QEMU NBD source reconnect delay attribute 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.: Signed-off-by: Christian Nautze Reviewed-by: Michal Privoznik --- docs/formatdomain.rst | 11 +++++++-- src/conf/domain_conf.c | 12 ++++++++++ src/conf/schemas/domaincommon.rng | 3 +++ src/conf/schemas/storagecommon.rng | 19 ++++++++++----- src/conf/storage_source_conf.c | 1 + src/conf/storage_source_conf.h | 4 ++++ src/qemu/qemu_block.c | 4 +++- src/qemu/qemu_domain.c | 9 ++++++++ .../disk-network-nbd.x86_64-latest.args | 23 +++++++++++-------- tests/qemuxml2argvdata/disk-network-nbd.xml | 8 +++++++ tests/qemuxml2xmloutdata/disk-network-nbd.xml | 9 ++++++++ 11 files changed, 84 insertions(+), 19 deletions(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 80612382ca..4f4874eba2 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -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 diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index be1ce1cc53..783d3a5fff 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -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, "\n", src->reconnectDelay); + } virBufferEscapeString(childBuf, "\n", src->snapshot); virBufferEscapeString(childBuf, "\n", src->configFile); diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index d9373977a8..6158ed79ac 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -2205,6 +2205,9 @@ + + + diff --git a/src/conf/schemas/storagecommon.rng b/src/conf/schemas/storagecommon.rng index 4d6e646c9a..23eff9ecb1 100644 --- a/src/conf/schemas/storagecommon.rng +++ b/src/conf/schemas/storagecommon.rng @@ -55,14 +55,21 @@ - - - - - + + + + + + + + + + + + - + diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c index cecd7e811e..58009fd06e 100644 --- a/src/conf/storage_source_conf.c +++ b/src/conf/storage_source_conf.c @@ -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 */ diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h index 14a6825d54..c6187dda59 100644 --- a/src/conf/storage_source_conf.h +++ b/src/conf/storage_source_conf.h @@ -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 */ diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 5e700eff99..8fcebd8992 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -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: diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index aa567f652a..0feab09bee 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -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 && diff --git a/tests/qemuxml2argvdata/disk-network-nbd.x86_64-latest.args b/tests/qemuxml2argvdata/disk-network-nbd.x86_64-latest.args index 20a388f414..8b5a0bfb9b 100644 --- a/tests/qemuxml2argvdata/disk-network-nbd.x86_64-latest.args +++ b/tests/qemuxml2argvdata/disk-network-nbd.x86_64-latest.args @@ -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 diff --git a/tests/qemuxml2argvdata/disk-network-nbd.xml b/tests/qemuxml2argvdata/disk-network-nbd.xml index 8ac6cc3b7b..4e8b1e5b03 100644 --- a/tests/qemuxml2argvdata/disk-network-nbd.xml +++ b/tests/qemuxml2argvdata/disk-network-nbd.xml @@ -49,6 +49,14 @@ + + + + + + + + diff --git a/tests/qemuxml2xmloutdata/disk-network-nbd.xml b/tests/qemuxml2xmloutdata/disk-network-nbd.xml index f8dcca4bab..38d1f290c8 100644 --- a/tests/qemuxml2xmloutdata/disk-network-nbd.xml +++ b/tests/qemuxml2xmloutdata/disk-network-nbd.xml @@ -54,6 +54,15 @@
+ + + + + + + +
+