diff --git a/docs/remote.html.in b/docs/remote.html.in index fbcc8bf01c..78e071a898 100644 --- a/docs/remote.html.in +++ b/docs/remote.html.in @@ -206,6 +206,24 @@ Note that parameter values must be
tls_priority=NORMAL:-VERS-SSL3.0
mode
+ auto
direct
legacy
libvirt.conf
as remote_mode
+ mode=direct
command
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 184268b596..ee4b408510 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1170,6 +1170,7 @@ rm -f po/stamp-po
--without-xenapi \
--without-vz \
--without-bhyve \
+ --with-remote-default-mode=legacy \
--with-interface \
--with-network \
--with-storage-fs \
diff --git a/m4/virt-driver-remote.m4 b/m4/virt-driver-remote.m4
index c7af5b3fc6..8d98e369b3 100644
--- a/m4/virt-driver-remote.m4
+++ b/m4/virt-driver-remote.m4
@@ -19,6 +19,7 @@ dnl
AC_DEFUN([LIBVIRT_DRIVER_ARG_REMOTE], [
LIBVIRT_ARG_WITH_FEATURE([REMOTE], [remote driver], [yes])
+ LIBVIRT_ARG_WITH([REMOTE_DEFAULT_MODE], [remote driver default mode], [legacy])
])
AC_DEFUN([LIBVIRT_DRIVER_CHECK_REMOTE], [
@@ -26,6 +27,20 @@ AC_DEFUN([LIBVIRT_DRIVER_CHECK_REMOTE], [
AC_DEFINE_UNQUOTED([WITH_REMOTE], 1, [whether Remote driver is enabled])
fi
AM_CONDITIONAL([WITH_REMOTE], [test "$with_remote" = "yes"])
+
+ case "$with_remote_default_mode" in
+ legacy)
+ REMOTE_DRIVER_MODE_DEFAULT=REMOTE_DRIVER_MODE_LEGACY
+ ;;
+ direct)
+ REMOTE_DRIVER_MODE_DEFAULT=REMOTE_DRIVER_MODE_DIRECT
+ ;;
+ *)
+ AC_MSG_ERROR([Unknown remote mode '$with_remote_default_mode'])
+ ;;
+ esac
+
+ AC_DEFINE_UNQUOTED([REMOTE_DRIVER_MODE_DEFAULT],[$REMOTE_DRIVER_MODE_DEFAULT], [Default remote driver mode])
])
AC_DEFUN([LIBVIRT_DRIVER_RESULT_REMOTE], [
diff --git a/src/driver.h b/src/driver.h
index 898fb96df4..f7d667a03c 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -108,6 +108,8 @@ int virSetSharedNWFilterDriver(virNWFilterDriverPtr driver) ATTRIBUTE_RETURN_CHE
int virSetSharedSecretDriver(virSecretDriverPtr driver) ATTRIBUTE_RETURN_CHECK;
int virSetSharedStorageDriver(virStorageDriverPtr driver) ATTRIBUTE_RETURN_CHECK;
+bool virHasDriverForURIScheme(const char *scheme);
+
int virDriverLoadModule(const char *name,
const char *regfunc,
bool required);
diff --git a/src/libvirt.c b/src/libvirt.c
index 906bab8128..956ccdea30 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -594,6 +594,33 @@ virRegisterConnectDriver(virConnectDriverPtr driver,
}
+/**
+ * virHasDriverForURIScheme:
+ * @scheme: the URI scheme
+ *
+ * Determine if there is a driver registered that explicitly
+ * handles URIs with the scheme @scheme.
+ *
+ * Returns: true if a driver is registered
+ */
+bool
+virHasDriverForURIScheme(const char *scheme)
+{
+ size_t i;
+ size_t j;
+
+ for (i = 0; i < virConnectDriverTabCount; i++) {
+ if (!virConnectDriverTab[i]->uriSchemes)
+ continue;
+ for (j = 0; virConnectDriverTab[i]->uriSchemes[j]; j++) {
+ if (STREQ(virConnectDriverTab[i]->uriSchemes[j], scheme))
+ return true;
+ }
+ }
+
+ return false;
+}
+
/**
* virRegisterStateDriver:
* @driver: pointer to a driver block
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 6e1001b385..daac506672 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -78,6 +78,24 @@ VIR_ENUM_IMPL(remoteDriverTransport,
"tcp",
"libssh");
+typedef enum {
+ /* Try to figure out the "best" choice magically */
+ REMOTE_DRIVER_MODE_AUTO,
+ /* Always use the legacy libvirtd */
+ REMOTE_DRIVER_MODE_LEGACY,
+ /* Always use the per-driver virt*d daemons */
+ REMOTE_DRIVER_MODE_DIRECT,
+
+ REMOTE_DRIVER_MODE_LAST
+} remoteDriverMode;
+
+VIR_ENUM_DECL(remoteDriverMode);
+VIR_ENUM_IMPL(remoteDriverMode,
+ REMOTE_DRIVER_MODE_LAST,
+ "auto",
+ "legacy",
+ "direct");
+
#if SIZEOF_LONG < 8
# define HYPER_TO_TYPE(_type, _to, _from) \
do { \
@@ -748,8 +766,9 @@ remoteConnectSupportsFeatureUnlocked(virConnectPtr conn,
static char *
-remoteGetUNIXSocket(remoteDriverTransport transport,
- unsigned int flags)
+remoteGetUNIXSocketHelper(remoteDriverTransport transport,
+ const char *sock_prefix,
+ unsigned int flags)
{
char *sockname = NULL;
VIR_AUTOFREE(char *) userdir = NULL;
@@ -766,21 +785,129 @@ remoteGetUNIXSocket(remoteDriverTransport transport,
if (!(userdir = virGetUserRuntimeDirectory()))
return NULL;
- if (virAsprintf(&sockname,
- "%s/" LIBVIRTD_USER_UNIX_SOCKET, userdir) < 0)
+ if (virAsprintf(&sockname, "%s/%s-sock",
+ userdir, sock_prefix) < 0)
return NULL;
} else {
- if (VIR_STRDUP(sockname,
- flags & VIR_DRV_OPEN_REMOTE_RO ?
- LIBVIRTD_PRIV_UNIX_SOCKET_RO :
- LIBVIRTD_PRIV_UNIX_SOCKET) < 0)
+ if (virAsprintf(&sockname, "%s/run/libvirt/%s-%s",
+ LOCALSTATEDIR, sock_prefix,
+ flags & VIR_DRV_OPEN_REMOTE_RO ?
+ "sock-ro" : "sock") < 0)
return NULL;
}
- VIR_DEBUG("Chosen UNIX sockname %s", sockname);
+ VIR_DEBUG("Built UNIX sockname %s for transport %s prefix %s flags=0x%x",
+ sockname, remoteDriverTransportTypeToString(transport),
+ sock_prefix, flags);
return sockname;
}
+
+static char *
+remoteGetUNIXSocket(remoteDriverTransport transport,
+ remoteDriverMode mode,
+ const char *driver,
+ char **daemon,
+ unsigned int flags)
+{
+ char *sock_name = NULL;
+ VIR_AUTOFREE(char *) direct_daemon = NULL;
+ VIR_AUTOFREE(char *) legacy_daemon = NULL;
+ VIR_AUTOFREE(char *) direct_sock_name = NULL;
+ VIR_AUTOFREE(char *) legacy_sock_name = NULL;
+
+ if (driver &&
+ virAsprintf(&direct_daemon, "virt%sd", driver) < 0)
+ return NULL;
+
+ if (VIR_STRDUP(legacy_daemon, "libvirtd") < 0)
+ return NULL;
+
+ if (driver &&
+ !(direct_sock_name = remoteGetUNIXSocketHelper(transport, direct_daemon, flags)))
+ return NULL;
+
+ if (!(legacy_sock_name = remoteGetUNIXSocketHelper(transport, "libvirt", flags)))
+ return NULL;
+
+ if (mode == REMOTE_DRIVER_MODE_AUTO) {
+ if (transport == REMOTE_DRIVER_TRANSPORT_UNIX) {
+ if (direct_sock_name && virFileExists(direct_sock_name)) {
+ mode = REMOTE_DRIVER_MODE_DIRECT;
+ } else if (virFileExists(legacy_sock_name)) {
+ mode = REMOTE_DRIVER_MODE_LEGACY;
+ } else if (driver) {
+ /*
+ * This constant comes from the configure script and
+ * maps to either the direct or legacy mode constant
+ */
+ mode = REMOTE_DRIVER_MODE_DEFAULT;
+ } else {
+ mode = REMOTE_DRIVER_MODE_LEGACY;
+ }
+ } else {
+ mode = REMOTE_DRIVER_MODE_LEGACY;
+ }
+ }
+
+ switch ((remoteDriverMode)mode) {
+ case REMOTE_DRIVER_MODE_LEGACY:
+ VIR_STEAL_PTR(sock_name, legacy_sock_name);
+ VIR_STEAL_PTR(*daemon, legacy_daemon);
+ break;
+
+ case REMOTE_DRIVER_MODE_DIRECT:
+ if (transport != REMOTE_DRIVER_TRANSPORT_UNIX) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+ _("Cannot use direct socket mode for %s transport"),
+ remoteDriverTransportTypeToString(transport));
+ return NULL;
+ }
+
+ if (!direct_sock_name) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("Cannot use direct socket mode if no URI is set"));
+ return NULL;
+ }
+
+ VIR_STEAL_PTR(sock_name, direct_sock_name);
+ VIR_STEAL_PTR(*daemon, direct_daemon);
+ break;
+
+ case REMOTE_DRIVER_MODE_AUTO:
+ case REMOTE_DRIVER_MODE_LAST:
+ default:
+ virReportEnumRangeError(remoteDriverMode, mode);
+ return NULL;
+ }
+
+ VIR_DEBUG("Chosen UNIX sockname %s daemon %s "
+ "for mode %s transport %s flags=0x%x",
+ sock_name, NULLSTR(*daemon),
+ remoteDriverModeTypeToString(mode),
+ remoteDriverTransportTypeToString(transport),
+ flags);
+ return sock_name;
+}
+
+
+#ifndef WIN32
+static const char *
+remoteGetDaemonPathEnv(void)
+{
+ /* We prefer a VIRTD_PATH env var to use for all daemons,
+ * but if it is not set we will fallback to LIBVIRTD_PATH
+ * for previous behaviour
+ */
+ if (getenv("VIRTD_PATH") != NULL) {
+ return "VIRTD_PATH";
+ } else {
+ return "LIBVIRTD_PATH";
+ }
+}
+#endif /* WIN32 */
+
+
/*
* URIs that this driver needs to handle:
*
@@ -827,11 +954,20 @@ doRemoteOpen(virConnectPtr conn,
VIR_AUTOFREE(char *) sshauth = NULL;
VIR_AUTOFREE(char *) knownHostsVerify = NULL;
VIR_AUTOFREE(char *) knownHosts = NULL;
+ VIR_AUTOFREE(char *) mode_str = NULL;
+ VIR_AUTOFREE(char *) daemon_name = NULL;
bool sanity = true;
bool verify = true;
#ifndef WIN32
bool tty = true;
#endif
+ int mode;
+
+ if (inside_daemon && !conn->uri->server) {
+ mode = REMOTE_DRIVER_MODE_DIRECT;
+ } else {
+ mode = REMOTE_DRIVER_MODE_AUTO;
+ }
/* We handle *ALL* URIs here. The caller has rejected any
* URIs we don't care about */
@@ -905,7 +1041,7 @@ doRemoteOpen(virConnectPtr conn,
EXTRACT_URI_ARG_STR("known_hosts", knownHosts);
EXTRACT_URI_ARG_STR("known_hosts_verify", knownHostsVerify);
EXTRACT_URI_ARG_STR("tls_priority", tls_priority);
-
+ EXTRACT_URI_ARG_STR("mode", mode_str);
EXTRACT_URI_ARG_BOOL("no_sanity", sanity);
EXTRACT_URI_ARG_BOOL("no_verify", verify);
#ifndef WIN32
@@ -952,6 +1088,21 @@ doRemoteOpen(virConnectPtr conn,
goto failed;
}
+ if (conf && !mode_str &&
+ virConfGetValueString(conf, "remote_mode", &mode_str) < 0)
+ goto failed;
+
+ if (mode_str &&
+ (mode = remoteDriverModeTypeFromString(mode_str)) < 0)
+ goto failed;
+
+ /* Sanity check that nothing requested !direct mode by mistake */
+ if (inside_daemon && !conn->uri->server && mode != REMOTE_DRIVER_MODE_DIRECT) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("Connections from inside daemon must be direct"));
+ return VIR_DRV_OPEN_ERROR;
+ }
+
VIR_DEBUG("proceeding with name = %s", name);
/* For ext transport, command is required. */
@@ -969,7 +1120,8 @@ doRemoteOpen(virConnectPtr conn,
case REMOTE_DRIVER_TRANSPORT_LIBSSH:
case REMOTE_DRIVER_TRANSPORT_LIBSSH2:
if (!sockname &&
- !(sockname = remoteGetUNIXSocket(transport, flags)))
+ !(sockname = remoteGetUNIXSocket(transport, mode, driver_str,
+ &daemon_name, flags)))
goto failed;
break;
@@ -1070,13 +1222,15 @@ doRemoteOpen(virConnectPtr conn,
#ifndef WIN32
case REMOTE_DRIVER_TRANSPORT_UNIX:
- if ((flags & VIR_DRV_OPEN_REMOTE_AUTOSTART) &&
- !(daemonPath = virFileFindResourceFull("libvirtd",
- NULL, NULL,
- abs_top_builddir "/src",
- SBINDIR,
- "LIBVIRTD_PATH")))
- goto failed;
+ if (flags & VIR_DRV_OPEN_REMOTE_AUTOSTART) {
+ const char *env_name = remoteGetDaemonPathEnv();
+ if (!(daemonPath = virFileFindResourceFull(daemon_name,
+ NULL, NULL,
+ abs_top_builddir "/src",
+ SBINDIR,
+ env_name)))
+ goto failed;
+ }
if (!(priv->client = virNetClientNewUNIX(sockname,
flags & VIR_DRV_OPEN_REMOTE_AUTOSTART,
@@ -1192,7 +1346,7 @@ doRemoteOpen(virConnectPtr conn,
{
remote_connect_open_args args = { &name, flags };
- VIR_DEBUG("Trying to open URI %s", name);
+ VIR_DEBUG("Trying to open URI '%s'", name);
if (call(conn, priv, 0, REMOTE_PROC_CONNECT_OPEN,
(xdrproc_t) xdr_remote_connect_open_args, (char *) &args,
(xdrproc_t) xdr_void, (char *) NULL) == -1)
@@ -1294,9 +1448,20 @@ remoteConnectOpen(virConnectPtr conn,
remoteSplitURIScheme(conn->uri, &driver, &transport) < 0)
goto cleanup;
- if (inside_daemon && (!conn->uri || !conn->uri->server)) {
- ret = VIR_DRV_OPEN_DECLINED;
- goto cleanup;
+ if (inside_daemon) {
+ if (!conn->uri) {
+ ret = VIR_DRV_OPEN_DECLINED;
+ goto cleanup;
+ }
+
+ /* If there's a driver registered we must defer to that.
+ * If there isn't a driver, we must connect in "direct"
+ * mode - see doRemoteOpen */
+ if (!conn->uri->server &&
+ virHasDriverForURIScheme(driver)) {
+ ret = VIR_DRV_OPEN_DECLINED;
+ goto cleanup;
+ }
}
if (!(priv = remoteAllocPrivateData()))
diff --git a/src/remote/remote_driver.h b/src/remote/remote_driver.h
index 132e478ef3..1fab5a6cc4 100644
--- a/src/remote/remote_driver.h
+++ b/src/remote/remote_driver.h
@@ -31,9 +31,6 @@ unsigned long remoteVersion(void);
#define LIBVIRTD_LISTEN_ADDR NULL
#define LIBVIRTD_TLS_PORT "16514"
#define LIBVIRTD_TCP_PORT "16509"
-#define LIBVIRTD_PRIV_UNIX_SOCKET LOCALSTATEDIR "/run/libvirt/libvirt-sock"
-#define LIBVIRTD_PRIV_UNIX_SOCKET_RO LOCALSTATEDIR "/run/libvirt/libvirt-sock-ro"
-#define LIBVIRTD_USER_UNIX_SOCKET "libvirt-sock"
/* Defaults for PKI directory. */
#define LIBVIRT_PKI_DIR SYSCONFDIR "/pki"