progresses on the proxy implementation.
* src/xend_internal.c src/xend_internal.h: exported one routine
Daniel
+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
#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
static virConnect conninfos;
static virConnectPtr conn = &conninfos;
+static unsigned long xenVersion = 0;
+
/************************************************************************
* *
* Interfaces with the Xen hypervisor *
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);
}
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:
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;
*/
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;
if (proxyListenUnixSocket(PROXY_SOCKET_PATH) < 0)
break;
proxyProcessRequests();
- proxyCloseUnixSocket();
}
proxyCloseClientSockets();
- proxyCloseUnixSocket();
}
/**
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);
/* 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);
}
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
*/
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);
{
static const char *serverPaths[] = {
#ifdef STANDALONE
- "./libvirt_proxy",
- BUILDDIR "/proxy/libvirt_proxy",
+ "/usr/bin/libvirt_proxy_dbg",
#endif
BINDIR "/libvirt_proxy",
NULL
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);
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);
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);
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,
fprintf(stderr, "gor asynchronous packet number %d\n", res->serial);
goto retry;
}
- if (answer != NULL)
- *answer = res;
return(0);
}
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);
* @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);
}
/**
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);
}
/**
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);
}
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);
* 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);
}
* 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);
}
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);
}
* 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;
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);