mirror of https://gitee.com/openkylin/libvirt.git
* 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>
|
||||
|
||||
* configure.in libvirt.spec.in docs/examples/* include/Makefile.am
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
## 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 \
|
||||
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 \
|
||||
include/libvirt/Makefile include/libvirt/libvirt.h \
|
||||
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_XML, /* Error in the XML code */
|
||||
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;
|
||||
|
||||
|
||||
|
|
|
@ -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 =
|
|
@ -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);
|
||||
}
|
|
@ -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__ */
|
|
@ -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 */
|
||||
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 */
|
||||
int type; /* PF_UNIX or PF_INET */
|
||||
|
|
|
@ -53,6 +53,7 @@ static const char * xenHypervisorGetType(virConnectPtr conn);
|
|||
static unsigned long xenHypervisorGetMaxMemory(virDomainPtr domain);
|
||||
static int xenHypervisorInit(void);
|
||||
|
||||
#ifndef XEN_RO
|
||||
static virDriver xenHypervisorDriver = {
|
||||
VIR_DRV_XEN_HYPERVISOR,
|
||||
"Xen",
|
||||
|
@ -88,6 +89,7 @@ static virDriver xenHypervisorDriver = {
|
|||
NULL, /* domainSave */
|
||||
NULL /* domainRestore */
|
||||
};
|
||||
#endif /* !XEN_RO */
|
||||
|
||||
/**
|
||||
* virXenError:
|
||||
|
@ -175,6 +177,7 @@ done:
|
|||
|
||||
}
|
||||
|
||||
#ifndef XEN_RO
|
||||
/**
|
||||
* xenHypervisorRegister:
|
||||
*
|
||||
|
@ -187,6 +190,7 @@ void xenHypervisorRegister(void)
|
|||
|
||||
virRegisterDriver(&xenHypervisorDriver);
|
||||
}
|
||||
#endif /* !XEN_RO */
|
||||
|
||||
/**
|
||||
* xenHypervisorOpen:
|
||||
|
|
|
@ -48,6 +48,7 @@ static virDomainPtr xenDaemonCreateLinux(virConnectPtr conn,
|
|||
const char *xmlDesc,
|
||||
unsigned int flags);
|
||||
|
||||
#ifndef XEN_RO
|
||||
static virDriver xenDaemonDriver = {
|
||||
VIR_DRV_XEN_DAEMON,
|
||||
"XenDaemon",
|
||||
|
@ -93,6 +94,7 @@ void xenDaemonRegister(void)
|
|||
{
|
||||
virRegisterDriver(&xenDaemonDriver);
|
||||
}
|
||||
#endif /* !XEN_RO */
|
||||
|
||||
/**
|
||||
* xend_connection_type:
|
||||
|
@ -1322,6 +1324,7 @@ xend_log(virConnectPtr xend, char *buffer, size_t n_buffer)
|
|||
******
|
||||
******
|
||||
*****************************************************************/
|
||||
#ifndef XEN_RO
|
||||
/**
|
||||
* xend_parse_sexp_desc:
|
||||
* @root: the root of the parsed S-Expression
|
||||
|
@ -1509,6 +1512,7 @@ xend_parse_sexp_desc(struct sexpr *root)
|
|||
free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
#endif /* !XEN_RO */
|
||||
|
||||
/**
|
||||
* sexpr_to_xend_domain_info:
|
||||
|
@ -1591,6 +1595,7 @@ sexpr_to_xend_node_info(struct sexpr *root, virNodeInfoPtr info)
|
|||
return (0);
|
||||
}
|
||||
|
||||
#ifndef XEN_RO
|
||||
/**
|
||||
* sexpr_to_domain:
|
||||
* @conn: an existing virtual connection block
|
||||
|
@ -1636,7 +1641,7 @@ error:
|
|||
virFreeDomain(conn, ret);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* !XEN_RO */
|
||||
|
||||
/*****************************************************************
|
||||
******
|
||||
|
@ -1649,6 +1654,7 @@ error:
|
|||
******
|
||||
******
|
||||
*****************************************************************/
|
||||
#ifndef XEN_RO
|
||||
/**
|
||||
* xenDaemonOpen:
|
||||
* @conn: an existing virtual connection block
|
||||
|
@ -1699,6 +1705,7 @@ xenDaemonOpen(virConnectPtr conn, const char *name, int flags)
|
|||
|
||||
return(ret);
|
||||
}
|
||||
#endif /* !XEN_RO */
|
||||
|
||||
/**
|
||||
* xenDaemonClose:
|
||||
|
@ -1958,6 +1965,7 @@ xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory)
|
|||
"target", buf, NULL);
|
||||
}
|
||||
|
||||
#ifndef XEN_RO
|
||||
/**
|
||||
* xenDaemonDomainDumpXML:
|
||||
* @domain: a domain object
|
||||
|
@ -1988,6 +1996,7 @@ xenDaemonDomainDumpXML(virDomainPtr domain)
|
|||
|
||||
return (ret);
|
||||
}
|
||||
#endif /* !XEN_RO */
|
||||
|
||||
/**
|
||||
* xenDaemonDomainGetInfo:
|
||||
|
@ -2022,6 +2031,7 @@ xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
|
|||
return (ret);
|
||||
}
|
||||
|
||||
#ifndef XEN_RO
|
||||
/**
|
||||
* xenDaemonDomainLookupByName:
|
||||
* @conn: A xend instance
|
||||
|
@ -2053,6 +2063,7 @@ error:
|
|||
sexpr_free(root);
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* xenDaemonNodeGetInfo:
|
||||
|
|
Loading…
Reference in New Issue