]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
* proxy/libvirt_proxy.c proxy/proxy.h proxy/proxy_client.c: more
authorDaniel Veillard <veillard@redhat.com>
Thu, 29 Jun 2006 14:44:37 +0000 (14:44 +0000)
committerDaniel Veillard <veillard@redhat.com>
Thu, 29 Jun 2006 14:44:37 +0000 (14:44 +0000)
  progresses on the proxy implementation.
* src/xend_internal.c src/xend_internal.h: exported one routine
Daniel

ChangeLog
proxy/libvirt_proxy.c
proxy/proxy.h
proxy/proxy_client.c
src/xend_internal.c
src/xend_internal.h

index b7d0ecb9ef841ef6db399b31a6c4021446e844ad..8bf95614c6b3e037ef24046a3554fa8d88801f6d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+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
+         progresses on the proxy implementation.
+       * src/xend_internal.c src/xend_internal.h: exported one routine
+
 Wed Jun 28 19:23:25 CEST 2006 Daniel Veillard <veillard@redhat.com>
 
        * configure.in Makefile.am proxy/Makefile.am proxy/libvirt_proxy.c
index c1eaa9dfe9bf334f0b815ea32e4e120471f10cf6..0eea73ac6046c2855f233653334b410e62539264 100644 (file)
 #include "proxy.h"
 #include "internal.h"
 #include "xen_internal.h"
+#include "xend_internal.h"
 
 static int fdServer = -1;
 static int debug = 0;
+static int persist = 0;
 static int done = 0;
 
 #define MAX_CLIENT 64
@@ -33,6 +35,8 @@ static struct pollfd pollInfos[MAX_CLIENT + 1];
 static virConnect conninfos;
 static virConnectPtr conn = &conninfos;
 
+static unsigned long xenVersion = 0;
+
 /************************************************************************
  *                                                                     *
  *     Interfaces with the Xen hypervisor                              *
@@ -49,17 +53,34 @@ static virConnectPtr conn = &conninfos;
 static int
 proxyInitXen(void) {
     int ret;
+    unsigned long xenVersion2;
 
     ret = xenHypervisorOpen(conn, NULL, VIR_DRV_OPEN_QUIET);
     if (ret < 0) {
         fprintf(stderr, "Failed to open Xen hypervisor\n");
         return(-1);
+    } else {
+        ret = xenHypervisorGetVersion(conn, &xenVersion);
+       if (ret != 0) {
+           fprintf(stderr, "Failed to get Xen hypervisor version\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);
     }
+    ret = xenDaemonGetVersion(conn, &xenVersion2);
+    if (ret != 0) {
+       fprintf(stderr, "Failed to get Xen daemon version\n");
+       return(-1);
+    }
+    if (debug)
+        fprintf(stderr, "Connected to hypervisor %lu and daemon %lu\n",
+               xenVersion, xenVersion2);
+    if (xenVersion2 > xenVersion)
+        xenVersion = xenVersion2;
     return(0);
 }
 
@@ -342,7 +363,7 @@ retry:
        goto comm_error;
     
     if (debug)
-        fprintf(stderr, "Gor command %d from client %d\n", req->command, nr);
+        fprintf(stderr, "Got command %d from client %d\n", req->command, nr);
 
     switch (req->command) {
        case VIR_PROXY_NONE:
@@ -352,17 +373,39 @@ retry:
        case VIR_PROXY_VERSION:
            if (req->len != sizeof(virProxyPacket))
                goto comm_error;
-           TODO;
-           req->data.larg = 3 * 1000000 + 2;
+           req->data.larg = xenVersion;
            break;
-       case VIR_PROXY_NODE_INFO:
-       case VIR_PROXY_LIST:
+       case VIR_PROXY_LIST: {
+           int maxids;
+
+           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);
+           if (ret < 0) {
+               req->len = sizeof(virProxyPacket);
+               req->data.arg = 0;
+           } else {
+               req->len = sizeof(virProxyPacket) + ret * sizeof(int);
+               req->data.arg = ret;
+           }
+           break;
+       }
        case VIR_PROXY_NUM_DOMAIN:
+           if (req->len != sizeof(virProxyPacket))
+               goto comm_error;
+           req->data.arg = xenHypervisorNumOfDomains(conn);
+           break;
+       case VIR_PROXY_MAX_MEMORY:
+       case VIR_PROXY_DOMAIN_INFO:
+       case VIR_PROXY_NODE_INFO:
        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:
+           TODO;
            break;
        default:
            goto comm_error;
@@ -399,7 +442,7 @@ proxyProcessRequests(void) {
         */
         ret = poll(&pollInfos[0], nbClients + 1, 1000);
        if (ret == 0) { /* timeout */
-           if (nbClients == 0) {
+           if ((nbClients == 0) && (persist == 0)) {
                exit_timeout--;
                if (exit_timeout == 0) {
                    done = 1;
@@ -465,10 +508,8 @@ proxyMainLoop(void) {
        if (proxyListenUnixSocket(PROXY_SOCKET_PATH) < 0)
            break;
        proxyProcessRequests();
-       proxyCloseUnixSocket();
     }
     proxyCloseClientSockets();
-    proxyCloseUnixSocket();
 }
 
 /**
@@ -497,6 +538,8 @@ int main(int argc, char **argv) {
     for (i = 1; i < argc; i++) {
          if (!strcmp(argv[i], "-v")) {
             debug++;
+         } else if (!strcmp(argv[i], "-no-timeout")) {
+            persist = 1;
         } else {
             usage(argv[0]);
             exit(1);
@@ -508,7 +551,22 @@ int main(int argc, char **argv) {
        /* exit(1); */
     }
 
-    proxyInitXen();
-    proxyMainLoop();
+    /*
+     * setup a connection block
+     */
+    memset(conn, 0, sizeof(conninfos));
+    conn->magic = VIR_CONNECT_MAGIC;
+
+    /*
+     * very fist thing, use the socket as an exclusive lock, this then
+     * allow to do timed exits, avoiding constant CPU usage in case of
+     * failure.
+     */
+    if (proxyListenUnixSocket(PROXY_SOCKET_PATH) < 0)
+        exit(0);
+    if (proxyInitXen() == 0)
+       proxyMainLoop();
+    sleep(1);
+    proxyCloseUnixSocket();
     exit(0);
 }
index 1a5f2055f67f0696d37b23be750696d49362ab6f..3035dc44375833de4742f865bb29280ecc043baf 100644 (file)
@@ -56,6 +56,29 @@ struct _virProxyPacket {
 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
  */
index 78bb33df1af8094b8e581bbfc3893ef53eaea8e7..668dca52b468bc93ffbe669be38f91042329c687 100644 (file)
@@ -42,12 +42,12 @@ static int debug = 1;
 static void
 virProxyError(virConnectPtr conn, virErrorNumber error, const char *info)
 {
-    const char *errmsg;
-
     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);
@@ -71,8 +71,7 @@ virProxyFindServerPath(void)
 {
     static const char *serverPaths[] = {
 #ifdef STANDALONE
-        "./libvirt_proxy",
-       BUILDDIR "/proxy/libvirt_proxy",
+        "/usr/bin/libvirt_proxy_dbg",
 #endif
         BINDIR "/libvirt_proxy",
         NULL
@@ -320,11 +319,10 @@ xenProxyClose(virConnectPtr conn) {
 
 static int 
 xenProxyCommand(virConnectPtr conn, virProxyPacketPtr request,
-                virProxyPacketPtr *answer) {
+                virProxyFullPacketPtr answer) {
     static int serial = 0;
     int ret;
     virProxyPacketPtr res = NULL;
-    char packet[4096];
 
     if ((conn == NULL) || (conn->proxy < 0))
         return(-1);
@@ -364,8 +362,8 @@ retry:
            return(-1);
        }
     } else {
-        /* read in packet and duplicate if needed */
-        ret  = virProxyReadClientSocket(conn->proxy, &packet[0],
+        /* read in packet provided */
+        ret  = virProxyReadClientSocket(conn->proxy, (char *) answer,
                                        sizeof(virProxyPacket));
        if (ret < 0)
            return(-1);
@@ -376,9 +374,9 @@ retry:
            xenProxyClose(conn);
            return(-1);
        }
-       res = (virProxyPacketPtr) &packet[0];
+       res = (virProxyPacketPtr) answer;
        if ((res->len < sizeof(virProxyPacket)) ||
-           (res->len > sizeof(packet))) {
+           (res->len > sizeof(virProxyFullPacket))) {
            fprintf(stderr,
                "Communication error with proxy: got %d bytes packet\n",
                    res->len);
@@ -386,7 +384,8 @@ retry:
            return(-1);
        }
        if (res->len > sizeof(virProxyPacket)) {
-           ret  = virProxyReadClientSocket(conn->proxy, &packet[ret],
+           ret  = virProxyReadClientSocket(conn->proxy,
+                                           &(answer->extra.arg[0]),
                                            res->len - ret);
            if (ret != (int) (res->len - sizeof(virProxyPacket))) {
                fprintf(stderr,
@@ -412,8 +411,6 @@ retry:
        fprintf(stderr, "gor asynchronous packet number %d\n", res->serial);
         goto retry;
     }
-    if (answer != NULL)
-       *answer = res;
     return(0);
 }
 
@@ -431,9 +428,10 @@ xenProxyInit(virConnectPtr conn) {
     int ret;
     int fd;
         
-
-    if (conn == NULL)
-        return(-1);
+    if (!VIR_IS_CONNECT(conn)) {
+        virProxyError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
+        return (-1);
+    }
 
     if (conn->proxy <= 0) {
        fd = virProxyOpenClientSocket(PROXY_SOCKET_PATH);
@@ -517,14 +515,41 @@ xenProxyNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) {
  * @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)
 {
+    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);
 }
 
 /**
@@ -538,6 +563,23 @@ xenProxyListDomains(virConnectPtr conn, int *ids, int maxids)
 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);
 }
 
 /**
@@ -617,13 +659,26 @@ int main(int argc, char **argv) {
     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);
     }
index 69a61ec17d06d1482a6b8f31f035e0f26bc66be9..23c20b7eacfe836796c27eb614b8bf9e2e55549b 100644 (file)
@@ -38,7 +38,6 @@
 
 static const char * xenDaemonGetType(virConnectPtr conn);
 static int xenDaemonNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
-static int xenDaemonGetVersion(virConnectPtr conn, unsigned long *hvVer);
 static int xenDaemonListDomains(virConnectPtr conn, int *ids, int maxids);
 static int xenDaemonNumOfDomains(virConnectPtr conn);
 static virDomainPtr xenDaemonLookupByID(virConnectPtr conn, int id);
@@ -885,24 +884,24 @@ urlencode(const char *string)
  * Returns 0 in case of success, -1 in case of error.
  */
 int
-xenDaemonOpen_unix(virConnectPtr xend, const char *path)
+xenDaemonOpen_unix(virConnectPtr conn, const char *path)
 {
     struct sockaddr_un *addr;
 
-    if ((xend == NULL) || (path == NULL))
+    if ((conn == NULL) || (path == NULL))
         return (-1);
 
-    addr = &xend->addr_un;
+    addr = &conn->addr_un;
     addr->sun_family = AF_UNIX;
     memset(addr->sun_path, 0, sizeof(addr->sun_path));
     strncpy(addr->sun_path, path, sizeof(addr->sun_path));
 
-    xend->len = sizeof(addr->sun_family) + strlen(addr->sun_path);
-    if ((unsigned int) xend->len > sizeof(addr->sun_path))
-        xend->len = sizeof(addr->sun_path);
+    conn->len = sizeof(addr->sun_family) + strlen(addr->sun_path);
+    if ((unsigned int) conn->len > sizeof(addr->sun_path))
+        conn->len = sizeof(addr->sun_path);
 
-    xend->addr = (struct sockaddr *) addr;
-    xend->type = PF_UNIX;
+    conn->addr = (struct sockaddr *) addr;
+    conn->type = PF_UNIX;
 
     return (0);
 }
@@ -919,18 +918,18 @@ xenDaemonOpen_unix(virConnectPtr xend, const char *path)
  * Returns 0 in case of success, -1 in case of error.
  */
 int
-xenDaemonOpen_tcp(virConnectPtr xend, const char *host, int port)
+xenDaemonOpen_tcp(virConnectPtr conn, const char *host, int port)
 {
     struct in_addr ip;
     struct hostent *pent;
 
-    if ((xend == NULL) || (host == NULL) || (port <= 0))
+    if ((conn == NULL) || (host == NULL) || (port <= 0))
         return (-1);
 
     pent = gethostbyname(host);
     if (pent == NULL) {
         if (inet_aton(host, &ip) == 0) {
-            virXendError(xend, VIR_ERR_UNKNOWN_HOST, host);
+            virXendError(conn, VIR_ERR_UNKNOWN_HOST, host);
             errno = ESRCH;
             return (-1);
         }
@@ -938,13 +937,13 @@ xenDaemonOpen_tcp(virConnectPtr xend, const char *host, int port)
         memcpy(&ip, pent->h_addr_list[0], sizeof(ip));
     }
 
-    xend->len = sizeof(struct sockaddr_in);
-    xend->addr = (struct sockaddr *) &xend->addr_in;
-    xend->type = PF_INET;
+    conn->len = sizeof(struct sockaddr_in);
+    conn->addr = (struct sockaddr *) &conn->addr_in;
+    conn->type = PF_INET;
 
-    xend->addr_in.sin_family = AF_INET;
-    xend->addr_in.sin_port = htons(port);
-    memcpy(&xend->addr_in.sin_addr, &ip, sizeof(ip));
+    conn->addr_in.sin_family = AF_INET;
+    conn->addr_in.sin_port = htons(port);
+    memcpy(&conn->addr_in.sin_addr, &ip, sizeof(ip));
 
     return (0);
 }
@@ -2128,7 +2127,7 @@ xenDaemonGetType(virConnectPtr conn)
  *    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
+int
 xenDaemonGetVersion(virConnectPtr conn, unsigned long *hvVer)
 {
     static unsigned long version = 0;
index 692ba8c239f52714cff0426e72a77affb05bb41c..f7f2a9a2da70a7d64ef7804fce1df0ca7ed0ef9c 100644 (file)
@@ -600,6 +600,7 @@ int xenDaemonDomainLookupByName_ids(virConnectPtr xend,
 void xenDaemonRegister(void);
 int xenDaemonOpen(virConnectPtr conn, const char *name, int flags);
 int xenDaemonClose(virConnectPtr conn);
+int xenDaemonGetVersion(virConnectPtr conn, unsigned long *hvVer);
 int xenDaemonDomainSuspend(virDomainPtr domain);
 int xenDaemonDomainResume(virDomainPtr domain);
 int xenDaemonDomainShutdown(virDomainPtr domain);