]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
* src/proxy_internal.c src/proxy_internal.h src/driver.h src/libvirt.c
authorDaniel Veillard <veillard@redhat.com>
Thu, 29 Jun 2006 22:12:47 +0000 (22:12 +0000)
committerDaniel Veillard <veillard@redhat.com>
Thu, 29 Jun 2006 22:12:47 +0000 (22:12 +0000)
  src/Makefile.am: moved proxy/proxy.h and proxy/proxy_client.c as
  proxy_internal.[ch] and integrated them as a new driver.
* proxy/Makefile.am proxy/libvirt_proxy.c src/xen_internal.c
  src/xen_internal.h src/xend_internal.c: various related cleanups.
Daniel

13 files changed:
ChangeLog
proxy/Makefile.am
proxy/libvirt_proxy.c
proxy/proxy.h [deleted file]
proxy/proxy_client.c [deleted file]
src/Makefile.am
src/driver.h
src/libvirt.c
src/proxy_internal.c [new file with mode: 0644]
src/proxy_internal.h [new file with mode: 0644]
src/xen_internal.c
src/xen_internal.h
src/xend_internal.c

index 8bf95614c6b3e037ef24046a3554fa8d88801f6d..4e309dc27d10a91129f42c32b74b40d1f923bbc9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Thu Jun 29 22:19:51 EDT 2006 Daniel Veillard <veillard@redhat.com>
+
+       * src/proxy_internal.c src/proxy_internal.h src/driver.h src/libvirt.c
+         src/Makefile.am: moved proxy/proxy.h and proxy/proxy_client.c as
+         proxy_internal.[ch] and integrated them as a new driver.
+       * proxy/Makefile.am proxy/libvirt_proxy.c src/xen_internal.c 
+         src/xen_internal.h src/xend_internal.c: various related cleanups.
+
 Thu Jun 29 14:53:01 EDT 2006 Daniel Veillard <veillard@redhat.com>
 
        * proxy/libvirt_proxy.c proxy/proxy.h proxy/proxy_client.c: more
index 1043412c40b3c40ded99e11f0f7799bcf1b1a28e..5b117a4f0d001d45138a1d2c833d5e72bdf116d6 100644 (file)
@@ -2,8 +2,6 @@
 
 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
 
 
@@ -13,13 +11,7 @@ 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 =
index 0eea73ac6046c2855f233653334b410e62539264..ca39c08136c995dd177b85b6c37d1ff0da65ce69 100644 (file)
@@ -17,8 +17,8 @@
 #include <sys/poll.h>
 #include <sys/socket.h>
 #include <sys/un.h>
-#include "proxy.h"
 #include "internal.h"
+#include "proxy_internal.h"
 #include "xen_internal.h"
 #include "xend_internal.h"
 
@@ -278,7 +278,8 @@ proxyWriteClientSocket(int nr, virProxyPacketPtr req) {
     int ret;
 
     if ((nr <= 0) || (nr > nbClients) || (req == NULL) ||
-        (req->len < sizeof(virProxyPacket)) || (req->len > 4096) ||
+        (req->len < sizeof(virProxyPacket)) ||
+       (req->len > sizeof(virProxyFullPacket)) ||
        (pollInfos[nr].fd < 0)) {
        fprintf(stderr, "write to client %d in error", nr);
        proxyCloseClientSocket(nr);
@@ -327,12 +328,12 @@ retry:
  */
 static int
 proxyReadClientSocket(int nr) {
-    char buffer[4096];
-    virProxyPacketPtr req;
+    virProxyFullPacket request;
+    virProxyPacketPtr req = (virProxyPacketPtr) &request;
     int ret;
 
 retry:
-    ret = read(pollInfos[nr].fd, buffer, sizeof(virProxyPacket));
+    ret = read(pollInfos[nr].fd, req, sizeof(virProxyPacket));
     if (ret < 0) {
         if (errno == EINTR) {
            if (debug > 0)
@@ -357,7 +358,6 @@ retry:
         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;
@@ -380,10 +380,8 @@ retry:
 
            if (req->len != sizeof(virProxyPacket))
                goto comm_error;
-           maxids = (sizeof(buffer) - sizeof(virProxyPacket)) / sizeof(int);
-           maxids -= 10; /* just to be sure that should still be plenty */
-           ret = xenHypervisorListDomains(conn,
-                                  (int *) &buffer[sizeof(virProxyPacket)],
+           maxids = sizeof(request.extra.arg) / sizeof(int);
+           ret = xenHypervisorListDomains(conn, &request.extra.arg[0],
                                           maxids);
            if (ret < 0) {
                req->len = sizeof(virProxyPacket);
@@ -400,6 +398,10 @@ retry:
            req->data.arg = xenHypervisorNumOfDomains(conn);
            break;
        case VIR_PROXY_MAX_MEMORY:
+           if (req->len != sizeof(virProxyPacket))
+               goto comm_error;
+           req->data.larg = xenHypervisorGetDomMaxMemory(conn, req->data.arg);
+           break;
        case VIR_PROXY_DOMAIN_INFO:
        case VIR_PROXY_NODE_INFO:
        case VIR_PROXY_LOOKUP_ID:
diff --git a/proxy/proxy.h b/proxy/proxy.h
deleted file mode 100644 (file)
index 3035dc4..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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;
-
-/*
- * If there is extra data sent from the proxy to the client, 
- * they are appended after the packet.
- * the size may not be fixed, it's passed as len and includes the
- * extra data.
- */
-struct _virProxyFullPacket {
-    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;
-    /* that should be aligned on a 16bytes boundary */
-    union {
-        int        arg[1020];   /* extra int array */
-    } extra;
-};
-typedef struct _virProxyFullPacket virProxyFullPacket;
-typedef  virProxyFullPacket *virProxyFullPacketPtr;
-/*
- * Functions callable from libvirt library
- */
-int xenProxyInit(virConnectPtr conn);
-void xenProxyClose(virConnectPtr conn);
-
-#ifdef __cplusplus
-}
-#endif                          /* __cplusplus */
-#endif /* __LIBVIR_PROXY_H__ */
diff --git a/proxy/proxy_client.c b/proxy/proxy_client.c
deleted file mode 100644 (file)
index 668dca5..0000000
+++ /dev/null
@@ -1,687 +0,0 @@
-/*
- * 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)
-{
-    if (error == VIR_ERR_OK)
-        return;
-
-#if 0
-    const char *errmsg;
-
-    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
-        "/usr/bin/libvirt_proxy_dbg",
-#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,
-                virProxyFullPacketPtr answer) {
-    static int serial = 0;
-    int ret;
-    virProxyPacketPtr res = NULL;
-
-    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 provided */
-        ret  = virProxyReadClientSocket(conn->proxy, (char *) answer,
-                                       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) answer;
-       if ((res->len < sizeof(virProxyPacket)) ||
-           (res->len > sizeof(virProxyFullPacket))) {
-           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,
-                                           &(answer->extra.arg[0]),
-                                           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;
-    }
-    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 (!VIR_IS_CONNECT(conn)) {
-        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        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
- *
- * Returns the number of domain found or -1 in case of error
- */
-static int
-xenProxyListDomains(virConnectPtr conn, int *ids, int maxids)
-{
-    virProxyPacket req;
-    virProxyFullPacket ans;
-    int ret;
-    int nb;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-    if ((ids == NULL) || (maxids <= 0)) {
-        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
-       return (-1);
-    }
-    memset(&req, 0, sizeof(req));
-    req.command = VIR_PROXY_LIST;
-    req.len = sizeof(req);
-    ret = xenProxyCommand(conn, &req, &ans);
-    if (ret < 0) {
-        xenProxyClose(conn);
-       return(-1);
-    }
-    nb = ans.data.arg;
-    if ((nb > 1020) || (nb <= 0))
-        return(-1);
-    if (nb > maxids)
-        nb = maxids;
-    memmove(ids, &ans.extra.arg[0], nb * sizeof(int));
-
-    return(nb);
-}
-
-/**
- * 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)
-{
-    virProxyPacket req;
-    int ret;
-    int nb;
-
-    if (!VIR_IS_CONNECT(conn)) {
-        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
-        return (-1);
-    }
-    memset(&req, 0, sizeof(req));
-    req.command = VIR_PROXY_NUM_DOMAIN;
-    req.len = sizeof(req);
-    ret = xenProxyCommand(conn, &req, NULL);
-    if (ret < 0) {
-        xenProxyClose(conn);
-       return(-1);
-    }
-    return(req.data.arg);
-}
-
-/**
- * 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));
-    conn.magic = VIR_CONNECT_MAGIC;
-    ret = xenProxyInit(&conn);
-    if (ret == 0) {
-        ret = xenProxyGetVersion(&conn, &ver);
-       if (ret != 0) {
-           fprintf(stderr, "Failed to get version from proxy\n");
-       } else {
-           int ids[50], i;
-
-           printf("Proxy running with version %lu\n", ver);
-           ret = xenProxyNumOfDomains(&conn);
-           printf("There is %d running domains:", ret);
-           ret = xenProxyListDomains(&conn, &ids, 50);
-           if (ret < 0) {
-               fprintf(stderr, "Failed to list domains\n");
-           }
-           for (i = 0;i < ret;i++)
-               printf(" %d", ids[i]);
-           printf("\n");
-
-       }
-       xenProxyClose(&conn);
-    }
-    exit(0);
-}
-#endif
index 2f814bf0583392b592a3193efbe88ea182f783a2..e85793ab34bcab94d279fe12c6258ca2721b1baa 100644 (file)
@@ -1,6 +1,7 @@
 ## Process this file with automake to produce Makefile.in
 
-INCLUDES = -I$(top_builddir)/include -I@top_srcdir@/include @LIBXML_CFLAGS@
+INCLUDES = -I$(top_builddir)/include -I@top_srcdir@/include @LIBXML_CFLAGS@ \
+          -DBINDIR=\""$(libexecdir)"\"
 DEPS = libvirt.la
 LDADDS = @STATIC_BINARIES@ libvirt.la
 VIRSH_LIBS = @VIRSH_LIBS@
@@ -23,7 +24,8 @@ libvirt_la_SOURCES =                                          \
                xend_internal.c xend_internal.h                 \
                sexpr.c sexpr.h                                 \
                virterror.c                                     \
-               driver.h
+               driver.h                                        \
+               proxy_internal.c proxy_internal.h
 
 bin_PROGRAMS = virsh
 
index 173bae19ffacfd591d5640623fd1c07cb87f06eb..838827df2897ddea15ec23c5c7708326cb1bfc3d 100644 (file)
@@ -20,7 +20,8 @@ typedef enum {
     VIR_DRV_XEN_HYPERVISOR = 1,
     VIR_DRV_XEN_STORE = 2,
     VIR_DRV_XEN_DAEMON = 3,
-    VIR_DRV_TEST = 4
+    VIR_DRV_TEST = 4,
+    VIR_DRV_XEN_PROXY = 5
 } virDrvNo;
 
 
index 70b46be427c82dd2b63b9f4ab20e3ef16f9360ba..6cfface03d78767d2bcbd6d4c0a5a41e1cb3bce3 100644 (file)
@@ -28,6 +28,7 @@
 #include "xen_internal.h"
 #include "xend_internal.h"
 #include "xs_internal.h"
+#include "proxy_internal.h"
 #include "xml.h"
 #include "test.h"
 
@@ -69,6 +70,7 @@ virInitialize(void)
      * Note that the order is important the first ones have a higher priority
      */
     xenHypervisorRegister();
+    xenProxyRegister();
     xenDaemonRegister();
     xenStoreRegister();
     testRegister();
@@ -244,7 +246,8 @@ virConnectOpen(const char *name)
             * all related drivers.
             */
            if ((res < 0) && (for_xen) &&
-               (!strncasecmp(virDriverTab[i]->name, "xen", 3)))
+               (!strncasecmp(virDriverTab[i]->name, "xen", 3)) &&
+               (virDriverTab[i]->no != VIR_DRV_XEN_PROXY))
                goto failed;
            if (res == 0)
                ret->drivers[ret->nb_drivers++] = virDriverTab[i];
diff --git a/src/proxy_internal.c b/src/proxy_internal.c
new file mode 100644 (file)
index 0000000..e2dac20
--- /dev/null
@@ -0,0 +1,794 @@
+/*
+ * 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 "internal.h"
+#include "driver.h"
+#include "proxy_internal.h"
+
+#define STANDALONE
+
+static int debug = 0;
+
+static int xenProxyClose(virConnectPtr conn);
+static int xenProxyOpen(virConnectPtr conn, const char *name, int flags);
+static int xenProxyGetVersion(virConnectPtr conn, unsigned long *hvVer);
+static int xenProxyNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
+static int xenProxyListDomains(virConnectPtr conn, int *ids, int maxids);
+static int xenProxyNumOfDomains(virConnectPtr conn);
+static virDomainPtr xenProxyLookupByID(virConnectPtr conn, int id);
+static virDomainPtr xenProxyLookupByUUID(virConnectPtr conn,
+                                        const unsigned char *uuid);
+static virDomainPtr xenProxyDomainLookupByName(virConnectPtr conn,
+                                              const char *domname);
+static unsigned long xenProxyDomainGetMaxMemory(virDomainPtr domain);
+static int xenProxyDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
+
+static virDriver xenProxyDriver = {
+    VIR_DRV_XEN_PROXY,
+    "XenProxy",
+    0,
+    NULL, /* init */
+    xenProxyOpen, /* open */
+    xenProxyClose, /* close */
+    NULL, /* type */
+    xenProxyGetVersion, /* version */
+    NULL, /* nodeGetInfo */
+    xenProxyListDomains, /* listDomains */
+    xenProxyNumOfDomains, /* numOfDomains */
+    NULL, /* domainCreateLinux */
+    xenProxyLookupByID, /* domainLookupByID */
+    xenProxyLookupByUUID, /* domainLookupByUUID */
+    xenProxyDomainLookupByName, /* domainLookupByName */
+    NULL, /* domainSuspend */
+    NULL, /* domainResume */
+    NULL, /* domainShutdown */
+    NULL, /* domainReboot */
+    NULL, /* domainDestroy */
+    NULL, /* domainFree */
+    NULL, /* domainGetName */
+    NULL, /* domainGetID */
+    NULL, /* domainGetUUID */
+    NULL, /* domainGetOSType */
+    xenProxyDomainGetMaxMemory, /* domainGetMaxMemory */
+    NULL, /* domainSetMaxMemory */
+    NULL, /* domainSetMemory */
+    xenProxyDomainGetInfo, /* domainGetInfo */
+    NULL, /* domainSave */
+    NULL /* domainRestore */
+};
+
+/**
+ * xenProxyRegister:
+ *
+ * Registers the xenHypervisor driver
+ */
+void xenProxyRegister(void)
+{
+    virRegisterDriver(&xenProxyDriver);
+}
+/************************************************************************
+ *                                                                     *
+ *                     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;
+
+    errmsg = __virErrorMsg(error, info);
+    __virRaiseError(conn, NULL, VIR_FROM_XEND, error, VIR_ERR_ERROR,
+                    errmsg, info, NULL, 0, 0, errmsg, info);
+}
+
+/************************************************************************
+ *                                                                     *
+ *     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[] = {
+        BINDIR "/libvirt_proxy",
+        "/usr/bin/libvirt_proxy_dbg",
+        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) {
+       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) {
+       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
+ */
+static int
+xenProxyClose(virConnectPtr conn) {
+    if ((conn == NULL) || (conn->proxy < 0))
+        return(-1);
+    virProxyCloseClientSocket(conn->proxy);
+    conn->proxy = -1;
+    return (0);
+}
+
+static int 
+xenProxyCommand(virConnectPtr conn, virProxyPacketPtr request,
+                virProxyFullPacketPtr answer) {
+    static int serial = 0;
+    int ret;
+    virProxyPacketPtr res = NULL;
+
+    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 provided */
+        ret  = virProxyReadClientSocket(conn->proxy, (char *) answer,
+                                       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) answer;
+       if ((res->len < sizeof(virProxyPacket)) ||
+           (res->len > sizeof(virProxyFullPacket))) {
+           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,
+                                  (char *) &(answer->extra.arg[0]),
+                                           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;
+    }
+    return(0);
+}
+
+/**
+ * xenProxyInit:
+ * @conn: pointer to the hypervisor connection
+ * @name: URL for the target, NULL for local
+ * @flags: combination of virDrvOpenFlag(s)
+ *
+ * Try to initialize the Xen proxy communication layer
+ * This can be opened only for a read-only kind of access
+ *
+ * Returns 0 in case of success, and -1 in case of failure
+ */
+int
+xenProxyOpen(virConnectPtr conn, const char *name, int flags)
+{
+    virProxyPacket req;
+    int ret;
+    int fd;
+    
+    if ((name != NULL) && (strcasecmp(name, "xen")))
+        return(-1);
+    if (!(flags & VIR_DRV_OPEN_RO))
+        return(-1);
+        
+    conn->proxy = -1;
+    fd = virProxyOpenClientSocket(PROXY_SOCKET_PATH);
+    if (fd < 0) {
+        if (!(flags & VIR_DRV_OPEN_QUIET))
+           virProxyError(conn, VIR_ERR_NO_XEN, PROXY_SOCKET_PATH);
+       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)) {
+        virProxyError(conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
+        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);
+}
+
+/**
+ * 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
+ *
+ * Returns the number of domain found or -1 in case of error
+ */
+static int
+xenProxyListDomains(virConnectPtr conn, int *ids, int maxids)
+{
+    virProxyPacket req;
+    virProxyFullPacket ans;
+    int ret;
+    int nb;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+    if ((ids == NULL) || (maxids <= 0)) {
+        virProxyError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+       return (-1);
+    }
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_LIST;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(conn, &req, &ans);
+    if (ret < 0) {
+        xenProxyClose(conn);
+       return(-1);
+    }
+    nb = ans.data.arg;
+    if ((nb > 1020) || (nb <= 0) ||
+        (ans.len <= sizeof(virProxyPacket)) ||
+       (ans.len > sizeof(virProxyFullPacket))) {
+        virProxyError(conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
+        return(-1);
+    }
+    if (nb > maxids)
+        nb = maxids;
+    memmove(ids, &ans.extra.arg[0], nb * sizeof(int));
+
+    return(nb);
+}
+
+/**
+ * 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)
+{
+    virProxyPacket req;
+    int ret;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_NUM_DOMAIN;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(conn, &req, NULL);
+    if (ret < 0) {
+        xenProxyClose(conn);
+       return(-1);
+    }
+    return(req.data.arg);
+}
+
+
+/**
+ * xenProxyDomainGetDomMaxMemory:
+ * @conn: pointer to the hypervisor connection
+ * @id: the domain ID number
+ *
+ * Ask the Xen Daemon for the maximum memory allowed for a domain
+ *
+ * Returns the memory size in kilobytes or 0 in case of error.
+ */
+static unsigned long
+xenProxyDomainGetDomMaxMemory(virConnectPtr conn, int id)
+{
+    virProxyPacket req;
+    int ret;
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_MAX_MEMORY;
+    req.data.arg = id;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(conn, &req, NULL);
+    if (ret < 0) {
+        xenProxyClose(conn);
+       return(-1);
+    }
+    return(req.data.larg);
+}
+
+/**
+ * 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.
+ */
+static unsigned long
+xenProxyDomainGetMaxMemory(virDomainPtr domain)
+{
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+       if (domain == NULL)
+           virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+       else
+           virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (0);
+    }
+    return(xenProxyDomainGetDomMaxMemory(domain->conn, domain->handle));
+}
+
+/**
+ * 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
+ */
+static int
+xenProxyDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
+{
+    virProxyPacket req;
+    virProxyFullPacket ans;
+    int ret;
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+       if (domain == NULL)
+           virProxyError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+       else
+           virProxyError(domain->conn, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        return (0);
+    }
+    if (info == NULL) {
+        virProxyError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+       return (-1);
+    }
+    memset(&req, 0, sizeof(req));
+    req.command = VIR_PROXY_DOMAIN_INFO;
+    req.len = sizeof(req);
+    ret = xenProxyCommand(domain->conn, &req, &ans);
+    if (ret < 0) {
+        xenProxyClose(domain->conn);
+       return(-1);
+    }
+    if (ans.len != sizeof(virProxyPacket) + sizeof(virDomainInfo)) {
+        virProxyError(domain->conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
+       return (-1);
+    }
+    memmove(info, &ans.extra.dinfo, sizeof(virDomainInfo));
+
+    return(0);
+}
+
+/**
+ * xenProxyLookupByID:
+ * @conn: pointer to the hypervisor connection
+ * @id: the domain ID number
+ *
+ * Try to find a domain based on the hypervisor ID number
+ *
+ * Returns a new domain object or NULL in case of failure
+ */
+static virDomainPtr
+xenProxyLookupByID(virConnectPtr conn, int id)
+{
+    TODO
+    return(NULL);
+}
+
+/**
+ * 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 a new domain object or NULL in case of failure
+ */
+static virDomainPtr
+xenProxyLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
+{
+    TODO
+    return(NULL);
+}
+
+/**
+ * xenProxyDomainLookupByName:
+ * @conn: A xend instance
+ * @name: The name of the domain
+ *
+ * This method looks up information about a domain based on its name
+ *
+ * Returns a new domain object or NULL in case of failure
+ */
+static virDomainPtr
+xenProxyDomainLookupByName(virConnectPtr conn, const char *domname)
+{
+    TODO
+    return(NULL);
+}
+
+/**
+ * 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) {
+    TODO
+    return(-1);
+}
+
diff --git a/src/proxy_internal.h b/src/proxy_internal.h
new file mode 100644 (file)
index 0000000..1a462fe
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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;
+
+/*
+ * If there is extra data sent from the proxy to the client, 
+ * they are appended after the packet.
+ * the size may not be fixed, it's passed as len and includes the
+ * extra data.
+ */
+struct _virProxyFullPacket {
+    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;
+    /* that should be aligned on a 16bytes boundary */
+    union {
+        char       str[4080];   /* extra char array */
+        int        arg[1020];   /* extra int array */
+       virDomainInfo dinfo;    /* domain informations */
+    } extra;
+};
+typedef struct _virProxyFullPacket virProxyFullPacket;
+typedef  virProxyFullPacket *virProxyFullPacketPtr;
+/*
+ * Functions callable from libvirt library
+ */
+void xenProxyRegister(void);
+
+#ifdef __cplusplus
+}
+#endif                          /* __cplusplus */
+#endif /* __LIBVIR_PROXY_H__ */
index ccf7f94f84977ebc6335e7c98a7df4372747b029..a5a8df88316849d34d19cc4cb4b90d160f3a3ded 100644 (file)
@@ -510,24 +510,23 @@ xenHypervisorListDomains(virConnectPtr conn, int *ids, int maxids)
 }
 
 /**
- * xenHypervisorGetMaxMemory:
- * @domain: a domain object or NULL
+ * xenHypervisorGetDomMaxMemory:
+ * @conn: connection data
+ * @id: domain id
  * 
  * Retrieve the maximum amount of physical memory allocated to a
- * domain. If domain is NULL, then this get the amount of memory reserved
- * to Domain0 i.e. the domain where the application runs.
+ * domain.
  *
  * Returns the memory size in kilobytes or 0 in case of error.
  */
-static unsigned long
-xenHypervisorGetMaxMemory(virDomainPtr domain)
+unsigned long
+xenHypervisorGetDomMaxMemory(virConnectPtr conn, int id)
 {
     dom0_op_t op;
     dom0_getdomaininfo_t dominfo;
     int ret;
 
-    if ((domain == NULL) || (domain->conn == NULL) ||
-        (domain->conn->handle < 0))
+    if ((conn == NULL) || (conn->handle < 0))
         return (0);
 
     memset(&dominfo, 0, sizeof(dom0_getdomaininfo_t));
@@ -539,13 +538,13 @@ xenHypervisorGetMaxMemory(virDomainPtr domain)
     }
 
     op.cmd = DOM0_GETDOMAININFOLIST;
-    op.u.getdomaininfolist.first_domain = (domid_t) domain->handle;
+    op.u.getdomaininfolist.first_domain = (domid_t) id;
     op.u.getdomaininfolist.max_domains = 1;
     op.u.getdomaininfolist.buffer = &dominfo;
     op.u.getdomaininfolist.num_domains = 1;
-    dominfo.domain = domain->handle;
+    dominfo.domain = id;
 
-    ret = xenHypervisorDoOp(domain->conn->handle, &op);
+    ret = xenHypervisorDoOp(conn->handle, &op);
 
     if (munlock(&dominfo, sizeof(dom0_getdomaininfo_t)) < 0) {
         virXenError(VIR_ERR_XEN_CALL, " release",
@@ -559,6 +558,26 @@ xenHypervisorGetMaxMemory(virDomainPtr domain)
     return((unsigned long) dominfo.max_pages * 4);
 }
 
+/**
+ * xenHypervisorGetMaxMemory:
+ * @domain: a domain object or NULL
+ * 
+ * Retrieve the maximum amount of physical memory allocated to a
+ * domain. If domain is NULL, then this get the amount of memory reserved
+ * to Domain0 i.e. the domain where the application runs.
+ *
+ * Returns the memory size in kilobytes or 0 in case of error.
+ */
+static unsigned long
+xenHypervisorGetMaxMemory(virDomainPtr domain)
+{
+    if ((domain == NULL) || (domain->conn == NULL) ||
+        (domain->conn->handle < 0))
+        return (0);
+
+    return(xenHypervisorGetDomMaxMemory(domain->conn, domain->handle));
+}
+
 /**
  * xenHypervisorGetDomainInfo:
  * @domain: pointer to the domain block
index dcb62f6c5db8846592342956c839a05292cecb98..514e02dcbe0f9228e281387f47e6a4a545e566d5 100644 (file)
@@ -25,6 +25,9 @@ int   xenHypervisorOpen               (virConnectPtr conn,
 int    xenHypervisorClose              (virConnectPtr conn);
 int    xenHypervisorGetVersion         (virConnectPtr conn,
                                         unsigned long *hvVer);
+unsigned long
+        xenHypervisorGetDomMaxMemory   (virConnectPtr conn,
+                                        int id);
 int    xenHypervisorNumOfDomains       (virConnectPtr conn);
 int    xenHypervisorListDomains        (virConnectPtr conn,
                                         int *ids,
index 23c20b7eacfe836796c27eb614b8bf9e2e55549b..9a46261f9d75b558f37455f3e487c2ae401008a9 100644 (file)
@@ -194,7 +194,6 @@ do_connect(virConnectPtr xend)
     }
 
     if (connect(s, xend->addr, xend->len) == -1) {
-        virXendError(xend, VIR_ERR_NO_CONNECT, "Xen Daemon");
         serrno = errno;
         close(s);
         errno = serrno;
@@ -2096,6 +2095,7 @@ xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) {
     return (ret);
 }
 
+#ifndef XEN_RO
 /**
  * xenDaemonGetType:
  * @conn: pointer to the Xen Daemon block
@@ -2115,6 +2115,7 @@ xenDaemonGetType(virConnectPtr conn)
     }
     return("XenDaemon");
 }
+#endif
 
 /**
  * xenDaemonGetVersion:
@@ -2243,6 +2244,7 @@ error:
     return(ret);
 }
 
+#ifndef XEN_RO
 /**
  * xenDaemonLookupByID:
  * @conn: pointer to the hypervisor connection
@@ -2430,3 +2432,5 @@ xenDaemonCreateLinux(virConnectPtr conn, const char *xmlDesc,
     return (NULL);
 }
 
+#endif
+