Implement support for inactive domains from Xen 3.0.4

This commit is contained in:
Daniel P. Berrange 2006-12-14 01:56:14 +00:00
parent 7a9f673e3e
commit 166d499f02
5 changed files with 242 additions and 64 deletions

View File

@ -1,4 +1,16 @@
Thu Dec 12 09:05:03 EST 2006 Daniel Berrange <berrange@redhat.com>
Wed Dec 13 17:24:03 EST 2006 Daniel Berrange <berrange@redhat.com>
* src/xend_internal.c: Implement the ListDefinedDomains, NumOfDefinedDomains,
DomainCreate ,DomainDefineXML, DomainUndefine APIs to manage inactive domains
when running with Xen 3.0.4. Make GetMaxMemory, SetMaxMemory, SetMemory,
GetInfo, SetVCPUs & DumpXML work with inactive domains. Cache xendConfigVersion
when first connecting to Xend.
* src/xend_internal.h: Prototypes for new APIs
* src/xm_internal.c: Updated for new way of getting xendConfigVersion
data
* src/internal.h: Added xendConfigVersion field for virConnect struct
Tue Dec 12 09:05:03 EST 2006 Daniel Berrange <berrange@redhat.com>
* src/xend_internal.c: Added support for vnclisten parameter
in generated XML

View File

@ -108,6 +108,7 @@ struct _virConnect {
int handle; /* internal handle used for hypercall */
struct xs_handle *xshandle;/* handle to talk to the xenstore */
int proxy; /* file descriptor if using the proxy */
int xendConfigVersion; /* XenD config version */
/* connection to xend */
int type; /* PF_UNIX or PF_INET */

View File

@ -41,6 +41,8 @@
static const char * xenDaemonGetType(virConnectPtr conn);
static int xenDaemonListDomains(virConnectPtr conn, int *ids, int maxids);
static int xenDaemonNumOfDomains(virConnectPtr conn);
static int xenDaemonListDefinedDomains(virConnectPtr conn, const char **names, int maxnames);
static int xenDaemonNumOfDefinedDomains(virConnectPtr conn);
static virDomainPtr xenDaemonLookupByID(virConnectPtr conn, int id);
static virDomainPtr xenDaemonLookupByUUID(virConnectPtr conn,
const unsigned char *uuid);
@ -93,11 +95,11 @@ static virDriver xenDaemonDriver = {
xenDaemonDomainPinVcpu, /* domainPinVcpu */
xenDaemonDomainGetVcpus, /* domainGetVcpus */
xenDaemonDomainDumpXML, /* domainDumpXML */
NULL, /* listDefinedDomains */
NULL, /* numOfDefinedDomains */
NULL, /* domainCreate */
NULL, /* domainDefineXML */
NULL, /* domainUndefine */
xenDaemonListDefinedDomains, /* listDefinedDomains */
xenDaemonNumOfDefinedDomains, /* numOfDefinedDomains */
xenDaemonDomainCreate, /* domainCreate */
xenDaemonDomainDefineXML, /* domainDefineXML */
xenDaemonDomainUndefine, /* domainUndefine */
xenDaemonAttachDevice, /* domainAttachDevice */
xenDaemonDetachDevice /* domainDetachDevice */
};
@ -702,6 +704,7 @@ sexpr_int(struct sexpr *sexpr, const char *name)
return 0;
}
/**
* sexpr_float:
* @sexpr: an S-Expression
@ -1273,8 +1276,8 @@ xend_get_node(virConnectPtr xend)
return node;
}
int
xend_get_config_version(virConnectPtr conn) {
static int
xend_detect_config_version(virConnectPtr conn) {
struct sexpr *root;
const char *value;
@ -1286,23 +1289,20 @@ xend_get_config_version(virConnectPtr conn) {
root = sexpr_get(conn, "/xend/node/");
if (root == NULL)
return (-1);
value = sexpr_node(root, "node/xend_config_format");
if (value) {
int version = strtol(value, NULL, 10);
sexpr_free(root);
return version;
}
conn->xendConfigVersion = strtol(value, NULL, 10);
} else {
/* Xen prior to 3.0.3 did not have the xend_config_format
field, and is implicitly version 1. */
conn->xendConfigVersion = 1;
}
sexpr_free(root);
/* Xen prior to 3.0.3 did not have the xend_config_format
field, and is implicitly version 1. */
return 1;
return conn->xendConfigVersion;
}
#ifndef PROXY
/**
* xend_node_shutdown:
@ -1853,7 +1853,7 @@ xend_parse_domain_sexp(virConnectPtr conn, char *sexpr, int xendConfigVersion) {
* Returns 0 in case of success, -1 in case of error
*/
static int
sexpr_to_xend_domain_info(struct sexpr *root, virDomainInfoPtr info)
sexpr_to_xend_domain_info(virDomainPtr domain, struct sexpr *root, virDomainInfoPtr info)
{
const char *flags;
@ -1879,7 +1879,12 @@ sexpr_to_xend_domain_info(struct sexpr *root, virDomainInfoPtr info)
else if (strchr(flags, 'r'))
info->state = VIR_DOMAIN_RUNNING;
} else {
info->state = VIR_DOMAIN_NOSTATE;
/* Inactive domains don't have a state reported, so
mark them SHUTOFF, rather than NOSTATE */
if (domain->handle < 0)
info->state = VIR_DOMAIN_SHUTOFF;
else
info->state = VIR_DOMAIN_NOSTATE;
}
info->cpuTime = sexpr_float(root, "domain/cpu_time") * 1000000000;
info->nrVirtCpu = sexpr_int(root, "domain/vcpus");
@ -1940,6 +1945,7 @@ sexpr_to_domain(virConnectPtr conn, struct sexpr *root)
char *dst_uuid = NULL;
char uuid[16];
const char *name;
const char *tmp;
if ((conn == NULL) || (root == NULL))
return(NULL);
@ -1954,12 +1960,20 @@ sexpr_to_domain(virConnectPtr conn, struct sexpr *root)
ret = virGetDomain(conn, name, (const unsigned char *) &uuid[0]);
if (ret == NULL) {
virXendError(conn, VIR_ERR_NO_MEMORY, _("allocating domain"));
return(NULL);
return(NULL);
}
ret->handle = sexpr_int(root, "domain/domid");
if (ret->handle < 0)
tmp = sexpr_node(root, "domain/domid");
/* New 3.0.4 XenD will not report a domid for inactive domains,
* so only error out for old XenD
*/
if (!tmp && conn->xendConfigVersion < 3)
goto error;
if (tmp)
ret->handle = sexpr_int(root, "domain/domid");
else
ret->handle = -1; /* An inactive domain */
return (ret);
error:
@ -2062,6 +2076,15 @@ try_http:
}
done:
/* The XenD config version is used to determine
* which APIs / features to activate. Lookup & cache
* it now to avoid repeated HTTP calls
*/
if (xend_detect_config_version(conn) < 0) {
virXendError(conn, VIR_ERR_INTERNAL_ERROR, "cannot determine xend config version");
goto failed;
}
if (uri != NULL)
xmlFreeURI(uri);
return(ret);
@ -2302,7 +2325,7 @@ xenDaemonDomainGetMaxMemory(virDomainPtr domain)
__FUNCTION__);
return(-1);
}
if (domain->handle < 0)
if (domain->handle < 0 && domain->conn->xendConfigVersion < 3)
return(-1);
/* can we ask for a subset ? worth it ? */
@ -2338,7 +2361,7 @@ xenDaemonDomainSetMaxMemory(virDomainPtr domain, unsigned long memory)
__FUNCTION__);
return(-1);
}
if (domain->handle < 0)
if (domain->handle < 0 && domain->conn->xendConfigVersion < 3)
return(-1);
snprintf(buf, sizeof(buf), "%lu", memory >> 10);
@ -2372,7 +2395,7 @@ xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory)
__FUNCTION__);
return(-1);
}
if (domain->handle < 0)
if (domain->handle < 0 && domain->conn->xendConfigVersion < 3)
return(-1);
snprintf(buf, sizeof(buf), "%lu", memory >> 10);
@ -2382,23 +2405,36 @@ xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory)
#endif /* ! PROXY */
/* XXX change proxy to use Name instead of ID, then
dumpxml will work over proxy for inactive domains
and this can be removed */
char *
xenDaemonDomainDumpXMLByID(virConnectPtr conn, int domid)
{
char *ret = NULL;
struct sexpr *root;
int xendConfigVersion;
root = sexpr_get(conn, "/xend/domain/%d?detail=1", domid);
if (root == NULL)
return (NULL);
if ((xendConfigVersion = xend_get_config_version(conn)) < 0) {
virXendError(conn, VIR_ERR_INTERNAL_ERROR, "cannot determine xend config version");
return (NULL);
}
ret = xend_parse_sexp_desc(conn, root, conn->xendConfigVersion);
sexpr_free(root);
ret = xend_parse_sexp_desc(conn, root, xendConfigVersion);
return (ret);
}
char *
xenDaemonDomainDumpXMLByName(virConnectPtr conn, const char *name)
{
char *ret = NULL;
struct sexpr *root;
root = sexpr_get(conn, "/xend/domain/%s?detail=1", name);
if (root == NULL)
return (NULL);
ret = xend_parse_sexp_desc(conn, root, conn->xendConfigVersion);
sexpr_free(root);
return (ret);
@ -2423,10 +2459,12 @@ xenDaemonDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED)
__FUNCTION__);
return(NULL);
}
if (domain->handle < 0)
if (domain->handle < 0 && domain->conn->xendConfigVersion < 3)
return(NULL);
return xenDaemonDomainDumpXMLByID(domain->conn, domain->handle);
if (domain->handle < 0)
return xenDaemonDomainDumpXMLByName(domain->conn, domain->name);
else
return xenDaemonDomainDumpXMLByID(domain->conn, domain->handle);
}
#endif /* !PROXY */
@ -2452,14 +2490,14 @@ xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
__FUNCTION__);
return(-1);
}
if (domain->handle < 0)
if (domain->handle < 0 && domain->conn->xendConfigVersion < 3)
return(-1);
root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name);
if (root == NULL)
return (-1);
ret = sexpr_to_xend_domain_info(root, info);
ret = sexpr_to_xend_domain_info(domain, root, info);
sexpr_free(root);
return (ret);
}
@ -2484,8 +2522,9 @@ xenDaemonDomainLookupByName(virConnectPtr conn, const char *domname)
if ((conn == NULL) || (domname == NULL)) {
virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return(NULL);
return(NULL);
}
root = sexpr_get(conn, "/xend/domain/%s?detail=1", domname);
if (root == NULL)
goto error;
@ -2735,7 +2774,7 @@ xenDaemonDomainSetVcpus(virDomainPtr domain, unsigned int vcpus)
__FUNCTION__);
return (-1);
}
if (domain->handle < 0)
if (domain->handle < 0 && domain->conn->xendConfigVersion < 3)
return(-1);
snprintf(buf, sizeof(buf), "%d", vcpus);
@ -2955,7 +2994,6 @@ xenDaemonCreateLinux(virConnectPtr conn, const char *xmlDesc,
char *sexpr;
char *name = NULL;
virDomainPtr dom;
int xendConfigVersion;
if (!VIR_IS_CONNECT(conn)) {
virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
@ -2966,13 +3004,7 @@ xenDaemonCreateLinux(virConnectPtr conn, const char *xmlDesc,
return (NULL);
}
if ((xendConfigVersion = xend_get_config_version(conn)) < 0) {
virXendError(conn, VIR_ERR_INTERNAL_ERROR,
"cannot determine xend config version");
return (NULL);
}
sexpr = virDomainParseXMLDesc(xmlDesc, &name, xendConfigVersion);
sexpr = virDomainParseXMLDesc(xmlDesc, &name, conn->xendConfigVersion);
if ((sexpr == NULL) || (name == NULL)) {
virXendError(conn, VIR_ERR_XML_ERROR, "domain");
if (sexpr != NULL)
@ -3032,21 +3064,17 @@ static int
xenDaemonAttachDevice(virDomainPtr domain, char *xml)
{
char *sexpr, *conf;
int xendConfigVersion, hvm = 0, ret;
int hvm = 0, ret;
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
__FUNCTION__);
return (-1);
}
if ((xendConfigVersion = xend_get_config_version(domain->conn)) < 0) {
virXendError(domain->conn, VIR_ERR_INTERNAL_ERROR,
"cannot determine xend config version");
return (-1);
}
if (strcmp(virDomainGetOSType(domain), "linux"))
hvm = 1;
sexpr = virParseXMLDevice(xml, hvm, xendConfigVersion);
sexpr = virParseXMLDevice(xml, hvm, domain->conn->xendConfigVersion);
if (sexpr == NULL)
return (-1);
if (!memcmp(sexpr, "(device ", 8)) {
@ -3084,8 +3112,144 @@ xenDaemonDetachDevice(virDomainPtr domain, char *xml)
return(xend_op(domain->conn, domain->name, "op", "device_destroy",
"type", class, "dev", ref, NULL));
}
virDomainPtr xenDaemonDomainDefineXML(virConnectPtr conn, const char *xmlDesc) {
int ret;
char *sexpr;
char *name = NULL;
virDomainPtr dom;
if (!VIR_IS_CONNECT(conn)) {
virXendError(conn, VIR_ERR_INVALID_CONN, __FUNCTION__);
return (NULL);
}
if (xmlDesc == NULL) {
virXendError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return (NULL);
}
sexpr = virDomainParseXMLDesc(xmlDesc, &name, conn->xendConfigVersion);
if ((sexpr == NULL) || (name == NULL)) {
virXendError(conn, VIR_ERR_XML_ERROR, "domain");
if (sexpr != NULL)
free(sexpr);
if (name != NULL)
free(name);
return (NULL);
}
ret = xend_op(conn, "", "op", "new", "config", sexpr, NULL);
free(sexpr);
if (ret != 0) {
fprintf(stderr, _("Failed to create inactive domain %s\n"), name);
goto error;
}
dom = virDomainLookupByName(conn, name);
if (dom == NULL) {
goto error;
}
return (dom);
error:
if (name != NULL)
free(name);
return (NULL);
}
int xenDaemonDomainCreate(virDomainPtr domain) {
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
__FUNCTION__);
return(-1);
}
if (domain->conn->xendConfigVersion < 3)
return(-1);
return xend_op(domain->conn, domain->name, "op", "start", NULL);
}
int xenDaemonDomainUndefine(virDomainPtr domain) {
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
__FUNCTION__);
return(-1);
}
if (domain->conn->xendConfigVersion < 3)
return(-1);
return xend_op(domain->conn, domain->name, "op", "delete", NULL);
}
/**
* xenDaemonNumOfDomains:
* @conn: pointer to the hypervisor connection
*
* Provides the number of active domains.
*
* Returns the number of domain found or -1 in case of error
*/
static int
xenDaemonNumOfDefinedDomains(virConnectPtr conn)
{
struct sexpr *root = NULL;
int ret = -1;
struct sexpr *_for_i, *node;
root = sexpr_get(conn, "/xend/domain?state=halted");
if (root == NULL)
goto error;
ret = 0;
for (_for_i = root, node = root->car; _for_i->kind == SEXPR_CONS;
_for_i = _for_i->cdr, node = _for_i->car) {
if (node->kind != SEXPR_VALUE)
continue;
ret++;
}
error:
if (root != NULL)
sexpr_free(root);
return(ret);
}
int xenDaemonListDefinedDomains(virConnectPtr conn, const char **names, int maxnames) {
struct sexpr *root = NULL;
int ret = -1;
struct sexpr *_for_i, *node;
if ((names == NULL) || (maxnames <= 0))
goto error;
root = sexpr_get(conn, "/xend/domain?state=halted");
if (root == NULL)
goto error;
ret = 0;
for (_for_i = root, node = root->car; _for_i->kind == SEXPR_CONS;
_for_i = _for_i->cdr, node = _for_i->car) {
if (node->kind != SEXPR_VALUE)
continue;
names[ret++] = strdup(node->value);
if (ret >= maxnames)
break;
}
error:
if (root != NULL)
sexpr_free(root);
return(ret);
}
#endif /* ! PROXY */
/*
* Local variables:
* indent-tabs-mode: nil

View File

@ -551,6 +551,9 @@ int xenDaemonDomainLookupByID(virConnectPtr xend,
char *xenDaemonDomainDumpXMLByID(virConnectPtr xend,
int domid);
char *xenDaemonDomainDumpXMLByName(virConnectPtr xend,
const char *name);
/**
* \brief Lookup information about the host machine
* \param xend A xend instance
@ -613,7 +616,6 @@ char *xenDaemonDomainDumpXMLByID(virConnectPtr xend,
*/
int xend_log(virConnectPtr xend, char *buffer, size_t n_buffer);
int xend_get_config_version(virConnectPtr conn);
char *xend_parse_domain_sexp(virConnectPtr conn, char *root, int xendConfigVersion);
/* refactored ones */
@ -637,6 +639,10 @@ virDomainPtr xenDaemonDomainLookupByName(virConnectPtr conn, const char *domname
unsigned long xenDaemonDomainGetMaxMemory(virDomainPtr domain);
char **xenDaemonListDomainsOld(virConnectPtr xend);
virDomainPtr xenDaemonDomainDefineXML(virConnectPtr xend, const char *sexpr);
int xenDaemonDomainCreate(virDomainPtr domain);
int xenDaemonDomainUndefine(virDomainPtr domain);
int xenDaemonDomainSetVcpus (virDomainPtr domain,
unsigned int vcpus);
int xenDaemonDomainPinVcpu (virDomainPtr domain,

View File

@ -994,7 +994,7 @@ virDomainPtr xenXMDomainLookupByUUID(virConnectPtr conn,
int xenXMDomainCreate(virDomainPtr domain) {
char *xml;
char *sexpr;
int ret, xendConfigVersion;
int ret;
unsigned char uuid[16];
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
@ -1011,12 +1011,7 @@ int xenXMDomainCreate(virDomainPtr domain) {
if (!(xml = xenXMDomainDumpXML(domain, 0)))
return (-1);
if ((xendConfigVersion = xend_get_config_version(domain->conn)) < 0) {
xenXMError(domain->conn, VIR_ERR_INTERNAL_ERROR, "cannot determine xend config version");
return (-1);
}
if (!(sexpr = virDomainParseXMLDesc(xml, NULL, xendConfigVersion))) {
if (!(sexpr = virDomainParseXMLDesc(xml, NULL, domain->conn->xendConfigVersion))) {
free(xml);
return (-1);
}