mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-09-08 16:54:49 +00:00
remote: handle autoprobing of driver within virtproxyd
The virtproxyd daemon is merely responsible for forwarding RPC calls to one of the other per-driver daemons. As such, it does not have any drivers loaded and so regular auto-probing logic will not work. We need it to be able to handle NULL URIs though, so must implement some kind of alternative probing logic. When running as root this is quite crude. If a per-driver daemon is running, its UNIX socket will exist and we can assume it will accept connections. If the per-driver daemon is not running, but socket autostart is enabled, we again just assume it will accept connections. The is not great, however, because a default install may well have all sockets available for activation. IOW, the virtxend socket may exist, despite the fact that the libxl driver will not actually work. When running as non-root this is slightly easier as we only have two drivers, QEMU and VirtualBox. These daemons will likely not be running and socket activation won't be used either, as libvirt spawns the daemon on demand. So we just check whether the daemon actually is installed. Reviewed-by: Andrea Bolognani <abologna@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
463629559d
commit
55c8d1a95f
@ -235,6 +235,7 @@ virtproxyd_CFLAGS = \
|
||||
-DSOCK_PREFIX="\"libvirt\"" \
|
||||
-DDAEMON_NAME="\"virtproxyd\"" \
|
||||
-DENABLE_IP \
|
||||
-DVIRTPROXYD \
|
||||
$(NULL)
|
||||
virtproxyd_LDFLAGS = $(REMOTE_DAEMON_LD_FLAGS)
|
||||
virtproxyd_LDADD = $(REMOTE_DAEMON_LD_ADD)
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "viraccessapicheckqemu.h"
|
||||
#include "virpolkit.h"
|
||||
#include "virthreadjob.h"
|
||||
#include "configmake.h"
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_RPC
|
||||
|
||||
@ -2094,6 +2095,131 @@ void *remoteClientNew(virNetServerClientPtr client,
|
||||
|
||||
/*----- Functions. -----*/
|
||||
|
||||
#ifdef VIRTPROXYD
|
||||
/*
|
||||
* When running in virtproxyd regular auto-probing of drivers
|
||||
* does not work as we don't have any drivers present (except
|
||||
* stateless ones inside libvirt.so). All the interesting
|
||||
* drivers are in separate daemons. Thus when we get a NULL
|
||||
* URI we need to simulate probing that virConnectOpen would
|
||||
* previously do. We use the existance of the UNIX domain
|
||||
* socket as our hook for probing.
|
||||
*
|
||||
* This assumes no stale sockets left over from a now dead
|
||||
* daemon, but that's reasonable since libvirtd unlinks
|
||||
* sockets it creates on shutdown, or uses systemd activation
|
||||
*
|
||||
* We only try to probe for primary hypervisor drivers,
|
||||
* not the secondary drivers.
|
||||
*/
|
||||
static int
|
||||
remoteDispatchProbeURI(bool readonly,
|
||||
char **probeduri)
|
||||
{
|
||||
*probeduri = NULL;
|
||||
VIR_DEBUG("Probing for driver daemon sockets");
|
||||
|
||||
/*
|
||||
* If running root, either the daemon is running and the socket
|
||||
* 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 (geteuid() != 0) {
|
||||
/* Order these the same as virDriverLoadModule
|
||||
* calls in daemonInitialize */
|
||||
const char *drivers[] = {
|
||||
# ifdef WITH_QEMU
|
||||
"qemu",
|
||||
# endif
|
||||
# ifdef WITH_VBOX
|
||||
"vbox",
|
||||
# endif
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_CARDINALITY(drivers) && !*probeduri; i++) {
|
||||
VIR_AUTOFREE(char *) daemonname = NULL;
|
||||
VIR_AUTOFREE(char *) daemonpath = NULL;
|
||||
|
||||
if (virAsprintf(&daemonname, "virt%sd", drivers[i]) < 0)
|
||||
return -1;
|
||||
|
||||
if (!(daemonpath = virFileFindResource(daemonname, "src", SBINDIR)))
|
||||
return -1;
|
||||
|
||||
if (!virFileExists(daemonpath)) {
|
||||
VIR_DEBUG("Missing daemon %s for driver %s", daemonpath, drivers[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (virAsprintf(probeduri, "%s:///session", drivers[i]) < 0)
|
||||
return -1;
|
||||
|
||||
VIR_DEBUG("Probed URI %s via daemon %s", *probeduri, daemonpath);
|
||||
return 0;
|
||||
}
|
||||
} 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
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_CARDINALITY(drivers) && !*probeduri; i++) {
|
||||
VIR_AUTOFREE(char *) sockname = NULL;
|
||||
|
||||
if (virAsprintf(&sockname, "%s/run/libvirt/virt%sd-%s",
|
||||
LOCALSTATEDIR, drivers[i],
|
||||
readonly ? "sock-ro" : "sock") < 0)
|
||||
return -1;
|
||||
|
||||
if (!virFileExists(sockname)) {
|
||||
VIR_DEBUG("Missing sock %s for driver %s", sockname, drivers[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (virAsprintf(probeduri, "%s:///system", drivers[i]) < 0)
|
||||
return -1;
|
||||
|
||||
VIR_DEBUG("Probed URI %s via sock %s", *probeduri, sockname);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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");
|
||||
return 0;
|
||||
}
|
||||
#endif /* VIRTPROXYD */
|
||||
|
||||
|
||||
static int
|
||||
remoteDispatchConnectOpen(virNetServerPtr server ATTRIBUTE_UNUSED,
|
||||
virNetServerClientPtr client,
|
||||
@ -2102,6 +2228,9 @@ remoteDispatchConnectOpen(virNetServerPtr server ATTRIBUTE_UNUSED,
|
||||
struct remote_connect_open_args *args)
|
||||
{
|
||||
const char *name;
|
||||
#ifdef VIRTPROXYD
|
||||
VIR_AUTOFREE(char *) probeduri = NULL;
|
||||
#endif
|
||||
unsigned int flags;
|
||||
struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client);
|
||||
int rv = -1;
|
||||
@ -2128,6 +2257,15 @@ remoteDispatchConnectOpen(virNetServerPtr server ATTRIBUTE_UNUSED,
|
||||
|
||||
priv->readonly = flags & VIR_CONNECT_RO;
|
||||
|
||||
#ifdef VIRTPROXYD
|
||||
if (!name || STREQ(name, "")) {
|
||||
if (remoteDispatchProbeURI(priv->readonly, &probeduri) < 0)
|
||||
goto cleanup;
|
||||
|
||||
name = probeduri;
|
||||
}
|
||||
#endif
|
||||
|
||||
VIR_DEBUG("Opening driver %s", name);
|
||||
if (priv->readonly) {
|
||||
if (!(priv->conn = virConnectOpenReadOnly(name)))
|
||||
|
Loading…
Reference in New Issue
Block a user