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 dd797a81f7..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; + if (remoteProbeSessionDriverFromSocket(false, &driver) < 0) + return -1; - for (i = 0; i < (ssize_t) G_N_ELEMENTS(drivers) && !*probeduri; i++) { - g_autofree char *daemonname = NULL; - g_autofree char *daemonpath = NULL; + if (driver == NULL && + remoteProbeSessionDriverFromBinary(&driver) < 0) + return -1; - 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; - } - - *probeduri = g_strdup_printf("%s:///session", drivers[i]); - - 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; + if (remoteProbeSystemDriverFromSocket(readonly, &driver) < 0) + return -1; - 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]); - - 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..85295f1bc2 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 + "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, 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,