* proxy/libvirt_proxy.c src/proxy_internal.[ch] src/xen_internal.c

src/xen_unified.[ch] src/xend_internal.[ch] src/xml.[ch]: last
  patch for the library NUMA support, allow to serialize CPU pinning
  to domain configs (but won't work though proxy access), includes
  many patches from Saori Fukuta.
Daniel
This commit is contained in:
Daniel Veillard 2007-10-31 09:39:13 +00:00
parent 8a0711c758
commit 390cca8125
12 changed files with 242 additions and 44 deletions

View File

@ -1,3 +1,11 @@
Wed Oct 31 10:36:00 CET 2007 Daniel Veillard <veillard@redhat.com>
* proxy/libvirt_proxy.c src/proxy_internal.[ch] src/xen_internal.c
src/xen_unified.[ch] src/xend_internal.[ch] src/xml.[ch]: last
patch for the library NUMA support, allow to serialize CPU pinning
to domain configs (but won't work though proxy access), includes
many patches from Saori Fukuta.
Fri Oct 26 21:20:44 EST 2007 Daniel P. Berrange <berrange@redhat.com>
* src/libvirt.c: Don't call state driver API if callback is NULL.

View File

@ -614,7 +614,13 @@ retry2:
if (req->len != sizeof(virProxyPacket))
goto comm_error;
xml = xenDaemonDomainDumpXMLByID(conn, request.data.arg, 0);
/*
* Ideally we should get the CPUs used by the domain
* but that information is really node specific and it
* rather hard to get from that code path. So proxy
* users won't see CPU pinning (last NULL arg)
*/
xml = xenDaemonDomainDumpXMLByID(conn, request.data.arg, 0, NULL);
if (!xml) {
req->data.arg = -1;
req->len = sizeof(virProxyPacket);

View File

@ -37,7 +37,6 @@ static int xenProxyListDomains(virConnectPtr conn, int *ids, int maxids);
static int xenProxyNumOfDomains(virConnectPtr conn);
static unsigned long xenProxyDomainGetMaxMemory(virDomainPtr domain);
static int xenProxyDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
static char *xenProxyDomainDumpXML(virDomainPtr domain, int flags);
static char *xenProxyDomainGetOSType(virDomainPtr domain);
struct xenUnifiedDriver xenProxyDriver = {
@ -69,7 +68,6 @@ struct xenUnifiedDriver xenProxyDriver = {
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
NULL, /* domainGetMaxVcpus */
xenProxyDomainDumpXML, /* domainDumpXML */
NULL, /* listDefinedDomains */
NULL, /* numOfDefinedDomains */
NULL, /* domainCreate */
@ -1014,7 +1012,7 @@ xenProxyGetCapabilities (virConnectPtr conn)
*
* Returns the XML document on success, NULL otherwise.
*/
static char *
char *
xenProxyDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED)
{
virProxyPacket req;

View File

@ -96,6 +96,8 @@ extern virDomainPtr xenProxyLookupByUUID(virConnectPtr conn,
extern virDomainPtr xenProxyLookupByName(virConnectPtr conn,
const char *domname);
extern char * xenProxyDomainDumpXML(virDomainPtr domain,
int flags);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -704,7 +704,6 @@ struct xenUnifiedDriver xenHypervisorDriver = {
xenHypervisorPinVcpu, /* domainPinVcpu */
xenHypervisorGetVcpus, /* domainGetVcpus */
xenHypervisorGetVcpuMax, /* domainGetMaxVcpus */
NULL, /* domainDumpXML */
NULL, /* listDefinedDomains */
NULL, /* numOfDefinedDomains */
NULL, /* domainCreate */

View File

@ -36,9 +36,16 @@
#include "xend_internal.h"
#include "xs_internal.h"
#include "xm_internal.h"
#include "xml.h"
static int
xenUnifiedNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info);
static int
xenUnifiedDomainGetMaxVcpus (virDomainPtr dom);
static int
xenUnifiedDomainGetVcpus (virDomainPtr dom,
virVcpuInfoPtr info, int maxinfo,
unsigned char *cpumaps, int maplen);
/* The five Xen drivers below us. */
static struct xenUnifiedDriver *drivers[XEN_UNIFIED_NR_DRIVERS] = {
@ -113,9 +120,9 @@ int xenNbCells(virConnectPtr conn) {
* xenNbCpus:
* @conn: pointer to the hypervisor connection
*
* Number of NUMa cells present in the actual Node
* Number of CPUs present in the actual Node
*
* Returns the number of NUMA cells available on that Node
* Returns the number of CPUs available on that Node
*/
int xenNbCpus(virConnectPtr conn) {
if (nbNodeCpus < 0)
@ -123,6 +130,81 @@ int xenNbCpus(virConnectPtr conn) {
return(nbNodeCpus);
}
/**
* xenDomainUsedCpus:
* @dom: the domain
*
* Analyze which set of CPUs are used by the domain and
* return a string providing the ranges.
*
* Returns the string which needs to be freed by the caller or
* NULL if the domain uses all CPU or in case of error.
*/
char *
xenDomainUsedCpus(virDomainPtr dom)
{
char *res = NULL;
int nb_cpu, ncpus;
int nb_vcpu;
char *cpulist = NULL;
unsigned char *cpumap = NULL;
size_t cpumaplen;
int nb = 0;
int n, m;
virVcpuInfoPtr cpuinfo = NULL;
virNodeInfo nodeinfo;
if (!VIR_IS_CONNECTED_DOMAIN(dom))
return (NULL);
nb_cpu = xenNbCpus(dom->conn);
if (nb_cpu <= 0)
return(NULL);
nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom);
if (nb_vcpu <= 0)
return(NULL);
if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0)
return(NULL);
cpulist = (char *) calloc(nb_cpu, sizeof(char));
if (cpulist == NULL)
goto done;
cpuinfo = malloc(sizeof(virVcpuInfo) * nb_vcpu);
if (cpuinfo == NULL)
goto done;
cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
cpumap = (unsigned char *) calloc(nb_vcpu, cpumaplen);
if (cpumap == NULL)
goto done;
if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu,
cpumap, cpumaplen)) >= 0) {
for (n = 0 ; n < ncpus ; n++) {
for (m = 0 ; m < nb_cpu; m++) {
if ((cpulist[m] == 0) &&
(VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
cpulist[m] = 1;
nb++;
/* if all CPU are used just return NULL */
if (nb == nb_cpu)
goto done;
}
}
}
res = virSaveCpuSet(dom->conn, cpulist, nb_cpu);
}
done:
if (cpulist != NULL)
free(cpulist);
if (cpumap != NULL)
free(cpumap);
if (cpuinfo != NULL)
free(cpuinfo);
return(res);
}
/*----- Dispatch functions. -----*/
/* These dispatch functions follow the model used historically
@ -862,19 +944,24 @@ static char *
xenUnifiedDomainDumpXML (virDomainPtr dom, int flags)
{
GET_PRIVATE(dom->conn);
int i;
char *ret;
for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
if (priv->opened[i] && drivers[i]->domainDumpXML) {
ret = drivers[i]->domainDumpXML (dom, flags);
if (ret) return ret;
if (dom->id == -1 && priv->xendConfigVersion < 3 ) {
if (priv->opened[XEN_UNIFIED_XM_OFFSET])
return xenXMDomainDumpXML(dom, flags);
} else {
if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
char *cpus, *res;
cpus = xenDomainUsedCpus(dom);
res = xenDaemonDomainDumpXML(dom, flags, cpus);
if (cpus != NULL)
free(cpus);
return(res);
}
if (priv->opened[XEN_UNIFIED_PROXY_OFFSET])
return xenProxyDomainDumpXML(dom, flags);
}
/* XXX May need to return an error here if sub-drivers didn't
* set one. We really should change these to direct calls to
* the sub-drivers at a later date.
*/
xenUnifiedError (dom->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
return NULL;
}

View File

@ -65,7 +65,6 @@ struct xenUnifiedDriver {
virDrvDomainPinVcpu domainPinVcpu;
virDrvDomainGetVcpus domainGetVcpus;
virDrvDomainGetMaxVcpus domainGetMaxVcpus;
virDrvDomainDumpXML domainDumpXML;
virDrvListDefinedDomains listDefinedDomains;
virDrvNumOfDefinedDomains numOfDefinedDomains;
virDrvDomainCreate domainCreate;
@ -119,6 +118,7 @@ typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr;
int xenNbCells(virConnectPtr conn);
int xenNbCpus(virConnectPtr conn);
char *xenDomainUsedCpus(virDomainPtr dom);
#ifdef __cplusplus
}
#endif

View File

@ -94,7 +94,6 @@ struct xenUnifiedDriver xenDaemonDriver = {
xenDaemonDomainPinVcpu, /* domainPinVcpu */
xenDaemonDomainGetVcpus, /* domainGetVcpus */
NULL, /* domainGetMaxVcpus */
xenDaemonDomainDumpXML, /* domainDumpXML */
xenDaemonListDefinedDomains, /* listDefinedDomains */
xenDaemonNumOfDefinedDomains, /* numOfDefinedDomains */
xenDaemonDomainCreate, /* domainCreate */
@ -1343,6 +1342,7 @@ xend_parse_sexp_desc_os(virConnectPtr xend, struct sexpr *node, virBufferPtr buf
* @root: the root of the parsed S-Expression
* @xendConfigVersion: version of xend
* @flags: a combination of virDomainXMLFlags
* @cpus: set of cpus the domain may be pinned to
*
* Parse the xend sexp description and turn it into the XML format similar
* to the one unsed for creation.
@ -1352,7 +1352,7 @@ xend_parse_sexp_desc_os(virConnectPtr xend, struct sexpr *node, virBufferPtr buf
*/
static char *
xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root,
int xendConfigVersion, int flags)
int xendConfigVersion, int flags, const char *cpus)
{
struct sexpr *cur, *node;
const char *tmp;
@ -1438,8 +1438,18 @@ xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root,
if ((cur_mem >= MIN_XEN_GUEST_SIZE) && (cur_mem != max_mem))
virBufferVSprintf(&buf, " <currentMemory>%d</currentMemory>\n",
cur_mem);
virBufferVSprintf(&buf, " <vcpu>%d</vcpu>\n",
virBufferVSprintf(&buf, " <vcpu");
if (cpus != NULL) {
virBufferVSprintf(&buf, " cpuset='%s'", cpus);
}
virBufferVSprintf(&buf, ">%d</vcpu>\n",
sexpr_int(root, "domain/vcpus"));
/* TODO if need to output the cpus values,
* - parse the cpus values if xend exports
* or
* - analyze the cpus values extracted by xenDaemonDomainGetVcpus
*/
tmp = sexpr_node(root, "domain/on_poweroff");
if (tmp != NULL)
virBufferVSprintf(&buf, " <on_poweroff>%s</on_poweroff>\n", tmp);
@ -1802,7 +1812,7 @@ xend_parse_domain_sexp(virConnectPtr conn, char *sexpr, int xendConfigVersion) {
if (!root)
return NULL;
data = xend_parse_sexp_desc(conn, root, xendConfigVersion, 0);
data = xend_parse_sexp_desc(conn, root, xendConfigVersion, 0, NULL);
sexpr_free(root);
@ -2481,7 +2491,8 @@ xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory)
dumpxml will work over proxy for inactive domains
and this can be removed */
char *
xenDaemonDomainDumpXMLByID(virConnectPtr conn, int domid, int flags)
xenDaemonDomainDumpXMLByID(virConnectPtr conn, int domid, int flags,
const char *cpus)
{
char *ret = NULL;
struct sexpr *root;
@ -2496,14 +2507,16 @@ xenDaemonDomainDumpXMLByID(virConnectPtr conn, int domid, int flags)
priv = (xenUnifiedPrivatePtr) conn->privateData;
ret = xend_parse_sexp_desc(conn, root, priv->xendConfigVersion, flags);
ret = xend_parse_sexp_desc(conn, root, priv->xendConfigVersion,
flags, cpus);
sexpr_free(root);
return (ret);
}
char *
xenDaemonDomainDumpXMLByName(virConnectPtr conn, const char *name, int flags)
xenDaemonDomainDumpXMLByName(virConnectPtr conn, const char *name, int flags,
const char *cpus)
{
char *ret = NULL;
struct sexpr *root;
@ -2518,7 +2531,8 @@ xenDaemonDomainDumpXMLByName(virConnectPtr conn, const char *name, int flags)
priv = (xenUnifiedPrivatePtr) conn->privateData;
ret = xend_parse_sexp_desc(conn, root, priv->xendConfigVersion, flags);
ret = xend_parse_sexp_desc(conn, root, priv->xendConfigVersion,
flags, cpus);
sexpr_free(root);
return (ret);
@ -2529,6 +2543,8 @@ xenDaemonDomainDumpXMLByName(virConnectPtr conn, const char *name, int flags)
/**
* xenDaemonDomainDumpXML:
* @domain: a domain object
* @flags: potential dump flags
* @cpus: list of cpu the domain is pinned to.
*
* Provide an XML description of the domain.
*
@ -2536,7 +2552,7 @@ xenDaemonDomainDumpXMLByName(virConnectPtr conn, const char *name, int flags)
* the caller must free() the returned value.
*/
char *
xenDaemonDomainDumpXML(virDomainPtr domain, int flags)
xenDaemonDomainDumpXML(virDomainPtr domain, int flags, const char *cpus)
{
xenUnifiedPrivatePtr priv;
@ -2553,9 +2569,11 @@ xenDaemonDomainDumpXML(virDomainPtr domain, int flags)
}
if (domain->id < 0)
return xenDaemonDomainDumpXMLByName(domain->conn, domain->name, flags);
return xenDaemonDomainDumpXMLByName(domain->conn, domain->name, flags,
cpus);
else
return xenDaemonDomainDumpXMLByID(domain->conn, domain->id, flags);
return xenDaemonDomainDumpXMLByID(domain->conn, domain->id, flags,
cpus);
}
#endif /* !PROXY */

View File

@ -110,11 +110,13 @@ int xenDaemonDomainLookupByID(virConnectPtr xend,
char *xenDaemonDomainDumpXMLByID(virConnectPtr xend,
int domid,
int flags);
int flags,
const char *cpus);
char *xenDaemonDomainDumpXMLByName(virConnectPtr xend,
const char *name,
int flags);
int flags,
const char *cpus);
/**
* \brief Lookup information about the host machine
@ -196,7 +198,7 @@ int xenDaemonDomainRestore(virConnectPtr conn, const char *filename);
int xenDaemonDomainSetMemory(virDomainPtr domain, unsigned long memory);
int xenDaemonDomainSetMaxMemory(virDomainPtr domain, unsigned long memory);
int xenDaemonDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info);
char *xenDaemonDomainDumpXML(virDomainPtr domain, int flags);
char *xenDaemonDomainDumpXML(virDomainPtr domain, int flags, const char *cpus);
unsigned long xenDaemonDomainGetMaxMemory(virDomainPtr domain);
char **xenDaemonListDomainsOld(virConnectPtr xend);

View File

@ -104,7 +104,6 @@ struct xenUnifiedDriver xenXMDriver = {
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
NULL, /* domainGetMaxVcpus */
xenXMDomainDumpXML, /* domainDumpXML */
xenXMListDefinedDomains, /* listDefinedDomains */
xenXMNumOfDefinedDomains, /* numOfDefinedDomains */
xenXMDomainCreate, /* domainCreate */
@ -660,11 +659,20 @@ char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf) {
val = MIN_XEN_GUEST_SIZE * 2;
virBufferVSprintf(buf, " <memory>%ld</memory>\n", val * 1024);
virBufferVSprintf(buf, " <vcpu"); /* DV */
if (xenXMConfigGetString(conf, "cpus", &str) == 0) {
char *ranges;
ranges = virConvertCpuSet(conn, str, 0);
if (ranges != NULL) {
virBufferVSprintf(buf, " cpuset='%s'", ranges);
free(ranges);
} else
virBufferVSprintf(buf, " cpuset='%s'", str);
}
if (xenXMConfigGetInt(conf, "vcpus", &val) < 0)
val = 1;
virBufferVSprintf(buf, " <vcpu>%ld</vcpu>\n", val);
virBufferVSprintf(buf, ">%ld</vcpu>\n", val);
if (xenXMConfigGetString(conf, "on_poweroff", &str) < 0)
str = "destroy";
@ -1763,6 +1771,7 @@ virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml) {
virConfPtr conf = NULL;
int hvm = 0, i;
xenUnifiedPrivatePtr priv;
char *cpus;
doc = xmlReadDoc((const xmlChar *) xml, "domain.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
@ -1821,6 +1830,32 @@ virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml) {
"cannot set vcpus config parameter") < 0)
goto error;
cpus = virXPathString("string(/domain/vcpu/@cpuset)", ctxt);
if (cpus != NULL) {
char *ranges;
ranges = virConvertCpuSet(conn, cpus, 0);
if (ranges != NULL) {
free(cpus);
if (xenXMConfigSetString(conf, "cpus", ranges) < 0) {
free(ranges);
goto error;
}
free(ranges);
} else {
if (xenXMConfigSetString(conf, "cpus", cpus) < 0) {
free(cpus);
goto error;
}
free(cpus);
}
}
if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "cpus", /* DV */
"string(/domain/vcpu/@cpuset)", 1,
"cannot set the cpuset parameter") < 0)
goto error;
obj = xmlXPathEval(BAD_CAST "string(/domain/os/type)", ctxt);
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
(obj->stringval != NULL) && !strcmp((char*)obj->stringval, "hvm"))

View File

@ -135,7 +135,7 @@ parseCpuNumber(const char **str, int maxcpu)
}
/**
* saveCpuSet:
* virSaveCpuSet:
* @conn: connection
* @cpuset: pointer to a char array for the CPU set
* @maxcpu: number of elements available in @cpuset
@ -145,8 +145,8 @@ parseCpuNumber(const char **str, int maxcpu)
* Returns the new string NULL in case of error. The string need to be
* freed by the caller.
*/
static char *
saveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu)
char *
virSaveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu)
{
virBufferPtr buf;
char *ret;
@ -174,8 +174,6 @@ saveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu)
first = 0;
if (cur == start + 1)
virBufferVSprintf(buf, "%d", start);
else if (cur == start + 2)
virBufferVSprintf(buf, "%d,%d", start, cur - 1);
else
virBufferVSprintf(buf, "%d-%d", start, cur - 1);
start = -1;
@ -187,8 +185,6 @@ saveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu)
virBufferAdd(buf, ",", -1);
if (maxcpu == start + 1)
virBufferVSprintf(buf, "%d", start);
else if (maxcpu == start + 2)
virBufferVSprintf(buf, "%d,%d", start, maxcpu - 1);
else
virBufferVSprintf(buf, "%d-%d", start, maxcpu - 1);
}
@ -198,6 +194,7 @@ saveCpuSet(virConnectPtr conn, char *cpuset, int maxcpu)
/**
* virParseCpuSet:
* @conn: connection
* @str: pointer to a CPU set string pointer
* @sep: potential character used to mark the end of string if not 0
* @cpuset: pointer to a char array for the CPU set
@ -300,6 +297,7 @@ virParseCpuSet(virConnectPtr conn, const char **str, char sep,
/**
* virParseXenCpuTopology:
* @conn: connection
* @xml: XML output buffer
* @str: the topology string
* @maxcpu: number of elements available in @cpuset
@ -362,7 +360,7 @@ virParseXenCpuTopology(virConnectPtr conn, virBufferPtr xml,
{
char *dump;
dump = saveCpuSet(conn, cpuset, maxcpu);
dump = virSaveCpuSet(conn, cpuset, maxcpu);
if (dump != NULL) {
virBufferVSprintf(xml, " <dump>%s</dump>\n",
dump);
@ -408,6 +406,45 @@ virParseXenCpuTopology(virConnectPtr conn, virBufferPtr xml,
return (-1);
}
/**
* virConvertCpuSet:
* @conn: connection
* @str: pointer to a Xen or user provided CPU set string pointer
* @maxcpu: number of CPUs on the node, if 0 4096 will be used
*
* Parse the given CPU set string and convert it to a range based
* string.
*
* Returns a new string which must be freed by the caller or NULL in
* case of error.
*/
char *
virConvertCpuSet(virConnectPtr conn, const char *str, int maxcpu) {
int ret;
char *res, *cpuset;
const char *cur = str;
if (str == NULL)
return(NULL);
if (maxcpu <= 0)
maxcpu = 4096;
cpuset = calloc(maxcpu, sizeof(char));
if (cpuset == NULL) {
virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
return(NULL);
}
ret = virParseCpuSet(conn, &cur, 0, cpuset, maxcpu);
if (ret < 0) {
free(cpuset);
return(NULL);
}
res = virSaveCpuSet(conn, cpuset, maxcpu);
free(cpuset);
return (res);
}
#ifndef PROXY
/************************************************************************
@ -1603,7 +1640,7 @@ virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name,
if (cpuset != NULL) {
res = virParseCpuSet(conn, &cur, 0, cpuset, maxcpu);
if (res > 0) {
ranges = saveCpuSet(conn, cpuset, maxcpu);
ranges = virSaveCpuSet(conn, cpuset, maxcpu);
if (ranges != NULL) {
virBufferVSprintf(&buf, "(cpus '%s')", ranges);
free(ranges);

View File

@ -41,6 +41,12 @@ int virParseCpuSet (virConnectPtr conn,
char sep,
char *cpuset,
int maxcpu);
char * virSaveCpuSet (virConnectPtr conn,
char *cpuset,
int maxcpu);
char * virConvertCpuSet(virConnectPtr conn,
const char *str,
int maxcpu);
char * virDomainParseXMLDesc(virConnectPtr conn,
const char *xmldesc,
char **name,