libvirt-10.10.0-7.el10
- qemu_migration: Refactor qemuMigrationSrcRestoreDomainState (RHEL-1071) - qemu_migration: Do not automatically resume domain after I/O error (RHEL-1071) - qemucapabilitiestest: Add data for the qemu-10.0 dev cycle on x86_64 (RHEL-78398) - qemucapabilitiestest: Update 'caps_10.0.0_x86_64' to 'v9.2.0-1636-gffaf7f0376' (RHEL-78398) - qemu: capabilies: Introduce QEMU_CAPS_BLOCKDEV_SET_ACTIVE (RHEL-78398) - qemu: monitor: Add monitor backend for 'blockdev-set-active' (RHEL-78398) - qemu: migration: Reactivate block nodes after migration if VM is left paused (RHEL-78398) - conf: change virDomainHostdevInsert() to return void (RHEL-77086) - qemu: fix qemu validation to forbid guest-side IP address for type='vdpa' (RHEL-77086) - qemu: validate that model is virtio for vhostuser and vdpa interfaces in the same place (RHEL-77086) - qemu: automatically set model type='virtio' for interface type='vhostuser' (RHEL-77086) - qemu: do all vhostuser attribute validation in qemu driver (RHEL-77086) - conf/qemu: make <source> element *almost* optional for type=vhostuser (RHEL-77086) - qemu: use switch instead of if in qemuProcessPrepareDomainNetwork() (RHEL-77086) - qemu: make qemuPasstCreateSocketPath() public (RHEL-77086) - qemu: complete vhostuser + passt support (RHEL-77086) - qemu: fail validation if a domain def has vhostuser/passt but no shared mem (RHEL-77086) - docs: improve type='user' docs to higlight differences between SLIRP and passt (RHEL-77086) - docs: document using passt backend with <interface type='vhostuser'> (RHEL-77086) - utils: Canonicalize paths before comparing them (RHEL-79165) Resolves: RHEL-1071, RHEL-77086, RHEL-78398, RHEL-79165
This commit is contained in:
parent
62c343d5fa
commit
582e7872e6
158
libvirt-conf-change-virDomainHostdevInsert-to-return-void.patch
Normal file
158
libvirt-conf-change-virDomainHostdevInsert-to-return-void.patch
Normal file
@ -0,0 +1,158 @@
|
||||
From 5083667a7f861364e293904a18bce550d9880536 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <5083667a7f861364e293904a18bce550d9880536.1739815540.git.jdenemar@redhat.com>
|
||||
From: Laine Stump <laine@redhat.com>
|
||||
Date: Tue, 11 Feb 2025 16:44:49 -0500
|
||||
Subject: [PATCH] conf: change virDomainHostdevInsert() to return void
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
We haven't checked for memalloc failure in many years, and that was
|
||||
the only reason this function would have ever failed.
|
||||
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit 956c6684113b46b2350db698dc75604f4c3a4b76)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-77086
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
---
|
||||
src/conf/domain_conf.c | 15 +++++----------
|
||||
src/conf/domain_conf.h | 2 +-
|
||||
src/libxl/libxl_domain.c | 5 +----
|
||||
src/libxl/libxl_driver.c | 3 +--
|
||||
src/lxc/lxc_driver.c | 3 +--
|
||||
src/qemu/qemu_driver.c | 3 +--
|
||||
src/qemu/qemu_process.c | 3 +--
|
||||
7 files changed, 11 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
|
||||
index d83f1ba240..cba0b162f4 100644
|
||||
--- a/src/conf/domain_conf.c
|
||||
+++ b/src/conf/domain_conf.c
|
||||
@@ -14456,12 +14456,10 @@ virDomainChrTargetTypeToString(int deviceType,
|
||||
return type;
|
||||
}
|
||||
|
||||
-int
|
||||
+void
|
||||
virDomainHostdevInsert(virDomainDef *def, virDomainHostdevDef *hostdev)
|
||||
{
|
||||
VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, hostdev);
|
||||
-
|
||||
- return 0;
|
||||
}
|
||||
|
||||
virDomainHostdevDef *
|
||||
@@ -14877,9 +14875,8 @@ virDomainDiskRemoveByName(virDomainDef *def, const char *name)
|
||||
int virDomainNetInsert(virDomainDef *def, virDomainNetDef *net)
|
||||
{
|
||||
/* hostdev net devices must also exist in the hostdevs array */
|
||||
- if (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV &&
|
||||
- virDomainHostdevInsert(def, &net->data.hostdev.def) < 0)
|
||||
- return -1;
|
||||
+ if (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)
|
||||
+ virDomainHostdevInsert(def, &net->data.hostdev.def);
|
||||
|
||||
VIR_APPEND_ELEMENT(def->nets, def->nnets, net);
|
||||
return 0;
|
||||
@@ -19257,10 +19254,8 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt,
|
||||
* where the actual network type is already known to be
|
||||
* hostdev) must also be in the hostdevs array.
|
||||
*/
|
||||
- if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_HOSTDEV &&
|
||||
- virDomainHostdevInsert(def, virDomainNetGetActualHostdev(net)) < 0) {
|
||||
- return NULL;
|
||||
- }
|
||||
+ if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_HOSTDEV)
|
||||
+ virDomainHostdevInsert(def, virDomainNetGetActualHostdev(net));
|
||||
}
|
||||
VIR_FREE(nodes);
|
||||
|
||||
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
|
||||
index 5237046196..2d38e8fa51 100644
|
||||
--- a/src/conf/domain_conf.h
|
||||
+++ b/src/conf/domain_conf.h
|
||||
@@ -3982,7 +3982,7 @@ virDomainNetDef *virDomainNetRemove(virDomainDef *def, size_t i);
|
||||
virDomainNetDef *virDomainNetRemoveByObj(virDomainDef *def, virDomainNetDef *net);
|
||||
void virDomainNetRemoveHostdev(virDomainDef *def, virDomainNetDef *net);
|
||||
|
||||
-int virDomainHostdevInsert(virDomainDef *def, virDomainHostdevDef *hostdev);
|
||||
+void virDomainHostdevInsert(virDomainDef *def, virDomainHostdevDef *hostdev);
|
||||
virDomainHostdevDef *
|
||||
virDomainHostdevRemove(virDomainDef *def, size_t i);
|
||||
int virDomainHostdevFind(virDomainDef *def, virDomainHostdevDef *match,
|
||||
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
|
||||
index cad6c9ce42..711e22b8df 100644
|
||||
--- a/src/libxl/libxl_domain.c
|
||||
+++ b/src/libxl/libxl_domain.c
|
||||
@@ -1015,10 +1015,7 @@ libxlNetworkPrepareDevices(virDomainDef *def)
|
||||
/* Each type='hostdev' network device must also have a
|
||||
* corresponding entry in the hostdevs array.
|
||||
*/
|
||||
- virDomainHostdevDef *hostdev = virDomainNetGetActualHostdev(net);
|
||||
-
|
||||
- if (virDomainHostdevInsert(def, hostdev) < 0)
|
||||
- return -1;
|
||||
+ virDomainHostdevInsert(def, virDomainNetGetActualHostdev(net));
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
|
||||
index 29dcee3cfc..b670e697c6 100644
|
||||
--- a/src/libxl/libxl_driver.c
|
||||
+++ b/src/libxl/libxl_driver.c
|
||||
@@ -3585,8 +3585,7 @@ libxlDomainAttachDeviceConfig(virDomainDef *vmdef, virDomainDeviceDef *dev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
- if (virDomainHostdevInsert(vmdef, hostdev) < 0)
|
||||
- return -1;
|
||||
+ virDomainHostdevInsert(vmdef, hostdev);
|
||||
dev->data.hostdev = NULL;
|
||||
break;
|
||||
|
||||
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
|
||||
index d682e7168a..9609d7d10c 100644
|
||||
--- a/src/lxc/lxc_driver.c
|
||||
+++ b/src/lxc/lxc_driver.c
|
||||
@@ -3025,8 +3025,7 @@ lxcDomainAttachDeviceConfig(virDomainDef *vmdef,
|
||||
_("device is already in the domain configuration"));
|
||||
return -1;
|
||||
}
|
||||
- if (virDomainHostdevInsert(vmdef, hostdev) < 0)
|
||||
- return -1;
|
||||
+ virDomainHostdevInsert(vmdef, hostdev);
|
||||
dev->data.hostdev = NULL;
|
||||
ret = 0;
|
||||
break;
|
||||
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
||||
index 9a69574f31..379f9fb74f 100644
|
||||
--- a/src/qemu/qemu_driver.c
|
||||
+++ b/src/qemu/qemu_driver.c
|
||||
@@ -6734,8 +6734,7 @@ qemuDomainAttachDeviceConfig(virDomainDef *vmdef,
|
||||
_("device is already in the domain configuration"));
|
||||
return -1;
|
||||
}
|
||||
- if (virDomainHostdevInsert(vmdef, hostdev))
|
||||
- return -1;
|
||||
+ virDomainHostdevInsert(vmdef, hostdev);
|
||||
dev->data.hostdev = NULL;
|
||||
break;
|
||||
|
||||
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
|
||||
index 1866c8f4e1..a45f1b5b7d 100644
|
||||
--- a/src/qemu/qemu_process.c
|
||||
+++ b/src/qemu/qemu_process.c
|
||||
@@ -5929,8 +5929,7 @@ qemuProcessPrepareDomainNetwork(virDomainObj *vm)
|
||||
if (qemuDomainPrepareHostdev(hostdev, priv) < 0)
|
||||
return -1;
|
||||
|
||||
- if (virDomainHostdevInsert(def, hostdev) < 0)
|
||||
- return -1;
|
||||
+ virDomainHostdevInsert(def, hostdev);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
--
|
||||
2.48.1
|
@ -0,0 +1,170 @@
|
||||
From 6cecf1cbd813f6b197920001a422e87d0999442a Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <6cecf1cbd813f6b197920001a422e87d0999442a.1739815540.git.jdenemar@redhat.com>
|
||||
From: Laine Stump <laine@redhat.com>
|
||||
Date: Sun, 9 Feb 2025 22:52:54 -0500
|
||||
Subject: [PATCH] conf/qemu: make <source> element *almost* optional for
|
||||
type=vhostuser
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
For some reason, when vhostuser interface support was added in 2014,
|
||||
the parser required that the XML for the <interface> have a <source>
|
||||
element with type, mode, and path, all 3 also required. This in spite
|
||||
of the fact that 'unix' is the only possible valid setting for type,
|
||||
and 95% of the time the mode is set to 'client' (as I understand from
|
||||
comments in the code, normally a guest will use mode='client' to
|
||||
connect to an existing socket that is precreated (by OVS?), and the
|
||||
only use for mode='server' is for test setups where one guest is setup
|
||||
with a listening vhostuser socket (i.e. 'server') and another guest
|
||||
connects to that socket (i.e. 'client')). (or maybe one guest connects
|
||||
to OVS in server mode, and all the others connect in client mode, not
|
||||
sure - I don't claim to be an expert on vhost-user.)
|
||||
|
||||
So from the point of view of existing vhost-user functionality, it
|
||||
seems reasonable to make 'type' and 'mode' optional, and by default
|
||||
fill in the vhostuser part of the NetDef as if they were 'unix' and
|
||||
'client'.
|
||||
|
||||
In theory, the <source> element itself is also not *directly* required
|
||||
after this patch, however, the path attribute of <source> *is*
|
||||
required (for now), so effectively the <source> element is still
|
||||
required.
|
||||
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit fb4bfa78589f7f556b6b0a176f109c94516d3cdd)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-77086
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
---
|
||||
src/conf/domain_conf.c | 56 ++++++++++++-------------------
|
||||
src/conf/schemas/domaincommon.rng | 4 ++-
|
||||
src/qemu/qemu_validate.c | 20 +++++++----
|
||||
3 files changed, 39 insertions(+), 41 deletions(-)
|
||||
|
||||
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
|
||||
index cba0b162f4..b1e9dda80e 100644
|
||||
--- a/src/conf/domain_conf.c
|
||||
+++ b/src/conf/domain_conf.c
|
||||
@@ -9767,50 +9767,38 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
|
||||
g_autofree char *vhostuser_type = NULL;
|
||||
virDomainNetVhostuserMode vhostuser_mode;
|
||||
|
||||
- if (virDomainNetDefParseXMLRequireSource(def, source_node) < 0)
|
||||
- return NULL;
|
||||
-
|
||||
- if (!(vhostuser_type = virXMLPropStringRequired(source_node, "type")))
|
||||
- return NULL;
|
||||
-
|
||||
- if (STRNEQ_NULLABLE(vhostuser_type, "unix")) {
|
||||
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
- _("Type='%1$s' unsupported for <interface type='vhostuser'>"),
|
||||
- vhostuser_type);
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
if (!(def->data.vhostuser = virDomainChrSourceDefNew(xmlopt)))
|
||||
return NULL;
|
||||
|
||||
+ /* Default (and only valid) value of type is "unix".
|
||||
+ * Everything else's default value is 0/NULL.
|
||||
+ */
|
||||
def->data.vhostuser->type = VIR_DOMAIN_CHR_TYPE_UNIX;
|
||||
|
||||
- if (!(def->data.vhostuser->data.nix.path = virXMLPropStringRequired(source_node, "path")))
|
||||
- return NULL;
|
||||
+ if (source_node) {
|
||||
+ if ((vhostuser_type = virXMLPropString(source_node, "type"))) {
|
||||
+ if (STRNEQ(vhostuser_type, "unix")) {
|
||||
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
+ _("Type='%1$s' unsupported for <interface type='vhostuser'>"),
|
||||
+ vhostuser_type);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (virXMLPropEnum(source_node, "mode",
|
||||
- virDomainNetVhostuserModeTypeFromString,
|
||||
- VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
|
||||
- &vhostuser_mode) < 0)
|
||||
- return NULL;
|
||||
+ def->data.vhostuser->data.nix.path = virXMLPropString(source_node, "path");
|
||||
|
||||
- switch (vhostuser_mode) {
|
||||
- case VIR_DOMAIN_NET_VHOSTUSER_MODE_CLIENT:
|
||||
- def->data.vhostuser->data.nix.listen = false;
|
||||
- break;
|
||||
+ if (virXMLPropEnum(source_node, "mode", virDomainNetVhostuserModeTypeFromString,
|
||||
+ VIR_XML_PROP_NONZERO, &vhostuser_mode) < 0) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
- case VIR_DOMAIN_NET_VHOSTUSER_MODE_SERVER:
|
||||
- def->data.vhostuser->data.nix.listen = true;
|
||||
- break;
|
||||
+ if (vhostuser_mode == VIR_DOMAIN_NET_VHOSTUSER_MODE_SERVER)
|
||||
+ def->data.vhostuser->data.nix.listen = true;
|
||||
|
||||
- case VIR_DOMAIN_NET_VHOSTUSER_MODE_NONE:
|
||||
- case VIR_DOMAIN_NET_VHOSTUSER_MODE_LAST:
|
||||
- break;
|
||||
+ if (virDomainChrSourceReconnectDefParseXML(&def->data.vhostuser->data.nix.reconnect,
|
||||
+ source_node, ctxt) < 0)
|
||||
+ return NULL;
|
||||
}
|
||||
-
|
||||
- if (virDomainChrSourceReconnectDefParseXML(&def->data.vhostuser->data.nix.reconnect,
|
||||
- source_node, ctxt) < 0)
|
||||
- return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
|
||||
index 7121519ca3..cbc093ca7b 100644
|
||||
--- a/src/conf/schemas/domaincommon.rng
|
||||
+++ b/src/conf/schemas/domaincommon.rng
|
||||
@@ -3485,7 +3485,9 @@
|
||||
<value>vhostuser</value>
|
||||
</attribute>
|
||||
<interleave>
|
||||
- <ref name="unixSocketSource"/>
|
||||
+ <optional>
|
||||
+ <ref name="unixSocketSource"/>
|
||||
+ </optional>
|
||||
<ref name="interface-options"/>
|
||||
</interleave>
|
||||
</group>
|
||||
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
|
||||
index b7b2e3d0af..eb8c5366f6 100644
|
||||
--- a/src/qemu/qemu_validate.c
|
||||
+++ b/src/qemu/qemu_validate.c
|
||||
@@ -1810,12 +1810,20 @@ qemuValidateDomainDeviceDefNetwork(const virDomainNetDef *net,
|
||||
}
|
||||
}
|
||||
|
||||
- if (net->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER &&
|
||||
- net->data.vhostuser->data.nix.listen &&
|
||||
- net->data.vhostuser->data.nix.reconnect.enabled == VIR_TRISTATE_BOOL_YES) {
|
||||
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
- _("'reconnect' attribute is not supported when source mode='server' for <interface type='vhostuser'>"));
|
||||
- return -1;
|
||||
+ if (net->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
|
||||
+ if (!net->data.vhostuser->data.nix.path) {
|
||||
+ virReportError(VIR_ERR_XML_ERROR,
|
||||
+ _("Missing required attribute '%1$s' in element '%2$s'"),
|
||||
+ "path", "source");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (net->data.vhostuser->data.nix.listen &&
|
||||
+ net->data.vhostuser->data.nix.reconnect.enabled == VIR_TRISTATE_BOOL_YES) {
|
||||
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
+ _("'reconnect' attribute is not supported when source mode='server' for <interface type='vhostuser'>"));
|
||||
+ return -1;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (!virDomainNetIsVirtioModel(net)) {
|
||||
--
|
||||
2.48.1
|
@ -0,0 +1,139 @@
|
||||
From 1be247ee9a7df932a3f2ff2126714755433fc94b Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <1be247ee9a7df932a3f2ff2126714755433fc94b.1739815540.git.jdenemar@redhat.com>
|
||||
From: Laine Stump <laine@redhat.com>
|
||||
Date: Fri, 14 Feb 2025 23:35:56 -0500
|
||||
Subject: [PATCH] docs: document using passt backend with <interface
|
||||
type='vhostuser'>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Almost everything is already there (in the section for using passt
|
||||
with type='user'), so we just need to point to that from the
|
||||
type='vhostuser' section (and vice versa), and add a bit of glue.
|
||||
|
||||
Also updated a few related details that have changed (e.g. default
|
||||
model type for vhostuser is now 'virtio', and source type/mode are now
|
||||
optional), and changed "vhost-user interface" to "vhost-user
|
||||
connection" because the interface is a virtio interface, and
|
||||
vhost-user is being used to connect that interface to the outside.
|
||||
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit 96fd17a99b514e585a94d43d40ab9a74907c7a5b)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-77086
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
---
|
||||
docs/formatdomain.rst | 73 ++++++++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 62 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
|
||||
index 577366b934..c077c09a39 100644
|
||||
--- a/docs/formatdomain.rst
|
||||
+++ b/docs/formatdomain.rst
|
||||
@@ -5131,6 +5131,15 @@ destined for the host toward the guest instead), and a socket between
|
||||
passt and QEMU forwards that traffic on to the guest (and back out,
|
||||
of course).
|
||||
|
||||
+*(:since:`Since 11.1.0 (QEMU and KVM only)` you may prefer to use the
|
||||
+passt backend with the more efficient and performant type='vhostuser'
|
||||
+rather than type='user'. All the options related to passt in the
|
||||
+paragraphs below here also apply when using the passt backend with
|
||||
+type='vhostuser'; any other details specific to vhostuser are
|
||||
+described* `here
|
||||
+<formatdomain.html#vhost-user-connection-with-passt-backend>`__.)
|
||||
+
|
||||
+
|
||||
Similar to SLIRP, passt has an internal DHCP server that provides a
|
||||
requesting guest with one ipv4 and one ipv6 address. There are default
|
||||
values for both of these, or you can use the ``<ip>`` element
|
||||
@@ -5823,7 +5832,7 @@ following attributes are available for the ``virtio`` NIC driver:
|
||||
The optional ``queues`` attribute controls the number of queues to be used
|
||||
for either `Multiqueue
|
||||
virtio-net <https://www.linux-kvm.org/page/Multiqueue>`__ or vhost-user (See
|
||||
- `vhost-user interface`_) network interfaces. Use of multiple packet
|
||||
+ `vhost-user connection`_) network interfaces. Use of multiple packet
|
||||
processing queues requires the interface having the
|
||||
``<model type='virtio'/>`` element. Each queue will potentially be handled by
|
||||
a different processor, resulting in much higher throughput.
|
||||
@@ -6267,8 +6276,8 @@ similarly named elements used to configure the guest side of the interface
|
||||
(described above).
|
||||
|
||||
|
||||
-vhost-user interface
|
||||
-^^^^^^^^^^^^^^^^^^^^
|
||||
+vhost-user connection
|
||||
+^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
:since:`Since 1.2.7` the vhost-user enables the communication between a QEMU
|
||||
virtual machine and other userspace process using the Virtio transport protocol.
|
||||
@@ -6295,16 +6304,58 @@ plane is based on shared memory.
|
||||
</devices>
|
||||
...
|
||||
|
||||
-The ``<source>`` element has to be specified along with the type of char device.
|
||||
-Currently, only type='unix' is supported, where the path (the directory path of
|
||||
-the socket) and mode attributes are required. Both ``mode='server'`` and
|
||||
-``mode='client'`` are supported. vhost-user requires the virtio model type, thus
|
||||
-the ``<model>`` element is mandatory. :since:`Since 4.1.0` the element has an
|
||||
-optional child element ``reconnect`` which configures reconnect timeout if the
|
||||
-connection is lost. It has two attributes ``enabled`` (which accepts ``yes`` and
|
||||
-``no``) and ``timeout`` which specifies the amount of seconds after which
|
||||
+The ``<source>`` element has to be specified along with the type of
|
||||
+char device. Currently, only type='unix' is supported, where the path
|
||||
+(the directory path of the socket) and mode attributes are
|
||||
+required. Both ``mode='server'`` and ``mode='client'`` are
|
||||
+supported. (:since:`Since 11.1.0` the default source type for
|
||||
+vhostuser interfaces is 'unix' and default mode is 'client', so those
|
||||
+two attributes are now optional).
|
||||
+
|
||||
+The vhost-user protocol only works with the virtio guest driver, so
|
||||
+the ``<model>`` element ``type`` attribute is mandatory (:since:`Since
|
||||
+11.1.0` the default model type for vhostuser interfaces is now
|
||||
+'virtio' so ``<model>`` is no longer mandatory). :since:`Since 4.1.0`
|
||||
+the ``<source>`` element has an optional child element ``reconnect``
|
||||
+which configures reconnect timeout if the connection is lost. It has
|
||||
+two attributes ``enabled`` (which accepts ``yes`` and ``no``) and
|
||||
+``timeout`` which specifies the amount of seconds after which
|
||||
hypervisor tries to reconnect.
|
||||
|
||||
+
|
||||
+vhost-user connection with passt backend
|
||||
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
+
|
||||
+:since:`Since 11.1.0 (QEMU and KVM only)` passt can be used as the
|
||||
+other end of the vhost-user connection. This is a compelling
|
||||
+alternative, because passt provides all of its network connectivity
|
||||
+without requiring any elevated privileges or capabilities, and
|
||||
+vhost-user uses shared memory to make this unprivileged connection
|
||||
+very high performance as well. You can set a type='vhostuser'
|
||||
+interface to use passt as the backend by adding ``<backend
|
||||
+type='passt'/>``. When passt is the backend, only a single driver
|
||||
+queue is supported, and the ``<source>`` path/type/mode are all
|
||||
+implied to be "matching the passt process" so **must not** be
|
||||
+specified. All of the passt options `described here
|
||||
+<formatdomain.html#userspace-connection-using-passt>`__, are also
|
||||
+supported for ``type='vhostuser'`` with the passt backend, e.g.
|
||||
+setting guest-side IP addresses with ``<ip>`` and port forwarding with
|
||||
+``<portForward``.
|
||||
+
|
||||
+::
|
||||
+
|
||||
+ ...
|
||||
+ <devices>
|
||||
+ <interface type='vhostuser'>
|
||||
+ <backend type='passt'/>
|
||||
+ <mac address='52:54:00:3b:83:1a'/>
|
||||
+ <source dev='enp1s0'/>
|
||||
+ <ip address='10.30.0.5 prefix='24'/>
|
||||
+ </interface>
|
||||
+ </devices>
|
||||
+ ...
|
||||
+
|
||||
+
|
||||
Traffic filtering with NWFilter
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
--
|
||||
2.48.1
|
@ -0,0 +1,177 @@
|
||||
From 2e71e35f0d78191d5ea36297877933e58e624a3a Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <2e71e35f0d78191d5ea36297877933e58e624a3a.1739815540.git.jdenemar@redhat.com>
|
||||
From: Laine Stump <laine@redhat.com>
|
||||
Date: Fri, 14 Feb 2025 22:43:03 -0500
|
||||
Subject: [PATCH] docs: improve type='user' docs to higlight differences
|
||||
between SLIRP and passt
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This reorganizes the section about <interface type='user'> and
|
||||
describes the differences in behavior between SLIRP and passt.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-46601
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit a47a89a9d335c111a9c2fbb3f4e1c3a13001e74b)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-77086
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
---
|
||||
docs/formatdomain.rst | 116 ++++++++++++++++++++++++++++--------------
|
||||
1 file changed, 78 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
|
||||
index 8d787ef59a..577366b934 100644
|
||||
--- a/docs/formatdomain.rst
|
||||
+++ b/docs/formatdomain.rst
|
||||
@@ -5072,25 +5072,34 @@ to the interface.
|
||||
</devices>
|
||||
...
|
||||
|
||||
-Userspace (SLIRP or passt) connection
|
||||
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
+Userspace connection using SLIRP
|
||||
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
-The ``user`` type connects the guest interface to the outside via a
|
||||
+The ``user`` interface type connects the guest interface to the outside via a
|
||||
transparent userspace proxy that doesn't require any special system
|
||||
privileges, making it usable in cases when libvirt itself is running
|
||||
with no privileges (e.g. libvirt's "session mode" daemon, or when
|
||||
libvirt is run inside an unprivileged container).
|
||||
|
||||
-By default, this user proxy is done with QEMU's internal SLIRP driver
|
||||
-which has DHCP & DNS services that give the guest IP addresses
|
||||
-starting from ``10.0.2.15``, a default route of ``10.0.2.2`` and DNS
|
||||
-server of ``10.0.2.3``. :since:`Since 3.8.0` it is possible to override
|
||||
-the default network address by including an ``ip`` element specifying
|
||||
-an IPv4 address in its one mandatory attribute,
|
||||
-``address``. Optionally, a second ``ip`` element with a ``family``
|
||||
-attribute set to "ipv6" can be specified to add an IPv6 address to the
|
||||
-interface. ``address``. Optionally, address ``prefix`` can be
|
||||
-specified.
|
||||
+By default, this user proxy is done with QEMU's SLIRP driver, a
|
||||
+userspace proxy built into QEMU that has DHCP & DNS services that give
|
||||
+the guest an IP address of ``10.0.2.15``, a default route of
|
||||
+``10.0.2.2`` and DNS server at ``10.0.2.3``.
|
||||
+
|
||||
+:since:`Since 3.8.0` it is possible to override the guest's default
|
||||
+network address by including an ``ip`` element specifying an IPv4
|
||||
+address in its one mandatory attribute, ``address``. Optionally, a
|
||||
+second ``ip`` element with a ``family`` attribute set to "ipv6" can be
|
||||
+specified to add an IPv6 address to the interface. ``address``.
|
||||
+Optionally, an address ``prefix`` can be specified. These settings are
|
||||
+surprisingly **not** used by SLIRP to set the exact IP address;
|
||||
+instead they are used to determine what network/subnet the guest's IP
|
||||
+address should be on, and the guest will be given an address in that
|
||||
+subnet, but the host portion of the address will still be "2.15". In
|
||||
+the example below, for example, the guest will be given the IP address
|
||||
+172.17.2.15 (**note that the '1.1' in the host portion of the address
|
||||
+has been ignored**), default route of 172.17.2.2, and DNS server
|
||||
+172.17.2.3.
|
||||
|
||||
::
|
||||
|
||||
@@ -5100,34 +5109,65 @@ specified.
|
||||
...
|
||||
<interface type='user'>
|
||||
<mac address="00:11:22:33:44:55"/>
|
||||
- <ip family='ipv4' address='172.17.2.0' prefix='24'/>
|
||||
- <ip family='ipv6' address='2001:db8:ac10:fd01::' prefix='64'/>
|
||||
+ <ip family='ipv4' address='172.17.1.1' prefix='16'/>
|
||||
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'/>
|
||||
</interface>
|
||||
</devices>
|
||||
...
|
||||
|
||||
-:since:`Since 9.0.0` an alternate backend implementation of the
|
||||
-``user`` interface type can be selected by setting the interface's
|
||||
-``<backend>`` subelement ``type`` attribute to ``passt``. In this
|
||||
-case, the passt transport (https://passt.top) is used. Similar to
|
||||
-SLIRP, passt has an internal DHCP server that provides a requesting
|
||||
-guest with one ipv4 and one ipv6 address; it then uses userspace
|
||||
-proxies and a separate network namespace to provide outgoing
|
||||
-UDP/TCP/ICMP sessions, and optionally redirect incoming traffic
|
||||
-destined for the host toward the guest instead.
|
||||
-
|
||||
-When the passt backend is used, the ``<backend>`` attribute
|
||||
-``logFile`` can be used to tell the passt process for this interface
|
||||
-where to write its message log, and the ``<source>`` attribute ``dev``
|
||||
-can tell it to use a particular host interface to derive the routes
|
||||
-given to the guest for forwarding traffic upstream. Due to the design
|
||||
-decisions of passt, if using SELinux, the log file is recommended to
|
||||
-reside in the runtime directory of a user under which the passt
|
||||
-process will run, most probably ``/run/user/$UID`` where ``$UID`` is
|
||||
-the UID of the user, e.g. ``qemu``. Beware that libvirt does not
|
||||
-create this directory if it does not already exist to avoid possible,
|
||||
-however unlikely, issues, especially since this logfile attribute is
|
||||
-meant mostly for debugging.
|
||||
+Userspace connection using passt
|
||||
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
+
|
||||
+:since:`Since 9.0.0 (QEMU and KVM only)` an alternate backend
|
||||
+implementation of the ``user`` interface type can be selected by
|
||||
+setting the interface's ``<backend>`` subelement ``type`` attribute to
|
||||
+``passt``. In this case, the passt transport `(details here)
|
||||
+<https://passt.top>`__ is used. passt is run as a separate process
|
||||
+from QEMU - the passt process handles the details of forwarding
|
||||
+network traffic back and forth to the physical network (using
|
||||
+userspace proxies and a separate network namespace to provide outgoing
|
||||
+UDP/TCP/ICMP sessions, and optionally redirecting incoming traffic
|
||||
+destined for the host toward the guest instead), and a socket between
|
||||
+passt and QEMU forwards that traffic on to the guest (and back out,
|
||||
+of course).
|
||||
+
|
||||
+Similar to SLIRP, passt has an internal DHCP server that provides a
|
||||
+requesting guest with one ipv4 and one ipv6 address. There are default
|
||||
+values for both of these, or you can use the ``<ip>`` element
|
||||
+(described above, with behavioral differences as outlined below) to
|
||||
+configure one IPv4 and one IPv6 address that passt's DHCP server can
|
||||
+provide to the guest.
|
||||
+
|
||||
+Unlike SLIRP, when no `<ip>`` address is specified, passt will by
|
||||
+default provide the guest with an IP address, DNS server, etc. that
|
||||
+are identical to those settings on the host itself (through the magic
|
||||
+of the proxies and a separate network namespace, this doesn't create
|
||||
+any conflict).
|
||||
+
|
||||
+Also different from SLIRP's behavior: if you do specify IP
|
||||
+address(es), the exact address and netmask/prefix you specify will be
|
||||
+provided to the guest (i.e. passt doesn't interpret the <ip> settings
|
||||
+as a network address like SLIRP does, but as a host address). In
|
||||
+example given above, the guest IP would be set to exactly 172.17.1.1.
|
||||
+
|
||||
+Just as with SLIRP, though, once traffic from the guest leaves the
|
||||
+host towards the rest of the network, it will always appear as if it
|
||||
+came from the host's IP.
|
||||
+
|
||||
+There are a few other options that are configurable only for the passt
|
||||
+backend. For example, the ``<backend>`` attribute ``logFile`` can be
|
||||
+used to tell the passt process for this interface where to write its
|
||||
+message log, and the ``<source>`` attribute ``dev`` can tell it a
|
||||
+particular host interface to use when deriving the routes given to the
|
||||
+guest for forwarding traffic upstream. Due to the design decisions of
|
||||
+passt, when using SELinux on the host, it is recommended that the log
|
||||
+file reside in the runtime directory of the user under which the passt
|
||||
+process will run, most probably ``/run/user/$UID`` (where ``$UID`` is
|
||||
+the UID of that user), e.g. ``/run/user/1000``. Be aware that libvirt
|
||||
+does not create this directory if it does not already exist to avoid
|
||||
+possible, however unlikely, issues with orphaned directories or
|
||||
+permissions, etc. The logfile attribute is meant mostly for debugging,
|
||||
+so it shouldn't be set under normal circumstances.
|
||||
|
||||
Additionally, when passt is used, multiple ``<portForward>`` elements
|
||||
can be added to forward incoming network traffic for the host to this
|
||||
@@ -5164,7 +5204,7 @@ ports **with the exception of some subset**.
|
||||
<backend type='passt' logFile='/run/user/$UID/passt-domain.log'/>
|
||||
<mac address="00:11:22:33:44:55"/>
|
||||
<source dev='eth0'/>
|
||||
- <ip family='ipv4' address='172.17.2.4' prefix='24'/>
|
||||
+ <ip family='ipv4' address='172.17.5.4' prefix='24'/>
|
||||
<ip family='ipv6' address='2001:db8:ac10:fd01::20'/>
|
||||
<portForward proto='tcp'>
|
||||
<range start='2022' to='22'/>
|
||||
--
|
||||
2.48.1
|
@ -0,0 +1,41 @@
|
||||
From e1e0d3f8b4b6d6694a57425e6a3f85015cee9225 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <e1e0d3f8b4b6d6694a57425e6a3f85015cee9225.1739815540.git.jdenemar@redhat.com>
|
||||
From: Laine Stump <laine@redhat.com>
|
||||
Date: Sun, 9 Feb 2025 18:23:03 -0500
|
||||
Subject: [PATCH] qemu: automatically set model type='virtio' for interface
|
||||
type='vhostuser'
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Both vdpa and vhostuser require that the guest device be virtio, and
|
||||
for interface type='vdpa', we already set <model type='virtio'/> if it
|
||||
is unspecified in the input XML, so let's be just as courteous for
|
||||
interface type='vhostuser'.
|
||||
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit c4746418d7e952888c0989db3a5c723d888fc32d)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-77086
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
---
|
||||
src/qemu/qemu_postparse.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_postparse.c b/src/qemu/qemu_postparse.c
|
||||
index 049a6ef2dc..892330646a 100644
|
||||
--- a/src/qemu/qemu_postparse.c
|
||||
+++ b/src/qemu/qemu_postparse.c
|
||||
@@ -100,7 +100,8 @@ qemuDomainDeviceNetDefPostParse(virDomainNetDef *net,
|
||||
const virDomainDef *def,
|
||||
virQEMUCaps *qemuCaps)
|
||||
{
|
||||
- if (net->type == VIR_DOMAIN_NET_TYPE_VDPA &&
|
||||
+ if ((net->type == VIR_DOMAIN_NET_TYPE_VDPA ||
|
||||
+ net->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER) &&
|
||||
!virDomainNetGetModelString(net)) {
|
||||
net->model = VIR_DOMAIN_NET_MODEL_VIRTIO;
|
||||
} else if (net->type != VIR_DOMAIN_NET_TYPE_HOSTDEV &&
|
||||
--
|
||||
2.48.1
|
@ -0,0 +1,76 @@
|
||||
From a26297c129ec05c129fda6da57ef8b8330d626be Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <a26297c129ec05c129fda6da57ef8b8330d626be.1739815540.git.jdenemar@redhat.com>
|
||||
From: Peter Krempa <pkrempa@redhat.com>
|
||||
Date: Mon, 10 Feb 2025 17:57:01 +0100
|
||||
Subject: [PATCH] qemu: capabilies: Introduce QEMU_CAPS_BLOCKDEV_SET_ACTIVE
|
||||
|
||||
The flag signals presence of the 'blockdev-set-active' QMP command.
|
||||
|
||||
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
||||
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
(cherry picked from commit b402e167b640bcd242ba518cfd7cbc469dba52e9)
|
||||
|
||||
Conflicts:
|
||||
src/qemu/qemu_capabilities.c
|
||||
src/qemu/qemu_capabilities.h
|
||||
tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml
|
||||
|
||||
Some capabilities were not backported:
|
||||
- QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION_DEPRECATED_PROPS
|
||||
- QEMU_CAPS_MIGRATE_INCOMING_EXIT_ON_ERROR
|
||||
- QEMU_CAPS_MACHINE_VIRT_AIA
|
||||
- QEMU_CAPS_DEVICE_VIRTIO_MEM_CCW
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-78398
|
||||
---
|
||||
src/qemu/qemu_capabilities.c | 2 ++
|
||||
src/qemu/qemu_capabilities.h | 1 +
|
||||
tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml | 1 +
|
||||
3 files changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
|
||||
index dec3199fce..65e19965dd 100644
|
||||
--- a/src/qemu/qemu_capabilities.c
|
||||
+++ b/src/qemu/qemu_capabilities.c
|
||||
@@ -721,6 +721,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
|
||||
"chardev-reconnect-miliseconds", /* QEMU_CAPS_CHARDEV_RECONNECT_MILISECONDS */
|
||||
"virtio-ccw.loadparm", /* QEMU_CAPS_VIRTIO_CCW_DEVICE_LOADPARM */
|
||||
"netdev-stream-reconnect-miliseconds", /* QEMU_CAPS_NETDEV_STREAM_RECONNECT_MILISECONDS */
|
||||
+ "blockdev-set-active", /* QEMU_CAPS_BLOCKDEV_SET_ACTIVE */
|
||||
);
|
||||
|
||||
|
||||
@@ -1242,6 +1243,7 @@ struct virQEMUCapsStringFlags virQEMUCapsCommands[] = {
|
||||
{ "query-stats-schemas", QEMU_CAPS_QUERY_STATS_SCHEMAS },
|
||||
{ "display-reload", QEMU_CAPS_DISPLAY_RELOAD },
|
||||
{ "snapshot-save", QEMU_CAPS_SNAPSHOT_INTERNAL_QMP },
|
||||
+ { "blockdev-set-active", QEMU_CAPS_BLOCKDEV_SET_ACTIVE },
|
||||
};
|
||||
|
||||
struct virQEMUCapsStringFlags virQEMUCapsMigration[] = {
|
||||
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
|
||||
index 48e4530c95..e93e6a01cc 100644
|
||||
--- a/src/qemu/qemu_capabilities.h
|
||||
+++ b/src/qemu/qemu_capabilities.h
|
||||
@@ -700,6 +700,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
|
||||
QEMU_CAPS_CHARDEV_RECONNECT_MILISECONDS, /* 'reconnect-ms' option for chardevs supported */
|
||||
QEMU_CAPS_VIRTIO_CCW_DEVICE_LOADPARM, /* loadparm available on CCW device for multi device boot */
|
||||
QEMU_CAPS_NETDEV_STREAM_RECONNECT_MILISECONDS, /* 'reconnect-ms' option for netdev stream supported */
|
||||
+ QEMU_CAPS_BLOCKDEV_SET_ACTIVE, /* blockdev-set-active QMP command supported */
|
||||
|
||||
QEMU_CAPS_LAST /* this must always be the last item */
|
||||
} virQEMUCapsFlags;
|
||||
diff --git a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml
|
||||
index aed0a58fa7..e09b6e6e1a 100644
|
||||
--- a/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml
|
||||
+++ b/tests/qemucapabilitiesdata/caps_10.0.0_x86_64.xml
|
||||
@@ -210,6 +210,7 @@
|
||||
<flag name='snapshot-internal-qmp'/>
|
||||
<flag name='chardev-reconnect-miliseconds'/>
|
||||
<flag name='netdev-stream-reconnect-miliseconds'/>
|
||||
+ <flag name='blockdev-set-active'/>
|
||||
<version>9002050</version>
|
||||
<microcodeVersion>43100285</microcodeVersion>
|
||||
<package>v9.2.0-1636-gffaf7f0376</package>
|
||||
--
|
||||
2.48.1
|
663
libvirt-qemu-complete-vhostuser-passt-support.patch
Normal file
663
libvirt-qemu-complete-vhostuser-passt-support.patch
Normal file
@ -0,0 +1,663 @@
|
||||
From cdc86b7722beaf209df71b57f76dfbb30c6c7305 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <cdc86b7722beaf209df71b57f76dfbb30c6c7305.1739815540.git.jdenemar@redhat.com>
|
||||
From: Laine Stump <laine@redhat.com>
|
||||
Date: Wed, 12 Feb 2025 16:16:44 -0500
|
||||
Subject: [PATCH] qemu: complete vhostuser + passt support
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
<interface type='vhostuser'><backend type='passt'/> needs to run the
|
||||
passt command just as is done for interface type='user', but then add
|
||||
vhostuser bits to the qemu commandline/monitor command.
|
||||
|
||||
There are some changes to the parsing/validation along with changes to
|
||||
the vhostuser codepath do do the extra stuff for passt. I tried
|
||||
keeping them separated into different patches, but then the unit test
|
||||
failed in a strange way deep down in the bowels of the commandline
|
||||
generation, so this patch both 1) makes the final changes to
|
||||
parsing/formatting and 2) adds passt stuff at appropriate places for
|
||||
vhostuser (as well as making a couple of things *not* happen when the
|
||||
passt backend is chosen). The result is that you can now have:
|
||||
|
||||
<interface type='vhostuser'>
|
||||
<backend type='passt'/>
|
||||
...
|
||||
</interface>
|
||||
|
||||
Then as long as you also have the following as a subelement of
|
||||
<domain>:
|
||||
|
||||
<memoryBacking>
|
||||
<access mode='shared'/>
|
||||
</memoryBacking>
|
||||
|
||||
your passt interfaces will benefit from the greatly improved
|
||||
efficiency of a vhost-user data path, and all without requiring
|
||||
special privileges or capabilities *anywhere* (i.e. it works for
|
||||
unprivileged libvirt (qemu:///session) as well as privileged libvirt).
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-77086
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit 1e9054b9c79d721a55f413c2983c5370044f8f60)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-69455
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
---
|
||||
src/conf/domain_conf.c | 36 ++++++---
|
||||
src/conf/domain_validate.c | 77 +++++++------------
|
||||
src/conf/schemas/domaincommon.rng | 32 +++++++-
|
||||
src/qemu/qemu_command.c | 7 +-
|
||||
src/qemu/qemu_extdevice.c | 6 +-
|
||||
src/qemu/qemu_hotplug.c | 21 ++++-
|
||||
src/qemu/qemu_passt.c | 3 +
|
||||
src/qemu/qemu_process.c | 15 +++-
|
||||
src/qemu/qemu_validate.c | 7 +-
|
||||
...t-user-slirp-portforward.x86_64-latest.err | 2 +-
|
||||
.../net-vhostuser-passt.x86_64-latest.args | 42 ++++++++++
|
||||
.../net-vhostuser-passt.x86_64-latest.xml | 72 +++++++++++++++++
|
||||
tests/qemuxmlconfdata/net-vhostuser-passt.xml | 70 +++++++++++++++++
|
||||
tests/qemuxmlconftest.c | 1 +
|
||||
14 files changed, 317 insertions(+), 74 deletions(-)
|
||||
create mode 100644 tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.args
|
||||
create mode 100644 tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml
|
||||
create mode 100644 tests/qemuxmlconfdata/net-vhostuser-passt.xml
|
||||
|
||||
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
|
||||
index b1e9dda80e..095b9bbaa2 100644
|
||||
--- a/src/conf/domain_conf.c
|
||||
+++ b/src/conf/domain_conf.c
|
||||
@@ -9448,9 +9448,25 @@ virDomainNetBackendParseXML(xmlNodePtr node,
|
||||
g_autofree char *tap = virXMLPropString(node, "tap");
|
||||
g_autofree char *vhost = virXMLPropString(node, "vhost");
|
||||
|
||||
- /* The VIR_DOMAIN_NET_BACKEND_DEFAULT really means 'use hypervisor's
|
||||
- * builtin SLIRP'. It's reported in domain caps and thus we need to accept
|
||||
- * it. Hence VIR_XML_PROP_NONE instead of VIR_XML_PROP_NONZERO. */
|
||||
+ /* In the case of NET_TYPE_USER, backend type can be unspecified
|
||||
+ * (i.e. VIR_DOMAIN_NET_BACKEND_DEFAULT) and that means 'use
|
||||
+ * hypervisor's builtin SLIRP (or if that isn't available, use
|
||||
+ * passt)'. Similarly, it can also be left unspecified in the case
|
||||
+ * of NET_TYPE_VHOSTUSER, and then it means "use the traditional
|
||||
+ * vhost-user backend (which auto-detects between connecting to a
|
||||
+ * socket created by OVS, or connecting to a standalone socket
|
||||
+ * used (mostly in testing) to connect the vhost-user interface of
|
||||
+ * one guest directly to the vhost-user interface of another
|
||||
+ * guest.
|
||||
+ *
|
||||
+ * If backend type is set to 'passt', then in both cases a passt
|
||||
+ * process will be started, and libvirt will connect that to the
|
||||
+ * guest interface (either communicating everything over the
|
||||
+ * socket created by passt using a specific-to-passt protocol
|
||||
+ * (interface type='user'>), or by using the socket for control
|
||||
+ * plane messages and shared memory for data using the vhost-user
|
||||
+ * protocol (<interface type='vhostuser'>)).
|
||||
+ */
|
||||
if (virXMLPropEnum(node, "type", virDomainNetBackendTypeFromString,
|
||||
VIR_XML_PROP_NONE, &def->backend.type) < 0) {
|
||||
return -1;
|
||||
@@ -24581,7 +24597,11 @@ virDomainNetDefFormat(virBuffer *buf,
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
||||
- if (def->data.vhostuser->type == VIR_DOMAIN_CHR_TYPE_UNIX) {
|
||||
+ if (def->data.vhostuser->type == VIR_DOMAIN_CHR_TYPE_UNIX &&
|
||||
+ def->backend.type != VIR_DOMAIN_NET_BACKEND_PASST) {
|
||||
+ /* in the case of BACKEND_PASST, the values of all of these are either
|
||||
+ * fixed (type, mode, reconnect), or derived from elsewhere (path)
|
||||
+ */
|
||||
virBufferAddLit(&sourceAttrBuf, " type='unix'");
|
||||
virBufferEscapeString(&sourceAttrBuf, " path='%s'",
|
||||
def->data.vhostuser->data.nix.path);
|
||||
@@ -24592,7 +24612,6 @@ virDomainNetDefFormat(virBuffer *buf,
|
||||
virDomainChrSourceReconnectDefFormat(&sourceChildBuf,
|
||||
&def->data.vhostuser->data.nix.reconnect);
|
||||
}
|
||||
-
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -24654,15 +24673,14 @@ virDomainNetDefFormat(virBuffer *buf,
|
||||
}
|
||||
|
||||
case VIR_DOMAIN_NET_TYPE_USER:
|
||||
- if (def->backend.type == VIR_DOMAIN_NET_BACKEND_PASST)
|
||||
- virBufferEscapeString(&sourceAttrBuf, " dev='%s'", def->sourceDev);
|
||||
- break;
|
||||
-
|
||||
case VIR_DOMAIN_NET_TYPE_NULL:
|
||||
case VIR_DOMAIN_NET_TYPE_LAST:
|
||||
break;
|
||||
}
|
||||
|
||||
+ if (def->backend.type == VIR_DOMAIN_NET_BACKEND_PASST)
|
||||
+ virBufferEscapeString(&sourceAttrBuf, " dev='%s'", def->sourceDev);
|
||||
+
|
||||
if (def->hostIP.nips || def->hostIP.nroutes) {
|
||||
if (virDomainNetIPInfoFormat(&sourceChildBuf, &def->hostIP) < 0)
|
||||
return -1;
|
||||
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
|
||||
index dacde1f780..597ae3d938 100644
|
||||
--- a/src/conf/domain_validate.c
|
||||
+++ b/src/conf/domain_validate.c
|
||||
@@ -2157,67 +2157,46 @@ virDomainNetDefValidate(const virDomainNetDef *net)
|
||||
return -1;
|
||||
}
|
||||
|
||||
- if (net->type != VIR_DOMAIN_NET_TYPE_USER) {
|
||||
+ if (net->type != VIR_DOMAIN_NET_TYPE_USER &&
|
||||
+ net->type != VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
|
||||
if (net->backend.type == VIR_DOMAIN_NET_BACKEND_PASST) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
- _("The 'passt' backend can only be used with interface type='user'"));
|
||||
+ _("The 'passt' backend can only be used with interface type='user' or type='vhostuser'"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
- if (net->nPortForwards > 0 &&
|
||||
- (net->type != VIR_DOMAIN_NET_TYPE_USER ||
|
||||
- (net->type == VIR_DOMAIN_NET_TYPE_USER &&
|
||||
- net->backend.type != VIR_DOMAIN_NET_BACKEND_PASST))) {
|
||||
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
- _("The <portForward> element can only be used with <interface type='user'> and its 'passt' backend"));
|
||||
- return -1;
|
||||
- }
|
||||
+ if (net->nPortForwards > 0) {
|
||||
+ size_t p;
|
||||
|
||||
- if (!virNetDevBandwidthValidate(net->bandwidth)) {
|
||||
- return -1;
|
||||
- }
|
||||
+ if ((net->type != VIR_DOMAIN_NET_TYPE_USER &&
|
||||
+ net->type != VIR_DOMAIN_NET_TYPE_VHOSTUSER) ||
|
||||
+ net->backend.type != VIR_DOMAIN_NET_BACKEND_PASST) {
|
||||
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
+ _("The <portForward> element can only be used with the 'passt' backend of interface type='user' or type='vhostuser'"));
|
||||
+ return -1;
|
||||
+ }
|
||||
|
||||
- switch (net->type) {
|
||||
- case VIR_DOMAIN_NET_TYPE_USER:
|
||||
- if (net->backend.type == VIR_DOMAIN_NET_BACKEND_PASST) {
|
||||
- size_t p;
|
||||
-
|
||||
- for (p = 0; p < net->nPortForwards; p++) {
|
||||
- size_t r;
|
||||
- virDomainNetPortForward *pf = net->portForwards[p];
|
||||
-
|
||||
- for (r = 0; r < pf->nRanges; r++) {
|
||||
- virDomainNetPortForwardRange *range = pf->ranges[r];
|
||||
-
|
||||
- if (!range->start
|
||||
- && (range->end || range->to
|
||||
- || range->exclude != VIR_TRISTATE_BOOL_ABSENT)) {
|
||||
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
- _("The 'range' of a 'portForward' requires 'start' attribute if 'end', 'to', or 'exclude' is specified"));
|
||||
- return -1;
|
||||
- }
|
||||
+ for (p = 0; p < net->nPortForwards; p++) {
|
||||
+ size_t r;
|
||||
+ virDomainNetPortForward *pf = net->portForwards[p];
|
||||
+
|
||||
+ for (r = 0; r < pf->nRanges; r++) {
|
||||
+ virDomainNetPortForwardRange *range = pf->ranges[r];
|
||||
+
|
||||
+ if (!range->start
|
||||
+ && (range->end || range->to
|
||||
+ || range->exclude != VIR_TRISTATE_BOOL_ABSENT)) {
|
||||
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
+ _("The 'range' of a 'portForward' requires 'start' attribute if 'end', 'to', or 'exclude' is specified"));
|
||||
+ return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
- break;
|
||||
+ }
|
||||
|
||||
- case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
||||
- case VIR_DOMAIN_NET_TYPE_NETWORK:
|
||||
- case VIR_DOMAIN_NET_TYPE_VDPA:
|
||||
- case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
||||
- case VIR_DOMAIN_NET_TYPE_CLIENT:
|
||||
- case VIR_DOMAIN_NET_TYPE_SERVER:
|
||||
- case VIR_DOMAIN_NET_TYPE_MCAST:
|
||||
- case VIR_DOMAIN_NET_TYPE_UDP:
|
||||
- case VIR_DOMAIN_NET_TYPE_INTERNAL:
|
||||
- case VIR_DOMAIN_NET_TYPE_DIRECT:
|
||||
- case VIR_DOMAIN_NET_TYPE_HOSTDEV:
|
||||
- case VIR_DOMAIN_NET_TYPE_VDS:
|
||||
- case VIR_DOMAIN_NET_TYPE_ETHERNET:
|
||||
- case VIR_DOMAIN_NET_TYPE_NULL:
|
||||
- case VIR_DOMAIN_NET_TYPE_LAST:
|
||||
- break;
|
||||
+ if (!virNetDevBandwidthValidate(net->bandwidth)) {
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
|
||||
index cbc093ca7b..d433e95d8b 100644
|
||||
--- a/src/conf/schemas/domaincommon.rng
|
||||
+++ b/src/conf/schemas/domaincommon.rng
|
||||
@@ -3486,8 +3486,36 @@
|
||||
</attribute>
|
||||
<interleave>
|
||||
<optional>
|
||||
- <ref name="unixSocketSource"/>
|
||||
- </optional>
|
||||
+ <element name="source">
|
||||
+ <optional>
|
||||
+ <attribute name="type">
|
||||
+ <value>unix</value>
|
||||
+ </attribute>
|
||||
+ </optional>
|
||||
+ <optional>
|
||||
+ <attribute name="path">
|
||||
+ <ref name="absFilePath"/>
|
||||
+ </attribute>
|
||||
+ </optional>
|
||||
+ <optional>
|
||||
+ <attribute name="mode">
|
||||
+ <choice>
|
||||
+ <value>server</value>
|
||||
+ <value>client</value>
|
||||
+ </choice>
|
||||
+ </attribute>
|
||||
+ </optional>
|
||||
+ <optional>
|
||||
+ <attribute name="dev">
|
||||
+ <ref name="deviceName"/>
|
||||
+ </attribute>
|
||||
+ </optional>
|
||||
+ <optional>
|
||||
+ <ref name="reconnect"/>
|
||||
+ </optional>
|
||||
+ <empty/>
|
||||
+ </element>
|
||||
+ </optional>
|
||||
<ref name="interface-options"/>
|
||||
</interleave>
|
||||
</group>
|
||||
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
|
||||
index 1f28de6194..24dac0ce0f 100644
|
||||
--- a/src/qemu/qemu_command.c
|
||||
+++ b/src/qemu/qemu_command.c
|
||||
@@ -8617,11 +8617,12 @@ qemuBuildInterfaceCommandLine(virQEMUDriver *driver,
|
||||
if (qemuInterfaceVhostuserConnect(cmd, net, qemuCaps) < 0)
|
||||
goto cleanup;
|
||||
|
||||
- if (virNetDevOpenvswitchGetVhostuserIfname(net->data.vhostuser->data.nix.path,
|
||||
+ if (net->backend.type != VIR_DOMAIN_NET_BACKEND_PASST &&
|
||||
+ virNetDevOpenvswitchGetVhostuserIfname(net->data.vhostuser->data.nix.path,
|
||||
net->data.vhostuser->data.nix.listen,
|
||||
- &net->ifname) < 0)
|
||||
+ &net->ifname) < 0) {
|
||||
goto cleanup;
|
||||
-
|
||||
+ }
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_NET_TYPE_VDPA:
|
||||
diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c
|
||||
index 954cb323a4..2384bab7a6 100644
|
||||
--- a/src/qemu/qemu_extdevice.c
|
||||
+++ b/src/qemu/qemu_extdevice.c
|
||||
@@ -212,13 +212,15 @@ qemuExtDevicesStart(virQEMUDriver *driver,
|
||||
for (i = 0; i < def->nnets; i++) {
|
||||
virDomainNetDef *net = def->nets[i];
|
||||
|
||||
- if (net->type != VIR_DOMAIN_NET_TYPE_USER)
|
||||
+ if (net->type != VIR_DOMAIN_NET_TYPE_USER &&
|
||||
+ net->type != VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
|
||||
continue;
|
||||
+ }
|
||||
|
||||
if (net->backend.type == VIR_DOMAIN_NET_BACKEND_PASST) {
|
||||
if (qemuPasstStart(vm, net) < 0)
|
||||
return -1;
|
||||
- } else {
|
||||
+ } else if (net->type == VIR_DOMAIN_NET_TYPE_USER) {
|
||||
if (qemuSlirpStart(vm, net, incomingMigration) < 0)
|
||||
return -1;
|
||||
}
|
||||
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
|
||||
index de0777d330..c8746f5e22 100644
|
||||
--- a/src/qemu/qemu_hotplug.c
|
||||
+++ b/src/qemu/qemu_hotplug.c
|
||||
@@ -1262,10 +1262,23 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
|
||||
if (!(charDevAlias = qemuAliasChardevFromDevAlias(net->info.alias)))
|
||||
goto cleanup;
|
||||
|
||||
- if (virNetDevOpenvswitchGetVhostuserIfname(net->data.vhostuser->data.nix.path,
|
||||
- net->data.vhostuser->data.nix.listen,
|
||||
- &net->ifname) < 0)
|
||||
- goto cleanup;
|
||||
+ if (net->backend.type == VIR_DOMAIN_NET_BACKEND_PASST) {
|
||||
+
|
||||
+ /* vhostuser needs socket path in this location, and when
|
||||
+ * backend is passt, the path is derived from other info,
|
||||
+ * not taken from config.
|
||||
+ */
|
||||
+ g_free(net->data.vhostuser->data.nix.path);
|
||||
+ net->data.vhostuser->data.nix.path = qemuPasstCreateSocketPath(vm, net);
|
||||
+
|
||||
+ if (qemuPasstStart(vm, net) < 0)
|
||||
+ goto cleanup;
|
||||
+ } else {
|
||||
+ if (virNetDevOpenvswitchGetVhostuserIfname(net->data.vhostuser->data.nix.path,
|
||||
+ net->data.vhostuser->data.nix.listen,
|
||||
+ &net->ifname) < 0)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
|
||||
if (qemuSecuritySetNetdevLabel(driver, vm, net) < 0)
|
||||
goto cleanup;
|
||||
diff --git a/src/qemu/qemu_passt.c b/src/qemu/qemu_passt.c
|
||||
index 8a3ac4e988..b9616d1c63 100644
|
||||
--- a/src/qemu/qemu_passt.c
|
||||
+++ b/src/qemu/qemu_passt.c
|
||||
@@ -180,6 +180,9 @@ qemuPasstStart(virDomainObj *vm,
|
||||
|
||||
virCommandClearCaps(cmd);
|
||||
|
||||
+ if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_VHOSTUSER)
|
||||
+ virCommandAddArg(cmd, "--vhost-user");
|
||||
+
|
||||
virCommandAddArgList(cmd,
|
||||
"--one-off",
|
||||
"--socket", passtSocketName,
|
||||
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
|
||||
index 26ca943dfc..7285fd5ce9 100644
|
||||
--- a/src/qemu/qemu_process.c
|
||||
+++ b/src/qemu/qemu_process.c
|
||||
@@ -64,6 +64,7 @@
|
||||
#include "qemu_backup.h"
|
||||
#include "qemu_dbus.h"
|
||||
#include "qemu_snapshot.h"
|
||||
+#include "qemu_passt.h"
|
||||
|
||||
#include "cpu/cpu.h"
|
||||
#include "cpu/cpu_x86.h"
|
||||
@@ -5932,12 +5933,23 @@ qemuProcessPrepareDomainNetwork(virDomainObj *vm)
|
||||
}
|
||||
break;
|
||||
|
||||
+ case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
||||
+ if (net->backend.type == VIR_DOMAIN_NET_BACKEND_PASST) {
|
||||
+ /* when using the passt backend, the path of the
|
||||
+ * unix socket is always derived from other info
|
||||
+ * *not* manually given in the config, but all the
|
||||
+ * vhostuser code looks for it there.
|
||||
+ */
|
||||
+ g_free(net->data.vhostuser->data.nix.path);
|
||||
+ net->data.vhostuser->data.nix.path = qemuPasstCreateSocketPath(vm, net);
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
case VIR_DOMAIN_NET_TYPE_DIRECT:
|
||||
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
||||
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
||||
case VIR_DOMAIN_NET_TYPE_ETHERNET:
|
||||
case VIR_DOMAIN_NET_TYPE_USER:
|
||||
- case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
||||
case VIR_DOMAIN_NET_TYPE_SERVER:
|
||||
case VIR_DOMAIN_NET_TYPE_CLIENT:
|
||||
case VIR_DOMAIN_NET_TYPE_MCAST:
|
||||
@@ -5949,7 +5961,6 @@ qemuProcessPrepareDomainNetwork(virDomainObj *vm)
|
||||
case VIR_DOMAIN_NET_TYPE_LAST:
|
||||
break;
|
||||
}
|
||||
-
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
|
||||
index eb8c5366f6..f33c0c07b4 100644
|
||||
--- a/src/qemu/qemu_validate.c
|
||||
+++ b/src/qemu/qemu_validate.c
|
||||
@@ -1736,7 +1736,9 @@ qemuValidateDomainDeviceDefNetwork(const virDomainNetDef *net,
|
||||
return -1;
|
||||
}
|
||||
|
||||
- if (net->type == VIR_DOMAIN_NET_TYPE_USER) {
|
||||
+ if (net->type == VIR_DOMAIN_NET_TYPE_USER ||
|
||||
+ (net->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER &&
|
||||
+ net->backend.type == VIR_DOMAIN_NET_BACKEND_PASST)) {
|
||||
virDomainCapsDeviceNet netCaps = { };
|
||||
|
||||
virQEMUCapsFillDomainDeviceNetCaps(qemuCaps, &netCaps);
|
||||
@@ -1811,7 +1813,8 @@ qemuValidateDomainDeviceDefNetwork(const virDomainNetDef *net,
|
||||
}
|
||||
|
||||
if (net->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
|
||||
- if (!net->data.vhostuser->data.nix.path) {
|
||||
+ if (!net->data.vhostuser->data.nix.path &&
|
||||
+ net->backend.type != VIR_DOMAIN_NET_BACKEND_PASST) {
|
||||
virReportError(VIR_ERR_XML_ERROR,
|
||||
_("Missing required attribute '%1$s' in element '%2$s'"),
|
||||
"path", "source");
|
||||
diff --git a/tests/qemuxmlconfdata/net-user-slirp-portforward.x86_64-latest.err b/tests/qemuxmlconfdata/net-user-slirp-portforward.x86_64-latest.err
|
||||
index eaa934742e..e231677e57 100644
|
||||
--- a/tests/qemuxmlconfdata/net-user-slirp-portforward.x86_64-latest.err
|
||||
+++ b/tests/qemuxmlconfdata/net-user-slirp-portforward.x86_64-latest.err
|
||||
@@ -1 +1 @@
|
||||
-unsupported configuration: The <portForward> element can only be used with <interface type='user'> and its 'passt' backend
|
||||
+unsupported configuration: The <portForward> element can only be used with the 'passt' backend of interface type='user' or type='vhostuser'
|
||||
diff --git a/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.args b/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.args
|
||||
new file mode 100644
|
||||
index 0000000000..21d78d6072
|
||||
--- /dev/null
|
||||
+++ b/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.args
|
||||
@@ -0,0 +1,42 @@
|
||||
+LC_ALL=C \
|
||||
+PATH=/bin \
|
||||
+HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \
|
||||
+USER=test \
|
||||
+LOGNAME=test \
|
||||
+XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \
|
||||
+XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \
|
||||
+XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
|
||||
+/usr/bin/qemu-system-x86_64 \
|
||||
+-name guest=QEMUGuest1,debug-threads=on \
|
||||
+-S \
|
||||
+-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \
|
||||
+-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
|
||||
+-accel tcg \
|
||||
+-cpu qemu64 \
|
||||
+-m size=219136k \
|
||||
+-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \
|
||||
+-overcommit mem-lock=off \
|
||||
+-smp 1,sockets=1,cores=1,threads=1 \
|
||||
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
|
||||
+-display none \
|
||||
+-no-user-config \
|
||||
+-nodefaults \
|
||||
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
|
||||
+-mon chardev=charmonitor,id=monitor,mode=control \
|
||||
+-rtc base=utc \
|
||||
+-no-shutdown \
|
||||
+-boot strict=on \
|
||||
+-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","read-only":false}' \
|
||||
+-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-storage","id":"ide0-0-0","bootindex":1}' \
|
||||
+-chardev socket,id=charnet0,path=/var/run/libvirt/qemu/passt/-1-QEMUGuest1-net0.socket \
|
||||
+-netdev '{"type":"vhost-user","chardev":"charnet0","id":"hostnet0"}' \
|
||||
+-device '{"driver":"virtio-net-pci","netdev":"hostnet0","id":"net0","mac":"00:11:22:33:44:55","bus":"pci.0","addr":"0x2"}' \
|
||||
+-chardev socket,id=charnet1,path=/var/run/libvirt/qemu/passt/-1-QEMUGuest1-net1.socket \
|
||||
+-netdev '{"type":"vhost-user","chardev":"charnet1","id":"hostnet1"}' \
|
||||
+-device '{"driver":"virtio-net-pci","netdev":"hostnet1","id":"net1","mac":"00:11:22:33:44:11","bus":"pci.0","addr":"0x3"}' \
|
||||
+-chardev socket,id=charnet2,path=/var/run/libvirt/qemu/passt/-1-QEMUGuest1-net2.socket \
|
||||
+-netdev '{"type":"vhost-user","chardev":"charnet2","id":"hostnet2"}' \
|
||||
+-device '{"driver":"virtio-net-pci","netdev":"hostnet2","id":"net2","mac":"00:11:22:33:44:11","bus":"pci.0","addr":"0x4"}' \
|
||||
+-audiodev '{"id":"audio1","driver":"none"}' \
|
||||
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
|
||||
+-msg timestamp=on
|
||||
diff --git a/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml b/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml
|
||||
new file mode 100644
|
||||
index 0000000000..26aa4c8d05
|
||||
--- /dev/null
|
||||
+++ b/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml
|
||||
@@ -0,0 +1,72 @@
|
||||
+<domain type='qemu'>
|
||||
+ <name>QEMUGuest1</name>
|
||||
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||
+ <memory unit='KiB'>219136</memory>
|
||||
+ <currentMemory unit='KiB'>219136</currentMemory>
|
||||
+ <vcpu placement='static'>1</vcpu>
|
||||
+ <os>
|
||||
+ <type arch='x86_64' machine='pc'>hvm</type>
|
||||
+ <boot dev='hd'/>
|
||||
+ </os>
|
||||
+ <cpu mode='custom' match='exact' check='none'>
|
||||
+ <model fallback='forbid'>qemu64</model>
|
||||
+ </cpu>
|
||||
+ <clock offset='utc'/>
|
||||
+ <on_poweroff>destroy</on_poweroff>
|
||||
+ <on_reboot>restart</on_reboot>
|
||||
+ <on_crash>destroy</on_crash>
|
||||
+ <devices>
|
||||
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
|
||||
+ <disk type='block' device='disk'>
|
||||
+ <driver name='qemu' type='raw'/>
|
||||
+ <source dev='/dev/HostVG/QEMUGuest1'/>
|
||||
+ <target dev='hda' bus='ide'/>
|
||||
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
|
||||
+ </disk>
|
||||
+ <controller type='usb' index='0' model='none'/>
|
||||
+ <controller type='ide' index='0'>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
|
||||
+ </controller>
|
||||
+ <controller type='pci' index='0' model='pci-root'/>
|
||||
+ <interface type='vhostuser'>
|
||||
+ <mac address='00:11:22:33:44:55'/>
|
||||
+ <ip address='172.17.2.0' family='ipv4' prefix='24'/>
|
||||
+ <ip address='2001:db8:ac10:fd01::feed' family='ipv6'/>
|
||||
+ <portForward proto='tcp' address='2001:db8:ac10:fd01::1:10'>
|
||||
+ <range start='22' to='2022'/>
|
||||
+ <range start='1000' end='1050'/>
|
||||
+ <range start='1020' exclude='yes'/>
|
||||
+ <range start='1030' end='1040' exclude='yes'/>
|
||||
+ </portForward>
|
||||
+ <portForward proto='udp' address='1.2.3.4' dev='eth0'>
|
||||
+ <range start='5000' end='5020' to='6000'/>
|
||||
+ <range start='5010' end='5015' exclude='yes'/>
|
||||
+ </portForward>
|
||||
+ <portForward proto='tcp'>
|
||||
+ <range start='80'/>
|
||||
+ </portForward>
|
||||
+ <portForward proto='tcp'>
|
||||
+ <range start='443' to='344'/>
|
||||
+ </portForward>
|
||||
+ <model type='virtio'/>
|
||||
+ <backend type='passt' logFile='/var/log/loglaw.blog'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
|
||||
+ </interface>
|
||||
+ <interface type='vhostuser'>
|
||||
+ <mac address='00:11:22:33:44:11'/>
|
||||
+ <model type='virtio'/>
|
||||
+ <backend type='passt'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
||||
+ </interface>
|
||||
+ <interface type='vhostuser'>
|
||||
+ <mac address='00:11:22:33:44:11'/>
|
||||
+ <model type='virtio'/>
|
||||
+ <backend type='passt'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
|
||||
+ </interface>
|
||||
+ <input type='mouse' bus='ps2'/>
|
||||
+ <input type='keyboard' bus='ps2'/>
|
||||
+ <audio id='1' type='none'/>
|
||||
+ <memballoon model='none'/>
|
||||
+ </devices>
|
||||
+</domain>
|
||||
diff --git a/tests/qemuxmlconfdata/net-vhostuser-passt.xml b/tests/qemuxmlconfdata/net-vhostuser-passt.xml
|
||||
new file mode 100644
|
||||
index 0000000000..e44c91e541
|
||||
--- /dev/null
|
||||
+++ b/tests/qemuxmlconfdata/net-vhostuser-passt.xml
|
||||
@@ -0,0 +1,70 @@
|
||||
+<domain type='qemu'>
|
||||
+ <name>QEMUGuest1</name>
|
||||
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||
+ <memory unit='KiB'>219136</memory>
|
||||
+ <currentMemory unit='KiB'>219136</currentMemory>
|
||||
+ <vcpu placement='static'>1</vcpu>
|
||||
+ <os>
|
||||
+ <type arch='x86_64' machine='pc'>hvm</type>
|
||||
+ <boot dev='hd'/>
|
||||
+ </os>
|
||||
+ <clock offset='utc'/>
|
||||
+ <on_poweroff>destroy</on_poweroff>
|
||||
+ <on_reboot>restart</on_reboot>
|
||||
+ <on_crash>destroy</on_crash>
|
||||
+ <devices>
|
||||
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
|
||||
+ <disk type='block' device='disk'>
|
||||
+ <driver name='qemu' type='raw'/>
|
||||
+ <source dev='/dev/HostVG/QEMUGuest1'/>
|
||||
+ <target dev='hda' bus='ide'/>
|
||||
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
|
||||
+ </disk>
|
||||
+ <controller type='usb' index='0' model='none'/>
|
||||
+ <controller type='ide' index='0'>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
|
||||
+ </controller>
|
||||
+ <controller type='pci' index='0' model='pci-root'/>
|
||||
+ <interface type='vhostuser'>
|
||||
+ <mac address='00:11:22:33:44:55'/>
|
||||
+ <ip address='172.17.2.0' family='ipv4' prefix='24'/>
|
||||
+ <ip address='2001:db8:ac10:fd01::feed' family='ipv6'/>
|
||||
+ <source dev='eth42'/>
|
||||
+ <portForward proto='tcp' address='2001:db8:ac10:fd01::1:10'>
|
||||
+ <range start='22' to='2022'/>
|
||||
+ <range start='1000' end='1050'/>
|
||||
+ <range start='1020' exclude='yes'/>
|
||||
+ <range start='1030' end='1040' exclude='yes'/>
|
||||
+ </portForward>
|
||||
+ <portForward proto='udp' address='1.2.3.4' dev='eth0'>
|
||||
+ <range start='5000' end='5020' to='6000'/>
|
||||
+ <range start='5010' end='5015' exclude='yes'/>
|
||||
+ </portForward>
|
||||
+ <portForward proto='tcp'>
|
||||
+ <range start='80'/>
|
||||
+ </portForward>
|
||||
+ <portForward proto='tcp'>
|
||||
+ <range start='443' to='344'/>
|
||||
+ </portForward>
|
||||
+ <model type='virtio'/>
|
||||
+ <backend type='passt' logFile='/var/log/loglaw.blog'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
|
||||
+ </interface>
|
||||
+ <interface type='vhostuser'>
|
||||
+ <mac address='00:11:22:33:44:11'/>
|
||||
+ <backend type='passt'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
||||
+ </interface>
|
||||
+ <interface type='vhostuser'>
|
||||
+ <mac address='00:11:22:33:44:11'/>
|
||||
+ <source dev='eth43'/>
|
||||
+ <model type='virtio'/>
|
||||
+ <backend type='passt'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
|
||||
+ </interface>
|
||||
+ <input type='mouse' bus='ps2'/>
|
||||
+ <input type='keyboard' bus='ps2'/>
|
||||
+ <audio id='1' type='none'/>
|
||||
+ <memballoon model='none'/>
|
||||
+ </devices>
|
||||
+</domain>
|
||||
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
|
||||
index 821d9b1048..9603984b60 100644
|
||||
--- a/tests/qemuxmlconftest.c
|
||||
+++ b/tests/qemuxmlconftest.c
|
||||
@@ -1791,6 +1791,7 @@ mymain(void)
|
||||
DO_TEST_CAPS_LATEST("net-user-passt");
|
||||
DO_TEST_CAPS_VER("net-user-passt", "7.2.0");
|
||||
DO_TEST_CAPS_LATEST_PARSE_ERROR("net-user-slirp-portforward");
|
||||
+ DO_TEST_CAPS_LATEST("net-vhostuser-passt");
|
||||
DO_TEST_CAPS_LATEST("net-virtio");
|
||||
DO_TEST_CAPS_LATEST("net-virtio-device");
|
||||
DO_TEST_CAPS_LATEST("net-virtio-disable-offloads");
|
||||
--
|
||||
2.48.1
|
@ -0,0 +1,75 @@
|
||||
From 83cb107badafc54fcd29eb000121d784cde92d84 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <83cb107badafc54fcd29eb000121d784cde92d84.1739815540.git.jdenemar@redhat.com>
|
||||
From: Laine Stump <laine@redhat.com>
|
||||
Date: Sun, 9 Feb 2025 19:01:32 -0500
|
||||
Subject: [PATCH] qemu: do all vhostuser attribute validation in qemu driver
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Since vhostuser is only used/supported by the QEMU driver, and all the
|
||||
rest of the vhostuser-specific validation is done in QEMU's
|
||||
validation, lets move the final check (to see if they've tried to
|
||||
enable auto-reconnect when this interface is on the server side of the
|
||||
vhostuser socket) to the QEMU validate.
|
||||
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit 56f4cc167a6c93ec420c82f15a265ec08469279d)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-77086
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
---
|
||||
src/conf/domain_validate.c | 10 +---------
|
||||
src/qemu/qemu_validate.c | 8 ++++++++
|
||||
2 files changed, 9 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
|
||||
index f56ff5b7bb..dacde1f780 100644
|
||||
--- a/src/conf/domain_validate.c
|
||||
+++ b/src/conf/domain_validate.c
|
||||
@@ -2179,15 +2179,6 @@ virDomainNetDefValidate(const virDomainNetDef *net)
|
||||
}
|
||||
|
||||
switch (net->type) {
|
||||
- case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
||||
- if (net->data.vhostuser->data.nix.listen &&
|
||||
- net->data.vhostuser->data.nix.reconnect.enabled == VIR_TRISTATE_BOOL_YES) {
|
||||
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
- _("'reconnect' attribute unsupported 'server' mode for <interface type='vhostuser'>"));
|
||||
- return -1;
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
case VIR_DOMAIN_NET_TYPE_USER:
|
||||
if (net->backend.type == VIR_DOMAIN_NET_BACKEND_PASST) {
|
||||
size_t p;
|
||||
@@ -2211,6 +2202,7 @@ virDomainNetDefValidate(const virDomainNetDef *net)
|
||||
}
|
||||
break;
|
||||
|
||||
+ case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
||||
case VIR_DOMAIN_NET_TYPE_NETWORK:
|
||||
case VIR_DOMAIN_NET_TYPE_VDPA:
|
||||
case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
||||
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
|
||||
index 841d320541..b7b2e3d0af 100644
|
||||
--- a/src/qemu/qemu_validate.c
|
||||
+++ b/src/qemu/qemu_validate.c
|
||||
@@ -1810,6 +1810,14 @@ qemuValidateDomainDeviceDefNetwork(const virDomainNetDef *net,
|
||||
}
|
||||
}
|
||||
|
||||
+ if (net->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER &&
|
||||
+ net->data.vhostuser->data.nix.listen &&
|
||||
+ net->data.vhostuser->data.nix.reconnect.enabled == VIR_TRISTATE_BOOL_YES) {
|
||||
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
+ _("'reconnect' attribute is not supported when source mode='server' for <interface type='vhostuser'>"));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
if (!virDomainNetIsVirtioModel(net)) {
|
||||
if (net->type == VIR_DOMAIN_NET_TYPE_VDPA ||
|
||||
net->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
|
||||
--
|
||||
2.48.1
|
@ -0,0 +1,203 @@
|
||||
From bd90132d08a4222f4103873b8532fb8b5d999018 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <bd90132d08a4222f4103873b8532fb8b5d999018.1739815540.git.jdenemar@redhat.com>
|
||||
From: Laine Stump <laine@redhat.com>
|
||||
Date: Fri, 14 Feb 2025 13:10:19 -0500
|
||||
Subject: [PATCH] qemu: fail validation if a domain def has vhostuser/passt but
|
||||
no shared mem
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This can/should also be done for a traditional vhost-user interface
|
||||
(ie not backend type='passt') but that will be a separate change.
|
||||
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit 70bce2e6ee7a6b738d08fa79d14342969f51668b)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-77086
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
---
|
||||
src/qemu/qemu_validate.c | 9 ++-
|
||||
...vhostuser-passt-no-shmem.x86_64-latest.err | 1 +
|
||||
.../net-vhostuser-passt-no-shmem.xml | 70 +++++++++++++++++++
|
||||
.../net-vhostuser-passt.x86_64-latest.args | 2 +-
|
||||
.../net-vhostuser-passt.x86_64-latest.xml | 3 +
|
||||
tests/qemuxmlconfdata/net-vhostuser-passt.xml | 3 +
|
||||
tests/qemuxmlconftest.c | 1 +
|
||||
7 files changed, 87 insertions(+), 2 deletions(-)
|
||||
create mode 100644 tests/qemuxmlconfdata/net-vhostuser-passt-no-shmem.x86_64-latest.err
|
||||
create mode 100644 tests/qemuxmlconfdata/net-vhostuser-passt-no-shmem.xml
|
||||
|
||||
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
|
||||
index f33c0c07b4..289a3f94cc 100644
|
||||
--- a/src/qemu/qemu_validate.c
|
||||
+++ b/src/qemu/qemu_validate.c
|
||||
@@ -1724,6 +1724,7 @@ qemuValidateDomainDefVhostUserRequireSharedMemory(const virDomainDef *def,
|
||||
|
||||
static int
|
||||
qemuValidateDomainDeviceDefNetwork(const virDomainNetDef *net,
|
||||
+ const virDomainDef *def,
|
||||
virQEMUCaps *qemuCaps)
|
||||
{
|
||||
bool hasIPv4 = false;
|
||||
@@ -1804,6 +1805,12 @@ qemuValidateDomainDeviceDefNetwork(const virDomainNetDef *net,
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ if (net->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER &&
|
||||
+ net->backend.type == VIR_DOMAIN_NET_BACKEND_PASST) {
|
||||
+ if (qemuValidateDomainDefVhostUserRequireSharedMemory(def, "interface type=\"vhostuser\" backend type=\"passt\"") < 0)
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
if (net->type == VIR_DOMAIN_NET_TYPE_VDPA) {
|
||||
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_NETDEV_VHOST_VDPA)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
@@ -5400,7 +5407,7 @@ qemuValidateDomainDeviceDef(const virDomainDeviceDef *dev,
|
||||
|
||||
switch (dev->type) {
|
||||
case VIR_DOMAIN_DEVICE_NET:
|
||||
- return qemuValidateDomainDeviceDefNetwork(dev->data.net, qemuCaps);
|
||||
+ return qemuValidateDomainDeviceDefNetwork(dev->data.net, def, qemuCaps);
|
||||
|
||||
case VIR_DOMAIN_DEVICE_CHR:
|
||||
return qemuValidateDomainChrDef(dev->data.chr, def, qemuCaps);
|
||||
diff --git a/tests/qemuxmlconfdata/net-vhostuser-passt-no-shmem.x86_64-latest.err b/tests/qemuxmlconfdata/net-vhostuser-passt-no-shmem.x86_64-latest.err
|
||||
new file mode 100644
|
||||
index 0000000000..274af5c722
|
||||
--- /dev/null
|
||||
+++ b/tests/qemuxmlconfdata/net-vhostuser-passt-no-shmem.x86_64-latest.err
|
||||
@@ -0,0 +1 @@
|
||||
+unsupported configuration: 'interface type="vhostuser" backend type="passt"' requires shared memory
|
||||
diff --git a/tests/qemuxmlconfdata/net-vhostuser-passt-no-shmem.xml b/tests/qemuxmlconfdata/net-vhostuser-passt-no-shmem.xml
|
||||
new file mode 100644
|
||||
index 0000000000..e44c91e541
|
||||
--- /dev/null
|
||||
+++ b/tests/qemuxmlconfdata/net-vhostuser-passt-no-shmem.xml
|
||||
@@ -0,0 +1,70 @@
|
||||
+<domain type='qemu'>
|
||||
+ <name>QEMUGuest1</name>
|
||||
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||
+ <memory unit='KiB'>219136</memory>
|
||||
+ <currentMemory unit='KiB'>219136</currentMemory>
|
||||
+ <vcpu placement='static'>1</vcpu>
|
||||
+ <os>
|
||||
+ <type arch='x86_64' machine='pc'>hvm</type>
|
||||
+ <boot dev='hd'/>
|
||||
+ </os>
|
||||
+ <clock offset='utc'/>
|
||||
+ <on_poweroff>destroy</on_poweroff>
|
||||
+ <on_reboot>restart</on_reboot>
|
||||
+ <on_crash>destroy</on_crash>
|
||||
+ <devices>
|
||||
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
|
||||
+ <disk type='block' device='disk'>
|
||||
+ <driver name='qemu' type='raw'/>
|
||||
+ <source dev='/dev/HostVG/QEMUGuest1'/>
|
||||
+ <target dev='hda' bus='ide'/>
|
||||
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
|
||||
+ </disk>
|
||||
+ <controller type='usb' index='0' model='none'/>
|
||||
+ <controller type='ide' index='0'>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
|
||||
+ </controller>
|
||||
+ <controller type='pci' index='0' model='pci-root'/>
|
||||
+ <interface type='vhostuser'>
|
||||
+ <mac address='00:11:22:33:44:55'/>
|
||||
+ <ip address='172.17.2.0' family='ipv4' prefix='24'/>
|
||||
+ <ip address='2001:db8:ac10:fd01::feed' family='ipv6'/>
|
||||
+ <source dev='eth42'/>
|
||||
+ <portForward proto='tcp' address='2001:db8:ac10:fd01::1:10'>
|
||||
+ <range start='22' to='2022'/>
|
||||
+ <range start='1000' end='1050'/>
|
||||
+ <range start='1020' exclude='yes'/>
|
||||
+ <range start='1030' end='1040' exclude='yes'/>
|
||||
+ </portForward>
|
||||
+ <portForward proto='udp' address='1.2.3.4' dev='eth0'>
|
||||
+ <range start='5000' end='5020' to='6000'/>
|
||||
+ <range start='5010' end='5015' exclude='yes'/>
|
||||
+ </portForward>
|
||||
+ <portForward proto='tcp'>
|
||||
+ <range start='80'/>
|
||||
+ </portForward>
|
||||
+ <portForward proto='tcp'>
|
||||
+ <range start='443' to='344'/>
|
||||
+ </portForward>
|
||||
+ <model type='virtio'/>
|
||||
+ <backend type='passt' logFile='/var/log/loglaw.blog'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
|
||||
+ </interface>
|
||||
+ <interface type='vhostuser'>
|
||||
+ <mac address='00:11:22:33:44:11'/>
|
||||
+ <backend type='passt'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
||||
+ </interface>
|
||||
+ <interface type='vhostuser'>
|
||||
+ <mac address='00:11:22:33:44:11'/>
|
||||
+ <source dev='eth43'/>
|
||||
+ <model type='virtio'/>
|
||||
+ <backend type='passt'/>
|
||||
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
|
||||
+ </interface>
|
||||
+ <input type='mouse' bus='ps2'/>
|
||||
+ <input type='keyboard' bus='ps2'/>
|
||||
+ <audio id='1' type='none'/>
|
||||
+ <memballoon model='none'/>
|
||||
+ </devices>
|
||||
+</domain>
|
||||
diff --git a/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.args b/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.args
|
||||
index 21d78d6072..7c030d7067 100644
|
||||
--- a/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.args
|
||||
+++ b/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.args
|
||||
@@ -14,7 +14,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
|
||||
-accel tcg \
|
||||
-cpu qemu64 \
|
||||
-m size=219136k \
|
||||
--object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \
|
||||
+-object '{"qom-type":"memory-backend-file","id":"pc.ram","mem-path":"/var/lib/libvirt/qemu/ram/-1-QEMUGuest1/pc.ram","share":true,"x-use-canonical-path-for-ramblock-id":false,"size":224395264}' \
|
||||
-overcommit mem-lock=off \
|
||||
-smp 1,sockets=1,cores=1,threads=1 \
|
||||
-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
|
||||
diff --git a/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml b/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml
|
||||
index 26aa4c8d05..a1f9366722 100644
|
||||
--- a/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml
|
||||
+++ b/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml
|
||||
@@ -3,6 +3,9 @@
|
||||
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||
<memory unit='KiB'>219136</memory>
|
||||
<currentMemory unit='KiB'>219136</currentMemory>
|
||||
+ <memoryBacking>
|
||||
+ <access mode='shared'/>
|
||||
+ </memoryBacking>
|
||||
<vcpu placement='static'>1</vcpu>
|
||||
<os>
|
||||
<type arch='x86_64' machine='pc'>hvm</type>
|
||||
diff --git a/tests/qemuxmlconfdata/net-vhostuser-passt.xml b/tests/qemuxmlconfdata/net-vhostuser-passt.xml
|
||||
index e44c91e541..71b845329b 100644
|
||||
--- a/tests/qemuxmlconfdata/net-vhostuser-passt.xml
|
||||
+++ b/tests/qemuxmlconfdata/net-vhostuser-passt.xml
|
||||
@@ -3,6 +3,9 @@
|
||||
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||
<memory unit='KiB'>219136</memory>
|
||||
<currentMemory unit='KiB'>219136</currentMemory>
|
||||
+ <memoryBacking>
|
||||
+ <access mode='shared'/>
|
||||
+ </memoryBacking>
|
||||
<vcpu placement='static'>1</vcpu>
|
||||
<os>
|
||||
<type arch='x86_64' machine='pc'>hvm</type>
|
||||
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
|
||||
index 9603984b60..3947f508a2 100644
|
||||
--- a/tests/qemuxmlconftest.c
|
||||
+++ b/tests/qemuxmlconftest.c
|
||||
@@ -1792,6 +1792,7 @@ mymain(void)
|
||||
DO_TEST_CAPS_VER("net-user-passt", "7.2.0");
|
||||
DO_TEST_CAPS_LATEST_PARSE_ERROR("net-user-slirp-portforward");
|
||||
DO_TEST_CAPS_LATEST("net-vhostuser-passt");
|
||||
+ DO_TEST_CAPS_LATEST_PARSE_ERROR("net-vhostuser-passt-no-shmem");
|
||||
DO_TEST_CAPS_LATEST("net-virtio");
|
||||
DO_TEST_CAPS_LATEST("net-virtio-device");
|
||||
DO_TEST_CAPS_LATEST("net-virtio-disable-offloads");
|
||||
--
|
||||
2.48.1
|
@ -0,0 +1,94 @@
|
||||
From eb843b8d21a68b245d53c0e54ec064918eb1e775 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <eb843b8d21a68b245d53c0e54ec064918eb1e775.1739815540.git.jdenemar@redhat.com>
|
||||
From: Laine Stump <laine@redhat.com>
|
||||
Date: Tue, 4 Feb 2025 16:06:18 -0500
|
||||
Subject: [PATCH] qemu: fix qemu validation to forbid guest-side IP address for
|
||||
type='vdpa'
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Because all the checks for VIR_DOMAIN_NET_TYPE_VDPA were inside an
|
||||
else-if clause that was immediately followed by another else-if clause
|
||||
that forbid setting guestIP.ips or guestIP.routes, we've been allowing
|
||||
users to set guestIP.* for vdpa interfaces (but then not doing
|
||||
validation of the attributes that should have been done if we *did*
|
||||
support setting IPs for vdpa (but we don't anyway, so :shrug:.)
|
||||
|
||||
This can be fixed by turning the vdpa else-if clause into a top-level
|
||||
if - this way vdpa interfaces will hit the "else if
|
||||
(net->guestIP.nips)" clause and reject guest-side IP address setting.
|
||||
|
||||
Also, since there are currently *no* interface types for QEMU that
|
||||
support adding guest-side routes, we put that check by itself (I think
|
||||
it may be possible to set some guest routes for passt interfaces, but
|
||||
we don't do that)
|
||||
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit 6345ee60d87a6490a51a58527dc9b47e4d0264f9)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-77086
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
---
|
||||
src/qemu/qemu_validate.c | 24 +++++++++++++-----------
|
||||
1 file changed, 13 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
|
||||
index aaa056379e..9310457cb1 100644
|
||||
--- a/src/qemu/qemu_validate.c
|
||||
+++ b/src/qemu/qemu_validate.c
|
||||
@@ -1730,6 +1730,12 @@ qemuValidateDomainDeviceDefNetwork(const virDomainNetDef *net,
|
||||
bool hasIPv6 = false;
|
||||
size_t i;
|
||||
|
||||
+ if (net->guestIP.nroutes) {
|
||||
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
+ _("Invalid attempt to set network interface guest-side IP route, not supported by QEMU"));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
if (net->type == VIR_DOMAIN_NET_TYPE_USER) {
|
||||
virDomainCapsDeviceNet netCaps = { };
|
||||
|
||||
@@ -1743,12 +1749,6 @@ qemuValidateDomainDeviceDefNetwork(const virDomainNetDef *net,
|
||||
return -1;
|
||||
}
|
||||
|
||||
- if (net->guestIP.nroutes) {
|
||||
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
- _("Invalid attempt to set network interface guest-side IP route, not supported by QEMU"));
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
for (i = 0; i < net->guestIP.nips; i++) {
|
||||
const virNetDevIPAddr *ip = net->guestIP.ips[i];
|
||||
|
||||
@@ -1796,7 +1796,13 @@ qemuValidateDomainDeviceDefNetwork(const virDomainNetDef *net,
|
||||
}
|
||||
}
|
||||
}
|
||||
- } else if (net->type == VIR_DOMAIN_NET_TYPE_VDPA) {
|
||||
+ } else if (net->guestIP.nips) {
|
||||
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
+ _("Invalid attempt to set network interface guest-side IP address info, not supported by QEMU"));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (net->type == VIR_DOMAIN_NET_TYPE_VDPA) {
|
||||
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_NETDEV_VHOST_VDPA)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("vDPA devices are not supported with this QEMU binary"));
|
||||
@@ -1810,10 +1816,6 @@ qemuValidateDomainDeviceDefNetwork(const virDomainNetDef *net,
|
||||
virDomainNetModelTypeToString(net->model));
|
||||
return -1;
|
||||
}
|
||||
- } else if (net->guestIP.nroutes || net->guestIP.nips) {
|
||||
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
- _("Invalid attempt to set network interface guest-side IP route and/or address info, not supported by QEMU"));
|
||||
- return -1;
|
||||
}
|
||||
|
||||
if (virDomainNetIsVirtioModel(net)) {
|
||||
--
|
||||
2.48.1
|
51
libvirt-qemu-make-qemuPasstCreateSocketPath-public.patch
Normal file
51
libvirt-qemu-make-qemuPasstCreateSocketPath-public.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From 7128909f7a0227a2977345e56ccc0516cc07ea05 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <7128909f7a0227a2977345e56ccc0516cc07ea05.1739815540.git.jdenemar@redhat.com>
|
||||
From: Laine Stump <laine@redhat.com>
|
||||
Date: Wed, 12 Feb 2025 12:12:04 -0500
|
||||
Subject: [PATCH] qemu: make qemuPasstCreateSocketPath() public
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
When passt is used with vhostuser, the vhostuser code that builds the
|
||||
qemu commandline will need to have the same socket path that is given
|
||||
to the passt command, so this patch makes it visible outside of
|
||||
qemu_passt.c.
|
||||
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit 7b7c56c3b81c0f525c6b2f1c89e0ef070bb4fb19)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-77086
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
---
|
||||
src/qemu/qemu_passt.c | 2 +-
|
||||
src/qemu/qemu_passt.h | 3 +++
|
||||
2 files changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_passt.c b/src/qemu/qemu_passt.c
|
||||
index dd4a8bb997..8a3ac4e988 100644
|
||||
--- a/src/qemu/qemu_passt.c
|
||||
+++ b/src/qemu/qemu_passt.c
|
||||
@@ -54,7 +54,7 @@ qemuPasstCreatePidFilename(virDomainObj *vm,
|
||||
}
|
||||
|
||||
|
||||
-static char *
|
||||
+char *
|
||||
qemuPasstCreateSocketPath(virDomainObj *vm,
|
||||
virDomainNetDef *net)
|
||||
{
|
||||
diff --git a/src/qemu/qemu_passt.h b/src/qemu/qemu_passt.h
|
||||
index 623b494b7a..e0b9aaac8d 100644
|
||||
--- a/src/qemu/qemu_passt.h
|
||||
+++ b/src/qemu/qemu_passt.h
|
||||
@@ -36,3 +36,6 @@ void qemuPasstStop(virDomainObj *vm,
|
||||
int qemuPasstSetupCgroup(virDomainObj *vm,
|
||||
virDomainNetDef *net,
|
||||
virCgroup *cgroup);
|
||||
+
|
||||
+char *qemuPasstCreateSocketPath(virDomainObj *vm,
|
||||
+ virDomainNetDef *net);
|
||||
--
|
||||
2.48.1
|
@ -0,0 +1,137 @@
|
||||
From 8012f23fe028ca0a4392094e2185d361ca568455 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <8012f23fe028ca0a4392094e2185d361ca568455.1739815540.git.jdenemar@redhat.com>
|
||||
From: Peter Krempa <pkrempa@redhat.com>
|
||||
Date: Mon, 10 Feb 2025 19:49:10 +0100
|
||||
Subject: [PATCH] qemu: migration: Reactivate block nodes after migration if VM
|
||||
is left paused
|
||||
|
||||
On incoming migration qemu doesn't activate the block graph nodes right
|
||||
away. This is to properly facilitate locking of the images.
|
||||
|
||||
The block nodes are normally re-activated when starting the CPUs after
|
||||
migration, but in cases (e.g. when a paused VM was migrated) when the VM
|
||||
is left paused the block nodes are not re-activated by qemu.
|
||||
|
||||
This means that blockjobs which would want to write to an existing
|
||||
backing chain member would fail. Generally read-only jobs would succeed
|
||||
with older qemu's but this was not intended.
|
||||
|
||||
Instead with new qemu you'll always get an error if attempting to access
|
||||
a inactive node:
|
||||
|
||||
error: internal error: unable to execute QEMU command 'blockdev-mirror': Inactive 'libvirt-1-storage' can't be a backing child of active '#block052'
|
||||
|
||||
This is the case for explicit blockjobs (virsh blockcopy) but also for
|
||||
non shared-storage migration (virsh migrate --copy-storage-all).
|
||||
|
||||
Since qemu now provides 'blockdev-set-active' QMP command which can
|
||||
on-demand re-activate the nodes we can re-activate them in similar cases
|
||||
as when we'd be starting vCPUs if the VM weren't left paused.
|
||||
|
||||
The only exception is on the source in case of a failed post-copy
|
||||
migration as the VM already ran on destination so it won't ever run on
|
||||
the source even when recovered.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-78398
|
||||
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
||||
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
(cherry picked from commit 2626fa0569781c0f42db247f4b7116c33cd88b43)
|
||||
---
|
||||
src/qemu/qemu_migration.c | 55 ++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 52 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
|
||||
index 4112e95a1e..62da892254 100644
|
||||
--- a/src/qemu/qemu_migration.c
|
||||
+++ b/src/qemu/qemu_migration.c
|
||||
@@ -220,6 +220,43 @@ qemuMigrationSrcStoreDomainState(virDomainObj *vm)
|
||||
}
|
||||
|
||||
|
||||
+/**
|
||||
+ * qemuMigrationBlockNodesReactivate:
|
||||
+ *
|
||||
+ * In case when we're keeping the VM paused qemu will not re-activate the block
|
||||
+ * device backend tree so blockjobs would fail. In case when qemu supports the
|
||||
+ * 'blockdev-set-active' command this function will re-activate the block nodes.
|
||||
+ */
|
||||
+static void
|
||||
+qemuMigrationBlockNodesReactivate(virDomainObj *vm,
|
||||
+ virDomainAsyncJob asyncJob)
|
||||
+{
|
||||
+ virErrorPtr orig_err;
|
||||
+ qemuDomainObjPrivate *priv = vm->privateData;
|
||||
+ int rc;
|
||||
+
|
||||
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_SET_ACTIVE))
|
||||
+ return;
|
||||
+
|
||||
+ VIR_DEBUG("re-activating block nodes");
|
||||
+
|
||||
+ virErrorPreserveLast(&orig_err);
|
||||
+
|
||||
+ if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ rc = qemuMonitorBlockdevSetActive(priv->mon, NULL, true);
|
||||
+
|
||||
+ qemuDomainObjExitMonitor(vm);
|
||||
+
|
||||
+ if (rc < 0)
|
||||
+ VIR_WARN("failed to re-activate block nodes after migration of VM '%s'", vm->def->name);
|
||||
+
|
||||
+ cleanup:
|
||||
+ virErrorRestore(&orig_err);
|
||||
+}
|
||||
+
|
||||
+
|
||||
static void
|
||||
qemuMigrationSrcRestoreDomainState(virQEMUDriver *driver, virDomainObj *vm)
|
||||
{
|
||||
@@ -236,14 +273,17 @@ qemuMigrationSrcRestoreDomainState(virQEMUDriver *driver, virDomainObj *vm)
|
||||
virDomainStateTypeToString(state),
|
||||
virDomainStateReasonToString(state, reason));
|
||||
|
||||
- if (preMigrationState != VIR_DOMAIN_RUNNING ||
|
||||
- state != VIR_DOMAIN_PAUSED ||
|
||||
+ if (state == VIR_DOMAIN_PAUSED &&
|
||||
reason == VIR_DOMAIN_PAUSED_POSTCOPY_FAILED)
|
||||
return;
|
||||
|
||||
+ if (preMigrationState != VIR_DOMAIN_RUNNING ||
|
||||
+ state != VIR_DOMAIN_PAUSED)
|
||||
+ goto reactivate;
|
||||
+
|
||||
if (reason == VIR_DOMAIN_PAUSED_IOERROR) {
|
||||
VIR_DEBUG("Domain is paused due to I/O error, skipping resume");
|
||||
- return;
|
||||
+ goto reactivate;
|
||||
}
|
||||
|
||||
VIR_DEBUG("Restoring pre-migration state due to migration error");
|
||||
@@ -266,7 +306,14 @@ qemuMigrationSrcRestoreDomainState(virQEMUDriver *driver, virDomainObj *vm)
|
||||
VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
|
||||
virObjectEventStateQueue(driver->domainEventState, event);
|
||||
}
|
||||
+
|
||||
+ goto reactivate;
|
||||
}
|
||||
+
|
||||
+ return;
|
||||
+
|
||||
+ reactivate:
|
||||
+ qemuMigrationBlockNodesReactivate(vm, VIR_ASYNC_JOB_MIGRATION_OUT);
|
||||
}
|
||||
|
||||
|
||||
@@ -6781,6 +6828,8 @@ qemuMigrationDstFinishFresh(virQEMUDriver *driver,
|
||||
|
||||
if (*inPostCopy)
|
||||
*doKill = false;
|
||||
+ } else {
|
||||
+ qemuMigrationBlockNodesReactivate(vm, VIR_ASYNC_JOB_MIGRATION_IN);
|
||||
}
|
||||
|
||||
if (mig->jobData) {
|
||||
--
|
||||
2.48.1
|
@ -0,0 +1,160 @@
|
||||
From 2eede6a92213c7f72fda218616635cd71efdab34 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <2eede6a92213c7f72fda218616635cd71efdab34.1739815540.git.jdenemar@redhat.com>
|
||||
From: Peter Krempa <pkrempa@redhat.com>
|
||||
Date: Mon, 10 Feb 2025 17:51:31 +0100
|
||||
Subject: [PATCH] qemu: monitor: Add monitor backend for 'blockdev-set-active'
|
||||
|
||||
The command will be used to re-activate block nodes after migration when
|
||||
we're leaving the VM paused so that blockjobs can be used.
|
||||
|
||||
As the 'node-name' field is optional the 'qemumonitorjsontest' case
|
||||
tests both variants.
|
||||
|
||||
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
||||
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
(cherry picked from commit d8f9cfb5e45111da0bd39f334f0643c0ab22ef49)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-78398
|
||||
---
|
||||
src/qemu/qemu_monitor.c | 21 +++++++++++++++++++++
|
||||
src/qemu/qemu_monitor.h | 5 +++++
|
||||
src/qemu/qemu_monitor_json.c | 21 +++++++++++++++++++++
|
||||
src/qemu/qemu_monitor_json.h | 5 +++++
|
||||
tests/qemumonitorjsontest.c | 31 +++++++++++++++++++++++++++++++
|
||||
5 files changed, 83 insertions(+)
|
||||
|
||||
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
|
||||
index 79ff4e2e87..82aa1cbc5f 100644
|
||||
--- a/src/qemu/qemu_monitor.c
|
||||
+++ b/src/qemu/qemu_monitor.c
|
||||
@@ -4555,3 +4555,24 @@ qemuMonitorDisplayReload(qemuMonitor *mon,
|
||||
|
||||
return qemuMonitorJSONDisplayReload(mon, type, tlsCerts);
|
||||
}
|
||||
+
|
||||
+
|
||||
+/**
|
||||
+ * qemuMonitorBlockdevSetActive:
|
||||
+ * @mon: monitor object
|
||||
+ * @nodename: optional nodename to (de)activate
|
||||
+ * @active: requested state
|
||||
+ *
|
||||
+ * Activate or deactivate @nodename based on @active. If @nodename is NULL,
|
||||
+ * qemu will act on all block nodes.
|
||||
+ */
|
||||
+int
|
||||
+qemuMonitorBlockdevSetActive(qemuMonitor *mon,
|
||||
+ const char *nodename,
|
||||
+ bool active)
|
||||
+{
|
||||
+ QEMU_CHECK_MONITOR(mon);
|
||||
+ VIR_DEBUG("nodename='%s', active='%d'", NULLSTR(nodename), active);
|
||||
+
|
||||
+ return qemuMonitorJSONBlockdevSetActive(mon, nodename, active);
|
||||
+}
|
||||
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
|
||||
index a4818a6aa1..672cd6487e 100644
|
||||
--- a/src/qemu/qemu_monitor.h
|
||||
+++ b/src/qemu/qemu_monitor.h
|
||||
@@ -1650,3 +1650,8 @@ qemuMonitorSnapshotDelete(qemuMonitor *mon,
|
||||
const char *jobname,
|
||||
const char *snapshotname,
|
||||
const char **disks);
|
||||
+
|
||||
+int
|
||||
+qemuMonitorBlockdevSetActive(qemuMonitor *mon,
|
||||
+ const char *nodename,
|
||||
+ bool active);
|
||||
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
|
||||
index 53648dea8b..6f9f495888 100644
|
||||
--- a/src/qemu/qemu_monitor_json.c
|
||||
+++ b/src/qemu/qemu_monitor_json.c
|
||||
@@ -8831,3 +8831,24 @@ qemuMonitorJSONSnapshotDelete(qemuMonitor *mon,
|
||||
|
||||
return qemuMonitorJSONCheckError(cmd, reply);
|
||||
}
|
||||
+
|
||||
+
|
||||
+int
|
||||
+qemuMonitorJSONBlockdevSetActive(qemuMonitor *mon,
|
||||
+ const char *nodename,
|
||||
+ bool active)
|
||||
+{
|
||||
+ g_autoptr(virJSONValue) cmd = NULL;
|
||||
+ g_autoptr(virJSONValue) reply = NULL;
|
||||
+
|
||||
+ if (!(cmd = qemuMonitorJSONMakeCommand("blockdev-set-active",
|
||||
+ "S:node-name", nodename,
|
||||
+ "b:active", active,
|
||||
+ NULL)))
|
||||
+ return -1;
|
||||
+
|
||||
+ if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ return qemuMonitorJSONCheckError(cmd, reply);
|
||||
+}
|
||||
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
|
||||
index 0214e9e9ff..68f60aec61 100644
|
||||
--- a/src/qemu/qemu_monitor_json.h
|
||||
+++ b/src/qemu/qemu_monitor_json.h
|
||||
@@ -816,3 +816,8 @@ qemuMonitorJSONSnapshotDelete(qemuMonitor *mon,
|
||||
const char *jobname,
|
||||
const char *snapshotname,
|
||||
const char **disks);
|
||||
+
|
||||
+int
|
||||
+qemuMonitorJSONBlockdevSetActive(qemuMonitor *mon,
|
||||
+ const char *nodename,
|
||||
+ bool active);
|
||||
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
|
||||
index f7fe0fb6f4..f0f6a329c8 100644
|
||||
--- a/tests/qemumonitorjsontest.c
|
||||
+++ b/tests/qemumonitorjsontest.c
|
||||
@@ -1249,6 +1249,36 @@ testQemuMonitorJSONqemuMonitorJSONSnapshot(const void *opaque)
|
||||
}
|
||||
|
||||
|
||||
+static int
|
||||
+testQemuMonitorJSONqemuMonitorJSONBlockdevSetActive(const void *opaque)
|
||||
+{
|
||||
+ const testGenericData *data = opaque;
|
||||
+ virDomainXMLOption *xmlopt = data->xmlopt;
|
||||
+ g_autoptr(qemuMonitorTest) test = NULL;
|
||||
+
|
||||
+ if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
|
||||
+ return -1;
|
||||
+
|
||||
+ if (qemuMonitorTestAddItem(test, "blockdev-set-active",
|
||||
+ "{\"return\":{}}") < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (qemuMonitorTestAddItem(test, "blockdev-set-active",
|
||||
+ "{\"return\":{}}") < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (qemuMonitorJSONBlockdevSetActive(qemuMonitorTestGetMonitor(test),
|
||||
+ NULL, true) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (qemuMonitorJSONBlockdevSetActive(qemuMonitorTestGetMonitor(test),
|
||||
+ "testnode", false) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static bool
|
||||
testQemuMonitorJSONqemuMonitorJSONQueryCPUsEqual(struct qemuMonitorQueryCpusEntry *a,
|
||||
struct qemuMonitorQueryCpusEntry *b)
|
||||
@@ -2989,6 +3019,7 @@ mymain(void)
|
||||
DO_TEST(qemuMonitorJSONSendKeyHoldtime);
|
||||
DO_TEST(qemuMonitorJSONNBDServerStart);
|
||||
DO_TEST(qemuMonitorJSONSnapshot);
|
||||
+ DO_TEST(qemuMonitorJSONBlockdevSetActive);
|
||||
|
||||
DO_TEST_CPU_DATA("host");
|
||||
DO_TEST_CPU_DATA("full");
|
||||
--
|
||||
2.48.1
|
@ -0,0 +1,132 @@
|
||||
From 0dc1ceab2611a06d5f108c8f74e1c876de05cd44 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <0dc1ceab2611a06d5f108c8f74e1c876de05cd44.1739815540.git.jdenemar@redhat.com>
|
||||
From: Laine Stump <laine@redhat.com>
|
||||
Date: Tue, 11 Feb 2025 16:30:11 -0500
|
||||
Subject: [PATCH] qemu: use switch instead of if in
|
||||
qemuProcessPrepareDomainNetwork()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
qemuProcessPrepareDomain()'s comments say that it should be the only
|
||||
place to change the "live XML" of a domain (i.e. the public parts of
|
||||
the virDomainDef object that is shown in the domain's status
|
||||
XML), and that seems like a reasonable idea (although there aren't
|
||||
many users of it to date).
|
||||
|
||||
qemuProcessPrepareDomainNetwork() is called by the aforementioned
|
||||
qemuProcessPrepareDomain() - this patch changes the "if (type ==
|
||||
HOSTDEV)" in that function to a "switch(type)" so it's simpler to add
|
||||
DomainDef modifications for various other types of virDomainNetDef,
|
||||
and also so that anyone who adds a new interface type is forced to
|
||||
look at the code and decide if anything needs to be done here for the
|
||||
new type.
|
||||
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit 6fe3d765e506b2954931e228ecd233f1200dce1a)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-77086
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
---
|
||||
src/qemu/qemu_process.c | 75 ++++++++++++++++++++++++++---------------
|
||||
1 file changed, 47 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
|
||||
index a45f1b5b7d..26ca943dfc 100644
|
||||
--- a/src/qemu/qemu_process.c
|
||||
+++ b/src/qemu/qemu_process.c
|
||||
@@ -5888,7 +5888,6 @@ qemuProcessPrepareDomainNetwork(virDomainObj *vm)
|
||||
|
||||
for (i = 0; i < def->nnets; i++) {
|
||||
virDomainNetDef *net = def->nets[i];
|
||||
- virDomainNetType actualType;
|
||||
|
||||
/* If appropriate, grab a physical device from the configured
|
||||
* network's pool of devices, or resolve bridge device name
|
||||
@@ -5901,36 +5900,56 @@ qemuProcessPrepareDomainNetwork(virDomainObj *vm)
|
||||
return -1;
|
||||
}
|
||||
|
||||
- actualType = virDomainNetGetActualType(net);
|
||||
- if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV &&
|
||||
- net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
||||
- /* Each type='hostdev' network device must also have a
|
||||
- * corresponding entry in the hostdevs array. For netdevs
|
||||
- * that are hardcoded as type='hostdev', this is already
|
||||
- * done by the parser, but for those allocated from a
|
||||
- * network / determined at runtime, we need to do it
|
||||
- * separately.
|
||||
- */
|
||||
- virDomainHostdevDef *hostdev = virDomainNetGetActualHostdev(net);
|
||||
- virDomainHostdevSubsysPCI *pcisrc = &hostdev->source.subsys.u.pci;
|
||||
-
|
||||
- if (virDomainHostdevFind(def, hostdev, NULL) >= 0) {
|
||||
- virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
- _("PCI device %1$04x:%2$02x:%3$02x.%4$x allocated from network %5$s is already in use by domain %6$s"),
|
||||
- pcisrc->addr.domain, pcisrc->addr.bus,
|
||||
- pcisrc->addr.slot, pcisrc->addr.function,
|
||||
- net->data.network.name, def->name);
|
||||
- return -1;
|
||||
- }
|
||||
+ switch (virDomainNetGetActualType(net)) {
|
||||
+ case VIR_DOMAIN_NET_TYPE_HOSTDEV:
|
||||
+ if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
|
||||
+ /* Each type='hostdev' network device must also have a
|
||||
+ * corresponding entry in the hostdevs array. For netdevs
|
||||
+ * that are hardcoded as type='hostdev', this is already
|
||||
+ * done by the parser, but for those allocated from a
|
||||
+ * network / determined at runtime, we need to do it
|
||||
+ * separately.
|
||||
+ */
|
||||
+ virDomainHostdevDef *hostdev = virDomainNetGetActualHostdev(net);
|
||||
+ virDomainHostdevSubsysPCI *pcisrc = &hostdev->source.subsys.u.pci;
|
||||
+
|
||||
+ if (virDomainHostdevFind(def, hostdev, NULL) >= 0) {
|
||||
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
+ _("PCI device %1$04x:%2$02x:%3$02x.%4$x allocated from network %5$s is already in use by domain %6$s"),
|
||||
+ pcisrc->addr.domain, pcisrc->addr.bus,
|
||||
+ pcisrc->addr.slot, pcisrc->addr.function,
|
||||
+ net->data.network.name, def->name);
|
||||
+ return -1;
|
||||
+ }
|
||||
|
||||
- /* For hostdev present in qemuProcessPrepareDomain() phase this was
|
||||
- * done already, but this code runs after that, so we have to call
|
||||
- * it ourselves. */
|
||||
- if (qemuDomainPrepareHostdev(hostdev, priv) < 0)
|
||||
- return -1;
|
||||
+ /* For hostdev present in qemuProcessPrepareDomain() phase this was
|
||||
+ * done already, but this code runs after that, so we have to call
|
||||
+ * it ourselves. */
|
||||
+ if (qemuDomainPrepareHostdev(hostdev, priv) < 0)
|
||||
+ return -1;
|
||||
|
||||
- virDomainHostdevInsert(def, hostdev);
|
||||
+ virDomainHostdevInsert(def, hostdev);
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case VIR_DOMAIN_NET_TYPE_DIRECT:
|
||||
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
|
||||
+ case VIR_DOMAIN_NET_TYPE_NETWORK:
|
||||
+ case VIR_DOMAIN_NET_TYPE_ETHERNET:
|
||||
+ case VIR_DOMAIN_NET_TYPE_USER:
|
||||
+ case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
||||
+ case VIR_DOMAIN_NET_TYPE_SERVER:
|
||||
+ case VIR_DOMAIN_NET_TYPE_CLIENT:
|
||||
+ case VIR_DOMAIN_NET_TYPE_MCAST:
|
||||
+ case VIR_DOMAIN_NET_TYPE_INTERNAL:
|
||||
+ case VIR_DOMAIN_NET_TYPE_UDP:
|
||||
+ case VIR_DOMAIN_NET_TYPE_VDPA:
|
||||
+ case VIR_DOMAIN_NET_TYPE_NULL:
|
||||
+ case VIR_DOMAIN_NET_TYPE_VDS:
|
||||
+ case VIR_DOMAIN_NET_TYPE_LAST:
|
||||
+ break;
|
||||
}
|
||||
+
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
2.48.1
|
@ -0,0 +1,82 @@
|
||||
From 5d7fa1e2def7a48f23dc908c504288d23f0bdafa Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <5d7fa1e2def7a48f23dc908c504288d23f0bdafa.1739815540.git.jdenemar@redhat.com>
|
||||
From: Laine Stump <laine@redhat.com>
|
||||
Date: Sun, 9 Feb 2025 18:46:00 -0500
|
||||
Subject: [PATCH] qemu: validate that model is virtio for vhostuser and vdpa
|
||||
interfaces in the same place
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Both vhostuser and vdpa interface types must use the virtio model in
|
||||
the guest (because part of the functionality is implemented in the
|
||||
guest virtio driver). Due to ["because that's the way it happened"]
|
||||
this has been validated for vhostuser in the hypervisor-agnostic
|
||||
validate function, but for vdpa it has been done in the QEMU-specific
|
||||
validate. Since these interface models are only supported by QEMU
|
||||
anyway, validate for both of them in the QEMU validation function.
|
||||
|
||||
Take advantage of this change to switch to using
|
||||
virDomainNetIsVirtioModel(net) instead of "net->model ==
|
||||
VIR_DOMAIN_NET_MODEL_VIRTIO" (the former also matches
|
||||
...VIRTIO_TRANSITIONAL and ...VIRTIO_NON_TRANSITIONAL, so is more
|
||||
correct).
|
||||
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit 154d44a585c40d0b6cf3bae674da2a8ca11ddb95)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-77086
|
||||
Signed-off-by: Laine Stump <laine@redhat.com>
|
||||
---
|
||||
src/conf/domain_validate.c | 6 ------
|
||||
src/qemu/qemu_validate.c | 11 ++++++-----
|
||||
2 files changed, 6 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
|
||||
index 1034bb57f5..f56ff5b7bb 100644
|
||||
--- a/src/conf/domain_validate.c
|
||||
+++ b/src/conf/domain_validate.c
|
||||
@@ -2180,12 +2180,6 @@ virDomainNetDefValidate(const virDomainNetDef *net)
|
||||
|
||||
switch (net->type) {
|
||||
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
|
||||
- if (!virDomainNetIsVirtioModel(net)) {
|
||||
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
- _("Wrong or no <model> 'type' attribute specified with <interface type='vhostuser'/>. vhostuser requires the virtio-net* frontend"));
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
if (net->data.vhostuser->data.nix.listen &&
|
||||
net->data.vhostuser->data.nix.reconnect.enabled == VIR_TRISTATE_BOOL_YES) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
|
||||
index 9310457cb1..841d320541 100644
|
||||
--- a/src/qemu/qemu_validate.c
|
||||
+++ b/src/qemu/qemu_validate.c
|
||||
@@ -1808,17 +1808,18 @@ qemuValidateDomainDeviceDefNetwork(const virDomainNetDef *net,
|
||||
_("vDPA devices are not supported with this QEMU binary"));
|
||||
return -1;
|
||||
}
|
||||
+ }
|
||||
|
||||
- if (net->model != VIR_DOMAIN_NET_MODEL_VIRTIO) {
|
||||
+ if (!virDomainNetIsVirtioModel(net)) {
|
||||
+ if (net->type == VIR_DOMAIN_NET_TYPE_VDPA ||
|
||||
+ net->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
- _("invalid model for interface of type '%1$s': '%2$s'"),
|
||||
+ _("invalid model for interface of type '%1$s': '%2$s' - must be 'virtio'"),
|
||||
virDomainNetTypeToString(net->type),
|
||||
virDomainNetModelTypeToString(net->model));
|
||||
return -1;
|
||||
}
|
||||
- }
|
||||
-
|
||||
- if (virDomainNetIsVirtioModel(net)) {
|
||||
+ } else {
|
||||
if (net->driver.virtio.rx_queue_size) {
|
||||
if (!VIR_IS_POW2(net->driver.virtio.rx_queue_size)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
--
|
||||
2.48.1
|
@ -0,0 +1,38 @@
|
||||
From 33c6c5a2061321e75fa1455a5ad9fa192b1a7825 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <33c6c5a2061321e75fa1455a5ad9fa192b1a7825.1739815540.git.jdenemar@redhat.com>
|
||||
From: Jiri Denemark <jdenemar@redhat.com>
|
||||
Date: Wed, 15 Jan 2025 16:02:00 +0100
|
||||
Subject: [PATCH] qemu_migration: Do not automatically resume domain after I/O
|
||||
error
|
||||
|
||||
When an I/O error happens (causing a domain to be paused) during live
|
||||
migration which is later cancelled by a user, trying to resume the
|
||||
domain doesn't make sense.
|
||||
|
||||
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
|
||||
(cherry picked from commit 3766891c5954c53370d7eb9c7a0a8e6ba3854ca4)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-1071
|
||||
---
|
||||
src/qemu/qemu_migration.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
|
||||
index fe0b9fc672..4112e95a1e 100644
|
||||
--- a/src/qemu/qemu_migration.c
|
||||
+++ b/src/qemu/qemu_migration.c
|
||||
@@ -241,6 +241,11 @@ qemuMigrationSrcRestoreDomainState(virQEMUDriver *driver, virDomainObj *vm)
|
||||
reason == VIR_DOMAIN_PAUSED_POSTCOPY_FAILED)
|
||||
return;
|
||||
|
||||
+ if (reason == VIR_DOMAIN_PAUSED_IOERROR) {
|
||||
+ VIR_DEBUG("Domain is paused due to I/O error, skipping resume");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
VIR_DEBUG("Restoring pre-migration state due to migration error");
|
||||
|
||||
/* we got here through some sort of failure; start the domain again */
|
||||
--
|
||||
2.48.1
|
@ -0,0 +1,110 @@
|
||||
From f9698e648654cf75af7ef2366c4ad7c2b8c19f6d Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <f9698e648654cf75af7ef2366c4ad7c2b8c19f6d.1739815540.git.jdenemar@redhat.com>
|
||||
From: Jiri Denemark <jdenemar@redhat.com>
|
||||
Date: Wed, 15 Jan 2025 15:59:22 +0100
|
||||
Subject: [PATCH] qemu_migration: Refactor qemuMigrationSrcRestoreDomainState
|
||||
|
||||
None of the callers really care about the return value so we can drop it
|
||||
and simplify the code a bit.
|
||||
|
||||
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
|
||||
(cherry picked from commit e46e64be501cd670a3f224fabd97705fb01c6f85)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-1071
|
||||
---
|
||||
src/qemu/qemu_migration.c | 64 +++++++++++++++++----------------------
|
||||
1 file changed, 28 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
|
||||
index b2b172a26c..fe0b9fc672 100644
|
||||
--- a/src/qemu/qemu_migration.c
|
||||
+++ b/src/qemu/qemu_migration.c
|
||||
@@ -219,57 +219,49 @@ qemuMigrationSrcStoreDomainState(virDomainObj *vm)
|
||||
priv->preMigrationState, vm);
|
||||
}
|
||||
|
||||
-/* Returns true if the domain was resumed, false otherwise */
|
||||
-static bool
|
||||
+
|
||||
+static void
|
||||
qemuMigrationSrcRestoreDomainState(virQEMUDriver *driver, virDomainObj *vm)
|
||||
{
|
||||
qemuDomainObjPrivate *priv = vm->privateData;
|
||||
+ virDomainState preMigrationState = priv->preMigrationState;
|
||||
int reason;
|
||||
virDomainState state = virDomainObjGetState(vm, &reason);
|
||||
- bool ret = false;
|
||||
+
|
||||
+ priv->preMigrationState = VIR_DOMAIN_NOSTATE;
|
||||
|
||||
VIR_DEBUG("driver=%p, vm=%p, pre-mig-state=%s, state=%s, reason=%s",
|
||||
driver, vm,
|
||||
- virDomainStateTypeToString(priv->preMigrationState),
|
||||
+ virDomainStateTypeToString(preMigrationState),
|
||||
virDomainStateTypeToString(state),
|
||||
virDomainStateReasonToString(state, reason));
|
||||
|
||||
- if (state != VIR_DOMAIN_PAUSED ||
|
||||
+ if (preMigrationState != VIR_DOMAIN_RUNNING ||
|
||||
+ state != VIR_DOMAIN_PAUSED ||
|
||||
reason == VIR_DOMAIN_PAUSED_POSTCOPY_FAILED)
|
||||
- goto cleanup;
|
||||
+ return;
|
||||
|
||||
- if (priv->preMigrationState == VIR_DOMAIN_RUNNING) {
|
||||
- /* This is basically the only restore possibility that's safe
|
||||
- * and we should attempt to do */
|
||||
-
|
||||
- VIR_DEBUG("Restoring pre-migration state due to migration error");
|
||||
-
|
||||
- /* we got here through some sort of failure; start the domain again */
|
||||
- if (qemuProcessStartCPUs(driver, vm,
|
||||
- VIR_DOMAIN_RUNNING_MIGRATION_CANCELED,
|
||||
- VIR_ASYNC_JOB_MIGRATION_OUT) < 0) {
|
||||
- /* Hm, we already know we are in error here. We don't want to
|
||||
- * overwrite the previous error, though, so we just throw something
|
||||
- * to the logs and hope for the best */
|
||||
- VIR_ERROR(_("Failed to resume guest %1$s after failure"), vm->def->name);
|
||||
- if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
|
||||
- virObjectEvent *event;
|
||||
-
|
||||
- virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
|
||||
- VIR_DOMAIN_PAUSED_API_ERROR);
|
||||
- event = virDomainEventLifecycleNewFromObj(vm,
|
||||
- VIR_DOMAIN_EVENT_SUSPENDED,
|
||||
- VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
|
||||
- virObjectEventStateQueue(driver->domainEventState, event);
|
||||
- }
|
||||
- goto cleanup;
|
||||
+ VIR_DEBUG("Restoring pre-migration state due to migration error");
|
||||
+
|
||||
+ /* we got here through some sort of failure; start the domain again */
|
||||
+ if (qemuProcessStartCPUs(driver, vm,
|
||||
+ VIR_DOMAIN_RUNNING_MIGRATION_CANCELED,
|
||||
+ VIR_ASYNC_JOB_MIGRATION_OUT) < 0) {
|
||||
+ /* Hm, we already know we are in error here. We don't want to
|
||||
+ * overwrite the previous error, though, so we just throw something
|
||||
+ * to the logs and hope for the best */
|
||||
+ VIR_ERROR(_("Failed to resume guest %1$s after failure"), vm->def->name);
|
||||
+ if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
|
||||
+ virObjectEvent *event;
|
||||
+
|
||||
+ virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
|
||||
+ VIR_DOMAIN_PAUSED_API_ERROR);
|
||||
+ event = virDomainEventLifecycleNewFromObj(vm,
|
||||
+ VIR_DOMAIN_EVENT_SUSPENDED,
|
||||
+ VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR);
|
||||
+ virObjectEventStateQueue(driver->domainEventState, event);
|
||||
}
|
||||
- ret = true;
|
||||
}
|
||||
-
|
||||
- cleanup:
|
||||
- priv->preMigrationState = VIR_DOMAIN_NOSTATE;
|
||||
- return ret;
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
2.48.1
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
55
libvirt-utils-Canonicalize-paths-before-comparing-them.patch
Normal file
55
libvirt-utils-Canonicalize-paths-before-comparing-them.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From d4bff9bd1d108937b70ce1c9931bcc13e3ad1437 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <d4bff9bd1d108937b70ce1c9931bcc13e3ad1437.1739815540.git.jdenemar@redhat.com>
|
||||
From: Andrea Bolognani <abologna@redhat.com>
|
||||
Date: Thu, 13 Feb 2025 09:54:05 +0100
|
||||
Subject: [PATCH] utils: Canonicalize paths before comparing them
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
In virFileIsSharedFSOverride() we compare a path against a list
|
||||
of overrides looking for a match.
|
||||
|
||||
All overrides are canonicalized ahead of time though, so e.g.
|
||||
/var/run/foo will be turned into /run/foo due to /var/run being
|
||||
a symlink on modern Linux systems. But the path we're trying to
|
||||
match with the overrides doesn't get the same treatment, so in
|
||||
this scenario the comparison will always fail.
|
||||
|
||||
Canonicalizing the path as well solves the issue.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-79165
|
||||
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
|
||||
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
(cherry picked from commit f2023e8018fe18550ad6aec66fe72bd1376f8522)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-79165
|
||||
|
||||
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
|
||||
---
|
||||
src/util/virfile.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/util/virfile.c b/src/util/virfile.c
|
||||
index 6ac0f4efb3..7cab3d0cd6 100644
|
||||
--- a/src/util/virfile.c
|
||||
+++ b/src/util/virfile.c
|
||||
@@ -3823,10 +3823,13 @@ virFileIsSharedFSOverride(const char *path,
|
||||
if (!path || path[0] != '/' || !overrides)
|
||||
return false;
|
||||
|
||||
- if (g_strv_contains((const char *const *) overrides, path))
|
||||
- return true;
|
||||
+ /* Overrides have been canonicalized ahead of time, so we need to
|
||||
+ * do the same for the provided path or we'll never be able to
|
||||
+ * find a match if symlinks are involved */
|
||||
+ dirpath = virFileCanonicalizePath(path);
|
||||
|
||||
- dirpath = g_strdup(path);
|
||||
+ if (g_strv_contains((const char *const *) overrides, dirpath))
|
||||
+ return true;
|
||||
|
||||
/* Continue until we've scanned the entire path */
|
||||
while (p != dirpath) {
|
||||
--
|
||||
2.48.1
|
44
libvirt.spec
44
libvirt.spec
@ -289,7 +289,7 @@
|
||||
Summary: Library providing a simple virtualization API
|
||||
Name: libvirt
|
||||
Version: 10.10.0
|
||||
Release: 6%{?dist}%{?extra_release}
|
||||
Release: 7%{?dist}%{?extra_release}
|
||||
License: GPL-2.0-or-later AND LGPL-2.1-only AND LGPL-2.1-or-later AND OFL-1.1
|
||||
URL: https://libvirt.org/
|
||||
|
||||
@ -363,6 +363,26 @@ Patch63: libvirt-qemu-snapshot-Ensure-that-NVRAM-image-exists-when-taking-inacti
|
||||
Patch64: libvirt-qemuxmlconftest-Allow-testing-of-the-writable-flag-for-passed-FDs-for-disks.patch
|
||||
Patch65: libvirt-qemuxmlconftest-Add-testing-of-FDs-with-writable-flag-in-disk-source-fd.patch
|
||||
Patch66: libvirt-qemu-domain-Initialize-FD-passthrough-for-a-virStorageSource-before-using-it.patch
|
||||
Patch67: libvirt-qemu_migration-Refactor-qemuMigrationSrcRestoreDomainState.patch
|
||||
Patch68: libvirt-qemu_migration-Do-not-automatically-resume-domain-after-I-O-error.patch
|
||||
Patch69: libvirt-qemucapabilitiestest-Add-data-for-the-qemu-10.0-dev-cycle-on-x86_64.patch
|
||||
Patch70: libvirt-qemucapabilitiestest-Update-caps_10.0.0_x86_64-to-v9.2.0-1636-gffaf7f0376.patch
|
||||
Patch71: libvirt-qemu-capabilies-Introduce-QEMU_CAPS_BLOCKDEV_SET_ACTIVE.patch
|
||||
Patch72: libvirt-qemu-monitor-Add-monitor-backend-for-blockdev-set-active.patch
|
||||
Patch73: libvirt-qemu-migration-Reactivate-block-nodes-after-migration-if-VM-is-left-paused.patch
|
||||
Patch74: libvirt-conf-change-virDomainHostdevInsert-to-return-void.patch
|
||||
Patch75: libvirt-qemu-fix-qemu-validation-to-forbid-guest-side-IP-address-for-type-vdpa.patch
|
||||
Patch76: libvirt-qemu-validate-that-model-is-virtio-for-vhostuser-and-vdpa-interfaces-in-the-same-place.patch
|
||||
Patch77: libvirt-qemu-automatically-set-model-type-virtio-for-interface-type-vhostuser.patch
|
||||
Patch78: libvirt-qemu-do-all-vhostuser-attribute-validation-in-qemu-driver.patch
|
||||
Patch79: libvirt-conf-qemu-make-source-element-almost-optional-for-type-vhostuser.patch
|
||||
Patch80: libvirt-qemu-use-switch-instead-of-if-in-qemuProcessPrepareDomainNetwork.patch
|
||||
Patch81: libvirt-qemu-make-qemuPasstCreateSocketPath-public.patch
|
||||
Patch82: libvirt-qemu-complete-vhostuser-passt-support.patch
|
||||
Patch83: libvirt-qemu-fail-validation-if-a-domain-def-has-vhostuser-passt-but-no-shared-mem.patch
|
||||
Patch84: libvirt-docs-improve-type-user-docs-to-higlight-differences-between-SLIRP-and-passt.patch
|
||||
Patch85: libvirt-docs-document-using-passt-backend-with-interface-type-vhostuser.patch
|
||||
Patch86: libvirt-utils-Canonicalize-paths-before-comparing-them.patch
|
||||
|
||||
|
||||
Requires: libvirt-daemon = %{version}-%{release}
|
||||
@ -2687,6 +2707,28 @@ exit 0
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Mon Feb 17 2025 Jiri Denemark <jdenemar@redhat.com> - 10.10.0-7
|
||||
- qemu_migration: Refactor qemuMigrationSrcRestoreDomainState (RHEL-1071)
|
||||
- qemu_migration: Do not automatically resume domain after I/O error (RHEL-1071)
|
||||
- qemucapabilitiestest: Add data for the qemu-10.0 dev cycle on x86_64 (RHEL-78398)
|
||||
- qemucapabilitiestest: Update 'caps_10.0.0_x86_64' to 'v9.2.0-1636-gffaf7f0376' (RHEL-78398)
|
||||
- qemu: capabilies: Introduce QEMU_CAPS_BLOCKDEV_SET_ACTIVE (RHEL-78398)
|
||||
- qemu: monitor: Add monitor backend for 'blockdev-set-active' (RHEL-78398)
|
||||
- qemu: migration: Reactivate block nodes after migration if VM is left paused (RHEL-78398)
|
||||
- conf: change virDomainHostdevInsert() to return void (RHEL-77086)
|
||||
- qemu: fix qemu validation to forbid guest-side IP address for type='vdpa' (RHEL-77086)
|
||||
- qemu: validate that model is virtio for vhostuser and vdpa interfaces in the same place (RHEL-77086)
|
||||
- qemu: automatically set model type='virtio' for interface type='vhostuser' (RHEL-77086)
|
||||
- qemu: do all vhostuser attribute validation in qemu driver (RHEL-77086)
|
||||
- conf/qemu: make <source> element *almost* optional for type=vhostuser (RHEL-77086)
|
||||
- qemu: use switch instead of if in qemuProcessPrepareDomainNetwork() (RHEL-77086)
|
||||
- qemu: make qemuPasstCreateSocketPath() public (RHEL-77086)
|
||||
- qemu: complete vhostuser + passt support (RHEL-77086)
|
||||
- qemu: fail validation if a domain def has vhostuser/passt but no shared mem (RHEL-77086)
|
||||
- docs: improve type='user' docs to higlight differences between SLIRP and passt (RHEL-77086)
|
||||
- docs: document using passt backend with <interface type='vhostuser'> (RHEL-77086)
|
||||
- utils: Canonicalize paths before comparing them (RHEL-79165)
|
||||
|
||||
* Fri Feb 7 2025 Jiri Denemark <jdenemar@redhat.com> - 10.10.0-6
|
||||
- build: Bump minimum glib2 version to 2.66.0 (RHEL-76802)
|
||||
- qemuProcessHandleIOError: Refactor to extract 'priv' instead of 'driver' (RHEL-76802)
|
||||
|
Loading…
Reference in New Issue
Block a user