Index: src/internal.h =================================================================== RCS file: /data/cvs/libvirt/src/internal.h,v retrieving revision 1.25 diff -u -p -r1.25 internal.h --- src/internal.h 16 Nov 2006 19:06:13 -0000 1.25 +++ src/internal.h 13 Dec 2006 20:17:24 -0000 @@ -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 */ Index: src/xend_internal.c =================================================================== RCS file: /data/cvs/libvirt/src/xend_internal.c,v retrieving revision 1.81 diff -u -p -r1.81 xend_internal.c --- src/xend_internal.c 13 Dec 2006 14:08:51 -0000 1.81 +++ src/xend_internal.c 13 Dec 2006 20:17:27 -0000 @@ -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 cha 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 co 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 con * 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 * 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, stru 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, stru 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); @@ -2338,7 +2361,7 @@ xenDaemonDomainSetMaxMemory(virDomainPtr __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 do __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 do #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"); + ret = xend_parse_sexp_desc(conn, root, conn->xendConfigVersion); + sexpr_free(root); + + 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, xendConfigVersion); + ret = xend_parse_sexp_desc(conn, root, conn->xendConfigVersion); sexpr_free(root); return (ret); @@ -2423,10 +2459,12 @@ xenDaemonDomainDumpXML(virDomainPtr doma __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 doma __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(virConnectPt 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 dom __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, 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, 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 domai 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 Index: src/xend_internal.h =================================================================== RCS file: /data/cvs/libvirt/src/xend_internal.h,v retrieving revision 1.27 diff -u -p -r1.27 xend_internal.h --- src/xend_internal.h 15 Nov 2006 21:03:35 -0000 1.27 +++ src/xend_internal.h 13 Dec 2006 20:17:27 -0000 @@ -551,6 +551,9 @@ int xenDaemonDomainLookupByID(virConnect 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(virConn */ 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 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, Index: src/xm_internal.c =================================================================== RCS file: /data/cvs/libvirt/src/xm_internal.c,v retrieving revision 1.3 diff -u -p -r1.3 xm_internal.c --- src/xm_internal.c 22 Nov 2006 17:48:29 -0000 1.3 +++ src/xm_internal.c 13 Dec 2006 20:17:28 -0000 @@ -994,7 +994,7 @@ virDomainPtr xenXMDomainLookupByUUID(vir 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 domai 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); }