]> xenbits.xensource.com Git - libvirt.git/commitdiff
* src/xs_internal.c src/xs_internal.h include/virterror.h
authorDaniel Veillard <veillard@redhat.com>
Thu, 23 Mar 2006 15:42:10 +0000 (15:42 +0000)
committerDaniel Veillard <veillard@redhat.com>
Thu, 23 Mar 2006 15:42:10 +0000 (15:42 +0000)
  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
Daniel

13 files changed:
ChangeLog
include/libvirt/virterror.h
include/virterror.h
python/tests/create.py
src/Makefile.am
src/libvirt.c
src/virterror.c
src/xen_internal.c
src/xen_internal.h
src/xend_internal.c
src/xend_internal.h
src/xs_internal.c [new file with mode: 0644]
src/xs_internal.h [new file with mode: 0644]

index 12605deb9622447edfa21ecfcb807d69a1e8cd2f..5f937cab39e03145049d7c586f68c53d0b9e7658 100644 (file)
--- 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
index eb28be0827a52fd4832edb6375d55753cd3ee710..1c7c22db4303caa73d0b2c60303a898c385b6e7e 100644 (file)
@@ -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;
 
 /**
index eb28be0827a52fd4832edb6375d55753cd3ee710..1c7c22db4303caa73d0b2c60303a898c385b6e7e 100644 (file)
@@ -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;
 
 /**
index 0c62edb5a0cbbf5349698d733ca6f25cce77d1bb..c897741edd4d0b345ceb87bacd0c1e629c1a8b15 100755 (executable)
@@ -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())
 
index a3812ad124600f91ded4ea5ecf47fd2a94601d7e..39795110bb9eae1bb81ace785e766abb4496713a 100644 (file)
@@ -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
index e954357bcb7d4f869a1f0460f3a3ce18b5412da8..5364e9304c077319dfe72d8216185efa91be8d72 100644 (file)
 #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,64 +218,36 @@ 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);
 }
 
 /**
index 552cb7964488f3c0270a7b68ea9273b0bae792b8..9fc08e9e16794e392ea2ef443ad963b5e4bfcb3d 100644 (file)
@@ -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;
index e3fc858e1175a30856edcd0ab5a3923b46fb0155..565d2c75374b6f8f963a7a7d05d8a4e64ca34c37 100644 (file)
@@ -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>
index 62c1840971f7a778a23b9f7c6d651cb81ac5ec70..fa06393f1118418250feb50708394177cc13e0e9 100644 (file)
 #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
index 5ef6d6e92ebf5021d8181dd644d3fbed131c804c..e3ddbc0acd6d62ac6c0b82455ddf3b5accfeb310 100644 (file)
@@ -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:
@@ -771,31 +712,6 @@ sexpr_node_system(struct sexpr *node, const char *path)
     return XEND_DEFAULT;
 }
 
-/**
- * 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
@@ -1170,211 +1086,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
@@ -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);
+}
+
 
 /*****************************************************************
  ******
@@ -1993,6 +1754,37 @@ xenDaemonDomainRestore(virConnectPtr conn, const char *filename)
     return xend_op(conn, "", "op", "restore", "file", filename, NULL);
 }
 
+/**
+ * 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
@@ -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);
+}
+
index 644afe0d5c49395d6c5e2d457152871bf3405333..4c0317eec042da43522ac6b4ed30b4f9ad379597 100644 (file)
@@ -562,19 +562,6 @@ int xenDaemonOpen_unix(virConnectPtr xend, const char *path);
     int xend_set_memory(virConnectPtr xend, const char *name,
                         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
@@ -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 (file)
index 0000000..3898e5d
--- /dev/null
@@ -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 (file)
index 0000000..2503d45
--- /dev/null
@@ -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__ */