提交 cfb192ad 编写于 作者: D Daniel Veillard

* docs/format.html docs/libvir.html: documentation cleaups

  from Jim Paris
Daniel
上级 a87420ae
Mon Oct 22 22:27:40 CEST 2007 Daniel Veillard <veillard@redhat.com>
* docs/format.html docs/libvir.html: documentation cleaups
from Jim Paris
Mon Oct 22 15:05:30 CEST 2007 Daniel Veillard <veillard@redhat.com>
* src/xend_internal.c: update to cpuset parsing code for NUMA
......
......@@ -230,7 +230,7 @@ support a variety of options:</p><ol><li>Userspace SLIRP stack
<pre>&lt;interface type='user'/&gt;</pre>
<pre>
&lt;interface type='user'&gt;
&lt;mac address="11:22:33:44:55:66:/&gt;
&lt;mac address="11:22:33:44:55:66"/&gt;
&lt;/interface&gt;
</pre>
</li>
......@@ -253,7 +253,7 @@ support a variety of options:</p><ol><li>Userspace SLIRP stack
&lt;interface type='network'&gt;
&lt;source network='default'/&gt;
&lt;target dev='vnet7'/&gt;
&lt;mac address="11:22:33:44:55:66:/&gt;
&lt;mac address="11:22:33:44:55:66"/&gt;
&lt;/interface&gt;
</pre>
</li>
......@@ -273,12 +273,8 @@ support a variety of options:</p><ol><li>Userspace SLIRP stack
&lt;interface type='bridge'&gt;
&lt;source dev='br0'/&gt;
&lt;target dev='vnet7'/&gt;
&lt;mac address="11:22:33:44:55:66:/&gt;
&lt;/interface&gt; &lt;interface type='bridge'&gt;
&lt;source dev='br0'/&gt;
&lt;target dev='vnet7'/&gt;
&lt;mac address="11:22:33:44:55:66:/&gt;
&lt;/interface&gt;</pre>
&lt;mac address="11:22:33:44:55:66"/&gt;
&lt;/interface&gt;</pre>
</li>
<li>Generic connection to LAN
<p>Provides a means for the administrator to execute an arbitrary script
......
......@@ -964,7 +964,7 @@ support a variety of options:</p>
<pre>&lt;interface type='user'/&gt;</pre>
<pre>
&lt;interface type='user'&gt;
&lt;mac address="11:22:33:44:55:66:/&gt;
&lt;mac address="11:22:33:44:55:66"/&gt;
&lt;/interface&gt;
</pre>
</li>
......@@ -987,7 +987,7 @@ support a variety of options:</p>
&lt;interface type='network'&gt;
&lt;source network='default'/&gt;
&lt;target dev='vnet7'/&gt;
&lt;mac address="11:22:33:44:55:66:/&gt;
&lt;mac address="11:22:33:44:55:66"/&gt;
&lt;/interface&gt;
</pre>
</li>
......@@ -1007,12 +1007,8 @@ support a variety of options:</p>
&lt;interface type='bridge'&gt;
&lt;source dev='br0'/&gt;
&lt;target dev='vnet7'/&gt;
&lt;mac address="11:22:33:44:55:66:/&gt;
&lt;/interface&gt; &lt;interface type='bridge'&gt;
&lt;source dev='br0'/&gt;
&lt;target dev='vnet7'/&gt;
&lt;mac address="11:22:33:44:55:66:/&gt;
&lt;/interface&gt;</pre>
&lt;mac address="11:22:33:44:55:66"/&gt;
&lt;/interface&gt;</pre>
</li>
<li>Generic connection to LAN
<p>Provides a means for the administrator to execute an arbitrary script
......
......@@ -3035,24 +3035,27 @@ xenHypervisorNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *free
xen_op_v2_sys op_sys;
int i, j, ret;
xenUnifiedPrivatePtr priv;
static int nbNodeCells = -1;
virNodeInfo nodeInfo;
int nbNodeCells;
if (conn == NULL) {
virXenErrorFunc (VIR_ERR_INVALID_ARG, __FUNCTION__,
"invalid argument", 0);
return -1;
}
if (nbNodeCells == -1) {
if (xenDaemonNodeGetInfo(conn, &nodeInfo)) {
virXenErrorFunc (VIR_ERR_XEN_CALL, __FUNCTION__,
"cannot determine actual number of cells",0);
return -1;
}
nbNodeCells = nodeInfo.nodes;
nbNodeCells = xenNbCells(conn);
if (nbNodeCells < 0) {
virXenErrorFunc (VIR_ERR_XEN_CALL, __FUNCTION__,
"cannot determine actual number of cells",0);
return(-1);
}
if ((conn == NULL) || (maxCells < 1) || (startCell >= nbNodeCells)) {
if ((maxCells < 1) || (startCell >= nbNodeCells)) {
virXenErrorFunc (VIR_ERR_INVALID_ARG, __FUNCTION__,
"invalid argument", 0);
return -1;
}
/*
* Support only sys_interface_version >=4
*/
......
......@@ -37,6 +37,9 @@
#include "xs_internal.h"
#include "xm_internal.h"
static int
xenUnifiedNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info);
/* The five Xen drivers below us. */
static struct xenUnifiedDriver *drivers[XEN_UNIFIED_NR_DRIVERS] = {
[XEN_UNIFIED_HYPERVISOR_OFFSET] = &xenHypervisorDriver,
......@@ -64,6 +67,62 @@ xenUnifiedError (virConnectPtr conn, virErrorNumber error, const char *info)
errmsg, info, NULL, 0, 0, errmsg, info);
}
/*
* Helper functions currently used in the NUMA code
* Those variables should not be accessed directly but through helper
* functions xenNbCells() and xenNbCpu() available to all Xen backends
*/
static int nbNodeCells = -1;
static int nbNodeCpus = -1;
/**
* xenNumaInit:
* @conn: pointer to the hypervisor connection
*
* Initializer for previous variables. We currently assume that
* the number of physical CPU and the numebr of NUMA cell is fixed
* until reboot which might be false in future Xen implementations.
*/
static void
xenNumaInit(virConnectPtr conn) {
virNodeInfo nodeInfo;
int ret;
ret = xenUnifiedNodeGetInfo(conn, &nodeInfo);
if (ret < 0)
return;
nbNodeCells = nodeInfo.nodes;
nbNodeCpus = nodeInfo.cpus;
}
/**
* xenNbCells:
* @conn: pointer to the hypervisor connection
*
* Number of NUMa cells present in the actual Node
*
* Returns the number of NUMA cells available on that Node
*/
int xenNbCells(virConnectPtr conn) {
if (nbNodeCells < 0)
xenNumaInit(conn);
return(nbNodeCells);
}
/**
* xenNbCpus:
* @conn: pointer to the hypervisor connection
*
* Number of NUMa cells present in the actual Node
*
* Returns the number of NUMA cells available on that Node
*/
int xenNbCpus(virConnectPtr conn) {
if (nbNodeCpus < 0)
xenNumaInit(conn);
return(nbNodeCpus);
}
/*----- Dispatch functions. -----*/
/* These dispatch functions follow the model used historically
......
......@@ -116,6 +116,9 @@ struct _xenUnifiedPrivate {
typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr;
int xenNbCells(virConnectPtr conn);
int xenNbCpus(virConnectPtr conn);
#ifdef __cplusplus
}
#endif
......
......@@ -1895,352 +1895,6 @@ sexpr_to_xend_node_info(struct sexpr *root, virNodeInfoPtr info)
return (0);
}
/**
* skipSpaces:
* @str: pointer to the char pointer used
*
* Skip potential blanks, this includes space tabs, line feed,
* carriage returns and also '\\' which can be erronously emitted
* by xend
*/
static void
skipSpaces(const char **str) {
const char *cur = *str;
while ((*cur == ' ') || (*cur == '\t') || (*cur == '\n') ||
(*cur == '\r') || (*cur == '\\')) cur++;
*str = cur;
}
/**
* parseNumber:
* @str: pointer to the char pointer used
*
* Parse a number
*
* Returns the CPU number or -1 in case of error. @str will be
* updated to skip the number.
*/
static int
parseNumber(const char **str) {
int ret = 0;
const char *cur = *str;
if ((*cur < '0') || (*cur > '9'))
return(-1);
while ((*cur >= '0') && (*cur <= '9')) {
ret = ret * 10 + (*cur - '0');
cur++;
}
*str = cur;
return(ret);
}
/**
* parseCpuNumber:
* @str: pointer to the char pointer used
* @maxcpu: maximum CPU number allowed
*
* Parse a CPU number
*
* Returns the CPU number or -1 in case of error. @str will be
* updated to skip the number.
*/
static int
parseCpuNumber(const char **str, int maxcpu) {
int ret = 0;
const char *cur = *str;
if ((*cur < '0') || (*cur > '9'))
return(-1);
while ((*cur >= '0') && (*cur <= '9')) {
ret = ret * 10 + (*cur - '0');
if (ret > maxcpu)
return(-1);
cur++;
}
*str = cur;
return(ret);
}
#if 0 /* Not used yet */
/**
* saveCpuSet:
* @conn: connection
* @cpuset: pointer to a char array for the CPU set
* @maxcpu: number of elements available in @cpuset
*
* Serialize the cpuset to a string
*
* 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)
{
virBufferPtr buf;
char *ret;
int start, cur;
int first = 1;
if ((cpuset == NULL) || (maxcpu <= 0) || (maxcpu >100000))
return(NULL);
buf = virBufferNew(1000);
if (buf == NULL) {
virXendError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"));
return(NULL);
}
cur = 0;
start = -1;
while (cur < maxcpu) {
if (cpuset[cur]) {
if (start == -1)
start = cur;
} else if (start != -1) {
if (!first)
virBufferAdd(buf, ",", -1);
else
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;
}
cur++;
}
if (start != -1) {
if (!first)
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);
}
ret = virBufferContentAndFree(buf);
return(ret);
}
#endif
/**
* parseCpuSet:
* @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
* @maxcpu: number of elements available in @cpuset
*
* Parse the cpu set, it will set the value for enabled CPUs in the @cpuset
* to 1, and 0 otherwise. The syntax allows coma separated entries each
* can be either a CPU number, ^N to unset that CPU or N-M for ranges.
*
* Returns the number of CPU found in that set, or -1 in case of error.
* @cpuset is modified accordingly to the value parsed.
* @str is updated to the end of the part parsed
*/
static int
parseCpuSet(virConnectPtr conn, const char **str, char sep, char *cpuset,
int maxcpu)
{
const char *cur;
int ret = 0;
int i, start, last;
int neg = 0;
if ((str == NULL) || (cpuset == NULL) || (maxcpu <= 0) || (maxcpu >100000))
return(-1);
cur = *str;
skipSpaces(&cur);
if (*cur == 0)
goto parse_error;
/* initialize cpumap to all 0s */
for (i = 0;i < maxcpu;i++)
cpuset[i] = 0;
ret = 0;
while ((*cur != 0) && (*cur != sep)) {
/*
* 3 constructs are allowed:
* - N : a single CPU number
* - N-M : a range of CPU numbers with N < M
* - ^N : remove a single CPU number from the current set
*/
if (*cur == '^') {
cur++;
neg = 1;
}
if ((*cur < '0') || (*cur > '9'))
goto parse_error;
start = parseCpuNumber(&cur, maxcpu);
if (start < 0)
goto parse_error;
skipSpaces(&cur);
if ((*cur == ',') || (*cur == 0) || (*cur == sep)) {
if (neg) {
if (cpuset[start] == 1) {
cpuset[start] = 0;
ret--;
}
} else {
if (cpuset[start] == 0) {
cpuset[start] = 1;
ret++;
}
}
} else if (*cur == '-') {
if (neg)
goto parse_error;
cur++;
skipSpaces(&cur);
last = parseCpuNumber(&cur, maxcpu);
if (last < start)
goto parse_error;
for (i = start;i <= last;i++) {
if (cpuset[i] == 0) {
cpuset[i] = 1;
ret++;
}
}
skipSpaces(&cur);
}
if (*cur == ',') {
cur++;
skipSpaces(&cur);
neg = 0;
} else if ((*cur == 0) || (*cur == sep)) {
break;
} else
goto parse_error;
}
*str = cur;
return(ret);
parse_error:
virXendError(conn, VIR_ERR_XEN_CALL,
_("topology cpuset syntax error"));
return(-1);
}
/**
* parseXenCpuTopology:
* @xml: XML output buffer
* @str: the topology string
* @maxcpu: number of elements available in @cpuset
*
* Parse a Xend CPU topology string and build the associated XML
* format.
*
* Returns 0 in case of success, -1 in case of error
*/
static int
parseTopology(virConnectPtr conn, virBufferPtr xml, const char *str,
int maxcpu)
{
const char *cur;
char *cpuset = NULL;
int cell, cpu, nb_cpus;
int ret;
if ((str == NULL) || (xml == NULL) || (maxcpu <= 0) || (maxcpu >100000))
return(-1);
cpuset = malloc(maxcpu * sizeof(char));
if (cpuset == NULL)
goto memory_error;
cur = str;
while (*cur != 0) {
/*
* Find the next NUMA cell described in the xend output
*/
cur = strstr(cur, "node");
if (cur == NULL)
break;
cur += 4;
cell = parseNumber(&cur);
if (cell < 0)
goto parse_error;
skipSpaces(&cur);
if (*cur != ':')
goto parse_error;
cur++;
skipSpaces(&cur);
if (!strncmp (cur, "no cpus", 7)) {
nb_cpus = 0;
for (cpu = 0;cpu < maxcpu;cpu++)
cpuset[cpu] = 0;
} else {
nb_cpus = parseCpuSet(conn, &cur, 'n', cpuset, maxcpu);
if (nb_cpus < 0)
goto error;
}
/*
* add xml for all cpus associated with that cell
*/
ret = virBufferVSprintf (xml, "\
<cell id='%d'>\n\
<cpus num='%d'>\n", cell, nb_cpus);
#ifdef STANDALONE
{
char *dump;
dump = saveCpuSet(conn, cpuset, maxcpu);
if (dump != NULL) {
virBufferVSprintf (xml, " <dump>%s</dump>\n", dump);
free(dump);
} else {
virBufferVSprintf (xml, " <error>%s</error>\n",
"Failed to dump CPU set");
}
}
#endif
if (ret < 0)
goto memory_error;
for (cpu = 0;cpu < maxcpu;cpu++) {
if (cpuset[cpu] == 1) {
ret = virBufferVSprintf (xml, "\
<cpu id='%d'/>\n", cpu);
if (ret < 0)
goto memory_error;
}
}
ret = virBufferAdd (xml, "\
</cpus>\n\
</cell>\n", -1);
if (ret < 0)
goto memory_error;
}
free(cpuset);
return(0);
parse_error:
virXendError(conn, VIR_ERR_XEN_CALL,
_("topology syntax error"));
error:
if (cpuset != NULL)
free(cpuset);
return(-1);
memory_error:
if (cpuset != NULL)
free(cpuset);
virXendError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"));
return(-1);
}
/**
* sexpr_to_xend_topology_xml:
* @root: an S-Expression describing a node
......@@ -2276,7 +1930,7 @@ sexpr_to_xend_topology_xml(virConnectPtr conn, struct sexpr *root, virBufferPtr
numCells);
if (r < 0) goto vir_buffer_failed;
r = parseTopology(conn, xml, nodeToCpu, numCpus);
r = virParseXenCpuTopology(conn, xml, nodeToCpu, numCpus);
if (r < 0) goto error;
r = virBufferAdd (xml, "\
......
......@@ -24,6 +24,7 @@
#include "xml.h"
#include "buf.h"
#include "xs_internal.h" /* for xenStoreDomainGetNetworkID */
#include "xen_unified.h"
#ifndef PROXY
/**
......@@ -48,6 +49,362 @@ virXMLError(virConnectPtr conn, virErrorNumber error, const char *info, int valu
errmsg, info, NULL, value, 0, errmsg, info, value);
}
/************************************************************************
* *
* Parser and converter for the CPUset strings used in libvirt *
* *
************************************************************************/
/**
* skipSpaces:
* @str: pointer to the char pointer used
*
* Skip potential blanks, this includes space tabs, line feed,
* carriage returns and also '\\' which can be erronously emitted
* by xend
*/
static void
skipSpaces(const char **str) {
const char *cur = *str;
while ((*cur == ' ') || (*cur == '\t') || (*cur == '\n') ||
(*cur == '\r') || (*cur == '\\')) cur++;
*str = cur;
}
/**
* parseNumber:
* @str: pointer to the char pointer used
*
* Parse a number
*
* Returns the CPU number or -1 in case of error. @str will be
* updated to skip the number.
*/
static int
parseNumber(const char **str) {
int ret = 0;
const char *cur = *str;
if ((*cur < '0') || (*cur > '9'))
return(-1);
while ((*cur >= '0') && (*cur <= '9')) {
ret = ret * 10 + (*cur - '0');
cur++;
}
*str = cur;
return(ret);
}
/**
* parseCpuNumber:
* @str: pointer to the char pointer used
* @maxcpu: maximum CPU number allowed
*
* Parse a CPU number
*
* Returns the CPU number or -1 in case of error. @str will be
* updated to skip the number.
*/
static int
parseCpuNumber(const char **str, int maxcpu) {
int ret = 0;
const char *cur = *str;
if ((*cur < '0') || (*cur > '9'))
return(-1);
while ((*cur >= '0') && (*cur <= '9')) {
ret = ret * 10 + (*cur - '0');
if (ret > maxcpu)
return(-1);
cur++;
}
*str = cur;
return(ret);
}
/**
* saveCpuSet:
* @conn: connection
* @cpuset: pointer to a char array for the CPU set
* @maxcpu: number of elements available in @cpuset
*
* Serialize the cpuset to a string
*
* 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)
{
virBufferPtr buf;
char *ret;
int start, cur;
int first = 1;
if ((cpuset == NULL) || (maxcpu <= 0) || (maxcpu >100000))
return(NULL);
buf = virBufferNew(1000);
if (buf == NULL) {
virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 1000);
return(NULL);
}
cur = 0;
start = -1;
while (cur < maxcpu) {
if (cpuset[cur]) {
if (start == -1)
start = cur;
} else if (start != -1) {
if (!first)
virBufferAdd(buf, ",", -1);
else
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;
}
cur++;
}
if (start != -1) {
if (!first)
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);
}
ret = virBufferContentAndFree(buf);
return(ret);
}
/**
* virParseCpuSet:
* @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
* @maxcpu: number of elements available in @cpuset
*
* Parse the cpu set, it will set the value for enabled CPUs in the @cpuset
* to 1, and 0 otherwise. The syntax allows coma separated entries each
* can be either a CPU number, ^N to unset that CPU or N-M for ranges.
*
* Returns the number of CPU found in that set, or -1 in case of error.
* @cpuset is modified accordingly to the value parsed.
* @str is updated to the end of the part parsed
*/
int
virParseCpuSet(virConnectPtr conn, const char **str, char sep, char *cpuset,
int maxcpu)
{
const char *cur;
int ret = 0;
int i, start, last;
int neg = 0;
if ((str == NULL) || (cpuset == NULL) || (maxcpu <= 0) || (maxcpu >100000))
return(-1);
cur = *str;
skipSpaces(&cur);
if (*cur == 0)
goto parse_error;
/* initialize cpumap to all 0s */
for (i = 0;i < maxcpu;i++)
cpuset[i] = 0;
ret = 0;
while ((*cur != 0) && (*cur != sep)) {
/*
* 3 constructs are allowed:
* - N : a single CPU number
* - N-M : a range of CPU numbers with N < M
* - ^N : remove a single CPU number from the current set
*/
if (*cur == '^') {
cur++;
neg = 1;
}
if ((*cur < '0') || (*cur > '9'))
goto parse_error;
start = parseCpuNumber(&cur, maxcpu);
if (start < 0)
goto parse_error;
skipSpaces(&cur);
if ((*cur == ',') || (*cur == 0) || (*cur == sep)) {
if (neg) {
if (cpuset[start] == 1) {
cpuset[start] = 0;
ret--;
}
} else {
if (cpuset[start] == 0) {
cpuset[start] = 1;
ret++;
}
}
} else if (*cur == '-') {
if (neg)
goto parse_error;
cur++;
skipSpaces(&cur);
last = parseCpuNumber(&cur, maxcpu);
if (last < start)
goto parse_error;
for (i = start;i <= last;i++) {
if (cpuset[i] == 0) {
cpuset[i] = 1;
ret++;
}
}
skipSpaces(&cur);
}
if (*cur == ',') {
cur++;
skipSpaces(&cur);
neg = 0;
} else if ((*cur == 0) || (*cur == sep)) {
break;
} else
goto parse_error;
}
*str = cur;
return(ret);
parse_error:
virXMLError(conn, VIR_ERR_XEN_CALL,
_("topology cpuset syntax error"), 0);
return(-1);
}
/**
* virParseXenCpuTopology:
* @xml: XML output buffer
* @str: the topology string
* @maxcpu: number of elements available in @cpuset
*
* Parse a Xend CPU topology string and build the associated XML
* format.
*
* Returns 0 in case of success, -1 in case of error
*/
int
virParseXenCpuTopology(virConnectPtr conn, virBufferPtr xml, const char *str,
int maxcpu)
{
const char *cur;
char *cpuset = NULL;
int cell, cpu, nb_cpus;
int ret;
if ((str == NULL) || (xml == NULL) || (maxcpu <= 0) || (maxcpu >100000))
return(-1);
cpuset = malloc(maxcpu * sizeof(char));
if (cpuset == NULL)
goto memory_error;
cur = str;
while (*cur != 0) {
/*
* Find the next NUMA cell described in the xend output
*/
cur = strstr(cur, "node");
if (cur == NULL)
break;
cur += 4;
cell = parseNumber(&cur);
if (cell < 0)
goto parse_error;
skipSpaces(&cur);
if (*cur != ':')
goto parse_error;
cur++;
skipSpaces(&cur);
if (!strncmp (cur, "no cpus", 7)) {
nb_cpus = 0;
for (cpu = 0;cpu < maxcpu;cpu++)
cpuset[cpu] = 0;
} else {
nb_cpus = virParseCpuSet(conn, &cur, 'n', cpuset, maxcpu);
if (nb_cpus < 0)
goto error;
}
/*
* add xml for all cpus associated with that cell
*/
ret = virBufferVSprintf (xml, "\
<cell id='%d'>\n\
<cpus num='%d'>\n", cell, nb_cpus);
#ifdef STANDALONE
{
char *dump;
dump = saveCpuSet(conn, cpuset, maxcpu);
if (dump != NULL) {
virBufferVSprintf (xml, " <dump>%s</dump>\n", dump);
free(dump);
} else {
virBufferVSprintf (xml, " <error>%s</error>\n",
"Failed to dump CPU set");
}
}
#endif
if (ret < 0)
goto memory_error;
for (cpu = 0;cpu < maxcpu;cpu++) {
if (cpuset[cpu] == 1) {
ret = virBufferVSprintf (xml, "\
<cpu id='%d'/>\n", cpu);
if (ret < 0)
goto memory_error;
}
}
ret = virBufferAdd (xml, "\
</cpus>\n\
</cell>\n", -1);
if (ret < 0)
goto memory_error;
}
free(cpuset);
return(0);
parse_error:
virXMLError(conn, VIR_ERR_XEN_CALL,
_("topology syntax error"), 0);
error:
if (cpuset != NULL)
free(cpuset);
return(-1);
memory_error:
if (cpuset != NULL)
free(cpuset);
virXMLError(conn, VIR_ERR_NO_MEMORY, _("allocate buffer"), 0);
return(-1);
}
/************************************************************************
* *
* Wrappers around libxml2 XPath specific functions *
* *
************************************************************************/
/**
* virXPathString:
* @xpath: the XPath string to evaluate
......@@ -271,6 +628,12 @@ virXPathNodeSet(const char *xpath, xmlXPathContextPtr ctxt, xmlNodePtr **list) {
return(ret);
}
/************************************************************************
* *
* Converter functions to go from the XML tree to an S-Expr for Xen *
* *
************************************************************************/
/**
* virtDomainParseXMLGraphicsDescImage:
* @conn: pointer to the hypervisor connection
......@@ -1167,6 +1530,36 @@ virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int
}
virBufferVSprintf(&buf, "(vcpus %u)", vcpus);
str = virXPathString("string(/domain/vcpu/@cpuset)", ctxt);
if (str != NULL) {
int maxcpu = xenNbCpus(conn);
char *cpuset = NULL;
char *ranges = NULL;
const char *cur = str;
/*
* Parse the CPUset attribute given in libvirt format and reserialize
* it in a range format guaranteed to be understood by Xen.
*/
if (maxcpu > 0) {
cpuset = malloc(maxcpu * sizeof(char));
if (cpuset != NULL) {
res = virParseCpuSet(conn, &cur, 0, cpuset, maxcpu);
if (res > 0) {
ranges = saveCpuSet(conn, cpuset, maxcpu);
if (ranges != NULL) {
virBufferVSprintf(&buf, "(cpus '%s')", ranges);
free(ranges);
}
}
free(cpuset);
} else {
virXMLError(conn, VIR_ERR_NO_MEMORY, xmldesc, 0);
}
}
free(str);
}
str = virXPathString("string(/domain/uuid[1])", ctxt);
if (str != NULL) {
virBufferVSprintf(&buf, "(uuid '%s')", str);
......
......@@ -7,6 +7,7 @@
#include "libvirt/libvirt.h"
#include "internal.h"
#include "buf.h"
#include <libxml/parser.h>
#include <libxml/tree.h>
......@@ -31,9 +32,28 @@ int virXPathNodeSet (const char *xpath,
xmlXPathContextPtr ctxt,
xmlNodePtr **list);
char *virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int xendConfigVersion);
char *virParseXMLDevice(virConnectPtr conn, const char *xmldesc, int hvm, int xendConfigVersion);
int virDomainXMLDevID(virDomainPtr domain, const char *xmldesc, char *class, char *ref, int ref_len);
int virParseXenCpuTopology(virConnectPtr conn,
virBufferPtr xml,
const char *str,
int maxcpu);
int virParseCpuSet (virConnectPtr conn,
const char **str,
char sep,
char *cpuset,
int maxcpu);
char * virDomainParseXMLDesc(virConnectPtr conn,
const char *xmldesc,
char **name,
int xendConfigVersion);
char * virParseXMLDevice(virConnectPtr conn,
const char *xmldesc,
int hvm,
int xendConfigVersion);
int virDomainXMLDevID(virDomainPtr domain,
const char *xmldesc,
char *class,
char *ref,
int ref_len);
#ifdef __cplusplus
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册