mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
* 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 Daniel
This commit is contained in:
parent
faf61d94c1
commit
a21472c0fd
@ -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
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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())
|
||||
|
||||
|
@ -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
|
||||
|
427
src/libvirt.c
427
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,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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
free(idlist);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
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);
|
||||
ret = xenStoreDomainLookupByName(conn, name);
|
||||
if (ret != NULL) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
590
src/xs_internal.c
Normal file
590
src/xs_internal.c
Normal file
@ -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"));
|
||||
}
|
||||
|
37
src/xs_internal.h
Normal file
37
src/xs_internal.h
Normal file
@ -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__ */
|
Loading…
Reference in New Issue
Block a user