From: Enrique Llorente via Devel Date: Fri, 30 May 2025 12:21:23 +0000 (+0200) Subject: qemu: support setting guest hostname/fqdn using DHCP on passt-backed interfaces X-Git-Tag: v11.8.0-rc1~49 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cca246e0cbd9f793f91537800f649179d8354244;p=thirdparty%2Flibvirt.git qemu: support setting guest hostname/fqdn using DHCP on passt-backed interfaces This commit introduces support for configuring hostnames in virtual machines (VMs) using DHCP via an interface backed by the passt transport. This is done with the new 'hostname' and 'fqdn' (Fully Qualified Domain Name) attributes in the subelement of . The values set in these attributes are added to the passt commandline for the interface (with the --hostname and --fqdn options), and passt will then send the settings to the guest by adding options to the DHCP response when the interface is started - for IPv4, hostname will be sent in option 12, or the FQDN will be sent in option 81, and for IPv6 the FQDN will be sent using option 39. This will enable a management application to easily configure guest hostnames without intervening in the guest's disk image (as long as the guest uses DHCP for it's network interface configuration). Here is an example of setting the hostname and fqdn for a guest (in practice, you would only use one or the other, since according to the RFC if option 81 is sent to the guest, option 12 should not be sent). ... Resolves: https://issues.redhat.com/browse/RHEL-79806 Signed-off-by: Enrique Llorente Reviewed-by: Laine Stump --- diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index b327ff87a7..f50dce477f 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -5468,19 +5468,26 @@ 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 ```` attribute ``logFile`` can be -used to tell the passt process for this interface where to write its -message log, and the ```` 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. +backend. For example, the ```` subelement's attribute +``logFile`` can be used to tell the passt process for this interface +where to write its message log (:since:`since 9.0.0`)[\*], while the +``hostname`` attribute is used to set the hostname sent to the guest +in a DHCPv4 response (using option 12) (:since:`since 11.8.0`), and +``fqdn`` sets the "fully qualified domain name" sent to the guest in +DHCPv4 response option 81 and DHCPv6 response option 39 (:since:`since +11.8.0`). Also, the ```` subelement attribute ``dev`` can +tell passt 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 ```` elements can be added to forward incoming network traffic for the host to this @@ -5514,7 +5521,7 @@ ports **with the exception of some subset**. ... - + @@ -6657,7 +6664,7 @@ setting guest-side IP addresses with ```` and port forwarding with ... - + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 8c0bf63925..281846dfbe 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2919,6 +2919,8 @@ virDomainNetDefFree(virDomainNetDef *def) g_free(def->backend.tap); g_free(def->backend.vhost); g_free(def->backend.logFile); + g_free(def->backend.hostname); + g_free(def->backend.fqdn); virDomainNetTeamingInfoFree(def->teaming); g_free(def->virtPortProfile); g_free(def->script); @@ -9804,6 +9806,8 @@ virDomainNetBackendParseXML(xmlNodePtr node, } def->backend.logFile = virXMLPropString(node, "logFile"); + def->backend.hostname = virXMLPropString(node, "hostname"); + def->backend.fqdn = virXMLPropString(node, "fqdn"); if (tap) def->backend.tap = virFileSanitizePath(tap); @@ -20880,7 +20884,9 @@ virDomainNetBackendIsEqual(virDomainNetBackend *src, if (src->type != dst->type || STRNEQ_NULLABLE(src->tap, dst->tap) || STRNEQ_NULLABLE(src->vhost, dst->vhost) || - STRNEQ_NULLABLE(src->logFile, dst->logFile)) { + STRNEQ_NULLABLE(src->logFile, dst->logFile) || + STRNEQ_NULLABLE(src->hostname, dst->hostname) || + STRNEQ_NULLABLE(src->fqdn, dst->fqdn)) { return false; } return true; @@ -25019,6 +25025,8 @@ virDomainNetBackendFormat(virBuffer *buf, virBufferEscapeString(&attrBuf, " tap='%s'", backend->tap); virBufferEscapeString(&attrBuf, " vhost='%s'", backend->vhost); virBufferEscapeString(&attrBuf, " logFile='%s'", backend->logFile); + virBufferEscapeString(&attrBuf, " hostname='%s'", backend->hostname); + virBufferEscapeString(&attrBuf, " fqdn='%s'", backend->fqdn); virXMLFormatElement(buf, "backend", &attrBuf, NULL); } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index eca820892e..39807b5fe3 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1077,6 +1077,8 @@ struct _virDomainNetBackend { char *vhost; /* The following are currently only valid/used when backend type='passt' */ char *logFile; /* path to logfile used by passt process */ + char *hostname; /* hostname of the passt process */ + char *fqdn; /* fully qualified domain name of the passt process */ }; struct _virDomainNetPortForwardRange { diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index 60a2e46b7e..93a2bc9b01 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -2284,10 +2284,22 @@ virDomainNetDefValidate(const virDomainNetDef *net) } } - if (net->sourceDev && net->backend.type != VIR_DOMAIN_NET_BACKEND_PASST) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("The 'dev' attribute of the element can only be used with type='user' or type='vhostuser' if the type='passt'")); - return -1; + if (net->backend.type != VIR_DOMAIN_NET_BACKEND_PASST) { + if (net->sourceDev) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("The 'dev' attribute of the element can only be used with type='user' or type='vhostuser' if the type='passt'")); + return -1; + } + if (net->backend.fqdn) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("The 'fqdn' attribute of the element can only be used with the type='passt'")); + return -1; + } + if (net->backend.hostname) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("The 'fqdn' attribute of the element can only be used with the type='passt'")); + return -1; + } } if (net->nPortForwards > 0) { diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 298afe0b7c..b9230a35b4 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -3978,6 +3978,16 @@ + + + + + + + + + + diff --git a/src/qemu/qemu_passt.c b/src/qemu/qemu_passt.c index fcc34de384..81e5c51f6c 100644 --- a/src/qemu/qemu_passt.c +++ b/src/qemu/qemu_passt.c @@ -229,6 +229,12 @@ qemuPasstStart(virDomainObj *vm, if (net->backend.logFile) virCommandAddArgList(cmd, "--log-file", net->backend.logFile, NULL); + if (net->backend.hostname) + virCommandAddArgList(cmd, "--hostname", net->backend.hostname, NULL); + + if (net->backend.fqdn) + virCommandAddArgList(cmd, "--fqdn", net->backend.fqdn, NULL); + /* Add IP address info */ for (i = 0; i < net->guestIP.nips; i++) { const virNetDevIPAddr *ip = net->guestIP.ips[i]; diff --git a/tests/qemuxmlconfdata/net-user-passt.x86_64-7.2.0.xml b/tests/qemuxmlconfdata/net-user-passt.x86_64-7.2.0.xml index cfe07cc627..77da297936 100644 --- a/tests/qemuxmlconfdata/net-user-passt.x86_64-7.2.0.xml +++ b/tests/qemuxmlconfdata/net-user-passt.x86_64-7.2.0.xml @@ -50,7 +50,7 @@ - +
diff --git a/tests/qemuxmlconfdata/net-user-passt.x86_64-latest.xml b/tests/qemuxmlconfdata/net-user-passt.x86_64-latest.xml index d7e0ef5f90..917a9edaa0 100644 --- a/tests/qemuxmlconfdata/net-user-passt.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/net-user-passt.x86_64-latest.xml @@ -50,7 +50,7 @@ - +
diff --git a/tests/qemuxmlconfdata/net-user-passt.xml b/tests/qemuxmlconfdata/net-user-passt.xml index 20c9f50542..80d15de2ed 100644 --- a/tests/qemuxmlconfdata/net-user-passt.xml +++ b/tests/qemuxmlconfdata/net-user-passt.xml @@ -47,7 +47,7 @@ - +
diff --git a/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml b/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml index 529aff11f8..5802754c4b 100644 --- a/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml +++ b/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml @@ -53,7 +53,7 @@ - +
diff --git a/tests/qemuxmlconfdata/net-vhostuser-passt.xml b/tests/qemuxmlconfdata/net-vhostuser-passt.xml index 71b845329b..0a37511a0f 100644 --- a/tests/qemuxmlconfdata/net-vhostuser-passt.xml +++ b/tests/qemuxmlconfdata/net-vhostuser-passt.xml @@ -50,7 +50,7 @@ - +