aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--include/libvirt/virterror.h2
-rw-r--r--include/virterror.h2
-rwxr-xr-xpython/tests/create.py2
-rw-r--r--src/Makefile.am1
-rw-r--r--src/libvirt.c427
-rw-r--r--src/virterror.c3
-rw-r--r--src/xen_internal.c4
-rw-r--r--src/xen_internal.h5
-rw-r--r--src/xend_internal.c433
-rw-r--r--src/xend_internal.h15
-rw-r--r--src/xs_internal.c590
-rw-r--r--src/xs_internal.h37
13 files changed, 856 insertions, 672 deletions
diff --git a/ChangeLog b/ChangeLog
index 12605deb9..5f937cab3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Thu Mar 23 16:40:37 CET 2006 Daniel Veillard <veillard@redhat.com>
+
+ * src/xs_internal.c src/xs_internal.h include/virterror.h
+ src/virterror.c: created a new module related to Xen Store accesses
+ * src/libvirt.c src/xen_internal.[ch] src/xend_internal.[ch]:
+ nearly completed the separation of the code from the different modules
+
Wed Mar 22 14:43:16 CET 2006 Daniel Veillard <veillard@redhat.com>
* python/tests/create.py: add one more image path
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index eb28be082..1c7c22db4 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -40,6 +40,7 @@ typedef enum {
VIR_FROM_NONE = 0,
VIR_FROM_XEN, /* Error at Xen hypervisor layer */
VIR_FROM_XEND, /* Error at connection with xend daemon */
+ VIR_FROM_XENSTORE, /* Error at connection with xen store */
VIR_FROM_SEXPR, /* Error in the S-Epression code */
VIR_FROM_XML, /* Error in the XML code */
VIR_FROM_DOM, /* Error when operating on a domain */
@@ -98,6 +99,7 @@ typedef enum {
VIR_ERR_NO_NAME, /* missing domain name informations */
VIR_ERR_NO_OS, /* missing domain OS informations */
VIR_ERR_NO_DEVICE, /* missing domain devices informations */
+ VIR_ERR_NO_XENSTORE,/* could not open Xen Store control */
} virErrorNumber;
/**
diff --git a/include/virterror.h b/include/virterror.h
index eb28be082..1c7c22db4 100644
--- a/include/virterror.h
+++ b/include/virterror.h
@@ -40,6 +40,7 @@ typedef enum {
VIR_FROM_NONE = 0,
VIR_FROM_XEN, /* Error at Xen hypervisor layer */
VIR_FROM_XEND, /* Error at connection with xend daemon */
+ VIR_FROM_XENSTORE, /* Error at connection with xen store */
VIR_FROM_SEXPR, /* Error in the S-Epression code */
VIR_FROM_XML, /* Error in the XML code */
VIR_FROM_DOM, /* Error when operating on a domain */
@@ -98,6 +99,7 @@ typedef enum {
VIR_ERR_NO_NAME, /* missing domain name informations */
VIR_ERR_NO_OS, /* missing domain OS informations */
VIR_ERR_NO_DEVICE, /* missing domain devices informations */
+ VIR_ERR_NO_XENSTORE,/* could not open Xen Store control */
} virErrorNumber;
/**
diff --git a/python/tests/create.py b/python/tests/create.py
index 0c62edb5a..c897741ed 100755
--- a/python/tests/create.py
+++ b/python/tests/create.py
@@ -84,7 +84,7 @@ if dom == None:
print 'Failed to create a test domain'
sys.exit(1)
-# print dom0
+print dom
print "Domain: id %d running %s" % (dom.ID(), dom.OSType())
diff --git a/src/Makefile.am b/src/Makefile.am
index a3812ad12..39795110b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -16,6 +16,7 @@ libvirt_la_SOURCES = \
hash.c hash.h \
xml.c xml.h \
xen_internal.c xen_internal.h \
+ xs_internal.c xs_internal.h \
xend_internal.c xend_internal.h \
sexpr.c sexpr.h \
virterror.c
diff --git a/src/libvirt.c b/src/libvirt.c
index e954357bc..5364e9304 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -17,11 +17,14 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+
#include <xs.h>
+
#include "internal.h"
#include "driver.h"
#include "xen_internal.h"
#include "xend_internal.h"
+#include "xs_internal.h"
#include "hash.h"
#include "xml.h"
@@ -138,8 +141,6 @@ virConnectPtr
virConnectOpen(const char *name)
{
virConnectPtr ret = NULL;
- int res;
- struct xs_handle *xshandle = NULL;
/* we can only talk to the local Xen supervisor ATM */
if (name != NULL) {
@@ -155,31 +156,30 @@ virConnectOpen(const char *name)
memset(ret, 0, sizeof(virConnect));
ret->magic = VIR_CONNECT_MAGIC;
- res = xenHypervisorOpen(ret, name, 0);
- if (res < 0) {
+ /*
+ * open connections to the hypervisor, store and daemon
+ */
+ if (xenHypervisorOpen(ret, name, 0) < 0)
goto failed;
- }
- xshandle = xs_daemon_open();
- if (xshandle == NULL) {
- virLibConnError(NULL, VIR_ERR_NO_CONNECT, "XenStore");
+ if (xenStoreOpen(ret, name, 0) < 0)
goto failed;
- }
-
- ret->xshandle = xshandle;
if (xenDaemonOpen(ret, name, 0) < 0)
goto failed;
+
ret->domains = virHashCreate(20);
- ret->flags = 0;
if (ret->domains == NULL)
goto failed;
+ ret->flags = 0;
return (ret);
- failed:
- xenHypervisorClose(ret);
- if (xshandle != NULL)
- xs_daemon_close(xshandle);
- if (ret != NULL)
+
+failed:
+ if (ret != NULL) {
+ xenHypervisorClose(ret);
+ xenStoreClose(ret);
+ xenDaemonClose(ret);
free(ret);
+ }
return (NULL);
}
@@ -199,7 +199,6 @@ virConnectOpenReadOnly(const char *name)
int method = 0;
int res;
virConnectPtr ret = NULL;
- struct xs_handle *xshandle = NULL;
/* we can only talk to the local Xen supervisor ATM */
if (name != NULL) {
@@ -219,65 +218,37 @@ virConnectOpenReadOnly(const char *name)
if (res >= 0)
method++;
- xshandle = xs_daemon_open_readonly();
- if (xshandle != NULL)
+ res = xenStoreOpen(ret, name, VIR_DRV_OPEN_QUIET | VIR_DRV_OPEN_RO);
+ if (res >= 0)
method++;
- ret->xshandle = xshandle;
if (xenDaemonOpen(ret, name, VIR_DRV_OPEN_QUIET | VIR_DRV_OPEN_RO) == 0)
method++;
- ret->domains = virHashCreate(20);
- if (ret->domains == NULL)
- goto failed;
- ret->flags = VIR_CONNECT_RO;
+
if (method == 0) {
virLibConnError(NULL, VIR_ERR_NO_CONNECT,
"could not connect to Xen Daemon nor Xen Store");
goto failed;
}
+ ret->domains = virHashCreate(20);
+ if (ret->domains == NULL)
+ goto failed;
+ ret->flags = VIR_CONNECT_RO;
+
return (ret);
- failed:
- xenHypervisorClose(ret);
- if (xshandle != NULL)
- xs_daemon_close(xshandle);
+
+failed:
if (ret != NULL) {
- if (ret->domains != NULL)
- virHashFree(ret->domains, NULL);
+ xenHypervisorClose(ret);
+ xenStoreClose(ret);
+ xenDaemonClose(ret);
free(ret);
}
return (NULL);
}
/**
- * virConnectCheckStoreID:
- * @conn: pointer to the hypervisor connection
- * @id: the id number as returned from Xenstore
- *
- * the xenstore sometimes list non-running domains, double check
- * from the hypervisor if we have direct access
- *
- * Returns -1 if the check failed, 0 if successful or not possible to check
- */
-static int
-virConnectCheckStoreID(virConnectPtr conn, int id)
-{
- if (conn->handle >= 0) {
- TODO
- /*
- dom0_getdomaininfo_t dominfo;
- int tmp;
-
- dominfo.domain = id;
- tmp = xenHypervisorGetDomainInfo(conn->handle, id, &dominfo);
- if (tmp < 0)
- return (-1);
- */
- }
- return (0);
-}
-
-/**
* virDomainFreeName:
* @domain: a domain object
*
@@ -309,12 +280,11 @@ virConnectClose(virConnectPtr conn)
if (!VIR_IS_CONNECT(conn))
return (-1);
virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
- conn->magic = -1;
- if (conn->xshandle != NULL)
- xs_daemon_close(conn->xshandle);
- conn->xshandle = NULL;
+ conn->domains = NULL;
+ xenDaemonClose(conn);
+ xenStoreClose(conn);
xenHypervisorClose(conn);
- conn->handle = -1;
+ conn->magic = -1;
free(conn);
return (0);
}
@@ -390,9 +360,9 @@ int
virConnectListDomains(virConnectPtr conn, int *ids, int maxids)
{
int ret = -1;
- unsigned int num, i;
+ unsigned int i;
long id;
- char **idlist = NULL, *endptr;
+ char **idlist = NULL;
if (!VIR_IS_CONNECT(conn)) {
virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
@@ -404,6 +374,9 @@ virConnectListDomains(virConnectPtr conn, int *ids, int maxids)
return (-1);
}
+ /*
+ * try first though the Xen Daemon
+ */
idlist = xenDaemonListDomains(conn);
if (idlist != NULL) {
for (ret = 0, i = 0; (idlist[i] != NULL) && (ret < maxids); i++) {
@@ -411,29 +384,14 @@ virConnectListDomains(virConnectPtr conn, int *ids, int maxids)
if (id >= 0)
ids[ret++] = (int) id;
}
- goto done;
+ free(idlist);
+ return(ret);
}
- if (conn->xshandle != NULL) {
- idlist = xs_directory(conn->xshandle, 0, "/local/domain", &num);
- if (idlist == NULL)
- goto done;
-
- for (ret = 0, i = 0; (i < num) && (ret < maxids); i++) {
- id = strtol(idlist[i], &endptr, 10);
- if ((endptr == idlist[i]) || (*endptr != 0)) {
- ret = -1;
- goto done;
- }
- if (virConnectCheckStoreID(conn, (int) id) < 0)
- continue;
- ids[ret++] = (int) id;
- }
- }
-
- done:
- if (idlist != NULL)
- free(idlist);
+ /*
+ * Then fallback to the XenStore
+ */
+ ret = xenStoreListDomains(conn, ids, maxids);
return (ret);
}
@@ -449,7 +407,6 @@ int
virConnectNumOfDomains(virConnectPtr conn)
{
int ret = -1;
- unsigned int num;
char **idlist = NULL;
if (!VIR_IS_CONNECT(conn)) {
@@ -457,6 +414,7 @@ virConnectNumOfDomains(virConnectPtr conn)
return (-1);
}
+ /* TODO: there must be a way to do that with an hypervisor call too ! */
/*
* try first with Xend interface
*/
@@ -469,15 +427,11 @@ virConnectNumOfDomains(virConnectPtr conn)
tmp++;
ret++;
}
-
- } else if (conn->xshandle != NULL) {
- idlist = xs_directory(conn->xshandle, 0, "/local/domain", &num);
- if (idlist) {
- free(idlist);
- ret = num;
- }
+ free(idlist);
+ return(ret);
}
- return (ret);
+ /* Then Xen Store */
+ return(xenStoreNumOfDomains(conn));
}
/**
@@ -556,146 +510,6 @@ virDomainCreateLinux(virConnectPtr conn,
return (NULL);
}
-/**
- * virConnectDoStoreList:
- * @conn: pointer to the hypervisor connection
- * @path: the absolute path of the directory in the store to list
- * @nb: OUT pointer to the number of items found
- *
- * Internal API querying the Xenstore for a list
- *
- * Returns a string which must be freed by the caller or NULL in case of error
- */
-static char **
-virConnectDoStoreList(virConnectPtr conn, const char *path,
- unsigned int *nb)
-{
- if ((conn == NULL) || (conn->xshandle == NULL) || (path == NULL) ||
- (nb == NULL))
- return (NULL);
-
- return xs_directory(conn->xshandle, 0, path, nb);
-}
-
-/**
- * virDomainDoStoreQuery:
- * @domain: a domain object
- * @path: the relative path of the data in the store to retrieve
- *
- * Internal API querying the Xenstore for a string value.
- *
- * Returns a string which must be freed by the caller or NULL in case of error
- */
-static char *
-virDomainDoStoreQuery(virDomainPtr domain, const char *path)
-{
- char s[256];
- unsigned int len = 0;
-
- if (!VIR_IS_CONNECTED_DOMAIN(domain))
- return (NULL);
- if (domain->conn->xshandle == NULL)
- return (NULL);
-
- snprintf(s, 255, "/local/domain/%d/%s", domain->handle, path);
- s[255] = 0;
-
- return xs_read(domain->conn->xshandle, 0, &s[0], &len);
-}
-
-
-/**
- * virDomainDoStoreWrite:
- * @domain: a domain object
- * @path: the relative path of the data in the store to retrieve
- *
- * Internal API setting up a string value in the Xenstore
- * Requires write access to the XenStore
- *
- * Returns 0 in case of success, -1 in case of failure
- */
-static int
-virDomainDoStoreWrite(virDomainPtr domain, const char *path,
- const char *value)
-{
- char s[256];
-
- int ret = -1;
-
- if (!VIR_IS_CONNECTED_DOMAIN(domain))
- return (-1);
- if (domain->conn->xshandle == NULL)
- return (-1);
- if (domain->conn->flags & VIR_CONNECT_RO)
- return (-1);
-
- snprintf(s, 255, "/local/domain/%d/%s", domain->handle, path);
- s[255] = 0;
-
- if (xs_write(domain->conn->xshandle, 0, &s[0], value, strlen(value)))
- ret = 0;
-
- return (ret);
-}
-
-/**
- * virDomainGetVM:
- * @domain: a domain object
- *
- * Internal API extracting a xenstore vm path.
- *
- * Returns the new string or NULL in case of error
- */
-char *
-virDomainGetVM(virDomainPtr domain)
-{
- char *vm;
- char query[200];
- unsigned int len;
-
- if (!VIR_IS_CONNECTED_DOMAIN(domain))
- return (NULL);
- if (domain->conn->xshandle == NULL)
- return (NULL);
-
- snprintf(query, 199, "/local/domain/%d/vm", virDomainGetID(domain));
- query[199] = 0;
-
- vm = xs_read(domain->conn->xshandle, 0, &query[0], &len);
-
- return (vm);
-}
-
-/**
- * virDomainGetVMInfo:
- * @domain: a domain object
- * @vm: the xenstore vm path
- * @name: the value's path
- *
- * Internal API extracting one information the device used
- * by the domain from xensttore
- *
- * Returns the new string or NULL in case of error
- */
-char *
-virDomainGetVMInfo(virDomainPtr domain, const char *vm, const char *name)
-{
- char s[256];
- char *ret = NULL;
- unsigned int len = 0;
-
- if (!VIR_IS_CONNECTED_DOMAIN(domain))
- return (NULL);
- if (domain->conn->xshandle == NULL)
- return (NULL);
-
- snprintf(s, 255, "%s/%s", vm, name);
- s[255] = 0;
-
- ret = xs_read(domain->conn->xshandle, 0, &s[0], &len);
-
- return (ret);
-}
/**
* virDomainLookupByID:
@@ -755,12 +569,8 @@ virDomainLookupByID(virConnectPtr conn, int id)
ret->conn = conn;
ret->handle = id;
ret->path = path;
- if (name == NULL) {
- ret->name = virDomainDoStoreQuery(ret, "name");
- } else {
- ret->name = name;
- memcpy(&ret->uuid[0], uuid, 16);
- }
+ ret->name = name;
+ memcpy(&ret->uuid[0], uuid, 16);
if (ret->name == NULL) {
goto error;
}
@@ -855,13 +665,6 @@ virDomainPtr
virDomainLookupByName(virConnectPtr conn, const char *name)
{
virDomainPtr ret = NULL;
- unsigned int num, i, len;
- long id = -1;
- char **idlist = NULL, *endptr;
- char prop[200], *tmp, *path = NULL;
- unsigned char *uuid = NULL;
- int found = 0;
- struct xend_domain *xenddomain = NULL;
if (!VIR_IS_CONNECT(conn)) {
virLibConnError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
@@ -873,62 +676,17 @@ virDomainLookupByName(virConnectPtr conn, const char *name)
}
/* try first though Xend */
- xenddomain = xenDaemonDomainLookupByName(conn, name);
- if (xenddomain != NULL) {
- id = xenddomain->live->id;
- uuid = xenddomain->uuid;
- found = 1;
- goto do_found;
+ ret = xenDaemonDomainLookupByName(conn, name);
+ if (ret != NULL) {
+ return(ret);
}
/* then though the XenStore */
- if (conn->xshandle != NULL) {
- idlist = xs_directory(conn->xshandle, 0, "/local/domain", &num);
- if (idlist == NULL)
- goto done;
-
- for (i = 0; i < num; i++) {
- id = strtol(idlist[i], &endptr, 10);
- if ((endptr == idlist[i]) || (*endptr != 0)) {
- goto done;
- }
- if (virConnectCheckStoreID(conn, (int) id) < 0)
- continue;
- snprintf(prop, 199, "/local/domain/%s/name", idlist[i]);
- prop[199] = 0;
- tmp = xs_read(conn->xshandle, 0, prop, &len);
- if (tmp != NULL) {
- found = !strcmp(name, tmp);
- free(tmp);
- if (found)
- break;
- }
- }
- path = xs_get_domain_path(conn->xshandle, (unsigned int) id);
- }
-
- do_found:
-
- if (found) {
- ret = (virDomainPtr) malloc(sizeof(virDomain));
- if (ret == NULL)
- goto done;
- memset(ret, 0, sizeof(virDomain));
- ret->magic = VIR_DOMAIN_MAGIC;
- ret->conn = conn;
- ret->handle = id;
- ret->path = path;
- if (uuid != NULL)
- memcpy(ret->uuid, uuid, 16);
- ret->name = strdup(name);
+ ret = xenStoreDomainLookupByName(conn, name);
+ if (ret != NULL) {
+ return(ret);
}
- done:
- if (xenddomain != NULL)
- free(xenddomain);
- if (idlist != NULL)
- free(idlist);
-
return (ret);
}
@@ -1182,14 +940,16 @@ virDomainShutdown(virDomainPtr domain)
* try first with the xend daemon
*/
ret = xenDaemonDomainShutdown(domain);
- if (ret == 0)
+ if (ret == 0) {
+ domain->flags |= DOMAIN_IS_SHUTDOWN;
return (0);
+ }
/*
* this is very hackish, the domU kernel probes for a special
* node in the xenstore and launch the shutdown command if found.
*/
- ret = virDomainDoStoreWrite(domain, "control/shutdown", "halt");
+ ret = xenDaemonDomainShutdown(domain);
if (ret == 0) {
domain->flags |= DOMAIN_IS_SHUTDOWN;
}
@@ -1322,22 +1082,21 @@ virDomainGetMaxMemory(virDomainPtr domain)
return (0);
}
- if (domain->conn->flags & VIR_CONNECT_RO) {
- char *tmp;
-
- tmp = virDomainDoStoreQuery(domain, "memory/target");
- if (tmp != NULL) {
- ret = (unsigned long) atol(tmp);
- free(tmp);
- }
- } else {
+ /*
+ * try first with the hypervisor if available
+ */
+ if (!(domain->conn->flags & VIR_CONNECT_RO)) {
virDomainInfo dominfo;
int tmp;
tmp = xenHypervisorGetDomainInfo(domain, &dominfo);
if (tmp >= 0)
- ret = dominfo.maxMem;
+ return(dominfo.maxMem);
}
+ ret = xenStoreDomainGetMaxMemory(domain);
+ if (ret > 0)
+ return(ret);
+ ret = xenDaemonDomainGetMaxMemory(domain);
return (ret);
}
@@ -1415,10 +1174,6 @@ int
virDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
{
int ret;
- char *tmp, **tmp2;
- unsigned int nb_vcpus;
- char request[200];
-
if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
virLibDomainError(domain, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
@@ -1447,44 +1202,12 @@ virDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
return (0);
/*
- * last fallback, try to get the inforamtions from the Xen store
+ * last fallback, try to get the informations from the Xen store
*/
+ if (xenStoreGetDomainInfo(domain, info) == 0)
+ return (0);
- tmp = virDomainDoStoreQuery(domain, "running");
- if (tmp != NULL) {
- if (tmp[0] == '1')
- info->state = VIR_DOMAIN_RUNNING;
- free(tmp);
- } else {
- info->state = VIR_DOMAIN_NONE;
- }
- tmp = virDomainDoStoreQuery(domain, "memory/target");
- if (tmp != NULL) {
- info->memory = atol(tmp);
- info->maxMem = atol(tmp);
- free(tmp);
- } else {
- info->memory = 0;
- info->maxMem = 0;
- }
-#if 0
- /* doesn't seems to work */
- tmp = virDomainDoStoreQuery(domain, "cpu_time");
- if (tmp != NULL) {
- info->cpuTime = atol(tmp);
- free(tmp);
- } else {
- info->cpuTime = 0;
- }
-#endif
- snprintf(request, 199, "/local/domain/%d/cpu", domain->handle);
- request[199] = 0;
- tmp2 = virConnectDoStoreList(domain->conn, request, &nb_vcpus);
- if (tmp2 != NULL) {
- info->nrVirtCpu = nb_vcpus;
- free(tmp2);
- }
- return (0);
+ return (-1);
}
/**
diff --git a/src/virterror.c b/src/virterror.c
index 552cb7964..9fc08e9e1 100644
--- a/src/virterror.c
+++ b/src/virterror.c
@@ -256,6 +256,9 @@ virDefaultErrorFunc(virErrorPtr err)
case VIR_FROM_XEND:
dom = "Xen Daemon ";
break;
+ case VIR_FROM_XENSTORE:
+ dom = "Xen Store ";
+ break;
case VIR_FROM_DOM:
dom = "Domain ";
break;
diff --git a/src/xen_internal.c b/src/xen_internal.c
index e3fc858e1..565d2c753 100644
--- a/src/xen_internal.c
+++ b/src/xen_internal.c
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <string.h>
+/* required for uint8_t, uint32_t, etc ... */
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -18,6 +19,9 @@
#include <sys/mman.h>
#include <sys/ioctl.h>
+#include <stdint.h>
+
+/* required for dom0_getdomaininfo_t */
#include <xen/dom0_ops.h>
#include <xen/version.h>
#include <xen/xen.h>
diff --git a/src/xen_internal.h b/src/xen_internal.h
index 62c184097..fa06393f1 100644
--- a/src/xen_internal.h
+++ b/src/xen_internal.h
@@ -11,10 +11,7 @@
#ifndef __VIR_XEN_INTERNAL_H__
#define __VIR_XEN_INTERNAL_H__
-/* required for uint8_t, uint32_t, etc ... */
-#include <stdint.h>
-
-/* required for dom0_getdomaininfo_t */
+/* required for dom0_getdomaininfo_t and DOM0_INTERFACE_VERSION */
#include <xen/dom0_ops.h>
#ifdef __cplusplus
diff --git a/src/xend_internal.c b/src/xend_internal.c
index 5ef6d6e92..e3ddbc0ac 100644
--- a/src/xend_internal.c
+++ b/src/xend_internal.c
@@ -666,35 +666,6 @@ sexpr_u64(struct sexpr *sexpr, const char *name)
return 0;
}
-/**
- * sexpr_u64:
- * @sexpr: an S-Expression
- * @name: the name for the value
- *
- * convenience function to lookup a value describing the default process when
- * a domain stops
- *
- * Returns the value found or 0 if not found (but may not be an error)
- */
-static virDomainRestart
-sexpr_poweroff(struct sexpr *sexpr, const char *name)
-{
- const char *value = sexpr_node(sexpr, name);
-
- if (value) {
- if (strcmp(value, "poweroff") == 0) {
- return VIR_DOMAIN_DESTROY;
- } else if (strcmp(value, "restart") == 0) {
- return VIR_DOMAIN_RESTART;
- } else if (strcmp(value, "preserve") == 0) {
- return VIR_DOMAIN_PRESERVE;
- } else if (strcmp(value, "rename-restart") == 0) {
- return VIR_DOMAIN_RENAME_RESTART;
- }
- }
- return XEND_DEFAULT;
-}
-
static int
sexpr_strlen(struct sexpr *sexpr, const char *path)
{
@@ -716,36 +687,6 @@ sexpr_strcpy(char **ptr, struct sexpr *node, const char *path)
return ret;
}
-/**
- * sexpr_mode:
- * @sexpr: an S-Expression
- * @name: the name for the value
- *
- * convenience function to lookup a value describing a virtual block device
- * mode from the S-Expression
- *
- * Returns the value found or 0 if not found (but may not be an error)
- */
-static virDeviceMode
-sexpr_mode(struct sexpr *node, const char *path)
-{
- const char *mode = sexpr_node(node, path);
- virDeviceMode ret;
-
- if (!mode) {
- ret = VIR_DEVICE_DEFAULT;
- } else if (strcmp(mode, "r") == 0) {
- ret = VIR_DEVICE_RO;
- } else if (strcmp(mode, "w") == 0) {
- ret = VIR_DEVICE_RW;
- } else if (strcmp(mode, "w!") == 0) {
- ret = VIR_DEVICE_RW_FORCE;
- } else {
- ret = VIR_DEVICE_DEFAULT;
- }
-
- return ret;
-}
/**
* sexpr_node_system:
@@ -772,31 +713,6 @@ sexpr_node_system(struct sexpr *node, const char *path)
}
/**
- * sexpr_node_system:
- * @mac: return value for the MAC address
- * @sexpr: an S-Expression
- * @name: the name for the value
- *
- * convenience function to lookup a MAC address (assumed ethernet and hence
- * six bytes in length) from the S-Expression
- * The value is returned in @mac
- */
-static void
-sexpr_mac(uint8_t * mac, struct sexpr *node, const char *path)
-{
- const char *r = sexpr_node(node, path);
- int mmac[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
- if (r) {
- int i;
-
- sscanf(r, "%02x:%02x:%02x:%02x:%02x:%02x",
- mmac + 0, mmac + 1, mmac + 2, mmac + 3, mmac + 4, mmac + 5);
- for (i = 0; i < 6; i++)
- mac[i] = mmac[i] & 0xFF;
- }
-}
-
-/**
* sexpr_uuid:
* @ptr: where to store the UUID, incremented
* @sexpr: an S-Expression
@@ -1171,211 +1087,6 @@ xend_set_memory(virConnectPtr xend, const char *name, uint64_t value)
/**
- * sexpr_to_xend_domain_size:
- * @sexpr: the S-Expression
- * @n_vbds: the number of virtual block devices used (OUT)
- * @n_vifs: the number of network interface devices used (OUT)
- *
- * Helper function to compute the size in byte needed for the strings
- * of a domain.
- *
- * Returns the number of bytes and the output parameters
- */
-static size_t
-sexpr_to_xend_domain_size(struct sexpr *root, int *n_vbds, int *n_vifs)
-{
- size_t size = 0;
- struct sexpr *_for_i, *node;
-
- size += sexpr_strlen(root, "domain/name");
- size += sexpr_strlen(root, "domain/image/linux/kernel");
- size += sexpr_strlen(root, "domain/image/linux/ramdisk");
- size += sexpr_strlen(root, "domain/image/linux/root");
- size += sexpr_strlen(root, "domain/image/linux/args");
- if (sexpr_node(root, "domain/uuid"))
- size += 16;
-
- for (_for_i = root, node = root->car; _for_i->kind == SEXPR_CONS;
- _for_i = _for_i->cdr, node = _for_i->car) {
- if (sexpr_lookup(node, "device/vbd")) {
- size += sexpr_strlen(node, "device/vbd/dev");
- size += sexpr_strlen(node, "device/vbd/uname");
- (*n_vbds)++;
- }
- }
-
- for (_for_i = root, node = root->car; _for_i->kind == SEXPR_CONS;
- _for_i = _for_i->cdr, node = _for_i->car) {
- if (sexpr_lookup(node, "device/vif")) {
- size += sexpr_strlen(node, "device/vif/bridge");
- size += sexpr_strlen(node, "device/vif/ip");
- size += sexpr_strlen(node, "device/vif/script");
- size += sexpr_strlen(node, "device/vif/vifname");
- (*n_vifs)++;
- }
- }
-
- size += (*n_vbds) * sizeof(struct xend_device_vbd *);
- size += (*n_vbds) * sizeof(struct xend_device_vbd);
-
- size += (*n_vifs) * sizeof(struct xend_device_vif *);
- size += (*n_vifs) * sizeof(struct xend_device_vif);
-
- size += sizeof(struct xend_domain_live);
-
- size += sizeof(struct xend_domain);
-
- return size;
-}
-
-/**
- * sexpr_to_xend_domain:
- * @root: an S-Expression describing a domain
- *
- * Internal routine creating a domain node based on the S-Expression
- * provided by the Xen Daemon
- *
- * Returns a new structure or NULL in case of error.
- */
-static struct xend_domain *
-sexpr_to_xend_domain(struct sexpr *root)
-{
- struct xend_domain *dom = NULL;
- char *ptr;
- int i;
- int n_vbds = 0;
- int n_vifs = 0;
- struct sexpr *_for_i, *node;
-
- ptr = malloc(sexpr_to_xend_domain_size(root, &n_vbds, &n_vifs));
- if (ptr == NULL)
- goto error;
-
- dom = (struct xend_domain *) ptr;
- ptr += sizeof(struct xend_domain);
-
- dom->vbds = (struct xend_device_vbd *) ptr;
- dom->n_vbds = n_vbds;
- ptr += n_vbds * sizeof(struct xend_device_vbd);
-
- dom->vifs = (struct xend_device_vif *) ptr;
- dom->n_vifs = n_vifs;
- ptr += n_vifs * sizeof(struct xend_device_vif);
-
- dom->live = (struct xend_domain_live *) ptr;
- ptr += sizeof(struct xend_domain_live);
-
- dom->name = sexpr_strcpy(&ptr, root, "domain/name");
- dom->uuid = sexpr_uuid(&ptr, root, "domain/uuid");
- dom->image.kernel =
- sexpr_strcpy(&ptr, root, "domain/image/linux/kernel");
- dom->image.ramdisk =
- sexpr_strcpy(&ptr, root, "domain/image/linux/ramdisk");
- dom->image.root = sexpr_strcpy(&ptr, root, "domain/image/linux/root");
- dom->image.extra = sexpr_strcpy(&ptr, root, "domain/image/linux/args");
- dom->memory = sexpr_u64(root, "domain/memory") << 20;
- dom->max_memory = sexpr_u64(root, "domain/maxmem") << 20;
- dom->ssidref = sexpr_int(root, "domain/ssidref");
- dom->on_poweroff = sexpr_poweroff(root, "domain/on_poweroff");
- dom->on_reboot = sexpr_poweroff(root, "domain/on_reboot");
- dom->on_crash = sexpr_poweroff(root, "domain/on_crash");
- dom->vcpus = sexpr_int(root, "domain/vcpus");
-
- {
- const char *flags = sexpr_node(root, "domain/state");
-
- if (flags) {
- dom->live->running = strchr(flags, 'r');
- dom->live->crashed = strchr(flags, 'c');
- dom->live->blocked = strchr(flags, 'b');
- dom->live->dying = strchr(flags, 'd');
- dom->live->paused = strchr(flags, 'p');
- dom->live->poweroff = false;
- dom->live->reboot = false;
- dom->live->suspend = false;
- if (strchr(flags, 's') &&
- (flags = sexpr_node(root, "domain/shutdown_reason"))) {
- if (strcmp(flags, "poweroff") == 0) {
- dom->live->poweroff = true;
- } else if (strcmp(flags, "reboot") == 0) {
- dom->live->reboot = true;
- } else if (strcmp(flags, "suspend") == 0) {
- dom->live->suspend = true;
- }
- }
- }
- }
-
- dom->live->id = sexpr_int(root, "domain/domid");
- dom->live->cpu_time = sexpr_float(root, "domain/cpu_time");
- dom->live->up_time = sexpr_float(root, "domain/up_time");
- dom->live->start_time = sexpr_float(root, "domain/start_time");
- dom->live->online_vcpus = sexpr_int(root, "domain/online_vcpus");
- dom->live->vcpu_avail = sexpr_int(root, "domain/vcpu_avail");
-
- i = 0;
- for (_for_i = root, node = root->car; _for_i->kind == SEXPR_CONS;
- _for_i = _for_i->cdr, node = _for_i->car) {
- if (sexpr_lookup(node, "device/vbd")) {
- dom->vbds[i].dev = sexpr_strcpy(&ptr, node, "device/vbd/dev");
- dom->vbds[i].uname =
- sexpr_strcpy(&ptr, node, "device/vbd/uname");
- dom->vbds[i].backend = sexpr_int(node, "device/vbd/backend");
- dom->vbds[i].mode = sexpr_mode(node, "device/vbd/mode");
- i++;
- }
- }
-
- i = 0;
- for (_for_i = root, node = root->car; _for_i->kind == SEXPR_CONS;
- _for_i = _for_i->cdr, node = _for_i->car) {
- if (sexpr_lookup(node, "device/vif")) {
- dom->vifs[i].backend = sexpr_int(node, "device/vif/backend");
- dom->vifs[i].bridge =
- sexpr_strcpy(&ptr, node, "device/vif/bridge");
- dom->vifs[i].ip = sexpr_strcpy(&ptr, node, "device/vif/ip");
- sexpr_mac(dom->vifs[i].mac, node, "device/vif/mac");
- dom->vifs[i].script =
- sexpr_strcpy(&ptr, node, "device/vif/script");
- dom->vifs[i].vifname =
- sexpr_strcpy(&ptr, node, "device/vif/vifname");
- i++;
- }
- }
-
- error:
- return dom;
-}
-
-/**
- * xenDaemonDomainLookupByName:
- * @xend: A xend instance
- * @name: The name of the domain
- *
- * This method looks up information about a domain and returns
- * it in the form of a struct xend_domain. This should be
- * free()'d when no longer needed.
- *
- * Returns domain info on success; NULL (with errno) on error
- */
-struct xend_domain *
-xenDaemonDomainLookupByName(virConnectPtr xend, const char *domname)
-{
- struct sexpr *root;
- struct xend_domain *dom = NULL;
-
- root = sexpr_get(xend, "/xend/domain/%s?detail=1", domname);
- if (root == NULL)
- goto error;
-
- dom = sexpr_to_xend_domain(root);
-
- error:
- sexpr_free(root);
- return dom;
-}
-
-/**
* xenDaemonDomainLookupByName_ids:
* @xend: A xend instance
* @domname: The name of the domain
@@ -1587,6 +1298,17 @@ xend_log(virConnectPtr xend, char *buffer, size_t n_buffer)
return http2unix(xend_get(xend, "/xend/node/log", buffer, n_buffer));
}
+/*****************************************************************
+ ******
+ ******
+ ******
+ ******
+ Needed helper code
+ ******
+ ******
+ ******
+ ******
+ *****************************************************************/
/**
* xend_parse_sexp_desc:
* @root: the root of the parsed S-Expression
@@ -1742,17 +1464,6 @@ xend_parse_sexp_desc(struct sexpr *root)
return (NULL);
}
-/*****************************************************************
- ******
- ******
- ******
- ******
- Needed helper code
- ******
- ******
- ******
- ******
- *****************************************************************/
/**
* sexpr_to_xend_domain_info:
* @root: an S-Expression describing a domain
@@ -1797,6 +1508,56 @@ sexpr_to_xend_domain_info(struct sexpr *root, virDomainInfoPtr info)
return (0);
}
+/**
+ * sexpr_to_domain:
+ * @conn: an existing virtual connection block
+ * @root: an S-Expression describing a domain
+ *
+ * Internal routine returning the associated virDomainPtr for this domain
+ *
+ * Returns the domain pointer or NULL in case of error.
+ */
+static virDomainPtr
+sexpr_to_domain(virConnectPtr conn, struct sexpr *root)
+{
+ virDomainPtr ret;
+ char *dst_uuid = NULL;
+ const char *name;
+
+ if ((conn == NULL) || (root == NULL))
+ return(NULL);
+
+ ret = (virDomainPtr) malloc(sizeof(virDomain));
+ if (ret == NULL) {
+ virXendError(conn, VIR_ERR_NO_MEMORY, "Allocating domain");
+ return(NULL);
+ }
+ memset(ret, 0, sizeof(virDomain));
+ ret->magic = VIR_DOMAIN_MAGIC;
+ ret->conn = conn;
+ ret->handle = sexpr_int(root, "domain/domid");
+ if (ret->handle < 0)
+ goto error;
+ dst_uuid = (char *) &(ret->uuid[0]);
+ if (sexpr_uuid(&dst_uuid, root, "domain/uuid") == NULL)
+ goto error;
+ name = sexpr_node(root, "domain/name");
+ if (name == NULL)
+ goto error;
+ ret->name = strdup(name);
+ if (ret->name == NULL)
+ goto error;
+
+ return (ret);
+error:
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ "failed to parse Xend domain informations");
+ if (ret->name != NULL)
+ free(ret->name );
+ free(ret);
+ return(NULL);
+}
+
/*****************************************************************
******
@@ -1994,6 +1755,37 @@ xenDaemonDomainRestore(virConnectPtr conn, const char *filename)
}
/**
+ * xenDaemonDomainGetMaxMemory:
+ * @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
+xenDaemonDomainGetMaxMemory(virDomainPtr domain)
+{
+ unsigned long ret = 0;
+ struct sexpr *root;
+
+ if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
+ virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+ __FUNCTION__);
+ return(-1);
+ }
+
+ /* can we ask for a subset ? worth it ? */
+ root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
+ if (root == NULL)
+ return(0);
+
+ ret = (unsigned long) sexpr_u64(root, "domain/memory") << 10;
+ sexpr_free(root);
+
+ return(ret);
+}
+
+/**
* xenDaemonDomainSetMaxMemory:
* @domain: pointer to the Domain block
* @memory: The maximum memory in kilobytes
@@ -2067,8 +1859,13 @@ xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
struct sexpr *root;
int ret;
- if ((domain == NULL) || (info == NULL))
- return (-1);
+ if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) ||
+ (info == NULL)) {
+ virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+ __FUNCTION__);
+ return(-1);
+ }
+
root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
if (root == NULL)
@@ -2079,3 +1876,35 @@ xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
return (ret);
}
+/**
+ * xenDaemonDomainLookupByName:
+ * @conn: A xend instance
+ * @name: The name of the domain
+ *
+ * This method looks up information about a domain and returns
+ * it in the form of a struct xend_domain. This should be
+ * free()'d when no longer needed.
+ *
+ * Returns domain info on success; NULL (with errno) on error
+ */
+virDomainPtr
+xenDaemonDomainLookupByName(virConnectPtr conn, const char *domname)
+{
+ struct sexpr *root;
+ virDomainPtr ret = NULL;
+
+ if ((conn == NULL) || (domname == NULL)) {
+ virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return(NULL);
+ }
+ root = sexpr_get(conn, "/xend/domain/%s?detail=1", domname);
+ if (root == NULL)
+ goto error;
+
+ ret = sexpr_to_domain(conn, root);
+
+error:
+ sexpr_free(root);
+ return(ret);
+}
+
diff --git a/src/xend_internal.h b/src/xend_internal.h
index 644afe0d5..4c0317eec 100644
--- a/src/xend_internal.h
+++ b/src/xend_internal.h
@@ -563,19 +563,6 @@ int xenDaemonOpen_unix(virConnectPtr xend, const char *path);
uint64_t value);
/**
- * \brief Lookup information about a domain
- * \param xend A xend instance
- * \param name The name of the domain
- * \return domain info on success; NULL (with errno) on error
- *
- * This method looks up information about a domain and returns
- * it in the form of a struct xend_domain. This should be
- * free()'d when no longer needed.
- */
- struct xend_domain *xenDaemonDomainLookupByName(virConnectPtr xend,
- const char *name);
-
-/**
* \brief Lookup the id of a domain
* \param xend A xend instance
* \param name The name of the domain
@@ -662,6 +649,8 @@ int xenDaemonDomainRestore(virConnectPtr conn, const char *filename);
int xenDaemonDomainSetMaxMemory(virDomainPtr domain, unsigned long memory);
int xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
char *xenDaemonDomainDumpXML(virDomainPtr domain);
+virDomainPtr xenDaemonDomainLookupByName(virConnectPtr conn, const char *domname);
+unsigned long xenDaemonDomainGetMaxMemory(virDomainPtr domain);
#ifdef __cplusplus
}
diff --git a/src/xs_internal.c b/src/xs_internal.c
new file mode 100644
index 000000000..3898e5d16
--- /dev/null
+++ b/src/xs_internal.c
@@ -0,0 +1,590 @@
+/*
+ * xs_internal.c: access to Xen Store
+ *
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Daniel Veillard <veillard@redhat.com>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include <stdint.h>
+
+#include <xen/dom0_ops.h>
+#include <xen/version.h>
+#include <xen/xen.h>
+
+#include <xs.h>
+
+#include "internal.h"
+#include "driver.h"
+#include "xs_internal.h"
+
+#define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd"
+
+static virDriver xenStoreDriver = {
+ "XenStore",
+ NULL, /* init */
+ xenStoreOpen, /* open */
+ xenStoreClose, /* close */
+ NULL, /* type */
+ NULL, /* version */
+ xenStoreListDomains, /* listDomains */
+ NULL, /* numOfDomains */
+ NULL, /* domainCreateLinux */
+ NULL, /* domainLookupByID */
+ NULL, /* domainLookupByUUID */
+ NULL, /* domainLookupByName */
+ NULL, /* domainSuspend */
+ NULL, /* domainResume */
+ NULL, /* domainShutdown */
+ NULL, /* domainDestroy */
+ NULL, /* domainFree */
+ NULL, /* domainGetName */
+ NULL, /* domainGetID */
+ NULL, /* domainGetUUID */
+ NULL, /* domainGetOSType */
+ xenStoreDomainGetMaxMemory, /* domainGetMaxMemory */
+ xenStoreDomainSetMaxMemory, /* domainSetMaxMemory */
+ xenStoreGetDomainInfo, /* domainGetInfo */
+ NULL, /* domainSave */
+ NULL /* domainRestore */
+};
+
+/**
+ * virXenStoreError:
+ * @conn: the connection if available
+ * @error: the error number
+ * @info: extra information string
+ *
+ * Handle an error at the xend store interface
+ */
+static void
+virXenStoreError(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_XENSTORE, error, VIR_ERR_ERROR,
+ errmsg, info, NULL, 0, 0, errmsg, info);
+}
+
+/************************************************************************
+ * *
+ * Helper internal APIs *
+ * *
+ ************************************************************************/
+/**
+ * virConnectDoStoreList:
+ * @conn: pointer to the hypervisor connection
+ * @path: the absolute path of the directory in the store to list
+ * @nb: OUT pointer to the number of items found
+ *
+ * Internal API querying the Xenstore for a list
+ *
+ * Returns a string which must be freed by the caller or NULL in case of error
+ */
+static char **
+virConnectDoStoreList(virConnectPtr conn, const char *path,
+ unsigned int *nb)
+{
+ if ((conn == NULL) || (conn->xshandle == NULL) || (path == NULL) ||
+ (nb == NULL))
+ return (NULL);
+
+ return xs_directory(conn->xshandle, 0, path, nb);
+}
+
+/**
+ * virDomainDoStoreQuery:
+ * @domain: a domain object
+ * @path: the relative path of the data in the store to retrieve
+ *
+ * Internal API querying the Xenstore for a string value.
+ *
+ * Returns a string which must be freed by the caller or NULL in case of error
+ */
+static char *
+virDomainDoStoreQuery(virDomainPtr domain, const char *path)
+{
+ char s[256];
+ unsigned int len = 0;
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain))
+ return (NULL);
+ if (domain->conn->xshandle == NULL)
+ return (NULL);
+
+ snprintf(s, 255, "/local/domain/%d/%s", domain->handle, path);
+ s[255] = 0;
+
+ return xs_read(domain->conn->xshandle, 0, &s[0], &len);
+}
+
+
+/**
+ * virDomainDoStoreWrite:
+ * @domain: a domain object
+ * @path: the relative path of the data in the store to retrieve
+ *
+ * Internal API setting up a string value in the Xenstore
+ * Requires write access to the XenStore
+ *
+ * Returns 0 in case of success, -1 in case of failure
+ */
+static int
+virDomainDoStoreWrite(virDomainPtr domain, const char *path,
+ const char *value)
+{
+ char s[256];
+
+ int ret = -1;
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain))
+ return (-1);
+ if (domain->conn->xshandle == NULL)
+ return (-1);
+ if (domain->conn->flags & VIR_CONNECT_RO)
+ return (-1);
+
+ snprintf(s, 255, "/local/domain/%d/%s", domain->handle, path);
+ s[255] = 0;
+
+ if (xs_write(domain->conn->xshandle, 0, &s[0], value, strlen(value)))
+ ret = 0;
+
+ return (ret);
+}
+
+/**
+ * virDomainGetVM:
+ * @domain: a domain object
+ *
+ * Internal API extracting a xenstore vm path.
+ *
+ * Returns the new string or NULL in case of error
+ */
+char *
+virDomainGetVM(virDomainPtr domain)
+{
+ char *vm;
+ char query[200];
+ unsigned int len;
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain))
+ return (NULL);
+ if (domain->conn->xshandle == NULL)
+ return (NULL);
+
+ snprintf(query, 199, "/local/domain/%d/vm", virDomainGetID(domain));
+ query[199] = 0;
+
+ vm = xs_read(domain->conn->xshandle, 0, &query[0], &len);
+
+ return (vm);
+}
+
+/**
+ * virDomainGetVMInfo:
+ * @domain: a domain object
+ * @vm: the xenstore vm path
+ * @name: the value's path
+ *
+ * Internal API extracting one information the device used
+ * by the domain from xensttore
+ *
+ * Returns the new string or NULL in case of error
+ */
+char *
+virDomainGetVMInfo(virDomainPtr domain, const char *vm, const char *name)
+{
+ char s[256];
+ char *ret = NULL;
+ unsigned int len = 0;
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain))
+ return (NULL);
+ if (domain->conn->xshandle == NULL)
+ return (NULL);
+
+ snprintf(s, 255, "%s/%s", vm, name);
+ s[255] = 0;
+
+ ret = xs_read(domain->conn->xshandle, 0, &s[0], &len);
+
+ return (ret);
+}
+
+/**
+ * virConnectCheckStoreID:
+ * @conn: pointer to the hypervisor connection
+ * @id: the id number as returned from Xenstore
+ *
+ * the xenstore sometimes list non-running domains, double check
+ * from the hypervisor if we have direct access
+ *
+ * Returns -1 if the check failed, 0 if successful or not possible to check
+ */
+static int
+virConnectCheckStoreID(virConnectPtr conn, int id)
+{
+ if (conn->handle >= 0) {
+ TODO
+ /*
+ dom0_getdomaininfo_t dominfo;
+ int tmp;
+
+ dominfo.domain = id;
+ tmp = xenHypervisorGetDomainInfo(conn->handle, id, &dominfo);
+ if (tmp < 0)
+ return (-1);
+ */
+ }
+ return (0);
+}
+
+/************************************************************************
+ * *
+ * Canonical internal APIs *
+ * *
+ ************************************************************************/
+/**
+ * xenStoreOpen:
+ * @conn: pointer to the connection block
+ * @name: URL for the target, NULL for local
+ * @flags: combination of virDrvOpenFlag(s)
+ *
+ * Connects to the Xen hypervisor.
+ *
+ * Returns 0 or -1 in case of error.
+ */
+int
+xenStoreOpen(virConnectPtr conn, const char *name, int flags)
+{
+ if ((name != NULL) && (strcmp(name, "xen")))
+ return(-1);
+
+ if (flags & VIR_DRV_OPEN_RO)
+ conn->xshandle = xs_daemon_open_readonly();
+ else
+ conn->xshandle = xs_daemon_open();
+
+ if (conn->xshandle == NULL) {
+ if (!(flags & VIR_DRV_OPEN_QUIET))
+ virXenStoreError(conn, VIR_ERR_NO_XEN,
+ "failed to connect to Xen Store");
+ return (-1);
+ }
+ return (0);
+}
+
+/**
+ * xenStoreClose:
+ * @conn: pointer to the connection block
+ *
+ * Close the connection to the Xen hypervisor.
+ *
+ * Returns 0 in case of success or -1 in case of error.
+ */
+int
+xenStoreClose(virConnectPtr conn)
+{
+ if (conn == NULL) {
+ virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return(-1);
+ }
+ if (conn->xshandle == NULL)
+ return(-1);
+
+ xs_daemon_close(conn->xshandle);
+ return (0);
+}
+
+/**
+ * xenStoreGetDomainInfo:
+ * @domain: pointer to the domain block
+ * @info: the place where informations should be stored
+ *
+ * Do an hypervisor call to get the related set of domain informations.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenStoreGetDomainInfo(virDomainPtr domain, virDomainInfoPtr info)
+{
+ char *tmp, **tmp2;
+ unsigned int nb_vcpus;
+ char request[200];
+
+ if ((domain == NULL) || (domain->conn == NULL) || (info == NULL)) {
+ virXenStoreError(domain ? domain->conn : NULL, VIR_ERR_INVALID_ARG,
+ __FUNCTION__);
+ return(-1);
+ }
+ if (domain->conn->xshandle == NULL)
+ return(-1);
+
+ tmp = virDomainDoStoreQuery(domain, "running");
+ if (tmp != NULL) {
+ if (tmp[0] == '1')
+ info->state = VIR_DOMAIN_RUNNING;
+ free(tmp);
+ } else {
+ info->state = VIR_DOMAIN_NONE;
+ }
+ tmp = virDomainDoStoreQuery(domain, "memory/target");
+ if (tmp != NULL) {
+ info->memory = atol(tmp);
+ info->maxMem = atol(tmp);
+ free(tmp);
+ } else {
+ info->memory = 0;
+ info->maxMem = 0;
+ }
+#if 0
+ /* doesn't seems to work */
+ tmp = virDomainDoStoreQuery(domain, "cpu_time");
+ if (tmp != NULL) {
+ info->cpuTime = atol(tmp);
+ free(tmp);
+ } else {
+ info->cpuTime = 0;
+ }
+#endif
+ snprintf(request, 199, "/local/domain/%d/cpu", domain->handle);
+ request[199] = 0;
+ tmp2 = virConnectDoStoreList(domain->conn, request, &nb_vcpus);
+ if (tmp2 != NULL) {
+ info->nrVirtCpu = nb_vcpus;
+ free(tmp2);
+ }
+ return (0);
+}
+
+/**
+ * xenStoreDomainSetMaxMemory:
+ * @domain: pointer to the domain block
+ * @memory: the max memory size in kilobytes.
+ *
+ * Change the maximum amount of memory allowed in the xen store
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenStoreDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
+{
+ int ret;
+ char value[20];
+
+ if ((domain == NULL) || (domain->conn == NULL) || (memory < 4096)) {
+ virXenStoreError(domain ? domain->conn : NULL, VIR_ERR_INVALID_ARG,
+ __FUNCTION__);
+ return(-1);
+ }
+ snprintf(value, 19, "%lu", memory);
+ value[19] = 0;
+ ret = virDomainDoStoreWrite(domain, "memory/target", &value[0]);
+ if (ret < 0)
+ return (-1);
+ return (0);
+}
+
+/**
+ * xenStoreDomainGetMaxMemory:
+ * @domain: pointer to the domain block
+ *
+ * Ask the xenstore for the maximum memory allowed for a domain
+ *
+ * Returns the memory size in kilobytes or 0 in case of error.
+ */
+unsigned long
+xenStoreDomainGetMaxMemory(virDomainPtr domain)
+{
+ char *tmp;
+ unsigned long ret = 0;
+
+ tmp = virDomainDoStoreQuery(domain, "memory/target");
+ if (tmp != NULL) {
+ ret = (unsigned long) atol(tmp);
+ free(tmp);
+ }
+ return(ret);
+}
+
+/**
+ * xenStoreNumOfDomains:
+ * @conn: pointer to the hypervisor connection
+ *
+ * Provides the number of active domains.
+ *
+ * Returns the number of domain found or -1 in case of error
+ */
+int
+xenStoreNumOfDomains(virConnectPtr conn)
+{
+ unsigned int num;
+ char **idlist;
+ int ret = -1;
+
+ if ((conn == NULL) || (conn->xshandle == NULL)) {
+ virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return(-1);
+ }
+ idlist = xs_directory(conn->xshandle, 0, "/local/domain", &num);
+ if (idlist) {
+ free(idlist);
+ ret = num;
+ }
+ return(ret);
+}
+
+/**
+ * xenStoreListDomains:
+ * @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
+ */
+int
+xenStoreListDomains(virConnectPtr conn, int *ids, int maxids)
+{
+ char **idlist = NULL, *endptr;
+ unsigned int num, i;
+ int ret;
+ long id;
+
+ if ((conn == NULL) || (ids == NULL)) {
+ virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return(-1);
+ }
+ if (conn->xshandle == NULL)
+ return(-1);
+
+ idlist = xs_directory(conn->xshandle, 0, "/local/domain", &num);
+ if (idlist == NULL)
+ return(-1);
+
+ for (ret = 0, i = 0; (i < num) && (ret < maxids); i++) {
+ id = strtol(idlist[i], &endptr, 10);
+ if ((endptr == idlist[i]) || (*endptr != 0)) {
+ ret = -1;
+ break;
+ }
+ if (virConnectCheckStoreID(conn, (int) id) < 0)
+ continue;
+ ids[ret++] = (int) id;
+ }
+ return(ret);
+}
+
+/**
+ * xenStoreDomainLookupByName:
+ * @conn: A xend instance
+ * @name: The name of the domain
+ *
+ * Try to lookup a domain on the Xen Store based on its name.
+ *
+ * Returns a new domain object or NULL in case of failure
+ */
+virDomainPtr
+xenStoreDomainLookupByName(virConnectPtr conn, const char *name)
+{
+ virDomainPtr ret = NULL;
+ unsigned int num, i, len;
+ long id = -1;
+ char **idlist = NULL, *endptr;
+ char prop[200], *tmp, *path = NULL;
+ int found = 0;
+ struct xend_domain *xenddomain = NULL;
+
+ if ((conn == NULL) || (name == NULL)) {
+ virXenStoreError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
+ return(NULL);
+ }
+ if (conn->xshandle == NULL)
+ return(NULL);
+
+ idlist = xs_directory(conn->xshandle, 0, "/local/domain", &num);
+ if (idlist == NULL)
+ goto done;
+
+ for (i = 0; i < num; i++) {
+ id = strtol(idlist[i], &endptr, 10);
+ if ((endptr == idlist[i]) || (*endptr != 0)) {
+ goto done;
+ }
+ if (virConnectCheckStoreID(conn, (int) id) < 0)
+ continue;
+ snprintf(prop, 199, "/local/domain/%s/name", idlist[i]);
+ prop[199] = 0;
+ tmp = xs_read(conn->xshandle, 0, prop, &len);
+ if (tmp != NULL) {
+ found = !strcmp(name, tmp);
+ free(tmp);
+ if (found)
+ break;
+ }
+ }
+ path = xs_get_domain_path(conn->xshandle, (unsigned int) id);
+
+ if (!found)
+ return(NULL);
+
+ ret = (virDomainPtr) malloc(sizeof(virDomain));
+ if (ret == NULL)
+ goto done;
+ memset(ret, 0, sizeof(virDomain));
+ ret->magic = VIR_DOMAIN_MAGIC;
+ ret->conn = conn;
+ ret->handle = id;
+ ret->path = path;
+ ret->name = strdup(name);
+
+done:
+ if (xenddomain != NULL)
+ free(xenddomain);
+ if (idlist != NULL)
+ free(idlist);
+
+ return(ret);
+}
+
+/**
+ * xenStoreDomainShutdown:
+ * @domain: pointer to the Domain block
+ *
+ * Shutdown the domain, the OS is requested to properly shutdown
+ * and the domain may ignore it. It will return immediately
+ * after queuing the request.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xenStoreDomainShutdown(virDomainPtr domain)
+{
+ if ((domain == NULL) || (domain->conn == NULL)) {
+ virXenStoreError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
+ __FUNCTION__);
+ return(-1);
+ }
+ /*
+ * this is very hackish, the domU kernel probes for a special
+ * node in the xenstore and launch the shutdown command if found.
+ */
+ return(virDomainDoStoreWrite(domain, "control/shutdown", "halt"));
+}
+
diff --git a/src/xs_internal.h b/src/xs_internal.h
new file mode 100644
index 000000000..2503d451e
--- /dev/null
+++ b/src/xs_internal.h
@@ -0,0 +1,37 @@
+/*
+ * xs_internal.h: internal API for access to XenStore
+ *
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Daniel Veillard <veillard@redhat.com>
+ */
+
+#ifndef __VIR_XS_INTERNAL_H__
+#define __VIR_XS_INTERNAL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int xenStoreOpen (virConnectPtr conn,
+ const char *name,
+ int flags);
+int xenStoreClose (virConnectPtr conn);
+int xenStoreGetDomainInfo (virDomainPtr domain,
+ virDomainInfoPtr info);
+int xenStoreNumOfDomains (virConnectPtr conn);
+int xenStoreListDomains (virConnectPtr conn,
+ int *ids,
+ int maxids);
+virDomainPtr xenStoreDomainLookupByName(virConnectPtr conn, const char *name);
+unsigned long xenStoreGetMaxMemory(virDomainPtr domain);
+int xenStoreDomainSetMaxMemory (virDomainPtr domain,
+ unsigned long memory);
+unsigned long xenStoreDomainGetMaxMemory(virDomainPtr domain);
+int xenStoreDomainShutdown(virDomainPtr domain);
+#ifdef __cplusplus
+}
+#endif
+#endif /* __VIR_XS_INTERNAL_H__ */