diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | include/libvirt/virterror.h | 2 | ||||
-rw-r--r-- | include/virterror.h | 2 | ||||
-rwxr-xr-x | python/tests/create.py | 2 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/libvirt.c | 427 | ||||
-rw-r--r-- | src/virterror.c | 3 | ||||
-rw-r--r-- | src/xen_internal.c | 4 | ||||
-rw-r--r-- | src/xen_internal.h | 5 | ||||
-rw-r--r-- | src/xend_internal.c | 433 | ||||
-rw-r--r-- | src/xend_internal.h | 15 | ||||
-rw-r--r-- | src/xs_internal.c | 590 | ||||
-rw-r--r-- | src/xs_internal.h | 37 |
13 files changed, 856 insertions, 672 deletions
@@ -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__ */ |