mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-03 03:25:20 +00:00
* configure.in Makefile.am proxy/Makefile.am proxy/libvirt_proxy.c
proxy/proxy.h proxy/proxy_client.c src/internal.h src/xen_internal.c src/xend_internal.c: started working on a proxy to access xend for unpriviledged users to avoid opening xend HTTP service to serve those read-only operations. Daniel
This commit is contained in:
parent
b62cdc1405
commit
27b7a8be52
@ -1,3 +1,11 @@
|
|||||||
|
Wed Jun 28 19:23:25 CEST 2006 Daniel Veillard <veillard@redhat.com>
|
||||||
|
|
||||||
|
* configure.in Makefile.am proxy/Makefile.am proxy/libvirt_proxy.c
|
||||||
|
proxy/proxy.h proxy/proxy_client.c src/internal.h src/xen_internal.c
|
||||||
|
src/xend_internal.c: started working on a proxy to access xend
|
||||||
|
for unpriviledged users to avoid opening xend HTTP service to
|
||||||
|
serve those read-only operations.
|
||||||
|
|
||||||
Mon Jun 26 16:05:27 CEST 2006 Daniel Veillard <veillard@redhat.com>
|
Mon Jun 26 16:05:27 CEST 2006 Daniel Veillard <veillard@redhat.com>
|
||||||
|
|
||||||
* configure.in libvirt.spec.in docs/examples/* include/Makefile.am
|
* configure.in libvirt.spec.in docs/examples/* include/Makefile.am
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
## Process this file with automake to produce Makefile.in
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
SUBDIRS = src include docs @PYTHON_SUBDIR@ tests
|
SUBDIRS = src include docs @PYTHON_SUBDIR@ tests proxy
|
||||||
|
|
||||||
EXTRA_DIST = libvirt.spec.in libvirt.spec COPYING.LIB \
|
EXTRA_DIST = libvirt.spec.in libvirt.spec COPYING.LIB \
|
||||||
libvirt.pc.in libvirt.pc TODO AUTHORS ChangeLog \
|
libvirt.pc.in libvirt.pc TODO AUTHORS ChangeLog \
|
||||||
|
@ -256,4 +256,4 @@ AC_OUTPUT(Makefile src/Makefile include/Makefile docs/Makefile \
|
|||||||
libvirt.pc libvirt.spec \
|
libvirt.pc libvirt.spec \
|
||||||
include/libvirt/Makefile include/libvirt/libvirt.h \
|
include/libvirt/Makefile include/libvirt/libvirt.h \
|
||||||
python/Makefile python/tests/Makefile \
|
python/Makefile python/tests/Makefile \
|
||||||
tests/Makefile)
|
tests/Makefile proxy/Makefile)
|
||||||
|
@ -44,7 +44,8 @@ typedef enum {
|
|||||||
VIR_FROM_SEXPR, /* Error in the S-Epression code */
|
VIR_FROM_SEXPR, /* Error in the S-Epression code */
|
||||||
VIR_FROM_XML, /* Error in the XML code */
|
VIR_FROM_XML, /* Error in the XML code */
|
||||||
VIR_FROM_DOM, /* Error when operating on a domain */
|
VIR_FROM_DOM, /* Error when operating on a domain */
|
||||||
VIR_FROM_RPC /* Error in the XML-RPC code */
|
VIR_FROM_RPC, /* Error in the XML-RPC code */
|
||||||
|
VIR_FROM_PROXY /* Error in the proxy code */
|
||||||
} virErrorDomain;
|
} virErrorDomain;
|
||||||
|
|
||||||
|
|
||||||
|
25
proxy/Makefile.am
Normal file
25
proxy/Makefile.am
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
INCLUDES = -I$(top_builddir)/include -I@top_srcdir@/include \
|
||||||
|
-I@top_srcdir@/proxy -I@top_srcdir@/src @LIBXML_CFLAGS@ \
|
||||||
|
-DBINDIR=\""$(libexecdir)"\" \
|
||||||
|
-DBUILDDIR=\""$(top_builddir)"\" \
|
||||||
|
-DXEN_RO
|
||||||
|
|
||||||
|
|
||||||
|
bin_PROGRAMS = libvirt_proxy
|
||||||
|
LIBS=
|
||||||
|
|
||||||
|
libvirt_proxy_SOURCES = libvirt_proxy.c @top_srcdir@/src/xend_internal.c \
|
||||||
|
@top_srcdir@/src/xen_internal.c @top_srcdir@/src/virterror.c \
|
||||||
|
@top_srcdir@/src/sexpr.c
|
||||||
|
|
||||||
|
libvirt_proxy_LDFLAGS =
|
||||||
|
libvirt_proxy_DEPENDENCIES =
|
||||||
|
libvirt_proxy_LDADD =
|
||||||
|
|
||||||
|
noinst_PROGRAMS= test_proxy
|
||||||
|
test_proxy_SOURCES = proxy_client.c
|
||||||
|
test_proxy_LDFLAGS =
|
||||||
|
test_proxy_DEPENDENCIES =
|
||||||
|
test_proxy_LDADD =
|
514
proxy/libvirt_proxy.c
Normal file
514
proxy/libvirt_proxy.c
Normal file
@ -0,0 +1,514 @@
|
|||||||
|
/*
|
||||||
|
* proxy_svr.c: root suid proxy server for Xen access to APIs with no
|
||||||
|
* side effects from unauthenticated clients.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* See COPYING.LIB for the License of this software
|
||||||
|
*
|
||||||
|
* Daniel Veillard <veillard@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include "proxy.h"
|
||||||
|
#include "internal.h"
|
||||||
|
#include "xen_internal.h"
|
||||||
|
|
||||||
|
static int fdServer = -1;
|
||||||
|
static int debug = 0;
|
||||||
|
static int done = 0;
|
||||||
|
|
||||||
|
#define MAX_CLIENT 64
|
||||||
|
|
||||||
|
static int nbClients = 0; /* client 0 is the unix listen socket */
|
||||||
|
static struct pollfd pollInfos[MAX_CLIENT + 1];
|
||||||
|
|
||||||
|
static virConnect conninfos;
|
||||||
|
static virConnectPtr conn = &conninfos;
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Interfaces with the Xen hypervisor *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* proxyInitXen:
|
||||||
|
*
|
||||||
|
* Initialize the communication layer with Xen
|
||||||
|
*
|
||||||
|
* Returns 0 or -1 in case of error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
proxyInitXen(void) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = xenHypervisorOpen(conn, NULL, VIR_DRV_OPEN_QUIET);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "Failed to open Xen hypervisor\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
ret = xenDaemonOpen_unix(conn, "/var/lib/xend/xend-socket");
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "Failed to connect to Xen daemon\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Processing of the unix socket to listen for clients *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* proxyCloseUnixSocket:
|
||||||
|
*
|
||||||
|
* close the unix socket
|
||||||
|
*
|
||||||
|
* Returns 0 or -1 in case of error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
proxyCloseUnixSocket(void) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (fdServer < 0)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
ret = close(fdServer);
|
||||||
|
if (debug > 0)
|
||||||
|
fprintf(stderr, "closing unix socket %d: %d\n", fdServer, ret);
|
||||||
|
fdServer = -1;
|
||||||
|
pollInfos[0].fd = -1;
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* proxyListenUnixSocket:
|
||||||
|
* @path: the fileame for the socket
|
||||||
|
*
|
||||||
|
* create a new abstract socket based on that path and listen on it
|
||||||
|
*
|
||||||
|
* Returns the associated file descriptor or -1 in case of failure
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
proxyListenUnixSocket(const char *path) {
|
||||||
|
int fd;
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
|
||||||
|
if (fdServer >= 0)
|
||||||
|
return(fdServer);
|
||||||
|
|
||||||
|
fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr, "Failed to create unix socket");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Abstract socket do not hit the filesystem, way more secure and
|
||||||
|
* garanteed to be atomic
|
||||||
|
*/
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
addr.sun_path[0] = '\0';
|
||||||
|
strncpy(&addr.sun_path[1], path, (sizeof(addr) - 4) - 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* now bind the socket to that address and listen on it
|
||||||
|
*/
|
||||||
|
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||||
|
fprintf(stderr, "Failed to bind to socket %s\n", path);
|
||||||
|
close(fd);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (listen(fd, 30 /* backlog */ ) < 0) {
|
||||||
|
fprintf(stderr, "Failed to listen to socket %s\n", path);
|
||||||
|
close(fd);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug > 0)
|
||||||
|
fprintf(stderr, "opened and bound unix socket %d\n", fd);
|
||||||
|
|
||||||
|
fdServer = fd;
|
||||||
|
pollInfos[0].fd = fd;
|
||||||
|
pollInfos[0].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
|
||||||
|
return (fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* proxyAcceptClientSocket:
|
||||||
|
*
|
||||||
|
* Process a request to the unix socket
|
||||||
|
*
|
||||||
|
* Returns the filedescriptor of the new client or -1 in case of error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
proxyAcceptClientSocket(void) {
|
||||||
|
int client;
|
||||||
|
socklen_t client_addrlen;
|
||||||
|
struct sockaddr client_addr;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
client_addrlen = sizeof(client_addr);
|
||||||
|
client = accept(pollInfos[0].fd, &client_addr, &client_addrlen);
|
||||||
|
if (client < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
if (debug > 0)
|
||||||
|
fprintf(stderr, "accept connection on socket %d interrupted\n",
|
||||||
|
pollInfos[0].fd);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Failed to accept incoming connection on socket %d\n",
|
||||||
|
pollInfos[0].fd);
|
||||||
|
done = 1;
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nbClients >= MAX_CLIENT) {
|
||||||
|
fprintf(stderr, "Too many client registered\n");
|
||||||
|
close(client);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
nbClients++;
|
||||||
|
pollInfos[nbClients].fd = client;
|
||||||
|
pollInfos[nbClients].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
|
||||||
|
if (debug > 0)
|
||||||
|
fprintf(stderr, "accept connection on socket %d for client %d\n",
|
||||||
|
client, nbClients);
|
||||||
|
return(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Processing of client sockets *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* proxyCloseClientSocket:
|
||||||
|
* @nr: client number
|
||||||
|
*
|
||||||
|
* Close the socket from that client, and recompact the pollInfo array
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success and -1 in case of error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
proxyCloseClientSocket(int nr) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = close(pollInfos[nr].fd);
|
||||||
|
if (ret != 0)
|
||||||
|
fprintf(stderr, "Failed to close socket %d from client %d\n",
|
||||||
|
pollInfos[nr].fd, nr);
|
||||||
|
else if (debug > 0)
|
||||||
|
fprintf(stderr, "Closed socket %d from client %d\n",
|
||||||
|
pollInfos[nr].fd, nr);
|
||||||
|
if (nr < nbClients) {
|
||||||
|
memmove(&pollInfos[nr], &pollInfos[nr + 1],
|
||||||
|
(nbClients - nr) * sizeof(pollInfos[0]));
|
||||||
|
}
|
||||||
|
nbClients--;
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* proxyCloseClientSockets:
|
||||||
|
*
|
||||||
|
* Close all the sockets from the clients
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
proxyCloseClientSockets(void) {
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
for (i = 1;i <= nbClients;i++) {
|
||||||
|
ret = close(pollInfos[i].fd);
|
||||||
|
if (ret != 0)
|
||||||
|
fprintf(stderr, "Failed to close socket %d from client %d\n",
|
||||||
|
pollInfos[i].fd, i);
|
||||||
|
else if (debug > 0)
|
||||||
|
fprintf(stderr, "Closed socket %d from client %d\n",
|
||||||
|
pollInfos[i].fd, i);
|
||||||
|
}
|
||||||
|
nbClients = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* proxyWriteClientSocket:
|
||||||
|
* @nr: the client number
|
||||||
|
* @req: pointer to the packet
|
||||||
|
*
|
||||||
|
* Send back a packet to the client. If it seems write would be blocking
|
||||||
|
* then try to disconnect from it.
|
||||||
|
*
|
||||||
|
* Return 0 in case of success and -1 in case of error.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
proxyWriteClientSocket(int nr, virProxyPacketPtr req) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((nr <= 0) || (nr > nbClients) || (req == NULL) ||
|
||||||
|
(req->len < sizeof(virProxyPacket)) || (req->len > 4096) ||
|
||||||
|
(pollInfos[nr].fd < 0)) {
|
||||||
|
fprintf(stderr, "write to client %d in error", nr);
|
||||||
|
proxyCloseClientSocket(nr);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
retry:
|
||||||
|
ret = write(pollInfos[nr].fd, (char *) req, req->len);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
if (debug > 0)
|
||||||
|
fprintf(stderr, "write socket %d to client %d interrupted\n",
|
||||||
|
pollInfos[nr].fd, nr);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "write %d bytes to socket %d from client %d failed\n",
|
||||||
|
req->len, pollInfos[nr].fd, nr);
|
||||||
|
proxyCloseClientSocket(nr);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
if (ret == 0) {
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "end of stream from client %d on socket %d\n",
|
||||||
|
nr, pollInfos[nr].fd);
|
||||||
|
proxyCloseClientSocket(nr);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != req->len) {
|
||||||
|
fprintf(stderr, "write %d of %d bytes to socket %d from client %d\n",
|
||||||
|
ret, req->len, pollInfos[nr].fd, nr);
|
||||||
|
proxyCloseClientSocket(nr);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "wrote %d bytes to client %d on socket %d\n",
|
||||||
|
ret, nr, pollInfos[nr].fd);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* proxyReadClientSocket:
|
||||||
|
* @nr: the client number
|
||||||
|
*
|
||||||
|
* Process a read from a client socket
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
proxyReadClientSocket(int nr) {
|
||||||
|
char buffer[4096];
|
||||||
|
virProxyPacketPtr req;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
ret = read(pollInfos[nr].fd, buffer, sizeof(virProxyPacket));
|
||||||
|
if (ret < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
if (debug > 0)
|
||||||
|
fprintf(stderr, "read socket %d from client %d interrupted\n",
|
||||||
|
pollInfos[nr].fd, nr);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Failed to read socket %d from client %d\n",
|
||||||
|
pollInfos[nr].fd, nr);
|
||||||
|
proxyCloseClientSocket(nr);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
if (ret == 0) {
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "end of stream from client %d on socket %d\n",
|
||||||
|
nr, pollInfos[nr].fd);
|
||||||
|
proxyCloseClientSocket(nr);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "read %d bytes from client %d on socket %d\n",
|
||||||
|
ret, nr, pollInfos[nr].fd);
|
||||||
|
|
||||||
|
req = (virProxyPacketPtr) &buffer[0];
|
||||||
|
if ((req->version != PROXY_PROTO_VERSION) ||
|
||||||
|
(req->len < sizeof(virProxyPacket)))
|
||||||
|
goto comm_error;
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "Gor command %d from client %d\n", req->command, nr);
|
||||||
|
|
||||||
|
switch (req->command) {
|
||||||
|
case VIR_PROXY_NONE:
|
||||||
|
if (req->len != sizeof(virProxyPacket))
|
||||||
|
goto comm_error;
|
||||||
|
break;
|
||||||
|
case VIR_PROXY_VERSION:
|
||||||
|
if (req->len != sizeof(virProxyPacket))
|
||||||
|
goto comm_error;
|
||||||
|
TODO;
|
||||||
|
req->data.larg = 3 * 1000000 + 2;
|
||||||
|
break;
|
||||||
|
case VIR_PROXY_NODE_INFO:
|
||||||
|
case VIR_PROXY_LIST:
|
||||||
|
case VIR_PROXY_NUM_DOMAIN:
|
||||||
|
case VIR_PROXY_LOOKUP_ID:
|
||||||
|
case VIR_PROXY_LOOKUP_UUID:
|
||||||
|
case VIR_PROXY_LOOKUP_NAME:
|
||||||
|
case VIR_PROXY_MAX_MEMORY:
|
||||||
|
case VIR_PROXY_DOMAIN_INFO:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto comm_error;
|
||||||
|
}
|
||||||
|
ret = proxyWriteClientSocket(nr, req);
|
||||||
|
return(ret);
|
||||||
|
|
||||||
|
comm_error:
|
||||||
|
fprintf(stderr,
|
||||||
|
"Communication error with client %d: malformed packet\n", nr);
|
||||||
|
proxyCloseClientSocket(nr);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Main loop processing *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* proxyProcessRequests:
|
||||||
|
*
|
||||||
|
* process requests and timers
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
proxyProcessRequests(void) {
|
||||||
|
int exit_timeout = 30;
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
|
while (!done) {
|
||||||
|
/*
|
||||||
|
* wait for requests, with a one second timeout
|
||||||
|
*/
|
||||||
|
ret = poll(&pollInfos[0], nbClients + 1, 1000);
|
||||||
|
if (ret == 0) { /* timeout */
|
||||||
|
if (nbClients == 0) {
|
||||||
|
exit_timeout--;
|
||||||
|
if (exit_timeout == 0) {
|
||||||
|
done = 1;
|
||||||
|
if (debug > 0) {
|
||||||
|
fprintf(stderr, "Exitting after 30s without clients\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
exit_timeout = 30;
|
||||||
|
if (debug > 1)
|
||||||
|
fprintf(stderr, "poll timeout\n");
|
||||||
|
continue;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
if (debug > 0)
|
||||||
|
fprintf(stderr, "poll syscall interrupted\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "poll syscall failed\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* there have been I/O to process
|
||||||
|
*/
|
||||||
|
exit_timeout = 30;
|
||||||
|
if (pollInfos[0].revents != 0) {
|
||||||
|
if (pollInfos[0].revents & POLLIN) {
|
||||||
|
proxyAcceptClientSocket();
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Got an error %d on incoming socket %d\n",
|
||||||
|
pollInfos[0].revents, pollInfos[0].fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* process the clients in reverse order since on error or disconnect
|
||||||
|
* pollInfos is compacted to remove the given client.
|
||||||
|
*/
|
||||||
|
for (i = nbClients;i > 0;i--) {
|
||||||
|
if (pollInfos[i].revents & POLLIN) {
|
||||||
|
proxyReadClientSocket(i);
|
||||||
|
} else if (pollInfos[i].revents != 0) {
|
||||||
|
fprintf(stderr, "Got an error %d on client %d socket %d\n",
|
||||||
|
pollInfos[i].revents, i, pollInfos[i].fd);
|
||||||
|
proxyCloseClientSocket(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* proxyMainLoop:
|
||||||
|
*
|
||||||
|
* main loop for the proxy, continually try to keep the unix socket
|
||||||
|
* open, serve client requests, and process timing events.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxyMainLoop(void) {
|
||||||
|
while (! done) {
|
||||||
|
if (proxyListenUnixSocket(PROXY_SOCKET_PATH) < 0)
|
||||||
|
break;
|
||||||
|
proxyProcessRequests();
|
||||||
|
proxyCloseUnixSocket();
|
||||||
|
}
|
||||||
|
proxyCloseClientSockets();
|
||||||
|
proxyCloseUnixSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* usage:
|
||||||
|
*
|
||||||
|
* dump on stdout informations about the program
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
usage(const char *progname) {
|
||||||
|
printf("Usage: %s [-v] [-v]\n", progname);
|
||||||
|
printf(" option -v increase the verbosity level for debugging\n");
|
||||||
|
printf("This is a proxy for xen services used by libvirt to offer\n");
|
||||||
|
printf("safe and fast status information on the Xen virtualization.\n");
|
||||||
|
printf("This need not be run manually it's started automatically.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* main:
|
||||||
|
*
|
||||||
|
* Check that we are running with root priviledges, initialize the
|
||||||
|
* connections to the daemon and or hypervisor, and then run the main loop
|
||||||
|
*/
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
if (!strcmp(argv[i], "-v")) {
|
||||||
|
debug++;
|
||||||
|
} else {
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (geteuid() != 0) {
|
||||||
|
fprintf(stderr, "%s must be run as root or suid\n", argv[0]);
|
||||||
|
/* exit(1); */
|
||||||
|
}
|
||||||
|
|
||||||
|
proxyInitXen();
|
||||||
|
proxyMainLoop();
|
||||||
|
exit(0);
|
||||||
|
}
|
68
proxy/proxy.h
Normal file
68
proxy/proxy.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* proxy.h: common definitions for proxy usage
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* See COPYING.LIB for the License of this software
|
||||||
|
*
|
||||||
|
* Daniel Veillard <veillard@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __LIBVIR_PROXY_H__
|
||||||
|
#define __LIBVIR_PROXY_H__
|
||||||
|
|
||||||
|
#include <libvirt/libvirt.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PROXY_SOCKET_PATH "/tmp/livirt_proxy_conn"
|
||||||
|
#define PROXY_PROTO_VERSION 1
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the command allowed though the proxy
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
VIR_PROXY_NONE = 0,
|
||||||
|
VIR_PROXY_VERSION = 1,
|
||||||
|
VIR_PROXY_NODE_INFO = 2,
|
||||||
|
VIR_PROXY_LIST = 3,
|
||||||
|
VIR_PROXY_NUM_DOMAIN = 4,
|
||||||
|
VIR_PROXY_LOOKUP_ID = 5,
|
||||||
|
VIR_PROXY_LOOKUP_UUID = 6,
|
||||||
|
VIR_PROXY_LOOKUP_NAME = 7,
|
||||||
|
VIR_PROXY_MAX_MEMORY = 8,
|
||||||
|
VIR_PROXY_DOMAIN_INFO = 9
|
||||||
|
} virProxyCommand;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* structure used by the client to make a request to the proxy
|
||||||
|
* and by the proxy when answering the client.
|
||||||
|
* the size may not be fixed, it's passed as len.
|
||||||
|
*/
|
||||||
|
struct _virProxyPacket {
|
||||||
|
unsigned short version; /* version of the proxy protocol */
|
||||||
|
unsigned short command; /* command number a virProxyCommand */
|
||||||
|
unsigned short serial; /* command serial number */
|
||||||
|
unsigned short len; /* the length of the request */
|
||||||
|
union {
|
||||||
|
char string[8]; /* string data */
|
||||||
|
int arg; /* or int argument */
|
||||||
|
long larg; /* or long argument */
|
||||||
|
} data;
|
||||||
|
};
|
||||||
|
typedef struct _virProxyPacket virProxyPacket;
|
||||||
|
typedef virProxyPacket *virProxyPacketPtr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions callable from libvirt library
|
||||||
|
*/
|
||||||
|
int xenProxyInit(virConnectPtr conn);
|
||||||
|
void xenProxyClose(virConnectPtr conn);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
#endif /* __LIBVIR_PROXY_H__ */
|
632
proxy/proxy_client.c
Normal file
632
proxy/proxy_client.c
Normal file
@ -0,0 +1,632 @@
|
|||||||
|
/*
|
||||||
|
* proxy_client.c: client side of the communication with the libvirt proxy.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* See COPYING.LIB for the License of this software
|
||||||
|
*
|
||||||
|
* Daniel Veillard <veillard@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include "proxy.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#define STANDALONE
|
||||||
|
|
||||||
|
static int debug = 1;
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Error handling *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virProxyError:
|
||||||
|
* @conn: the connection if available
|
||||||
|
* @error: the error noumber
|
||||||
|
* @info: extra information string
|
||||||
|
*
|
||||||
|
* Handle an error at the xend daemon interface
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
virProxyError(virConnectPtr conn, virErrorNumber error, const char *info)
|
||||||
|
{
|
||||||
|
const char *errmsg;
|
||||||
|
|
||||||
|
if (error == VIR_ERR_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
errmsg = __virErrorMsg(error, info);
|
||||||
|
__virRaiseError(conn, NULL, VIR_FROM_XEND, error, VIR_ERR_ERROR,
|
||||||
|
errmsg, info, NULL, 0, 0, errmsg, info);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Automatic startup of the proxy server if it is not running *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
/**
|
||||||
|
* virProxyFindServerPath:
|
||||||
|
*
|
||||||
|
* Tries to find the path to the gam_server binary.
|
||||||
|
*
|
||||||
|
* Returns path on success or NULL in case of error.
|
||||||
|
*/
|
||||||
|
static const char *
|
||||||
|
virProxyFindServerPath(void)
|
||||||
|
{
|
||||||
|
static const char *serverPaths[] = {
|
||||||
|
#ifdef STANDALONE
|
||||||
|
"./libvirt_proxy",
|
||||||
|
BUILDDIR "/proxy/libvirt_proxy",
|
||||||
|
#endif
|
||||||
|
BINDIR "/libvirt_proxy",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
const char *debugProxy = getenv("LIBVIRT_DEBUG_PROXY");
|
||||||
|
|
||||||
|
if (debugProxy)
|
||||||
|
return(debugProxy);
|
||||||
|
|
||||||
|
for (i = 0; serverPaths[i]; i++) {
|
||||||
|
if (access(serverPaths[i], X_OK | R_OK) == 0) {
|
||||||
|
return serverPaths[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virProxyForkServer:
|
||||||
|
*
|
||||||
|
* Forks and try to launch the proxy server processing the requests for
|
||||||
|
* libvirt when communicating with Xen.
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success or -1 in case of detected error.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
virProxyForkServer(void)
|
||||||
|
{
|
||||||
|
const char *proxyPath = virProxyFindServerPath();
|
||||||
|
int ret, pid, status;
|
||||||
|
|
||||||
|
if (!proxyPath) {
|
||||||
|
fprintf(stderr, "failed to find libvirt_proxy\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "Asking to launch %s\n", proxyPath);
|
||||||
|
|
||||||
|
/* Become a daemon */
|
||||||
|
pid = fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
long open_max;
|
||||||
|
long i;
|
||||||
|
|
||||||
|
/* don't hold open fd opened from the client of the library */
|
||||||
|
open_max = sysconf (_SC_OPEN_MAX);
|
||||||
|
for (i = 0; i < open_max; i++)
|
||||||
|
fcntl (i, F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
|
setsid();
|
||||||
|
if (fork() == 0) {
|
||||||
|
execl(proxyPath, proxyPath, NULL);
|
||||||
|
fprintf(stderr, "failed to exec %s\n", proxyPath);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* calling exit() generate troubles for termination handlers
|
||||||
|
*/
|
||||||
|
_exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Processing of client sockets *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virProxyOpenClientSocket:
|
||||||
|
* @path: the fileame for the socket
|
||||||
|
*
|
||||||
|
* try to connect to the socket open by libvirt_proxy
|
||||||
|
*
|
||||||
|
* Returns the associated file descriptor or -1 in case of failure
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
virProxyOpenClientSocket(const char *path) {
|
||||||
|
int fd;
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
int trials = 0;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr, "Failed to create unix socket");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Abstract socket do not hit the filesystem, way more secure and
|
||||||
|
* garanteed to be atomic
|
||||||
|
*/
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
addr.sun_path[0] = '\0';
|
||||||
|
strncpy(&addr.sun_path[1], path, (sizeof(addr) - 4) - 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* now bind the socket to that address and listen on it
|
||||||
|
*/
|
||||||
|
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||||
|
fprintf(stderr, "Failed to connect to socket %s\n", path);
|
||||||
|
close(fd);
|
||||||
|
if (trials < 3) {
|
||||||
|
if (virProxyForkServer() < 0)
|
||||||
|
return(-1);
|
||||||
|
trials++;
|
||||||
|
usleep(5000 * trials * trials);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug > 0)
|
||||||
|
fprintf(stderr, "connected to unix socket %s via %d\n", path, fd);
|
||||||
|
|
||||||
|
return (fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virProxyCloseClientSocket:
|
||||||
|
* @fd: the file descriptor for the socket
|
||||||
|
*
|
||||||
|
* Close the socket from that client
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success and -1 in case of error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
virProxyCloseClientSocket(int fd) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
ret = close(fd);
|
||||||
|
if (ret != 0)
|
||||||
|
fprintf(stderr, "Failed to close socket %d\n", fd);
|
||||||
|
else if (debug > 0)
|
||||||
|
fprintf(stderr, "Closed socket %d\n", fd);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virProxyReadClientSocket:
|
||||||
|
* @fd: the socket
|
||||||
|
* @buffer: the target memory area
|
||||||
|
* @len: the lenght in bytes
|
||||||
|
*
|
||||||
|
* Process a read from a client socket
|
||||||
|
*
|
||||||
|
* Returns the number of byte read or -1 in case of error.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
virProxyReadClientSocket(int fd, char *buffer, int len) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((fd < 0) || (buffer == NULL) || (len < 0))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
retry:
|
||||||
|
ret = read(fd, buffer, len);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
if (debug > 0)
|
||||||
|
fprintf(stderr, "read socket %d interrupted\n", fd);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Failed to read socket %d\n", fd);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "read %d bytes from socket %d\n",
|
||||||
|
ret, fd);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virProxyWriteClientSocket:
|
||||||
|
* @fd: the socket
|
||||||
|
* @data: the data
|
||||||
|
* @len: the lenght of data in bytes
|
||||||
|
*
|
||||||
|
* Process a read from a client socket
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
virProxyWriteClientSocket(int fd, const char *data, int len) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((fd < 0) || (data == NULL) || (len < 0))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
retry:
|
||||||
|
ret = write(fd, data, len);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
if (debug > 0)
|
||||||
|
fprintf(stderr, "write socket %d, %d bytes interrupted\n",
|
||||||
|
fd, len);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Failed to write to socket %d\n", fd);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
if (debug)
|
||||||
|
fprintf(stderr, "wrote %d bytes to socket %d\n",
|
||||||
|
len, fd);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Proxy commands processing *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xenProxyClose:
|
||||||
|
* @conn: pointer to the hypervisor connection
|
||||||
|
*
|
||||||
|
* Shutdown the Xen proxy communication layer
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xenProxyClose(virConnectPtr conn) {
|
||||||
|
if ((conn == NULL) || (conn->proxy < 0))
|
||||||
|
return;
|
||||||
|
virProxyCloseClientSocket(conn->proxy);
|
||||||
|
conn->proxy = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
xenProxyCommand(virConnectPtr conn, virProxyPacketPtr request,
|
||||||
|
virProxyPacketPtr *answer) {
|
||||||
|
static int serial = 0;
|
||||||
|
int ret;
|
||||||
|
virProxyPacketPtr res = NULL;
|
||||||
|
char packet[4096];
|
||||||
|
|
||||||
|
if ((conn == NULL) || (conn->proxy < 0))
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* normal communication serial numbers are in 0..4095
|
||||||
|
*/
|
||||||
|
++serial;
|
||||||
|
if (serial >= 4096)
|
||||||
|
serial = 0;
|
||||||
|
request->version = PROXY_PROTO_VERSION;
|
||||||
|
request->serial = serial;
|
||||||
|
ret = virProxyWriteClientSocket(conn->proxy, (const char *) request,
|
||||||
|
request->len);
|
||||||
|
if (ret < 0)
|
||||||
|
return(-1);
|
||||||
|
retry:
|
||||||
|
if (answer == NULL) {
|
||||||
|
/* read in situ */
|
||||||
|
ret = virProxyReadClientSocket(conn->proxy, (char *) request,
|
||||||
|
sizeof(virProxyPacket));
|
||||||
|
if (ret < 0)
|
||||||
|
return(-1);
|
||||||
|
if (ret != sizeof(virProxyPacket)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Communication error with proxy: got %d bytes of %d\n",
|
||||||
|
ret, sizeof(virProxyPacket));
|
||||||
|
xenProxyClose(conn);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
res = request;
|
||||||
|
if (res->len != sizeof(virProxyPacket)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Communication error with proxy: expected %d bytes got %d\n",
|
||||||
|
sizeof(virProxyPacket), res->len);
|
||||||
|
xenProxyClose(conn);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* read in packet and duplicate if needed */
|
||||||
|
ret = virProxyReadClientSocket(conn->proxy, &packet[0],
|
||||||
|
sizeof(virProxyPacket));
|
||||||
|
if (ret < 0)
|
||||||
|
return(-1);
|
||||||
|
if (ret != sizeof(virProxyPacket)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Communication error with proxy: got %d bytes of %d\n",
|
||||||
|
ret, sizeof(virProxyPacket));
|
||||||
|
xenProxyClose(conn);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
res = (virProxyPacketPtr) &packet[0];
|
||||||
|
if ((res->len < sizeof(virProxyPacket)) ||
|
||||||
|
(res->len > sizeof(packet))) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Communication error with proxy: got %d bytes packet\n",
|
||||||
|
res->len);
|
||||||
|
xenProxyClose(conn);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
if (res->len > sizeof(virProxyPacket)) {
|
||||||
|
ret = virProxyReadClientSocket(conn->proxy, &packet[ret],
|
||||||
|
res->len - ret);
|
||||||
|
if (ret != (int) (res->len - sizeof(virProxyPacket))) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Communication error with proxy: got %d bytes of %d\n",
|
||||||
|
ret, sizeof(virProxyPacket));
|
||||||
|
xenProxyClose(conn);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* do more checks on the incoming packet.
|
||||||
|
*/
|
||||||
|
if ((res == NULL) || (res->version != PROXY_PROTO_VERSION) ||
|
||||||
|
(res->len < sizeof(virProxyPacket))) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Communication error with proxy: malformed packet\n");
|
||||||
|
xenProxyClose(conn);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
if (res->serial != serial) {
|
||||||
|
TODO /* Asynchronous communication */
|
||||||
|
fprintf(stderr, "gor asynchronous packet number %d\n", res->serial);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
if (answer != NULL)
|
||||||
|
*answer = res;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xenProxyInit:
|
||||||
|
* @conn: pointer to the hypervisor connection
|
||||||
|
*
|
||||||
|
* Try to initialize the Xen proxy communication layer
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success, and -1 in case of failure
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xenProxyInit(virConnectPtr conn) {
|
||||||
|
virProxyPacket req;
|
||||||
|
int ret;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
|
||||||
|
if (conn == NULL)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (conn->proxy <= 0) {
|
||||||
|
fd = virProxyOpenClientSocket(PROXY_SOCKET_PATH);
|
||||||
|
if (fd < 0) {
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
conn->proxy = fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
req.command = VIR_PROXY_NONE;
|
||||||
|
req.len = sizeof(req);
|
||||||
|
ret = xenProxyCommand(conn, &req, NULL);
|
||||||
|
if ((ret < 0) || (req.command != VIR_PROXY_NONE)) {
|
||||||
|
xenProxyClose(conn);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* *
|
||||||
|
* Driver entry points *
|
||||||
|
* *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xenProxyGetVersion:
|
||||||
|
* @conn: pointer to the Xen Daemon block
|
||||||
|
* @hvVer: return value for the version of the running hypervisor (OUT)
|
||||||
|
*
|
||||||
|
* Get the version level of the Hypervisor running.
|
||||||
|
*
|
||||||
|
* Returns -1 in case of error, 0 otherwise. if the version can't be
|
||||||
|
* extracted by lack of capacities returns 0 and @hvVer is 0, otherwise
|
||||||
|
* @hvVer value is major * 1,000,000 + minor * 1,000 + release
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xenProxyGetVersion(virConnectPtr conn, unsigned long *hvVer)
|
||||||
|
{
|
||||||
|
virProxyPacket req;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!VIR_IS_CONNECT(conn)) {
|
||||||
|
virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (hvVer == NULL) {
|
||||||
|
virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
req.command = VIR_PROXY_VERSION;
|
||||||
|
req.len = sizeof(req);
|
||||||
|
ret = xenProxyCommand(conn, &req, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
xenProxyClose(conn);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
*hvVer = req.data.larg;
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xenProxyNodeGetInfo:
|
||||||
|
* @conn: pointer to the Xen Daemon block
|
||||||
|
* @info: pointer to a virNodeInfo structure allocated by the user
|
||||||
|
*
|
||||||
|
* Extract hardware information about the node.
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success and -1 in case of failure.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xenProxyNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xenProxyListDomains:
|
||||||
|
* @conn: pointer to the hypervisor connection
|
||||||
|
* @ids: array to collect the list of IDs of active domains
|
||||||
|
* @maxids: size of @ids
|
||||||
|
*
|
||||||
|
* Collect the list of active domains, and store their ID in @maxids
|
||||||
|
* TODO: this is quite expensive at the moment since there isn't one
|
||||||
|
* xend RPC providing both name and id for all domains.
|
||||||
|
*
|
||||||
|
* Returns the number of domain found or -1 in case of error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xenProxyListDomains(virConnectPtr conn, int *ids, int maxids)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xenProxyNumOfDomains:
|
||||||
|
* @conn: pointer to the hypervisor connection
|
||||||
|
*
|
||||||
|
* Provides the number of active domains.
|
||||||
|
*
|
||||||
|
* Returns the number of domain found or -1 in case of error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xenProxyNumOfDomains(virConnectPtr conn)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xenProxyLookupByID:
|
||||||
|
* @conn: pointer to the hypervisor connection
|
||||||
|
* @id: the domain ID number
|
||||||
|
*
|
||||||
|
* Try to find a domain based on the hypervisor ID number
|
||||||
|
*
|
||||||
|
* Returns the domain name (to be freed) or NULL in case of failure
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
xenProxyLookupByID(virConnectPtr conn, int id) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xenProxyLookupByUUID:
|
||||||
|
* @conn: pointer to the hypervisor connection
|
||||||
|
* @uuid: the raw UUID for the domain
|
||||||
|
*
|
||||||
|
* Try to lookup a domain on xend based on its UUID.
|
||||||
|
*
|
||||||
|
* Returns the domain id or -1 in case of error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xenProxyLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xenProxyDomainLookupByName:
|
||||||
|
* @conn: A xend instance
|
||||||
|
* @name: The name of the domain
|
||||||
|
*
|
||||||
|
* This method looks up information about a domain based on its name
|
||||||
|
*
|
||||||
|
* Returns domain id or -1 in case of error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xenProxyDomainLookupByName(virConnectPtr conn, const char *domname)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xenProxyDomainGetMaxMemory:
|
||||||
|
* @domain: pointer to the domain block
|
||||||
|
*
|
||||||
|
* Ask the Xen Daemon for the maximum memory allowed for a domain
|
||||||
|
*
|
||||||
|
* Returns the memory size in kilobytes or 0 in case of error.
|
||||||
|
*/
|
||||||
|
unsigned long
|
||||||
|
xenProxyDomainGetMaxMemory(virDomainPtr domain)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xenProxyDomainGetInfo:
|
||||||
|
* @domain: a domain object
|
||||||
|
* @info: pointer to a virDomainInfo structure allocated by the user
|
||||||
|
*
|
||||||
|
* This method looks up information about a domain and update the
|
||||||
|
* information block provided.
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success, -1 in case of error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xenProxyDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef STANDALONE
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int ret;
|
||||||
|
unsigned long ver;
|
||||||
|
virConnect conn;
|
||||||
|
|
||||||
|
memset(&conn, 0, sizeof(conn));
|
||||||
|
ret = xenProxyInit(&conn);
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = xenProxyGetVersion(&conn, &ver);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "Failed to get version from proxy\n");
|
||||||
|
} else {
|
||||||
|
printf("Proxy running with version %lu\n", ver);
|
||||||
|
}
|
||||||
|
xenProxyClose(&conn);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
#endif
|
@ -101,7 +101,8 @@ struct _virConnect {
|
|||||||
|
|
||||||
/* extra data needed by drivers */
|
/* extra data needed by drivers */
|
||||||
int handle; /* internal handle used for hypercall */
|
int handle; /* internal handle used for hypercall */
|
||||||
struct xs_handle *xshandle; /* handle to talk to the xenstore */
|
struct xs_handle *xshandle;/* handle to talk to the xenstore */
|
||||||
|
int proxy; /* file descriptor if using the proxy */
|
||||||
|
|
||||||
/* connection to xend */
|
/* connection to xend */
|
||||||
int type; /* PF_UNIX or PF_INET */
|
int type; /* PF_UNIX or PF_INET */
|
||||||
|
@ -53,6 +53,7 @@ static const char * xenHypervisorGetType(virConnectPtr conn);
|
|||||||
static unsigned long xenHypervisorGetMaxMemory(virDomainPtr domain);
|
static unsigned long xenHypervisorGetMaxMemory(virDomainPtr domain);
|
||||||
static int xenHypervisorInit(void);
|
static int xenHypervisorInit(void);
|
||||||
|
|
||||||
|
#ifndef XEN_RO
|
||||||
static virDriver xenHypervisorDriver = {
|
static virDriver xenHypervisorDriver = {
|
||||||
VIR_DRV_XEN_HYPERVISOR,
|
VIR_DRV_XEN_HYPERVISOR,
|
||||||
"Xen",
|
"Xen",
|
||||||
@ -88,6 +89,7 @@ static virDriver xenHypervisorDriver = {
|
|||||||
NULL, /* domainSave */
|
NULL, /* domainSave */
|
||||||
NULL /* domainRestore */
|
NULL /* domainRestore */
|
||||||
};
|
};
|
||||||
|
#endif /* !XEN_RO */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virXenError:
|
* virXenError:
|
||||||
@ -175,6 +177,7 @@ done:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef XEN_RO
|
||||||
/**
|
/**
|
||||||
* xenHypervisorRegister:
|
* xenHypervisorRegister:
|
||||||
*
|
*
|
||||||
@ -187,6 +190,7 @@ void xenHypervisorRegister(void)
|
|||||||
|
|
||||||
virRegisterDriver(&xenHypervisorDriver);
|
virRegisterDriver(&xenHypervisorDriver);
|
||||||
}
|
}
|
||||||
|
#endif /* !XEN_RO */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xenHypervisorOpen:
|
* xenHypervisorOpen:
|
||||||
|
@ -48,6 +48,7 @@ static virDomainPtr xenDaemonCreateLinux(virConnectPtr conn,
|
|||||||
const char *xmlDesc,
|
const char *xmlDesc,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
|
||||||
|
#ifndef XEN_RO
|
||||||
static virDriver xenDaemonDriver = {
|
static virDriver xenDaemonDriver = {
|
||||||
VIR_DRV_XEN_DAEMON,
|
VIR_DRV_XEN_DAEMON,
|
||||||
"XenDaemon",
|
"XenDaemon",
|
||||||
@ -93,6 +94,7 @@ void xenDaemonRegister(void)
|
|||||||
{
|
{
|
||||||
virRegisterDriver(&xenDaemonDriver);
|
virRegisterDriver(&xenDaemonDriver);
|
||||||
}
|
}
|
||||||
|
#endif /* !XEN_RO */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xend_connection_type:
|
* xend_connection_type:
|
||||||
@ -1322,6 +1324,7 @@ xend_log(virConnectPtr xend, char *buffer, size_t n_buffer)
|
|||||||
******
|
******
|
||||||
******
|
******
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
|
#ifndef XEN_RO
|
||||||
/**
|
/**
|
||||||
* xend_parse_sexp_desc:
|
* xend_parse_sexp_desc:
|
||||||
* @root: the root of the parsed S-Expression
|
* @root: the root of the parsed S-Expression
|
||||||
@ -1509,6 +1512,7 @@ xend_parse_sexp_desc(struct sexpr *root)
|
|||||||
free(ret);
|
free(ret);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
#endif /* !XEN_RO */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sexpr_to_xend_domain_info:
|
* sexpr_to_xend_domain_info:
|
||||||
@ -1591,6 +1595,7 @@ sexpr_to_xend_node_info(struct sexpr *root, virNodeInfoPtr info)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef XEN_RO
|
||||||
/**
|
/**
|
||||||
* sexpr_to_domain:
|
* sexpr_to_domain:
|
||||||
* @conn: an existing virtual connection block
|
* @conn: an existing virtual connection block
|
||||||
@ -1636,7 +1641,7 @@ error:
|
|||||||
virFreeDomain(conn, ret);
|
virFreeDomain(conn, ret);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
#endif /* !XEN_RO */
|
||||||
|
|
||||||
/*****************************************************************
|
/*****************************************************************
|
||||||
******
|
******
|
||||||
@ -1649,6 +1654,7 @@ error:
|
|||||||
******
|
******
|
||||||
******
|
******
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
|
#ifndef XEN_RO
|
||||||
/**
|
/**
|
||||||
* xenDaemonOpen:
|
* xenDaemonOpen:
|
||||||
* @conn: an existing virtual connection block
|
* @conn: an existing virtual connection block
|
||||||
@ -1699,6 +1705,7 @@ xenDaemonOpen(virConnectPtr conn, const char *name, int flags)
|
|||||||
|
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
#endif /* !XEN_RO */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xenDaemonClose:
|
* xenDaemonClose:
|
||||||
@ -1958,6 +1965,7 @@ xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory)
|
|||||||
"target", buf, NULL);
|
"target", buf, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef XEN_RO
|
||||||
/**
|
/**
|
||||||
* xenDaemonDomainDumpXML:
|
* xenDaemonDomainDumpXML:
|
||||||
* @domain: a domain object
|
* @domain: a domain object
|
||||||
@ -1988,6 +1996,7 @@ xenDaemonDomainDumpXML(virDomainPtr domain)
|
|||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
#endif /* !XEN_RO */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xenDaemonDomainGetInfo:
|
* xenDaemonDomainGetInfo:
|
||||||
@ -2022,6 +2031,7 @@ xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
|
|||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef XEN_RO
|
||||||
/**
|
/**
|
||||||
* xenDaemonDomainLookupByName:
|
* xenDaemonDomainLookupByName:
|
||||||
* @conn: A xend instance
|
* @conn: A xend instance
|
||||||
@ -2053,6 +2063,7 @@ error:
|
|||||||
sexpr_free(root);
|
sexpr_free(root);
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xenDaemonNodeGetInfo:
|
* xenDaemonNodeGetInfo:
|
||||||
|
Loading…
Reference in New Issue
Block a user