mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-26 18:41:17 +00:00
Make network APIs go via remote driver. Autospawn per-user daemon
This commit is contained in:
parent
6bdad268f4
commit
483f6d6951
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
|||||||
|
Mon Jul 2 09:35:00 EST 2007 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
|
* src/qemu_driver.c: Change 'qemu' to 'QEMU' to get compatability
|
||||||
|
with previous releases reporting of driver type. Allow QEMU to
|
||||||
|
handle qemu:///session for root users too. Fix network lookup
|
||||||
|
functions to use networkPrivateData instead of privateData
|
||||||
|
* src/remote_internal.c: Add auto-spawn of daemons for networking.
|
||||||
|
Make network activate for Xen / Test drivers. Make the network
|
||||||
|
functions use networkPrivateData instead of privateData
|
||||||
|
|
||||||
Fri Jun 29 15:46:34 CEST 2007 Daniel Veillard <veillard@redhat.com>
|
Fri Jun 29 15:46:34 CEST 2007 Daniel Veillard <veillard@redhat.com>
|
||||||
|
|
||||||
* src/virsh.c: applied patch from Masayuki Sunou to remove leaks
|
* src/virsh.c: applied patch from Masayuki Sunou to remove leaks
|
||||||
|
@ -1495,7 +1495,8 @@ static virDrvOpenStatus qemudOpen(virConnectPtr conn,
|
|||||||
if (strcmp(name, "qemu:///session"))
|
if (strcmp(name, "qemu:///session"))
|
||||||
return VIR_DRV_OPEN_DECLINED;
|
return VIR_DRV_OPEN_DECLINED;
|
||||||
} else {
|
} else {
|
||||||
if (strcmp(name, "qemu:///system"))
|
if (strcmp(name, "qemu:///system") &&
|
||||||
|
strcmp(name, "qemu:///session"))
|
||||||
return VIR_DRV_OPEN_DECLINED;
|
return VIR_DRV_OPEN_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1513,7 +1514,7 @@ static int qemudClose(virConnectPtr conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char *qemudGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
|
static const char *qemudGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
|
||||||
return "qemu";
|
return "QEMU";
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qemudGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED,
|
static int qemudGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||||
@ -2174,7 +2175,7 @@ static int qemudDomainSetAutostart(virDomainPtr dom,
|
|||||||
|
|
||||||
static virNetworkPtr qemudNetworkLookupByUUID(virConnectPtr conn ATTRIBUTE_UNUSED,
|
static virNetworkPtr qemudNetworkLookupByUUID(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||||
const unsigned char *uuid) {
|
const unsigned char *uuid) {
|
||||||
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
|
struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
|
||||||
struct qemud_network *network = qemudFindNetworkByUUID(driver, uuid);
|
struct qemud_network *network = qemudFindNetworkByUUID(driver, uuid);
|
||||||
virNetworkPtr net;
|
virNetworkPtr net;
|
||||||
|
|
||||||
@ -2192,7 +2193,7 @@ static virNetworkPtr qemudNetworkLookupByUUID(virConnectPtr conn ATTRIBUTE_UNUSE
|
|||||||
}
|
}
|
||||||
static virNetworkPtr qemudNetworkLookupByName(virConnectPtr conn ATTRIBUTE_UNUSED,
|
static virNetworkPtr qemudNetworkLookupByName(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
|
struct qemud_driver *driver = (struct qemud_driver *)conn->networkPrivateData;
|
||||||
struct qemud_network *network = qemudFindNetworkByName(driver, name);
|
struct qemud_network *network = qemudFindNetworkByName(driver, name);
|
||||||
virNetworkPtr net;
|
virNetworkPtr net;
|
||||||
|
|
||||||
|
@ -31,6 +31,10 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <paths.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
@ -60,17 +64,24 @@ struct private_data {
|
|||||||
char *type; /* Cached return from remoteType. */
|
char *type; /* Cached return from remoteType. */
|
||||||
int counter; /* Generates serial numbers for RPC. */
|
int counter; /* Generates serial numbers for RPC. */
|
||||||
char *uri; /* Original (remote) URI. */
|
char *uri; /* Original (remote) URI. */
|
||||||
|
int networkOnly; /* Only used for network API */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GET_PRIVATE(conn,retcode) \
|
#define GET_PRIVATE(conn,retcode) \
|
||||||
struct private_data *priv = (struct private_data *) (conn)->privateData; \
|
struct private_data *priv = (struct private_data *) (conn)->privateData; \
|
||||||
assert (priv); \
|
if (!priv || priv->magic != MAGIC) { \
|
||||||
if (priv->magic == DEAD) { \
|
|
||||||
error (conn, VIR_ERR_INVALID_ARG, \
|
error (conn, VIR_ERR_INVALID_ARG, \
|
||||||
"tried to use a closed or uninitialised handle"); \
|
"tried to use a closed or uninitialised handle"); \
|
||||||
return (retcode); \
|
return (retcode); \
|
||||||
} \
|
}
|
||||||
assert (priv->magic == MAGIC)
|
|
||||||
|
#define GET_NETWORK_PRIVATE(conn,retcode) \
|
||||||
|
struct private_data *priv = (struct private_data *) (conn)->networkPrivateData; \
|
||||||
|
if (!priv || priv->magic != MAGIC) { \
|
||||||
|
error (conn, VIR_ERR_INVALID_ARG, \
|
||||||
|
"tried to use a closed or uninitialised handle"); \
|
||||||
|
return (retcode); \
|
||||||
|
}
|
||||||
|
|
||||||
static int call (virConnectPtr conn, struct private_data *priv, int in_open, int proc_nr, xdrproc_t args_filter, char *args, xdrproc_t ret_filter, char *ret);
|
static int call (virConnectPtr conn, struct private_data *priv, int in_open, int proc_nr, xdrproc_t args_filter, char *args, xdrproc_t ret_filter, char *ret);
|
||||||
static void error (virConnectPtr conn, virErrorNumber code, const char *info);
|
static void error (virConnectPtr conn, virErrorNumber code, const char *info);
|
||||||
@ -105,8 +116,126 @@ static void query_free (struct query_fields *fields);
|
|||||||
static int initialise_gnutls (virConnectPtr conn);
|
static int initialise_gnutls (virConnectPtr conn);
|
||||||
static gnutls_session_t negotiate_gnutls_on_connection (virConnectPtr conn, int sock, int no_verify, const char *hostname);
|
static gnutls_session_t negotiate_gnutls_on_connection (virConnectPtr conn, int sock, int no_verify, const char *hostname);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remoteFindServerPath:
|
||||||
|
*
|
||||||
|
* Tries to find the path to the libvirtd binary.
|
||||||
|
*
|
||||||
|
* Returns path on success or NULL in case of error.
|
||||||
|
*/
|
||||||
|
static const char *
|
||||||
|
remoteFindDaemonPath(void)
|
||||||
|
{
|
||||||
|
static const char *serverPaths[] = {
|
||||||
|
SBINDIR "/libvirtd",
|
||||||
|
SBINDIR "/libvirtd_dbg",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
const char *customDaemon = getenv("LIBVIRTD_PATH");
|
||||||
|
|
||||||
|
if (customDaemon)
|
||||||
|
return(customDaemon);
|
||||||
|
|
||||||
|
for (i = 0; serverPaths[i]; i++) {
|
||||||
|
if (access(serverPaths[i], X_OK | R_OK) == 0) {
|
||||||
|
return serverPaths[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuForkDaemon:
|
||||||
|
*
|
||||||
|
* Forks and try to launch the libvirtd daemon
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success or -1 in case of detected error.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
remoteOpen (virConnectPtr conn, const char *uri_str, int flags)
|
remoteForkDaemon(virConnectPtr conn)
|
||||||
|
{
|
||||||
|
const char *daemonPath = remoteFindDaemonPath();
|
||||||
|
int ret, pid, status;
|
||||||
|
|
||||||
|
if (!daemonPath) {
|
||||||
|
error(conn, VIR_ERR_INTERNAL_ERROR, "failed to find libvirtd binary");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Become a daemon */
|
||||||
|
pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
int stdinfd = -1;
|
||||||
|
int stdoutfd = -1;
|
||||||
|
int i, open_max;
|
||||||
|
if ((stdinfd = open(_PATH_DEVNULL, O_RDONLY)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
if ((stdoutfd = open(_PATH_DEVNULL, O_WRONLY)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
if (dup2(stdinfd, STDIN_FILENO) != STDIN_FILENO)
|
||||||
|
goto cleanup;
|
||||||
|
if (dup2(stdoutfd, STDOUT_FILENO) != STDOUT_FILENO)
|
||||||
|
goto cleanup;
|
||||||
|
if (dup2(stdoutfd, STDERR_FILENO) != STDERR_FILENO)
|
||||||
|
goto cleanup;
|
||||||
|
if (close(stdinfd) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
stdinfd = -1;
|
||||||
|
if (close(stdoutfd) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
stdoutfd = -1;
|
||||||
|
|
||||||
|
open_max = sysconf (_SC_OPEN_MAX);
|
||||||
|
for (i = 0; i < open_max; i++)
|
||||||
|
if (i != STDIN_FILENO &&
|
||||||
|
i != STDOUT_FILENO &&
|
||||||
|
i != STDERR_FILENO)
|
||||||
|
close(i);
|
||||||
|
|
||||||
|
setsid();
|
||||||
|
if (fork() == 0) {
|
||||||
|
/* Run daemon in auto-shutdown mode, so it goes away when
|
||||||
|
no longer needed by an active guest, or client */
|
||||||
|
execl(daemonPath, daemonPath, "--timeout", "30", NULL);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* calling exit() generate troubles for termination handlers
|
||||||
|
*/
|
||||||
|
_exit(0);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (stdoutfd != -1)
|
||||||
|
close(stdoutfd);
|
||||||
|
if (stdinfd != -1)
|
||||||
|
close(stdinfd);
|
||||||
|
_exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do a waitpid on the intermediate process to avoid zombies.
|
||||||
|
*/
|
||||||
|
retry_wait:
|
||||||
|
ret = waitpid(pid, &status, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
goto retry_wait;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Must not overlap with virDrvOpenFlags */
|
||||||
|
enum {
|
||||||
|
VIR_DRV_OPEN_REMOTE_RO = (1 << 0),
|
||||||
|
VIR_DRV_OPEN_REMOTE_UNIX = (1 << 1),
|
||||||
|
VIR_DRV_OPEN_REMOTE_USER = (1 << 2),
|
||||||
|
VIR_DRV_OPEN_REMOTE_AUTOSTART = (1 << 3),
|
||||||
|
} virDrvOpenRemoteFlags;
|
||||||
|
|
||||||
|
static int
|
||||||
|
doRemoteOpen (virConnectPtr conn, struct private_data *priv, const char *uri_str, int flags)
|
||||||
{
|
{
|
||||||
if (!uri_str) return VIR_DRV_OPEN_DECLINED;
|
if (!uri_str) return VIR_DRV_OPEN_DECLINED;
|
||||||
|
|
||||||
@ -146,11 +275,12 @@ remoteOpen (virConnectPtr conn, const char *uri_str, int flags)
|
|||||||
return VIR_DRV_OPEN_ERROR;
|
return VIR_DRV_OPEN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(uri_str, "qemu:///system") ||
|
if (!uri->server && !transport_str) {
|
||||||
!strcmp(uri_str, "qemu:///session"))
|
if (flags & VIR_DRV_OPEN_REMOTE_UNIX)
|
||||||
transport = trans_unix;
|
transport = trans_unix;
|
||||||
else if (!uri->server && !transport_str)
|
else
|
||||||
return VIR_DRV_OPEN_DECLINED; /* Decline - not a remote URL. */
|
return VIR_DRV_OPEN_DECLINED; /* Decline - not a remote URL. */
|
||||||
|
}
|
||||||
|
|
||||||
/* Local variables which we will initialise. These can
|
/* Local variables which we will initialise. These can
|
||||||
* get freed in the failed: path.
|
* get freed in the failed: path.
|
||||||
@ -162,7 +292,6 @@ remoteOpen (virConnectPtr conn, const char *uri_str, int flags)
|
|||||||
|
|
||||||
/* Return code from this function, and the private data. */
|
/* Return code from this function, and the private data. */
|
||||||
int retcode = VIR_DRV_OPEN_ERROR;
|
int retcode = VIR_DRV_OPEN_ERROR;
|
||||||
struct private_data priv = { .magic = DEAD, .sock = -1 };
|
|
||||||
|
|
||||||
/* Remote server defaults to "localhost" if not specified. */
|
/* Remote server defaults to "localhost" if not specified. */
|
||||||
server = strdup (uri->server ? uri->server : "localhost");
|
server = strdup (uri->server ? uri->server : "localhost");
|
||||||
@ -282,7 +411,7 @@ remoteOpen (virConnectPtr conn, const char *uri_str, int flags)
|
|||||||
switch (transport) {
|
switch (transport) {
|
||||||
case trans_tls:
|
case trans_tls:
|
||||||
if (initialise_gnutls (conn) == -1) goto failed;
|
if (initialise_gnutls (conn) == -1) goto failed;
|
||||||
priv.uses_tls = 1;
|
priv->uses_tls = 1;
|
||||||
|
|
||||||
/*FALLTHROUGH*/
|
/*FALLTHROUGH*/
|
||||||
case trans_tcp: {
|
case trans_tcp: {
|
||||||
@ -312,30 +441,30 @@ remoteOpen (virConnectPtr conn, const char *uri_str, int flags)
|
|||||||
for (r = res; r; r = r->ai_next) {
|
for (r = res; r; r = r->ai_next) {
|
||||||
int no_slow_start = 1;
|
int no_slow_start = 1;
|
||||||
|
|
||||||
priv.sock = socket (r->ai_family, SOCK_STREAM, 0);
|
priv->sock = socket (r->ai_family, SOCK_STREAM, 0);
|
||||||
if (priv.sock == -1) {
|
if (priv->sock == -1) {
|
||||||
error (NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
|
error (NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable Nagle - Dan Berrange. */
|
/* Disable Nagle - Dan Berrange. */
|
||||||
setsockopt (priv.sock,
|
setsockopt (priv->sock,
|
||||||
IPPROTO_TCP, TCP_NODELAY, (void *)&no_slow_start,
|
IPPROTO_TCP, TCP_NODELAY, (void *)&no_slow_start,
|
||||||
sizeof no_slow_start);
|
sizeof no_slow_start);
|
||||||
|
|
||||||
if (connect (priv.sock, r->ai_addr, r->ai_addrlen) == -1) {
|
if (connect (priv->sock, r->ai_addr, r->ai_addrlen) == -1) {
|
||||||
error (NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
|
error (NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
|
||||||
close (priv.sock);
|
close (priv->sock);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv.uses_tls) {
|
if (priv->uses_tls) {
|
||||||
priv.session =
|
priv->session =
|
||||||
negotiate_gnutls_on_connection
|
negotiate_gnutls_on_connection
|
||||||
(conn, priv.sock, no_verify, server);
|
(conn, priv->sock, no_verify, server);
|
||||||
if (!priv.session) {
|
if (!priv->session) {
|
||||||
close (priv.sock);
|
close (priv->sock);
|
||||||
priv.sock = -1;
|
priv->sock = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,9 +484,7 @@ remoteOpen (virConnectPtr conn, const char *uri_str, int flags)
|
|||||||
|
|
||||||
case trans_unix: {
|
case trans_unix: {
|
||||||
if (!sockname) {
|
if (!sockname) {
|
||||||
if (!strcmp(uri->scheme, "qemu") &&
|
if (flags & VIR_DRV_OPEN_REMOTE_USER) {
|
||||||
uri->path &&
|
|
||||||
!strcmp(uri->path, "/session")) {
|
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
uid_t uid = getuid();
|
uid_t uid = getuid();
|
||||||
|
|
||||||
@ -371,7 +498,7 @@ remoteOpen (virConnectPtr conn, const char *uri_str, int flags)
|
|||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (flags & VIR_DRV_OPEN_RO)
|
if (flags & VIR_DRV_OPEN_REMOTE_RO)
|
||||||
sockname = strdup (LIBVIRTD_PRIV_UNIX_SOCKET_RO);
|
sockname = strdup (LIBVIRTD_PRIV_UNIX_SOCKET_RO);
|
||||||
else
|
else
|
||||||
sockname = strdup (LIBVIRTD_PRIV_UNIX_SOCKET);
|
sockname = strdup (LIBVIRTD_PRIV_UNIX_SOCKET);
|
||||||
@ -382,18 +509,39 @@ remoteOpen (virConnectPtr conn, const char *uri_str, int flags)
|
|||||||
#define UNIX_PATH_MAX(addr) (sizeof (addr).sun_path)
|
#define UNIX_PATH_MAX(addr) (sizeof (addr).sun_path)
|
||||||
#endif
|
#endif
|
||||||
struct sockaddr_un addr;
|
struct sockaddr_un addr;
|
||||||
|
int trials = 0;
|
||||||
|
|
||||||
memset (&addr, 0, sizeof addr);
|
memset (&addr, 0, sizeof addr);
|
||||||
addr.sun_family = AF_UNIX;
|
addr.sun_family = AF_UNIX;
|
||||||
strncpy (addr.sun_path, sockname, UNIX_PATH_MAX (addr));
|
strncpy (addr.sun_path, sockname, UNIX_PATH_MAX (addr));
|
||||||
if (addr.sun_path[0] == '@')
|
if (addr.sun_path[0] == '@')
|
||||||
addr.sun_path[0] = '\0';
|
addr.sun_path[0] = '\0';
|
||||||
|
|
||||||
priv.sock = socket (AF_UNIX, SOCK_STREAM, 0);
|
autostart_retry:
|
||||||
if (priv.sock == -1) {
|
priv->sock = socket (AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (priv->sock == -1) {
|
||||||
error (NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
|
error (NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
if (connect (priv.sock, (struct sockaddr *) &addr, sizeof addr) == -1){
|
if (connect (priv->sock, (struct sockaddr *) &addr, sizeof addr) == -1) {
|
||||||
|
/* We might have to autostart the daemon in some cases....
|
||||||
|
* It takes a short while for the daemon to startup, hence we
|
||||||
|
* have a number of retries, with a small sleep. This will
|
||||||
|
* sometimes cause multiple daemons to be started - this is
|
||||||
|
* ok because the duplicates will fail to bind to the socket
|
||||||
|
* and immediately exit, leaving just one daemon.
|
||||||
|
*/
|
||||||
|
if (errno == ECONNREFUSED &&
|
||||||
|
flags & VIR_DRV_OPEN_REMOTE_AUTOSTART &&
|
||||||
|
trials < 5) {
|
||||||
|
close(priv->sock);
|
||||||
|
priv->sock = -1;
|
||||||
|
if (remoteForkDaemon(conn) == 0) {
|
||||||
|
trials++;
|
||||||
|
usleep(5000 * trials * trials);
|
||||||
|
goto autostart_retry;
|
||||||
|
}
|
||||||
|
}
|
||||||
error (NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
|
error (NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
@ -465,45 +613,35 @@ remoteOpen (virConnectPtr conn, const char *uri_str, int flags)
|
|||||||
|
|
||||||
/* Parent continues here. */
|
/* Parent continues here. */
|
||||||
close (sv[1]);
|
close (sv[1]);
|
||||||
priv.sock = sv[0];
|
priv->sock = sv[0];
|
||||||
}
|
}
|
||||||
} /* switch (transport) */
|
} /* switch (transport) */
|
||||||
|
|
||||||
/* Finally we can call the remote side's open function. */
|
/* Finally we can call the remote side's open function. */
|
||||||
remote_open_args args = { &name, flags };
|
remote_open_args args = { &name, flags };
|
||||||
|
|
||||||
if (call (conn, &priv, 1, REMOTE_PROC_OPEN,
|
if (call (conn, priv, 1, REMOTE_PROC_OPEN,
|
||||||
(xdrproc_t) xdr_remote_open_args, (char *) &args,
|
(xdrproc_t) xdr_remote_open_args, (char *) &args,
|
||||||
(xdrproc_t) xdr_void, (char *) NULL) == -1)
|
(xdrproc_t) xdr_void, (char *) NULL) == -1)
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
/* Finally allocate private data. */
|
|
||||||
conn->privateData = malloc (sizeof priv);
|
|
||||||
if (!conn->privateData) {
|
|
||||||
error (NULL, VIR_ERR_NO_MEMORY, "malloc");
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
/* Duplicate and save the uri_str. */
|
/* Duplicate and save the uri_str. */
|
||||||
priv.uri = strdup (uri_str);
|
priv->uri = strdup (uri_str);
|
||||||
if (!priv.uri) {
|
if (!priv->uri) {
|
||||||
error (NULL, VIR_ERR_NO_MEMORY, "allocating priv->uri");
|
error (NULL, VIR_ERR_NO_MEMORY, "allocating priv->uri");
|
||||||
free (conn->privateData);
|
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv.magic = MAGIC;
|
|
||||||
memcpy (conn->privateData, &priv, sizeof priv);
|
|
||||||
|
|
||||||
/* Successful. */
|
/* Successful. */
|
||||||
retcode = VIR_DRV_OPEN_SUCCESS;
|
retcode = VIR_DRV_OPEN_SUCCESS;
|
||||||
|
|
||||||
/*FALLTHROUGH*/
|
/*FALLTHROUGH*/
|
||||||
failed:
|
failed:
|
||||||
/* Close the socket if we failed. */
|
/* Close the socket if we failed. */
|
||||||
if (retcode != VIR_DRV_OPEN_SUCCESS && priv.sock >= 0) {
|
if (retcode != VIR_DRV_OPEN_SUCCESS && priv->sock >= 0) {
|
||||||
if (priv.uses_tls && priv.session)
|
if (priv->uses_tls && priv->session)
|
||||||
gnutls_bye (priv.session, GNUTLS_SHUT_RDWR);
|
gnutls_bye (priv->session, GNUTLS_SHUT_RDWR);
|
||||||
close (priv.sock);
|
close (priv->sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free up the URL and strings. */
|
/* Free up the URL and strings. */
|
||||||
@ -527,6 +665,47 @@ remoteOpen (virConnectPtr conn, const char *uri_str, int flags)
|
|||||||
return retcode;
|
return retcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
remoteOpen (virConnectPtr conn, const char *uri_str, int flags)
|
||||||
|
{
|
||||||
|
struct private_data *priv = malloc (sizeof(struct private_data));
|
||||||
|
int ret, rflags = 0;
|
||||||
|
|
||||||
|
if (!priv) {
|
||||||
|
error (NULL, VIR_ERR_NO_MEMORY, "struct private_data");
|
||||||
|
return VIR_DRV_OPEN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & VIR_DRV_OPEN_RO)
|
||||||
|
rflags |= VIR_DRV_OPEN_REMOTE_RO;
|
||||||
|
|
||||||
|
if (uri_str) {
|
||||||
|
if (!strcmp(uri_str, "qemu:///system")) {
|
||||||
|
rflags |= VIR_DRV_OPEN_REMOTE_UNIX;
|
||||||
|
} else if (!strcmp(uri_str, "qemu:///session")) {
|
||||||
|
rflags |= VIR_DRV_OPEN_REMOTE_UNIX;
|
||||||
|
if (getuid() > 0) {
|
||||||
|
rflags |= VIR_DRV_OPEN_REMOTE_USER;
|
||||||
|
rflags |= VIR_DRV_OPEN_REMOTE_AUTOSTART;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(priv, 0, sizeof(struct private_data));
|
||||||
|
priv->magic = DEAD;
|
||||||
|
priv->sock = -1;
|
||||||
|
ret = doRemoteOpen(conn, priv, uri_str, rflags);
|
||||||
|
if (ret != VIR_DRV_OPEN_SUCCESS) {
|
||||||
|
conn->privateData = NULL;
|
||||||
|
free(priv);
|
||||||
|
} else {
|
||||||
|
priv->magic = MAGIC;
|
||||||
|
conn->privateData = priv;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* In a string "driver+transport" return a pointer to "transport". */
|
/* In a string "driver+transport" return a pointer to "transport". */
|
||||||
static char *
|
static char *
|
||||||
get_transport_from_scheme (char *scheme)
|
get_transport_from_scheme (char *scheme)
|
||||||
@ -948,11 +1127,10 @@ verify_certificate (virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int
|
|
||||||
remoteClose (virConnectPtr conn)
|
|
||||||
{
|
|
||||||
GET_PRIVATE (conn, -1);
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
doRemoteClose (virConnectPtr conn, struct private_data *priv)
|
||||||
|
{
|
||||||
if (call (conn, priv, 0, REMOTE_PROC_CLOSE,
|
if (call (conn, priv, 0, REMOTE_PROC_CLOSE,
|
||||||
(xdrproc_t) xdr_void, (char *) NULL,
|
(xdrproc_t) xdr_void, (char *) NULL,
|
||||||
(xdrproc_t) xdr_void, (char *) NULL) == -1)
|
(xdrproc_t) xdr_void, (char *) NULL) == -1)
|
||||||
@ -971,11 +1149,23 @@ remoteClose (virConnectPtr conn)
|
|||||||
|
|
||||||
/* Free private data. */
|
/* Free private data. */
|
||||||
priv->magic = DEAD;
|
priv->magic = DEAD;
|
||||||
free (conn->privateData);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
remoteClose (virConnectPtr conn)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
GET_PRIVATE (conn, -1);
|
||||||
|
|
||||||
|
ret = doRemoteClose(conn, priv);
|
||||||
|
free (priv);
|
||||||
|
conn->privateData = NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Unfortunately this function is defined to return a static string.
|
/* Unfortunately this function is defined to return a static string.
|
||||||
* Since the remote end always answers with the same type (for a
|
* Since the remote end always answers with the same type (for a
|
||||||
* single connection anyway) we cache the type in the connection's
|
* single connection anyway) we cache the type in the connection's
|
||||||
@ -1951,36 +2141,80 @@ remoteDomainSetSchedulerParameters (virDomainPtr domain,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
remoteNetworkOpen (virConnectPtr conn,
|
remoteNetworkOpen (virConnectPtr conn,
|
||||||
const char *uri_str ATTRIBUTE_UNUSED,
|
const char *uri_str,
|
||||||
int flags ATTRIBUTE_UNUSED)
|
int flags)
|
||||||
{
|
{
|
||||||
/* If the main connection is a remote, then just catch the
|
|
||||||
* network open too. Nothing is forwarded because the
|
|
||||||
* main remoteOpen call above will have already opened
|
|
||||||
* network on the remote side.
|
|
||||||
*/
|
|
||||||
if (conn &&
|
if (conn &&
|
||||||
conn->driver &&
|
conn->driver &&
|
||||||
strcmp (conn->driver->name, "remote") == 0)
|
strcmp (conn->driver->name, "remote") == 0) {
|
||||||
|
/* If we're here, the remote driver is already
|
||||||
|
* in use due to a) a QEMU uri, or b) a remote
|
||||||
|
* URI. So we can re-use existing connection
|
||||||
|
*/
|
||||||
|
conn->networkPrivateData = conn->privateData;
|
||||||
return VIR_DRV_OPEN_SUCCESS;
|
return VIR_DRV_OPEN_SUCCESS;
|
||||||
else
|
} else {
|
||||||
return VIR_DRV_OPEN_DECLINED;
|
/* Using a non-remote driver, so we need to open a
|
||||||
|
* new connection for network APIs, forcing it to
|
||||||
|
* use the UNIX transport. This handles Xen / Test
|
||||||
|
* drivers which don't have their own impl of the
|
||||||
|
* network APIs.
|
||||||
|
*/
|
||||||
|
struct private_data *priv = malloc (sizeof(struct private_data));
|
||||||
|
int ret, rflags = 0;
|
||||||
|
if (!priv) {
|
||||||
|
error (NULL, VIR_ERR_NO_MEMORY, "struct private_data");
|
||||||
|
return VIR_DRV_OPEN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & VIR_DRV_OPEN_RO)
|
||||||
|
rflags |= VIR_DRV_OPEN_REMOTE_RO;
|
||||||
|
/* Xen driver is a single system-wide driver, so
|
||||||
|
* we need the main daemon. Test driver is per
|
||||||
|
* user, so use the per-user daemon, potentially
|
||||||
|
* autostarting
|
||||||
|
*/
|
||||||
|
flags |= VIR_DRV_OPEN_REMOTE_UNIX;
|
||||||
|
if (getuid() > 0 &&
|
||||||
|
!strcmp(conn->driver->name, "test")) {
|
||||||
|
flags |= VIR_DRV_OPEN_REMOTE_USER;
|
||||||
|
flags |= VIR_DRV_OPEN_REMOTE_AUTOSTART;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(priv, 0, sizeof(struct private_data));
|
||||||
|
priv->magic = DEAD;
|
||||||
|
priv->sock = -1;
|
||||||
|
ret = doRemoteOpen(conn, priv, uri_str, rflags);
|
||||||
|
if (ret != VIR_DRV_OPEN_SUCCESS) {
|
||||||
|
conn->networkPrivateData = NULL;
|
||||||
|
free(priv);
|
||||||
|
} else {
|
||||||
|
priv->magic = MAGIC;
|
||||||
|
priv->networkOnly = 1;
|
||||||
|
conn->networkPrivateData = priv;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
remoteNetworkClose (virConnectPtr conn ATTRIBUTE_UNUSED)
|
remoteNetworkClose (virConnectPtr conn)
|
||||||
{
|
{
|
||||||
/* No need to pass this to the remote side, because
|
int ret = 0;
|
||||||
* libvirt.c will soon call remoteClose.
|
GET_NETWORK_PRIVATE (conn, -1);
|
||||||
*/
|
if (priv->networkOnly) {
|
||||||
return 0;
|
ret = doRemoteClose(conn, priv);
|
||||||
|
free(priv);
|
||||||
|
conn->networkPrivateData = NULL;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
remoteNumOfNetworks (virConnectPtr conn)
|
remoteNumOfNetworks (virConnectPtr conn)
|
||||||
{
|
{
|
||||||
remote_num_of_networks_ret ret;
|
remote_num_of_networks_ret ret;
|
||||||
GET_PRIVATE (conn, -1);
|
GET_NETWORK_PRIVATE (conn, -1);
|
||||||
|
|
||||||
memset (&ret, 0, sizeof ret);
|
memset (&ret, 0, sizeof ret);
|
||||||
if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_NETWORKS,
|
if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_NETWORKS,
|
||||||
@ -1997,7 +2231,7 @@ remoteListNetworks (virConnectPtr conn, char **const names, int maxnames)
|
|||||||
int i;
|
int i;
|
||||||
remote_list_networks_args args;
|
remote_list_networks_args args;
|
||||||
remote_list_networks_ret ret;
|
remote_list_networks_ret ret;
|
||||||
GET_PRIVATE (conn, -1);
|
GET_NETWORK_PRIVATE (conn, -1);
|
||||||
|
|
||||||
if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
|
if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
|
||||||
error (conn, VIR_ERR_RPC, "maxnames > REMOTE_NETWORK_NAME_LIST_MAX");
|
error (conn, VIR_ERR_RPC, "maxnames > REMOTE_NETWORK_NAME_LIST_MAX");
|
||||||
@ -2034,7 +2268,7 @@ static int
|
|||||||
remoteNumOfDefinedNetworks (virConnectPtr conn)
|
remoteNumOfDefinedNetworks (virConnectPtr conn)
|
||||||
{
|
{
|
||||||
remote_num_of_defined_networks_ret ret;
|
remote_num_of_defined_networks_ret ret;
|
||||||
GET_PRIVATE (conn, -1);
|
GET_NETWORK_PRIVATE (conn, -1);
|
||||||
|
|
||||||
memset (&ret, 0, sizeof ret);
|
memset (&ret, 0, sizeof ret);
|
||||||
if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_NETWORKS,
|
if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_NETWORKS,
|
||||||
@ -2052,7 +2286,7 @@ remoteListDefinedNetworks (virConnectPtr conn,
|
|||||||
int i;
|
int i;
|
||||||
remote_list_defined_networks_args args;
|
remote_list_defined_networks_args args;
|
||||||
remote_list_defined_networks_ret ret;
|
remote_list_defined_networks_ret ret;
|
||||||
GET_PRIVATE (conn, -1);
|
GET_NETWORK_PRIVATE (conn, -1);
|
||||||
|
|
||||||
if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
|
if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
|
||||||
error (conn, VIR_ERR_RPC, "maxnames > REMOTE_NETWORK_NAME_LIST_MAX");
|
error (conn, VIR_ERR_RPC, "maxnames > REMOTE_NETWORK_NAME_LIST_MAX");
|
||||||
@ -2092,7 +2326,7 @@ remoteNetworkLookupByUUID (virConnectPtr conn,
|
|||||||
virNetworkPtr net;
|
virNetworkPtr net;
|
||||||
remote_network_lookup_by_uuid_args args;
|
remote_network_lookup_by_uuid_args args;
|
||||||
remote_network_lookup_by_uuid_ret ret;
|
remote_network_lookup_by_uuid_ret ret;
|
||||||
GET_PRIVATE (conn, NULL);
|
GET_NETWORK_PRIVATE (conn, NULL);
|
||||||
|
|
||||||
memcpy (args.uuid, uuid, VIR_UUID_BUFLEN);
|
memcpy (args.uuid, uuid, VIR_UUID_BUFLEN);
|
||||||
|
|
||||||
@ -2118,7 +2352,7 @@ remoteNetworkLookupByName (virConnectPtr conn,
|
|||||||
virNetworkPtr net;
|
virNetworkPtr net;
|
||||||
remote_network_lookup_by_name_args args;
|
remote_network_lookup_by_name_args args;
|
||||||
remote_network_lookup_by_name_ret ret;
|
remote_network_lookup_by_name_ret ret;
|
||||||
GET_PRIVATE (conn, NULL);
|
GET_NETWORK_PRIVATE (conn, NULL);
|
||||||
|
|
||||||
args.name = (char *) name;
|
args.name = (char *) name;
|
||||||
|
|
||||||
@ -2143,7 +2377,7 @@ remoteNetworkCreateXML (virConnectPtr conn, const char *xmlDesc)
|
|||||||
virNetworkPtr net;
|
virNetworkPtr net;
|
||||||
remote_network_create_xml_args args;
|
remote_network_create_xml_args args;
|
||||||
remote_network_create_xml_ret ret;
|
remote_network_create_xml_ret ret;
|
||||||
GET_PRIVATE (conn, NULL);
|
GET_NETWORK_PRIVATE (conn, NULL);
|
||||||
|
|
||||||
args.xml = (char *) xmlDesc;
|
args.xml = (char *) xmlDesc;
|
||||||
|
|
||||||
@ -2168,7 +2402,7 @@ remoteNetworkDefineXML (virConnectPtr conn, const char *xml)
|
|||||||
virNetworkPtr net;
|
virNetworkPtr net;
|
||||||
remote_network_define_xml_args args;
|
remote_network_define_xml_args args;
|
||||||
remote_network_define_xml_ret ret;
|
remote_network_define_xml_ret ret;
|
||||||
GET_PRIVATE (conn, NULL);
|
GET_NETWORK_PRIVATE (conn, NULL);
|
||||||
|
|
||||||
args.xml = (char *) xml;
|
args.xml = (char *) xml;
|
||||||
|
|
||||||
@ -2191,7 +2425,7 @@ static int
|
|||||||
remoteNetworkUndefine (virNetworkPtr network)
|
remoteNetworkUndefine (virNetworkPtr network)
|
||||||
{
|
{
|
||||||
remote_network_undefine_args args;
|
remote_network_undefine_args args;
|
||||||
GET_PRIVATE (network->conn, -1);
|
GET_NETWORK_PRIVATE (network->conn, -1);
|
||||||
|
|
||||||
make_nonnull_network (&args.net, network);
|
make_nonnull_network (&args.net, network);
|
||||||
|
|
||||||
@ -2207,7 +2441,7 @@ static int
|
|||||||
remoteNetworkCreate (virNetworkPtr network)
|
remoteNetworkCreate (virNetworkPtr network)
|
||||||
{
|
{
|
||||||
remote_network_create_args args;
|
remote_network_create_args args;
|
||||||
GET_PRIVATE (network->conn, -1);
|
GET_NETWORK_PRIVATE (network->conn, -1);
|
||||||
|
|
||||||
make_nonnull_network (&args.net, network);
|
make_nonnull_network (&args.net, network);
|
||||||
|
|
||||||
@ -2223,7 +2457,7 @@ static int
|
|||||||
remoteNetworkDestroy (virNetworkPtr network)
|
remoteNetworkDestroy (virNetworkPtr network)
|
||||||
{
|
{
|
||||||
remote_network_destroy_args args;
|
remote_network_destroy_args args;
|
||||||
GET_PRIVATE (network->conn, -1);
|
GET_NETWORK_PRIVATE (network->conn, -1);
|
||||||
|
|
||||||
make_nonnull_network (&args.net, network);
|
make_nonnull_network (&args.net, network);
|
||||||
|
|
||||||
@ -2240,7 +2474,7 @@ remoteNetworkDumpXML (virNetworkPtr network, int flags)
|
|||||||
{
|
{
|
||||||
remote_network_dump_xml_args args;
|
remote_network_dump_xml_args args;
|
||||||
remote_network_dump_xml_ret ret;
|
remote_network_dump_xml_ret ret;
|
||||||
GET_PRIVATE (network->conn, NULL);
|
GET_NETWORK_PRIVATE (network->conn, NULL);
|
||||||
|
|
||||||
make_nonnull_network (&args.net, network);
|
make_nonnull_network (&args.net, network);
|
||||||
args.flags = flags;
|
args.flags = flags;
|
||||||
@ -2260,7 +2494,7 @@ remoteNetworkGetBridgeName (virNetworkPtr network)
|
|||||||
{
|
{
|
||||||
remote_network_get_bridge_name_args args;
|
remote_network_get_bridge_name_args args;
|
||||||
remote_network_get_bridge_name_ret ret;
|
remote_network_get_bridge_name_ret ret;
|
||||||
GET_PRIVATE (network->conn, NULL);
|
GET_NETWORK_PRIVATE (network->conn, NULL);
|
||||||
|
|
||||||
make_nonnull_network (&args.net, network);
|
make_nonnull_network (&args.net, network);
|
||||||
|
|
||||||
@ -2279,7 +2513,7 @@ remoteNetworkGetAutostart (virNetworkPtr network, int *autostart)
|
|||||||
{
|
{
|
||||||
remote_network_get_autostart_args args;
|
remote_network_get_autostart_args args;
|
||||||
remote_network_get_autostart_ret ret;
|
remote_network_get_autostart_ret ret;
|
||||||
GET_PRIVATE (network->conn, -1);
|
GET_NETWORK_PRIVATE (network->conn, -1);
|
||||||
|
|
||||||
make_nonnull_network (&args.net, network);
|
make_nonnull_network (&args.net, network);
|
||||||
|
|
||||||
@ -2298,7 +2532,7 @@ static int
|
|||||||
remoteNetworkSetAutostart (virNetworkPtr network, int autostart)
|
remoteNetworkSetAutostart (virNetworkPtr network, int autostart)
|
||||||
{
|
{
|
||||||
remote_network_set_autostart_args args;
|
remote_network_set_autostart_args args;
|
||||||
GET_PRIVATE (network->conn, -1);
|
GET_NETWORK_PRIVATE (network->conn, -1);
|
||||||
|
|
||||||
make_nonnull_network (&args.net, network);
|
make_nonnull_network (&args.net, network);
|
||||||
args.autostart = autostart;
|
args.autostart = autostart;
|
||||||
|
Loading…
Reference in New Issue
Block a user