]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
remote: extract logic for probing for modular daemons
authorDaniel P. Berrangé <berrange@redhat.com>
Mon, 24 May 2021 16:10:05 +0000 (17:10 +0100)
committerDaniel P. Berrangé <berrange@redhat.com>
Fri, 18 Jun 2021 15:19:42 +0000 (16:19 +0100)
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.

Tested-by: Jim Fehlig <jfehlig@suse.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
src/libvirt_remote.syms
src/remote/remote_daemon_dispatch.c
src/remote/remote_sockets.c
src/remote/remote_sockets.h

index 11c9e2cb735382a22dc2268100c889009a936bf0..b4265adf2ee2722b4f8d33d2e130e38ac924a951 100644 (file)
@@ -14,6 +14,11 @@ xdr_*;
 xdr_virNetMessageError;
 
 
+# remote/remote_sockets.h
+remoteProbeSessionDriverFromBinary;
+remoteProbeSessionDriverFromSocket;
+remoteProbeSystemDriverFromSocket;
+
 # rpc/virnetclient.h
 virNetClientAddProgram;
 virNetClientAddStream;
index dd797a81f7fa3b6e619eef8ae0833549e5045ad1..36d4d00b798e2d8baaa8f2552c6e76d0db53dd40 100644 (file)
@@ -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
-            "xen",
-# 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 */
index 0f85b999fda5271e5eeb6e97f0944c67ed453e21..85295f1bc2107bc6307d818a847b5850a05b39b4 100644 (file)
@@ -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
+        "xen",
+#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,
index 11934dbf7055ea2670bec5e731a599eeda644c05..00e654d46c2a5178957e7c88db2ad4c97d5debca 100644 (file)
@@ -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,