* src/xml.[ch]: first patch to clean up XPath accesses with new
routines, only xml.c is cleaned up, other modules to follow. Daniel
This commit is contained in:
parent
18cd1a1e57
commit
4bdac20ad6
@ -1,3 +1,8 @@
|
|||||||
|
Fri Apr 6 14:27:13 CEST 2007 Daniel Veillard <veillard@redhat.com>
|
||||||
|
|
||||||
|
* src/xml.[ch]: first patch to clean up XPath accesses with new
|
||||||
|
routines, only xml.c is cleaned up, other modules to follow.
|
||||||
|
|
||||||
Wed Apr 4 15:18:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
|
Wed Apr 4 15:18:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
|
||||||
|
|
||||||
* src/xen_unified.c et al: Unified Xen driver. Architecture
|
* src/xen_unified.c et al: Unified Xen driver. Architecture
|
||||||
|
521
src/xml.c
521
src/xml.c
@ -17,9 +17,6 @@
|
|||||||
#ifdef WITH_XEN
|
#ifdef WITH_XEN
|
||||||
#include <xs.h>
|
#include <xs.h>
|
||||||
#endif
|
#endif
|
||||||
#include <libxml/parser.h>
|
|
||||||
#include <libxml/tree.h>
|
|
||||||
#include <libxml/xpath.h>
|
|
||||||
#include <math.h> /* for isnan() */
|
#include <math.h> /* for isnan() */
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
@ -27,6 +24,15 @@
|
|||||||
#include "xml.h"
|
#include "xml.h"
|
||||||
#include "xs_internal.h" /* for xenStoreDomainGetNetworkID */
|
#include "xs_internal.h" /* for xenStoreDomainGetNetworkID */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virXMLError:
|
||||||
|
* @conn: a connection if any
|
||||||
|
* @error: the error number
|
||||||
|
* @info: information/format string
|
||||||
|
* @value: extra integer parameter for the error string
|
||||||
|
*
|
||||||
|
* Report an error coming from the XML module.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
virXMLError(virConnectPtr conn, virErrorNumber error, const char *info, int value)
|
virXMLError(virConnectPtr conn, virErrorNumber error, const char *info, int value)
|
||||||
{
|
{
|
||||||
@ -40,6 +46,227 @@ virXMLError(virConnectPtr conn, virErrorNumber error, const char *info, int valu
|
|||||||
errmsg, info, NULL, value, 0, errmsg, info, value);
|
errmsg, info, NULL, value, 0, errmsg, info, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef PROXY
|
||||||
|
/**
|
||||||
|
* virXPathString:
|
||||||
|
* @xpath: the XPath string to evaluate
|
||||||
|
* @ctxt: an XPath context
|
||||||
|
*
|
||||||
|
* Convenience function to evaluate an XPath string
|
||||||
|
*
|
||||||
|
* Returns a new string which must be deallocated by the caller or NULL
|
||||||
|
* if the evaluation failed.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
virXPathString(const char *xpath, xmlXPathContextPtr ctxt) {
|
||||||
|
xmlXPathObjectPtr obj;
|
||||||
|
char *ret;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (xpath == NULL)) {
|
||||||
|
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"Invalid parameter to virXPathString()", 0);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
|
||||||
|
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
||||||
|
(obj->stringval == NULL) || (obj->stringval[0] == 0))
|
||||||
|
return(NULL);
|
||||||
|
ret = strdup((char *) obj->stringval);
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
if (ret == NULL) {
|
||||||
|
virXMLError(NULL, VIR_ERR_NO_MEMORY, "strdup", 0);
|
||||||
|
}
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virXPathNumber:
|
||||||
|
* @xpath: the XPath string to evaluate
|
||||||
|
* @ctxt: an XPath context
|
||||||
|
* @value: the returned double value
|
||||||
|
*
|
||||||
|
* Convenience function to evaluate an XPath number
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success in which case @value is set,
|
||||||
|
* or -1 if the evaluation failed.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virXPathNumber(const char *xpath, xmlXPathContextPtr ctxt, double *value) {
|
||||||
|
xmlXPathObjectPtr obj;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) {
|
||||||
|
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"Invalid parameter to virXPathNumber()", 0);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
|
||||||
|
if ((obj == NULL) || (obj->type != XPATH_NUMBER) ||
|
||||||
|
(isnan(obj->floatval))) {
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = obj->floatval;
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virXPathLong:
|
||||||
|
* @xpath: the XPath string to evaluate
|
||||||
|
* @ctxt: an XPath context
|
||||||
|
* @value: the returned long value
|
||||||
|
*
|
||||||
|
* Convenience function to evaluate an XPath number
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success in which case @value is set,
|
||||||
|
* or -1 if the evaluation failed.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virXPathLong(const char *xpath, xmlXPathContextPtr ctxt, long *value) {
|
||||||
|
xmlXPathObjectPtr obj;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) {
|
||||||
|
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"Invalid parameter to virXPathNumber()", 0);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
|
||||||
|
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
|
||||||
|
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
|
||||||
|
char *conv = NULL;
|
||||||
|
long val;
|
||||||
|
|
||||||
|
val = strtol((const char*)obj->stringval, &conv, 10);
|
||||||
|
if (conv == (const char*)obj->stringval) {
|
||||||
|
ret = -2;
|
||||||
|
} else {
|
||||||
|
*value = val;
|
||||||
|
}
|
||||||
|
} else if ((obj != NULL) && (obj->type == XPATH_NUMBER) &&
|
||||||
|
(!(isnan(obj->floatval)))) {
|
||||||
|
*value = (long) obj->floatval;
|
||||||
|
if (*value != obj->floatval) {
|
||||||
|
ret = -2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virXPathBoolean:
|
||||||
|
* @xpath: the XPath string to evaluate
|
||||||
|
* @ctxt: an XPath context
|
||||||
|
*
|
||||||
|
* Convenience function to evaluate an XPath boolean
|
||||||
|
*
|
||||||
|
* Returns 0 if false, 1 if true, or -1 if the evaluation failed.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virXPathBoolean(const char *xpath, xmlXPathContextPtr ctxt) {
|
||||||
|
xmlXPathObjectPtr obj;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (xpath == NULL)) {
|
||||||
|
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"Invalid parameter to virXPathBoolean()", 0);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
|
||||||
|
if ((obj == NULL) || (obj->type != XPATH_BOOLEAN) ||
|
||||||
|
(obj->boolval < 0) || (obj->boolval > 1)) {
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
ret = obj->boolval;
|
||||||
|
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virXPathNode:
|
||||||
|
* @xpath: the XPath string to evaluate
|
||||||
|
* @ctxt: an XPath context
|
||||||
|
*
|
||||||
|
* Convenience function to evaluate an XPath node set and returning
|
||||||
|
* only one node, the first one in the set if any
|
||||||
|
*
|
||||||
|
* Returns a pointer to the node or NULL if the evaluation failed.
|
||||||
|
*/
|
||||||
|
xmlNodePtr
|
||||||
|
virXPathNode(const char *xpath, xmlXPathContextPtr ctxt) {
|
||||||
|
xmlXPathObjectPtr obj;
|
||||||
|
xmlNodePtr ret;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (xpath == NULL)) {
|
||||||
|
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"Invalid parameter to virXPathNode()", 0);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
|
||||||
|
if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
|
||||||
|
(obj->nodesetval == NULL) || (obj->nodesetval->nodeNr <= 0) ||
|
||||||
|
(obj->nodesetval->nodeTab == NULL)) {
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = obj->nodesetval->nodeTab[0];
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* virXPathNodeSet:
|
||||||
|
* @xpath: the XPath string to evaluate
|
||||||
|
* @ctxt: an XPath context
|
||||||
|
* @list: the returned list of nodes (or NULL if only count matters)
|
||||||
|
*
|
||||||
|
* Convenience function to evaluate an XPath node set
|
||||||
|
*
|
||||||
|
* Returns the number of nodes found in which case @list is set (and
|
||||||
|
* must be freed) or -1 if the evaluation failed.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virXPathNodeSet(const char *xpath, xmlXPathContextPtr ctxt, xmlNodePtr **list) {
|
||||||
|
xmlXPathObjectPtr obj;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ctxt == NULL) || (xpath == NULL)) {
|
||||||
|
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"Invalid parameter to virXPathNodeSet()", 0);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
|
||||||
|
if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
|
||||||
|
(obj->nodesetval == NULL) || (obj->nodesetval->nodeNr <= 0) ||
|
||||||
|
(obj->nodesetval->nodeTab == NULL)) {
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
if (list != NULL)
|
||||||
|
*list = NULL;
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = obj->nodesetval->nodeNr;
|
||||||
|
if (list != NULL) {
|
||||||
|
*list = malloc(ret * sizeof(xmlNodePtr));
|
||||||
|
if (*list == NULL) {
|
||||||
|
virXMLError(NULL, VIR_ERR_NO_MEMORY,
|
||||||
|
_("allocate string array"), ret * sizeof(xmlNodePtr));
|
||||||
|
} else {
|
||||||
|
memcpy(*list, obj->nodesetval->nodeTab, ret * sizeof(xmlNodePtr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlXPathFreeObject(obj);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
#endif /* !PROXY */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virBufferGrow:
|
* virBufferGrow:
|
||||||
* @buf: the buffer
|
* @buf: the buffer
|
||||||
@ -360,12 +587,12 @@ static int virDomainParseXMLGraphicsDescVFB(virConnectPtr conn ATTRIBUTE_UNUSED,
|
|||||||
static int
|
static int
|
||||||
virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int vcpus, int xendConfigVersion)
|
virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int vcpus, int xendConfigVersion)
|
||||||
{
|
{
|
||||||
xmlXPathObjectPtr obj = NULL;
|
|
||||||
xmlNodePtr cur, txt;
|
xmlNodePtr cur, txt;
|
||||||
xmlChar *type = NULL;
|
xmlChar *type = NULL;
|
||||||
xmlChar *loader = NULL;
|
xmlChar *loader = NULL;
|
||||||
xmlChar *boot_dev = NULL;
|
xmlChar *boot_dev = NULL;
|
||||||
int res;
|
int res;
|
||||||
|
char *str;
|
||||||
|
|
||||||
cur = node->children;
|
cur = node->children;
|
||||||
while (cur != NULL) {
|
while (cur != NULL) {
|
||||||
@ -403,16 +630,13 @@ virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* get the device emulation model */
|
/* get the device emulation model */
|
||||||
obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt);
|
str = virXPathString("string(/domain/devices/emulator[1])", ctxt);
|
||||||
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
if (str == NULL) {
|
||||||
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
|
||||||
virXMLError(conn, VIR_ERR_NO_KERNEL, NULL, 0); /* TODO: error */
|
virXMLError(conn, VIR_ERR_NO_KERNEL, NULL, 0); /* TODO: error */
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
virBufferVSprintf(buf, "(device_model '%s')",
|
virBufferVSprintf(buf, "(device_model '%s')", str);
|
||||||
(const char *) obj->stringval);
|
xmlFree(str);
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
obj = NULL;
|
|
||||||
|
|
||||||
virBufferVSprintf(buf, "(vcpus %d)", vcpus);
|
virBufferVSprintf(buf, "(vcpus %d)", vcpus);
|
||||||
|
|
||||||
@ -429,102 +653,78 @@ virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* get the 1st floppy device file */
|
/* get the 1st floppy device file */
|
||||||
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='floppy' and target/@dev='fda']/source", ctxt);
|
cur = virXPathNode(
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
"/domain/devices/disk[@device='floppy' and target/@dev='fda']/source",
|
||||||
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
|
ctxt);
|
||||||
cur = obj->nodesetval->nodeTab[0];
|
if (cur != NULL) {
|
||||||
virBufferVSprintf(buf, "(fda '%s')",
|
xmlChar *fdfile;
|
||||||
(const char *) xmlGetProp(cur, BAD_CAST "file"));
|
|
||||||
cur = NULL;
|
fdfile = xmlGetProp(cur, BAD_CAST "file");
|
||||||
}
|
if (fdfile != NULL) {
|
||||||
if (obj) {
|
virBufferVSprintf(buf, "(fda '%s')", fdfile);
|
||||||
xmlXPathFreeObject(obj);
|
free(fdfile);
|
||||||
obj = NULL;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the 2nd floppy device file */
|
/* get the 2nd floppy device file */
|
||||||
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='floppy' and target/@dev='fdb']/source", ctxt);
|
cur = virXPathNode(
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
"/domain/devices/disk[@device='floppy' and target/@dev='fdb']/source",
|
||||||
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
|
ctxt);
|
||||||
xmlChar *fdfile = NULL;
|
if (cur != NULL) {
|
||||||
cur = obj->nodesetval->nodeTab[0];
|
xmlChar *fdfile;
|
||||||
|
|
||||||
fdfile = xmlGetProp(cur, BAD_CAST "file");
|
fdfile = xmlGetProp(cur, BAD_CAST "file");
|
||||||
virBufferVSprintf(buf, "(fdb '%s')",
|
if (fdfile != NULL) {
|
||||||
(const char *) fdfile);
|
virBufferVSprintf(buf, "(fdb '%s')", fdfile);
|
||||||
xmlFree(fdfile);
|
free(fdfile);
|
||||||
cur = NULL;
|
}
|
||||||
}
|
|
||||||
if (obj) {
|
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
obj = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* get the cdrom device file */
|
/* get the cdrom device file */
|
||||||
/* Only XenD <= 3.0.2 wants cdrom config here */
|
/* Only XenD <= 3.0.2 wants cdrom config here */
|
||||||
if (xendConfigVersion == 1) {
|
if (xendConfigVersion == 1) {
|
||||||
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='cdrom' and target/@dev='hdc']/source", ctxt);
|
cur = virXPathNode(
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
"/domain/devices/disk[@device='cdrom' and target/@dev='hdc']/source",
|
||||||
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
|
ctxt);
|
||||||
xmlChar *cdfile = NULL;
|
if (cur != NULL) {
|
||||||
cur = obj->nodesetval->nodeTab[0];
|
xmlChar *cdfile;
|
||||||
|
|
||||||
cdfile = xmlGetProp(cur, BAD_CAST "file");
|
cdfile = xmlGetProp(cur, BAD_CAST "file");
|
||||||
virBufferVSprintf(buf, "(cdrom '%s')",
|
if (cdfile != NULL) {
|
||||||
(const char *)cdfile);
|
virBufferVSprintf(buf, "(cdrom '%s')",
|
||||||
xmlFree(cdfile);
|
(const char *)cdfile);
|
||||||
cur = NULL;
|
xmlFree(cdfile);
|
||||||
}
|
}
|
||||||
if (obj) {
|
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
obj = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
obj = xmlXPathEval(BAD_CAST "/domain/features/acpi", ctxt);
|
if (virXPathNode("/domain/features/acpi", ctxt) != NULL)
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
|
||||||
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
|
|
||||||
virBufferAdd(buf, "(acpi 1)", 8);
|
virBufferAdd(buf, "(acpi 1)", 8);
|
||||||
}
|
if (virXPathNode("/domain/features/apic", ctxt) != NULL)
|
||||||
if (obj)
|
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
obj = xmlXPathEval(BAD_CAST "/domain/features/apic", ctxt);
|
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
|
||||||
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
|
|
||||||
virBufferAdd(buf, "(apic 1)", 8);
|
virBufferAdd(buf, "(apic 1)", 8);
|
||||||
}
|
if (virXPathNode("/domain/features/pae", ctxt) != NULL)
|
||||||
if (obj)
|
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
obj = xmlXPathEval(BAD_CAST "/domain/features/pae", ctxt);
|
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
|
||||||
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
|
|
||||||
virBufferAdd(buf, "(pae 1)", 7);
|
virBufferAdd(buf, "(pae 1)", 7);
|
||||||
}
|
|
||||||
if (obj)
|
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
obj = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
obj = xmlXPathEval(BAD_CAST "count(domain/devices/console) > 0", ctxt);
|
res = virXPathBoolean("count(domain/devices/console) > 0", ctxt);
|
||||||
if ((obj == NULL) || (obj->type != XPATH_BOOLEAN)) {
|
if (res < 0) {
|
||||||
virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0);
|
virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (obj->boolval) {
|
if (res) {
|
||||||
virBufferAdd(buf, "(serial pty)", 12);
|
virBufferAdd(buf, "(serial pty)", 12);
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
obj = NULL;
|
|
||||||
|
|
||||||
/* Is a graphics device specified? */
|
/* Is a graphics device specified? */
|
||||||
obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics[1]", ctxt);
|
cur = virXPathNode("/domain/devices/graphics[1]", ctxt);
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
if (cur != NULL) {
|
||||||
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
|
res = virDomainParseXMLGraphicsDescImage(conn, cur, buf,
|
||||||
res = virDomainParseXMLGraphicsDescImage(conn, obj->nodesetval->nodeTab[0], buf, xendConfigVersion);
|
xendConfigVersion);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
|
|
||||||
virBufferAdd(buf, "))", 2);
|
virBufferAdd(buf, "))", 2);
|
||||||
|
|
||||||
@ -535,8 +735,6 @@ virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf
|
|||||||
error:
|
error:
|
||||||
if (boot_dev)
|
if (boot_dev)
|
||||||
xmlFree(boot_dev);
|
xmlFree(boot_dev);
|
||||||
if (obj != NULL)
|
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,7 +757,6 @@ static int
|
|||||||
virDomainParseXMLOSDescPV(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int xendConfigVersion)
|
virDomainParseXMLOSDescPV(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int xendConfigVersion)
|
||||||
{
|
{
|
||||||
xmlNodePtr cur, txt;
|
xmlNodePtr cur, txt;
|
||||||
xmlXPathObjectPtr obj = NULL;
|
|
||||||
const xmlChar *type = NULL;
|
const xmlChar *type = NULL;
|
||||||
const xmlChar *root = NULL;
|
const xmlChar *root = NULL;
|
||||||
const xmlChar *kernel = NULL;
|
const xmlChar *kernel = NULL;
|
||||||
@ -626,15 +823,14 @@ virDomainParseXMLOSDescPV(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf,
|
|||||||
/* Is a graphics device specified? */
|
/* Is a graphics device specified? */
|
||||||
/* Old style config before merge of PVFB */
|
/* Old style config before merge of PVFB */
|
||||||
if (xendConfigVersion < 3) {
|
if (xendConfigVersion < 3) {
|
||||||
obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics[1]", ctxt);
|
cur = virXPathNode("/domain/devices/graphics[1]", ctxt);
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
if (cur != NULL) {
|
||||||
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
|
res = virDomainParseXMLGraphicsDescImage(conn, cur, buf,
|
||||||
res = virDomainParseXMLGraphicsDescImage(conn, obj->nodesetval->nodeTab[0], buf, xendConfigVersion);
|
xendConfigVersion);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@ -958,14 +1154,16 @@ virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int
|
|||||||
virBuffer buf;
|
virBuffer buf;
|
||||||
xmlChar *prop;
|
xmlChar *prop;
|
||||||
xmlParserCtxtPtr pctxt;
|
xmlParserCtxtPtr pctxt;
|
||||||
xmlXPathObjectPtr obj = NULL;
|
|
||||||
xmlXPathObjectPtr tmpobj = NULL;
|
|
||||||
xmlXPathContextPtr ctxt = NULL;
|
xmlXPathContextPtr ctxt = NULL;
|
||||||
int i, res;
|
int i, res;
|
||||||
int bootloader = 0;
|
int bootloader = 0;
|
||||||
int hvm = 0;
|
int hvm = 0;
|
||||||
unsigned int vcpus = 1;
|
unsigned int vcpus = 1;
|
||||||
unsigned long mem = 0, max_mem = 0;
|
unsigned long mem = 0, max_mem = 0;
|
||||||
|
char *str;
|
||||||
|
double f;
|
||||||
|
xmlNodePtr *nodes;
|
||||||
|
int nb_nodes;
|
||||||
|
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
*name = NULL;
|
*name = NULL;
|
||||||
@ -1012,117 +1210,90 @@ virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int
|
|||||||
/*
|
/*
|
||||||
* extract some of the basics, name, memory, cpus ...
|
* extract some of the basics, name, memory, cpus ...
|
||||||
*/
|
*/
|
||||||
obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt);
|
nam = virXPathString("string(/domain/name[1])", ctxt);
|
||||||
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
if (nam == NULL) {
|
||||||
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
|
||||||
virXMLError(conn, VIR_ERR_NO_NAME, xmldesc, 0);
|
virXMLError(conn, VIR_ERR_NO_NAME, xmldesc, 0);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
virBufferVSprintf(&buf, "(name '%s')", obj->stringval);
|
virBufferVSprintf(&buf, "(name '%s')", nam);
|
||||||
nam = strdup((const char *) obj->stringval);
|
|
||||||
if (nam == NULL) {
|
|
||||||
virXMLError(conn, VIR_ERR_NO_MEMORY, "copying name", 0);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
|
|
||||||
obj = xmlXPathEval(BAD_CAST "number(/domain/memory[1])", ctxt);
|
if ((virXPathNumber("number(/domain/memory[1])", ctxt, &f) < 0) ||
|
||||||
if ((obj == NULL) || (obj->type != XPATH_NUMBER) ||
|
(f < MIN_XEN_GUEST_SIZE * 1024)) {
|
||||||
(isnan(obj->floatval)) || (obj->floatval < MIN_XEN_GUEST_SIZE * 1024)) {
|
|
||||||
max_mem = 128;
|
max_mem = 128;
|
||||||
} else {
|
} else {
|
||||||
max_mem = (obj->floatval / 1024);
|
max_mem = (f / 1024);
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
obj = xmlXPathEval(BAD_CAST "number(/domain/currentMemory[1])", ctxt);
|
if ((virXPathNumber("number(/domain/currentMemory[1])", ctxt, &f) < 0) ||
|
||||||
if ((obj == NULL) || (obj->type != XPATH_NUMBER) ||
|
(f < MIN_XEN_GUEST_SIZE * 1024)) {
|
||||||
(isnan(obj->floatval)) || (obj->floatval < MIN_XEN_GUEST_SIZE * 1024)) {
|
|
||||||
mem = max_mem;
|
mem = max_mem;
|
||||||
} else {
|
} else {
|
||||||
mem = (obj->floatval / 1024);
|
mem = (f / 1024);
|
||||||
if (mem > max_mem) {
|
if (mem > max_mem) {
|
||||||
max_mem = mem;
|
max_mem = mem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", mem, max_mem);
|
virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", mem, max_mem);
|
||||||
|
|
||||||
obj = xmlXPathEval(BAD_CAST "number(/domain/vcpu[1])", ctxt);
|
if ((virXPathNumber("number(/domain/vcpu[1])", ctxt, &f) == 0) &&
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NUMBER) &&
|
(f > 0)) {
|
||||||
(!isnan(obj->floatval)) && (obj->floatval > 0)) {
|
vcpus = (unsigned int) f;
|
||||||
vcpus = (unsigned int) obj->floatval;
|
|
||||||
}
|
}
|
||||||
virBufferVSprintf(&buf, "(vcpus %u)", vcpus);
|
virBufferVSprintf(&buf, "(vcpus %u)", vcpus);
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
|
|
||||||
obj = xmlXPathEval(BAD_CAST "string(/domain/uuid[1])", ctxt);
|
str = virXPathString("string(/domain/uuid[1])", ctxt);
|
||||||
if ((obj == NULL) || ((obj->type == XPATH_STRING) &&
|
if (str != NULL) {
|
||||||
(obj->stringval != NULL) && (obj->stringval[0] != 0))) {
|
virBufferVSprintf(&buf, "(uuid '%s')", str);
|
||||||
virBufferVSprintf(&buf, "(uuid '%s')", obj->stringval);
|
free(str);
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
|
|
||||||
obj = xmlXPathEval(BAD_CAST "string(/domain/bootloader[1])", ctxt);
|
str = virXPathString("string(/domain/bootloader[1])", ctxt);
|
||||||
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
|
if (str != NULL) {
|
||||||
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
|
virBufferVSprintf(&buf, "(bootloader '%s')", str);
|
||||||
virBufferVSprintf(&buf, "(bootloader '%s')", obj->stringval);
|
|
||||||
/*
|
/*
|
||||||
* if using pygrub, the kernel and initrd strings are not
|
* if using pygrub, the kernel and initrd strings are not
|
||||||
* significant and should be discarded
|
* significant and should be discarded
|
||||||
*/
|
*/
|
||||||
if (xmlStrstr(obj->stringval, BAD_CAST "pygrub"))
|
if (strstr(str, "pygrub"))
|
||||||
bootloader = 2;
|
bootloader = 2;
|
||||||
else
|
else
|
||||||
bootloader = 1;
|
bootloader = 1;
|
||||||
|
free(str);
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
|
|
||||||
obj = xmlXPathEval(BAD_CAST "string(/domain/on_poweroff[1])", ctxt);
|
str = virXPathString("string(/domain/on_poweroff[1])", ctxt);
|
||||||
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
|
if (str != NULL) {
|
||||||
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
|
virBufferVSprintf(&buf, "(on_poweroff '%s')", str);
|
||||||
virBufferVSprintf(&buf, "(on_poweroff '%s')", obj->stringval);
|
free(str);
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
|
|
||||||
obj = xmlXPathEval(BAD_CAST "string(/domain/on_reboot[1])", ctxt);
|
str = virXPathString("string(/domain/on_reboot[1])", ctxt);
|
||||||
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
|
if (str != NULL) {
|
||||||
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
|
virBufferVSprintf(&buf, "(on_reboot '%s')", str);
|
||||||
virBufferVSprintf(&buf, "(on_reboot '%s')", obj->stringval);
|
free(str);
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
|
|
||||||
obj = xmlXPathEval(BAD_CAST "string(/domain/on_crash[1])", ctxt);
|
str = virXPathString("string(/domain/on_crash[1])", ctxt);
|
||||||
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
|
if (str != NULL) {
|
||||||
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
|
virBufferVSprintf(&buf, "(on_crash '%s')", str);
|
||||||
virBufferVSprintf(&buf, "(on_crash '%s')", obj->stringval);
|
free(str);
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
|
|
||||||
if (bootloader != 2) {
|
if (bootloader != 2) {
|
||||||
obj = xmlXPathEval(BAD_CAST "/domain/os[1]", ctxt);
|
if ((node = virXPathNode("/domain/os[1]", ctxt)) != NULL) {
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
|
||||||
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
|
|
||||||
/* Analyze of the os description, based on HVM or PV. */
|
/* Analyze of the os description, based on HVM or PV. */
|
||||||
tmpobj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1])", ctxt);
|
str = virXPathString("string(/domain/os/type[1])", ctxt);
|
||||||
if ((tmpobj != NULL) &&
|
|
||||||
((tmpobj->type != XPATH_STRING) || (tmpobj->stringval == NULL)
|
|
||||||
|| (tmpobj->stringval[0] == 0))) {
|
|
||||||
xmlXPathFreeObject(tmpobj);
|
|
||||||
virXMLError(conn, VIR_ERR_OS_TYPE, nam, 0);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((tmpobj == NULL)
|
if ((str == NULL) || (strcmp(str, "hvm"))) {
|
||||||
|| !xmlStrEqual(tmpobj->stringval, BAD_CAST "hvm")) {
|
res = virDomainParseXMLOSDescPV(conn, node,
|
||||||
res = virDomainParseXMLOSDescPV(conn, obj->nodesetval->nodeTab[0],
|
|
||||||
&buf, ctxt, xendConfigVersion);
|
&buf, ctxt, xendConfigVersion);
|
||||||
} else {
|
} else {
|
||||||
hvm = 1;
|
hvm = 1;
|
||||||
res = virDomainParseXMLOSDescHVM(conn, obj->nodesetval->nodeTab[0],
|
res = virDomainParseXMLOSDescHVM(conn, node, &buf, ctxt,
|
||||||
&buf, ctxt, vcpus, xendConfigVersion);
|
vcpus, xendConfigVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlXPathFreeObject(tmpobj);
|
if (str != NULL) free(str);
|
||||||
|
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
goto error;
|
goto error;
|
||||||
@ -1130,49 +1301,49 @@ virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int
|
|||||||
virXMLError(conn, VIR_ERR_NO_OS, nam, 0);
|
virXMLError(conn, VIR_ERR_NO_OS, nam, 0);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* analyze of the devices */
|
/* analyze of the devices */
|
||||||
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt);
|
nb_nodes = virXPathNodeSet("/domain/devices/disk", ctxt, &nodes);
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
if (nb_nodes > 0) {
|
||||||
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
|
for (i = 0; i < nb_nodes; i++) {
|
||||||
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
|
res = virDomainParseXMLDiskDesc(conn, nodes[i], &buf,
|
||||||
res = virDomainParseXMLDiskDesc(conn, obj->nodesetval->nodeTab[i], &buf, hvm, xendConfigVersion);
|
hvm, xendConfigVersion);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
|
free(nodes);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(nodes);
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
|
|
||||||
obj = xmlXPathEval(BAD_CAST "/domain/devices/interface", ctxt);
|
nb_nodes = virXPathNodeSet("/domain/devices/interface", ctxt, &nodes);
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
if (nb_nodes > 0) {
|
||||||
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
|
for (i = 0; i < nb_nodes; i++) {
|
||||||
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
|
|
||||||
virBufferAdd(&buf, "(device ", 8);
|
virBufferAdd(&buf, "(device ", 8);
|
||||||
res = virDomainParseXMLIfDesc(conn, obj->nodesetval->nodeTab[i], &buf, hvm);
|
res = virDomainParseXMLIfDesc(conn, nodes[i], &buf, hvm);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
|
free(nodes);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
virBufferAdd(&buf, ")", 1);
|
virBufferAdd(&buf, ")", 1);
|
||||||
}
|
}
|
||||||
|
free(nodes);
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
|
|
||||||
/* New style PVFB config - 3.0.4 merge */
|
/* New style PVFB config - 3.0.4 merge */
|
||||||
if (xendConfigVersion >= 3 && !hvm) {
|
if (xendConfigVersion >= 3 && !hvm) {
|
||||||
obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics", ctxt);
|
nb_nodes = virXPathNodeSet("/domain/devices/graphics", ctxt, &nodes);
|
||||||
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
|
if (nb_nodes > 0) {
|
||||||
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
|
for (i = 0; i < nb_nodes; i++) {
|
||||||
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
|
res = virDomainParseXMLGraphicsDescVFB(conn, nodes[i], &buf);
|
||||||
res = virDomainParseXMLGraphicsDescVFB(conn, obj->nodesetval->nodeTab[i], &buf);
|
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
|
free(nodes);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(nodes);
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1195,8 +1366,6 @@ virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int
|
|||||||
free(nam);
|
free(nam);
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
*name = NULL;
|
*name = NULL;
|
||||||
if (obj != NULL)
|
|
||||||
xmlXPathFreeObject(obj);
|
|
||||||
if (ctxt != NULL)
|
if (ctxt != NULL)
|
||||||
xmlXPathFreeContext(ctxt);
|
xmlXPathFreeContext(ctxt);
|
||||||
if (xml != NULL)
|
if (xml != NULL)
|
||||||
|
21
src/xml.h
21
src/xml.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* internal.h: internal definitions just used by code from the library
|
* xml.h: internal definitions used for XML parsing routines.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __VIR_XML_H__
|
#ifndef __VIR_XML_H__
|
||||||
@ -8,6 +8,9 @@
|
|||||||
#include "libvirt/libvirt.h"
|
#include "libvirt/libvirt.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <libxml/parser.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/xpath.h>
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -32,6 +35,22 @@ int virBufferVSprintf(virBufferPtr buf, const char *format, ...)
|
|||||||
ATTRIBUTE_FORMAT(printf, 2, 3);
|
ATTRIBUTE_FORMAT(printf, 2, 3);
|
||||||
int virBufferStrcat(virBufferPtr buf, ...);
|
int virBufferStrcat(virBufferPtr buf, ...);
|
||||||
|
|
||||||
|
int virXPathBoolean (const char *xpath,
|
||||||
|
xmlXPathContextPtr ctxt);
|
||||||
|
char * virXPathString (const char *xpath,
|
||||||
|
xmlXPathContextPtr ctxt);
|
||||||
|
int virXPathNumber (const char *xpath,
|
||||||
|
xmlXPathContextPtr ctxt,
|
||||||
|
double *value);
|
||||||
|
int virXPathLong (const char *xpath,
|
||||||
|
xmlXPathContextPtr ctxt,
|
||||||
|
long *value);
|
||||||
|
xmlNodePtr virXPathNode (const char *xpath,
|
||||||
|
xmlXPathContextPtr ctxt);
|
||||||
|
int virXPathNodeSet (const char *xpath,
|
||||||
|
xmlXPathContextPtr ctxt,
|
||||||
|
xmlNodePtr **list);
|
||||||
|
|
||||||
char *virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int xendConfigVersion);
|
char *virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int xendConfigVersion);
|
||||||
unsigned char *virParseUUID(char **ptr, const char *uuid);
|
unsigned char *virParseUUID(char **ptr, const char *uuid);
|
||||||
char *virParseXMLDevice(virConnectPtr conn, char *xmldesc, int hvm, int xendConfigVersion);
|
char *virParseXMLDevice(virConnectPtr conn, char *xmldesc, int hvm, int xendConfigVersion);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user