From c386d9747b79f0421056e4679973f5bf37b7f98a Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Thu, 29 Jun 2006 14:44:37 +0000 Subject: [PATCH] * 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 Daniel --- ChangeLog | 6 +++ proxy/libvirt_proxy.c | 82 ++++++++++++++++++++++++++++++++------ proxy/proxy.h | 23 +++++++++++ proxy/proxy_client.c | 91 ++++++++++++++++++++++++++++++++++--------- src/xend_internal.c | 37 +++++++++--------- src/xend_internal.h | 1 + 6 files changed, 191 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index b7d0ecb9ef..8bf95614c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Thu Jun 29 14:53:01 EDT 2006 Daniel Veillard + + * 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 * configure.in Makefile.am proxy/Makefile.am proxy/libvirt_proxy.c diff --git a/proxy/libvirt_proxy.c b/proxy/libvirt_proxy.c index c1eaa9dfe9..0eea73ac60 100644 --- a/proxy/libvirt_proxy.c +++ b/proxy/libvirt_proxy.c @@ -20,9 +20,11 @@ #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); } diff --git a/proxy/proxy.h b/proxy/proxy.h index 1a5f2055f6..3035dc4437 100644 --- a/proxy/proxy.h +++ b/proxy/proxy.h @@ -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 */ diff --git a/proxy/proxy_client.c b/proxy/proxy_client.c index 78bb33df1a..668dca52b4 100644 --- a/proxy/proxy_client.c +++ b/proxy/proxy_client.c @@ -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); } diff --git a/src/xend_internal.c b/src/xend_internal.c index 69a61ec17d..23c20b7eac 100644 --- a/src/xend_internal.c +++ b/src/xend_internal.c @@ -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; diff --git a/src/xend_internal.h b/src/xend_internal.h index 692ba8c239..f7f2a9a2da 100644 --- a/src/xend_internal.h +++ b/src/xend_internal.h @@ -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); -- GitLab