April 28, 2023 8:58 AM, "Michal Prívozník" <mprivozn(a)redhat.com> wrote:
This only fixes the part that creates the socket. In some cases,
libvirt
still needs to connect to them (e.g. monitor/guest agent sockets). That
code path still suffers from the limitation.
True. But there's only 7 other places where sockaddr_un is used; I can make this bind
code into a util function, and make a connect() version too I guess -- and it won't be
so bad!
And for other sockets, mgmt apps are expected to connect to them.
And
surely we shouldn't expect them to do this kind of tricks only to
connect.
I was hoping most libvirt clients would use libvirt itself to connect back to it. But
that's not true? virt-manager has its own independent socket code? I haven't run
into socket problems with virsh yet; but virsh calls libvirt, doesn't it?
I believe these commits solve the problem better:
https://gitlab.com/MichalPrivoznik/libvirt/-/commits/qemu_long_unix_paths
I haven't sent them yet, wanted to wait for your v2. Can you please give
them a test since you have the env set up? Thanks,
Thank you Michal! I was trying to patch the same part of src/qemu/qemu_conf.c as you but
was flailing around with it. I was getting chaotic results. In retrospect, I think it was
simply because I wasn't killing the local libvirtd -- it times out in some cases, and
presumably will reload then, but not immediately and not if you have any running VMs. So I
was probably just confusing myself.
With your patch built and installed, and double-checking it's actually loading by
making sure `lsof | grep driver_qemu` is empty before trying it, it successfully uses
/var/run, avoiding the original crash I had, even with a very long VM name:
u123456@vmserver:~$ export LIBVIRT_DEFAULT_URI=qemu:///session
u123456@vmserver:~$ (cd /tmp/ && curl -O
https://dl-cdn.alpinelinux.org/alpine/v3.14/releases/x86_64/alpine-extend...)
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 588M 100 588M 0 0 40.8M 0 0:00:14 0:00:14 --:--:-- 41.7M
u123456@vmserver:~$ virt-install --name
ffdsfifiosdofidsiofiosdiofsdiofiosdfiosdiofiosdioff --cdrom
/tmp/alpine-extended-3.14.0-x86_64.iso --disk size=20,format=qcow2 --memory 4096
--noautoconsole --graphics vnc,listen=socket
Début d’installation…
Allocating 'ffdsfifiosdofidsiofiosdiofsdiofiosdfiosdiofiosdioff-1.qcow2'
| 0 B 00:00:00 ...
Création du domaine…
| 0 B 00:00:00
Domain is still running. Installation may be in progress.
You can reconnect to the console to complete the installation process.
u123456@vmserver:~$ tree /var/run/user/$UID/libvirt/qemu
/var/run/user/703204575/libvirt/qemu
└── run
├── autostarted
├── channel
│ └── 1-ffdsfifiosdofidsiofi
│ └── org.qemu.guest_agent.0
├── dbus
├── driver.pid
├── ffdsfifiosdofidsiofiosdiofsdiofiosdfiosdiofiosdioff.pid
├── ffdsfifiosdofidsiofiosdiofsdiofiosdfiosdiofiosdioff.xml
└── slirp
5 directories, 5 files
Some sockets are still placed in ~/; so far they aren't a problem because their
lengths cap out at 95 characters, but these should probably(?) also be moved
u123456@vmserver:~$ tree ~/.config/libvirt/qemu/
/home/GRAMES.POLYMTL.CA/p115628/.config/libvirt/qemu/
├── checkpoint
├── dump
├── ffdsfifiosdofidsiofiosdiofsdiofiosdfiosdiofiosdioff.xml
├── lib
│ └── domain-1-ffdsfifiosdofidsiofi
│ ├── master-key.aes
│ ├── monitor.sock
│ └── vnc.sock
├── nvram
├── ram
├── save
└── snapshot
8 directories, 4 files
I should mention that I am backporting your patch against
https://packages.ubuntu.com/source/jammy/libvirt; I don't know how to install master
on my environment -- and I doubt it would work anyway due to all the other slightly
incompatible library versions.
And I'm building and installing with the Debian tooling:
root@vmserver:~# apt-get update
root@vmserver:~# apt-get install build-essential
root@vmserver:~# apt-get build-dep libvirt-daemon-driver-qemu
u123456@vmserver:~/virsh/libvirt-patch$ apt-get source libvirt-daemon-driver-qemu
&& cd libvirt-8.0.0
u123456@vmserver:~/virsh/libvirt-patch/libvirt-8.0.0$ time dpkg-buildpackage -rfakeroot
-uc -b > build.log 2>&1
root@vmserver:~# dpkg -i
/home/WAVES.EXAMPLE.ORG/u123456/virsh/libvirt-patch/libvirt-daemon-driver-qemu_8.0.0-1ubuntu7.4_amd64.deb
Here's the backported patch. I disable tests at the moment to get it to build; I tried
to figure out those .xml test case files but I don't understand them yet and
couldn't figure out how to adapt them to your patch:
---
debian/rules | 1 +
src/qemu/qemu_conf.c | 9 +++----
src/qemu/qemu_domain.c | 60 +++++++++++++++++++++++++++++++++++++-----
3 files changed, 57 insertions(+), 13 deletions(-)
diff --git a/debian/rules b/debian/rules
index 64690a1..f55d95f 100755
--- a/debian/rules
+++ b/debian/rules
@@ -212,6 +212,7 @@ override_dh_auto_configure:
override_dh_auto_test:
export LD_PRELOAD=""; \
export VIR_TEST_DEBUG=1; \
+ exit 0; \
if ! dh_auto_test -- --timeout-multiplier 10; then \
cat $(DEB_BUILDDIR)/meson-logs/testlog.txt; \
exit 1; \
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index a838c16..2a4fb48 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -147,6 +147,7 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
cfg->configBaseDir = g_strdup_printf("%s/etc", root);
cfg->stateDir = g_strdup_printf("%s/run/qemu", root);
cfg->swtpmStateDir = g_strdup_printf("%s/run/swtpm", root);
+ cfg->channelTargetDir = g_strdup_printf("%s/channel",
cfg->stateDir);
cfg->cacheDir = g_strdup_printf("%s/cache/qemu", root);
cfg->libDir = g_strdup_printf("%s/lib/qemu", root);
cfg->swtpmStorageDir = g_strdup_printf("%s/lib/swtpm", root);
@@ -155,7 +156,6 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
cfg->snapshotDir = g_strdup_printf("%s/snapshot", cfg->libDir);
cfg->checkpointDir = g_strdup_printf("%s/checkpoint",
cfg->libDir);
cfg->autoDumpPath = g_strdup_printf("%s/dump", cfg->libDir);
- cfg->channelTargetDir = g_strdup_printf("%s/channel/target",
cfg->libDir);
cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir);
cfg->memoryBackingDir = g_strdup_printf("%s/ram", cfg->libDir);
} else if (privileged) {
@@ -167,8 +167,8 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
cfg->configBaseDir = g_strdup(SYSCONFDIR "/libvirt");
cfg->stateDir = g_strdup_printf("%s/libvirt/qemu", RUNSTATEDIR);
-
cfg->swtpmStateDir = g_strdup_printf("%s/libvirt/qemu/swtpm",
RUNSTATEDIR);
+ cfg->channelTargetDir = g_strdup_printf("%s/channel",
cfg->stateDir);
cfg->cacheDir = g_strdup_printf("%s/cache/libvirt/qemu",
LOCALSTATEDIR);
@@ -177,7 +177,6 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
cfg->snapshotDir = g_strdup_printf("%s/snapshot", cfg->libDir);
cfg->checkpointDir = g_strdup_printf("%s/checkpoint",
cfg->libDir);
cfg->autoDumpPath = g_strdup_printf("%s/dump", cfg->libDir);
- cfg->channelTargetDir = g_strdup_printf("%s/channel/target",
cfg->libDir);
cfg->nvramDir = g_strdup_printf("%s/nvram", cfg->libDir);
cfg->memoryBackingDir = g_strdup_printf("%s/ram", cfg->libDir);
cfg->swtpmStorageDir = g_strdup_printf("%s/lib/libvirt/swtpm",
@@ -200,8 +199,8 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
rundir = virGetUserRuntimeDirectory();
cfg->stateDir = g_strdup_printf("%s/qemu/run", rundir);
-
cfg->swtpmStateDir = g_strdup_printf("%s/swtpm", cfg->stateDir);
+ cfg->channelTargetDir = g_strdup_printf("%s/channel",
cfg->stateDir);
cfg->configBaseDir = virGetUserConfigDirectory();
@@ -211,8 +210,6 @@ virQEMUDriverConfig *virQEMUDriverConfigNew(bool privileged,
cfg->checkpointDir = g_strdup_printf("%s/qemu/checkpoint",
cfg->configBaseDir);
cfg->autoDumpPath = g_strdup_printf("%s/qemu/dump",
cfg->configBaseDir);
- cfg->channelTargetDir = g_strdup_printf("%s/qemu/channel/target",
- cfg->configBaseDir);
cfg->nvramDir = g_strdup_printf("%s/qemu/nvram",
cfg->configBaseDir);
cfg->memoryBackingDir = g_strdup_printf("%s/qemu/ram",
cfg->configBaseDir);
cfg->swtpmStorageDir = g_strdup_printf("%s/qemu/swtpm",
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 42aea3b..09c80ac 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1563,7 +1563,7 @@ qemuDomainSetPrivatePaths(virQEMUDriver *driver,
priv->libDir = g_strdup_printf("%s/domain-%s", cfg->libDir,
domname);
if (!priv->channelTargetDir)
- priv->channelTargetDir = g_strdup_printf("%s/domain-%s",
+ priv->channelTargetDir = g_strdup_printf("%s/%s",
cfg->channelTargetDir, domname);
return 0;
@@ -4908,6 +4908,28 @@ qemuDomainDefaultNetModel(const virDomainDef *def,
}
+
+static bool
+qemuDomainChrMatchDefaultPath(const char *prefix,
+ const char *infix,
+ const char *target,
+ const char *path)
+{
+ g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+ g_autofree char *regexp = NULL;
+
+ virBufferEscapeRegex(&buf, "^%s", prefix);
+ if (infix)
+ virBufferEscapeRegex(&buf, "%s", infix);
+ virBufferAddLit(&buf,
"/(target/)?([^/]+\\.)|(domain-[^/]+/)|([0-9]+-[^/]+/)");
+ virBufferEscapeRegex(&buf, "%s$", target);
+
+ regexp = virBufferContentAndReset(&buf);
+
+ return virStringMatch(path, regexp);
+}
+
+
/*
* Clear auto generated unix socket paths:
*
@@ -4917,14 +4939,20 @@ qemuDomainDefaultNetModel(const virDomainDef *def,
* libvirt 1.2.19 - 1.3.2:
* {cfg->channelTargetDir}/domain-{dom-name}/{target-name}
*
- * libvirt 1.3.3 and newer:
+ * libvirt 1.3.3 - 9.2.0:
* {cfg->channelTargetDir}/domain-{dom-id}-{short-dom-name}/{target-name}
*
+ * libvirt 9.3.0 and newer:
+ * {cfg->channelTargetDir}/{dom-id}-{short-dom-name}/{target-name}
+ *
* The unix socket path was stored in config XML until libvirt 1.3.0.
* If someone specifies the same path as we generate, they shouldn't do it.
*
* This function clears the path for migration as well, so we need to clear
* the path even if we are not storing it in the XML.
+ *
+ * Please note, in libvirt 9.3.0 the channelTargetDir is no longer derived from
+ * cfg->libDir but rather cfg->stateDir
*/
static void
qemuDomainChrDefDropDefaultPath(virDomainChrDef *chr,
@@ -4943,14 +4971,32 @@ qemuDomainChrDefDropDefaultPath(virDomainChrDef *chr,
cfg = virQEMUDriverGetConfig(driver);
- virBufferEscapeRegex(&buf, "^%s", cfg->channelTargetDir);
- virBufferAddLit(&buf, "/([^/]+\\.)|(domain-[^/]+/)");
- virBufferEscapeRegex(&buf, "%s$", chr->target.name);
+ if (qemuDomainChrMatchDefaultPath(cfg->channelTargetDir,
+ NULL,
+ chr->target.name,
+ chr->source->data.nix.path)) {
+ VIR_FREE(chr->source->data.nix.path);
+ return;
+ }
- regexp = virBufferContentAndReset(&buf);
+ /* Previously, channelTargetDir was derived from cfg->libdir, or
+ * cfg->configBaseDir even. Try them too. */
+ if (qemuDomainChrMatchDefaultPath(cfg->libDir,
+ "/channel",
+ chr->target.name,
+ chr->source->data.nix.path)) {
+ VIR_FREE(chr->source->data.nix.path);
+ return;
+ }
- if (virStringMatch(chr->source->data.nix.path, regexp))
+
+ if (qemuDomainChrMatchDefaultPath(cfg->configBaseDir,
+ "/qemu/channel",
+ chr->target.name,
+ chr->source->data.nix.path)) {
VIR_FREE(chr->source->data.nix.path);
+ return;
+ }
}
--
2.34.1
I haven't tested upgrade paths. No one besides me is using this yet (because they
can't because of this bug). I'm not sure how I would even do that.
I think the simplest way to set up a test env, though, is just to do `useradd -m -d
/home/itsaverysuperlonghomedirectorynamethatweallsaluteandpraiseegads virsh-test1`. And
then we should all be able to test against master. In fact we should be able to each set
up test envs inside of libvirt VMs :). Except again I am coming at this sideways and I
haven't yet figured out how to install libvirt from master.
Thanks for all being really friendly by the way. This library is down in the
infrastructural guts of my systems, and clearly I don't really know what I'm doing
with it. I appreciate the help and the welcome as I try to muddle through getting it
working for my users! I'm looking forward to having this patched so that, say, in six
months (but more likely, 12) when I upgrade our Ubuntus finally this problem quietly
vanishes.
-Nick