On 6/10/21 7:43 AM, Daniel P. Berrangé wrote:
When virtproxyd gets a NULL URI, it needs to implement probing logic
similar to that found in virConnectOpen. The latter can't be used
directly since it relied on directly calling into the internal drivers
in libvirtd. virtproxyd approximates this behaviour by looking to see
what modular daemon sockets exist, or what daemon binaries are installed.
This same logic is also going to be needed when the regular libvirt
remote client switches to prefer modular daemons by default, as we
don't want to continue spawning libvirtd going forward.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
src/libvirt_remote.syms | 5 +
src/remote/remote_daemon_dispatch.c | 98 +++++---------------
src/remote/remote_sockets.c | 139 ++++++++++++++++++++++++++++
src/remote/remote_sockets.h | 7 ++
4 files changed, 173 insertions(+), 76 deletions(-)
diff --git a/src/libvirt_remote.syms b/src/libvirt_remote.syms
index 11c9e2cb73..b4265adf2e 100644
--- a/src/libvirt_remote.syms
+++ b/src/libvirt_remote.syms
@@ -14,6 +14,11 @@ xdr_*;
xdr_virNetMessageError;
+# remote/remote_sockets.h
+remoteProbeSessionDriverFromBinary;
+remoteProbeSessionDriverFromSocket;
+remoteProbeSystemDriverFromSocket;
+
# rpc/virnetclient.h
virNetClientAddProgram;
virNetClientAddStream;
diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c
index 838f4a925f..36d4d00b79 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -24,6 +24,7 @@
#include "remote_daemon_dispatch.h"
#include "remote_daemon.h"
+#include "remote_sockets.h"
#include "libvirt_internal.h"
#include "datatypes.h"
#include "viralloc.h"
@@ -1968,6 +1969,8 @@ static int
remoteDispatchProbeURI(bool readonly,
char **probeduri)
{
+ g_autofree char *driver = NULL;
+ const char *suffix;
*probeduri = NULL;
VIR_DEBUG("Probing for driver daemon sockets");
@@ -1976,94 +1979,37 @@ remoteDispatchProbeURI(bool readonly,
* exists, or we're using socket activation so the socket exists
* too.
*
- * If running non-root, chances are that the daemon won't be
- * running, nor any socket activation is used. We need to
- * be able to auto-spawn the daemon. We thus just check to
- * see what daemons are installed. This is not a big deal as
- * only QEMU & VBox run as non-root, anyway.
+ * If running non-root, the daemon may or may not already be
+ * running, and socket activation probably isn't relevant.
+ * So if no viable socket exists, we need to check which daemons
+ * are actually installed. This is not a big deal as only QEMU &
+ * VBox run as non-root, anyway.
*/
if (geteuid() != 0) {
- /* Order these the same as virDriverLoadModule
- * calls in daemonInitialize */
- const char *drivers[] = {
-# ifdef WITH_QEMU
- "qemu",
-# endif
-# ifdef WITH_VBOX
- "vbox",
-# endif
- };
- ssize_t i;
-
- for (i = 0; i < (ssize_t) G_N_ELEMENTS(drivers) && !*probeduri; i++)
{
- g_autofree char *daemonname = NULL;
- g_autofree char *daemonpath = NULL;
-
- daemonname = g_strdup_printf("virt%sd", drivers[i]);
-
- if (!(daemonpath = virFileFindResource(daemonname,
- abs_top_builddir "/src",
- SBINDIR)))
- return -1;
-
- if (!virFileExists(daemonpath)) {
- VIR_DEBUG("Missing daemon %s for driver %s", daemonpath,
drivers[i]);
- continue;
- }
+ if (remoteProbeSessionDriverFromSocket(false, &driver) < 0)
+ return -1;
- *probeduri = g_strdup_printf("%s:///session", drivers[i]);
+ if (driver == NULL &&
+ remoteProbeSessionDriverFromBinary(&driver) < 0)
+ return -1;
- VIR_DEBUG("Probed URI %s via daemon %s", *probeduri, daemonpath);
- return 0;
- }
+ suffix = "session";
} else {
- /* Order these the same as virDriverLoadModule
- * calls in daemonInitialize */
- const char *drivers[] = {
-# ifdef WITH_LIBXL
- "libxl",
-# endif
-# ifdef WITH_QEMU
- "qemu",
-# endif
-# ifdef WITH_LXC
- "lxc",
-# endif
-# ifdef WITH_VBOX
- "vbox",
-# endif
-# ifdef WITH_BHYVE
- "bhyve",
-# endif
-# ifdef WITH_VZ
- "vz",
-# endif
- };
- ssize_t i;
-
- for (i = 0; i < (ssize_t) G_N_ELEMENTS(drivers) && !*probeduri; i++)
{
- g_autofree char *sockname = NULL;
-
- sockname = g_strdup_printf("%s/libvirt/virt%sd-%s", RUNSTATEDIR,
- drivers[i], readonly ? "sock-ro" :
"sock");
-
- if (!virFileExists(sockname)) {
- VIR_DEBUG("Missing sock %s for driver %s", sockname,
drivers[i]);
- continue;
- }
-
- *probeduri = g_strdup_printf("%s:///system", drivers[i]);
+ if (remoteProbeSystemDriverFromSocket(readonly, &driver) < 0)
+ return -1;
- VIR_DEBUG("Probed URI %s via sock %s", *probeduri, sockname);
- return 0;
- }
+ suffix = "system";
}
/* Even if we didn't probe any socket, we won't
* return error. Just let virConnectOpen's normal
* logic run which will likely return an error anyway
*/
- VIR_DEBUG("No driver sock exists");
+ if (!driver)
+ return 0;
+
+ *probeduri = g_strdup_printf("%s:///%s", driver, suffix);
+ VIR_DEBUG("Probed URI %s for driver %s", *probeduri, driver);
return 0;
}
#endif /* VIRTPROXYD */
diff --git a/src/remote/remote_sockets.c b/src/remote/remote_sockets.c
index 0f85b999fd..dd28c9dd5e 100644
--- a/src/remote/remote_sockets.c
+++ b/src/remote/remote_sockets.c
@@ -146,6 +146,145 @@ remoteGetUNIXSocketHelper(remoteDriverTransport transport,
return sockname;
}
+/*
+ * Determine which driver is probably usable based on
+ * which modular daemon binaries are installed.
+ */
+int
+remoteProbeSessionDriverFromBinary(char **driver)
+{
+ /* Order these the same as virDriverLoadModule
+ * calls in daemonInitialize, so we replicate
+ * probing order that virConnectOpen would use
+ * if running inside libvirtd */
+ const char *drivers[] = {
+#ifdef WITH_QEMU
+ "qemu",
+#endif
+#ifdef WITH_VBOX
+ "vbox",
+#endif
+ };
+ ssize_t i;
+
+ VIR_DEBUG("Probing for driver from daemon binaries");
+
+ *driver = NULL;
+
+ for (i = 0; i < (ssize_t) G_N_ELEMENTS(drivers); i++) {
+ g_autofree char *daemonname = NULL;
+ g_autofree char *daemonpath = NULL;
+
+ daemonname = g_strdup_printf("virt%sd", drivers[i]);
+ VIR_DEBUG("Probing driver '%s' via daemon %s", drivers[i],
daemonpath);
+
+ if (!(daemonpath = virFileFindResource(daemonname,
+ abs_top_builddir "/src",
+ SBINDIR)))
+ return -1;
+
+ if (virFileExists(daemonpath)) {
+ VIR_DEBUG("Found driver '%s' via daemon %s", drivers[i],
daemonpath);
+ *driver = g_strdup(drivers[i]);
+ return 0;
+ }
+
+ VIR_DEBUG("Missing daemon %s for driver %s", daemonpath, drivers[i]);
+ }
+
+ VIR_DEBUG("No more drivers to probe for");
+ return 0;
+}
+
+
+int
+remoteProbeSystemDriverFromSocket(bool readonly, char **driver)
+{
+ /* Order these the same as virDriverLoadModule
+ * calls in daemonInitialize, so we replicate
+ * probing order that virConnectOpen would use
+ * if running inside libvirtd */
+ const char *drivers[] = {
+#ifdef WITH_LIBXL
+ "libxl",
Pre-existing bug due to libxl vs xen naming fiasco, but here it should be
"xen".
Regards,
Jim
+#endif
+#ifdef WITH_QEMU
+ "qemu",
+#endif
+#ifdef WITH_LXC
+ "lxc",
+#endif
+#ifdef WITH_VBOX
+ "vbox",
+#endif
+#ifdef WITH_BHYVE
+ "bhyve",
+#endif
+#ifdef WITH_VZ
+ "vz",
+#endif
+ };
+ ssize_t i;
+
+ for (i = 0; i < (ssize_t) G_N_ELEMENTS(drivers); i++) {
+ g_autofree char *sockname =
+ g_strdup_printf("%s/libvirt/virt%sd-%s", RUNSTATEDIR,
+ drivers[i], readonly ? "sock-ro" :
"sock");
+
+ if (virFileExists(sockname)) {
+ VIR_DEBUG("Probed driver '%s' via sock '%s'",
drivers[i], sockname);
+ *driver = g_strdup(drivers[i]);
+ return 0;
+ }
+
+ VIR_DEBUG("Missing sock %s for driver %s", sockname, drivers[i]);
+ }
+
+ /* Even if we didn't probe any socket, we won't
+ * return error. Just let virConnectOpen's normal
+ * logic run which will likely return an error anyway
+ */
+ VIR_DEBUG("No more drivers to probe for");
+ return 0;
+}
+
+int
+remoteProbeSessionDriverFromSocket(bool readonly, char **driver)
+{
+ /* Order these the same as virDriverLoadModule
+ * calls in daemonInitialize */
+ const char *drivers[] = {
+#ifdef WITH_QEMU
+ "qemu",
+#endif
+#ifdef WITH_VBOX
+ "vbox",
+#endif
+ };
+ ssize_t i;
+
+ for (i = 0; i < (ssize_t) G_N_ELEMENTS(drivers); i++) {
+ g_autofree char *userdir = virGetUserRuntimeDirectory();
+ g_autofree char *sockname =
+ g_strdup_printf("%s/virt%sd-%s",
+ userdir, drivers[i], readonly ? "sock-ro" :
"sock");
+
+ if (virFileExists(sockname)) {
+ VIR_DEBUG("Probed driver '%s' via sock '%s'",
drivers[i], sockname);
+ *driver = g_strdup(drivers[i]);
+ return 0;
+ }
+
+ VIR_DEBUG("Missing sock %s for driver %s", sockname, drivers[i]);
+ }
+
+ /* Even if we didn't probe any socket, we won't
+ * return error. Just let virConnectOpen's normal
+ * logic run which will likely return an error anyway
+ */
+ VIR_DEBUG("No more drivers to probe for");
+ return 0;
+}
char *
remoteGetUNIXSocket(remoteDriverTransport transport,
diff --git a/src/remote/remote_sockets.h b/src/remote/remote_sockets.h
index 11934dbf70..00e654d46c 100644
--- a/src/remote/remote_sockets.h
+++ b/src/remote/remote_sockets.h
@@ -62,6 +62,13 @@ remoteSplitURIScheme(virURI *uri,
char **driver,
remoteDriverTransport *transport);
+int
+remoteProbeSessionDriverFromBinary(char **driver);
+int
+remoteProbeSystemDriverFromSocket(bool readonly, char **driver);
+int
+remoteProbeSessionDriverFromSocket(bool readonly, char **driver);
+
char *
remoteGetUNIXSocket(remoteDriverTransport transport,
remoteDriverMode mode,