mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-26 10:31:16 +00:00
Improve error messages when XML is not well-formed.
* src/domain_conf.c, src/network_conf.c, src/storage_conf.c: Improve error messages from commands such as 'virsh define' when the XML is not well-formed by passing libxml2 errors back out through virterror.
This commit is contained in:
parent
eba65e1c6d
commit
cf11bb2249
@ -1,3 +1,11 @@
|
|||||||
|
Fri Aug 1 10:38:00 BST 2008 Richard W.M. Jones <rjones@redhat.com>
|
||||||
|
|
||||||
|
Improve error messages when XML is not well-formed.
|
||||||
|
* src/domain_conf.c, src/network_conf.c, src/storage_conf.c:
|
||||||
|
Improve error messages from commands such as 'virsh define'
|
||||||
|
when the XML is not well-formed by passing libxml2 errors
|
||||||
|
back out through virterror.
|
||||||
|
|
||||||
Fri Aug 1 08:40:48 CEST 2008 Daniel Veillard <veillard@redhat.com>
|
Fri Aug 1 08:40:48 CEST 2008 Daniel Veillard <veillard@redhat.com>
|
||||||
|
|
||||||
* docs/formatdomain.html docs/formatdomain.html.in docs/libvirt-api.xml
|
* docs/formatdomain.html docs/formatdomain.html.in docs/libvirt-api.xml
|
||||||
|
@ -1838,32 +1838,65 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Called from SAX on parsing errors in the XML. */
|
||||||
|
static void
|
||||||
|
catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
|
||||||
|
{
|
||||||
|
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
|
||||||
|
|
||||||
|
if (ctxt) {
|
||||||
|
virConnectPtr conn = ctxt->_private;
|
||||||
|
|
||||||
|
if (conn &&
|
||||||
|
conn->err.code == VIR_ERR_NONE &&
|
||||||
|
ctxt->lastError.level == XML_ERR_FATAL &&
|
||||||
|
ctxt->lastError.message != NULL) {
|
||||||
|
virDomainReportError (conn, VIR_ERR_XML_DETAIL,
|
||||||
|
_("at line %d: %s"),
|
||||||
|
ctxt->lastError.line,
|
||||||
|
ctxt->lastError.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virDomainDefPtr virDomainDefParseString(virConnectPtr conn,
|
virDomainDefPtr virDomainDefParseString(virConnectPtr conn,
|
||||||
virCapsPtr caps,
|
virCapsPtr caps,
|
||||||
const char *xmlStr)
|
const char *xmlStr)
|
||||||
{
|
{
|
||||||
xmlDocPtr xml;
|
xmlParserCtxtPtr pctxt;
|
||||||
|
xmlDocPtr xml = NULL;
|
||||||
xmlNodePtr root;
|
xmlNodePtr root;
|
||||||
virDomainDefPtr def = NULL;
|
virDomainDefPtr def = NULL;
|
||||||
|
|
||||||
if (!(xml = xmlReadDoc(BAD_CAST xmlStr, "domain.xml", NULL,
|
/* Set up a parser context so we can catch the details of XML errors. */
|
||||||
XML_PARSE_NOENT | XML_PARSE_NONET |
|
pctxt = xmlNewParserCtxt ();
|
||||||
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
|
if (!pctxt || !pctxt->sax)
|
||||||
virDomainReportError(conn, VIR_ERR_XML_ERROR, NULL);
|
goto cleanup;
|
||||||
return NULL;
|
pctxt->sax->error = catchXMLError;
|
||||||
|
pctxt->_private = conn;
|
||||||
|
|
||||||
|
if (conn) virResetError (&conn->err);
|
||||||
|
xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr, "domain.xml", NULL,
|
||||||
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
||||||
|
XML_PARSE_NOWARNING);
|
||||||
|
if (!xml) {
|
||||||
|
if (conn && conn->err.code == VIR_ERR_NONE)
|
||||||
|
virDomainReportError(conn, VIR_ERR_XML_ERROR,
|
||||||
|
_("failed to parse xml document"));
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((root = xmlDocGetRootElement(xml)) == NULL) {
|
if ((root = xmlDocGetRootElement(xml)) == NULL) {
|
||||||
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
"%s", _("missing root element"));
|
"%s", _("missing root element"));
|
||||||
xmlFreeDoc(xml);
|
goto cleanup;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def = virDomainDefParseNode(conn, caps, xml, root);
|
def = virDomainDefParseNode(conn, caps, xml, root);
|
||||||
|
|
||||||
xmlFreeDoc(xml);
|
cleanup:
|
||||||
|
xmlFreeParserCtxt (pctxt);
|
||||||
|
xmlFreeDoc (xml);
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1871,27 +1904,40 @@ virDomainDefPtr virDomainDefParseFile(virConnectPtr conn,
|
|||||||
virCapsPtr caps,
|
virCapsPtr caps,
|
||||||
const char *filename)
|
const char *filename)
|
||||||
{
|
{
|
||||||
xmlDocPtr xml;
|
xmlParserCtxtPtr pctxt;
|
||||||
|
xmlDocPtr xml = NULL;
|
||||||
xmlNodePtr root;
|
xmlNodePtr root;
|
||||||
virDomainDefPtr def = NULL;
|
virDomainDefPtr def = NULL;
|
||||||
|
|
||||||
if (!(xml = xmlReadFile(filename, NULL,
|
/* Set up a parser context so we can catch the details of XML errors. */
|
||||||
XML_PARSE_NOENT | XML_PARSE_NONET |
|
pctxt = xmlNewParserCtxt ();
|
||||||
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
|
if (!pctxt || !pctxt->sax)
|
||||||
virDomainReportError(conn, VIR_ERR_XML_ERROR, NULL);
|
goto cleanup;
|
||||||
return NULL;
|
pctxt->sax->error = catchXMLError;
|
||||||
|
pctxt->_private = conn;
|
||||||
|
|
||||||
|
if (conn) virResetError (&conn->err);
|
||||||
|
xml = xmlCtxtReadFile (pctxt, filename, NULL,
|
||||||
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
||||||
|
XML_PARSE_NOWARNING);
|
||||||
|
if (!xml) {
|
||||||
|
if (conn && conn->err.code == VIR_ERR_NONE)
|
||||||
|
virDomainReportError(conn, VIR_ERR_XML_ERROR,
|
||||||
|
_("failed to parse xml document"));
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((root = xmlDocGetRootElement(xml)) == NULL) {
|
if ((root = xmlDocGetRootElement(xml)) == NULL) {
|
||||||
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
"%s", _("missing root element"));
|
"%s", _("missing root element"));
|
||||||
xmlFreeDoc(xml);
|
goto cleanup;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def = virDomainDefParseNode(conn, caps, xml, root);
|
def = virDomainDefParseNode(conn, caps, xml, root);
|
||||||
|
|
||||||
xmlFreeDoc(xml);
|
cleanup:
|
||||||
|
xmlFreeParserCtxt (pctxt);
|
||||||
|
xmlFreeDoc (xml);
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,57 +348,104 @@ virNetworkDefParseXML(virConnectPtr conn,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Called from SAX on parsing errors in the XML. */
|
||||||
|
static void
|
||||||
|
catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
|
||||||
|
{
|
||||||
|
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
|
||||||
|
|
||||||
|
if (ctxt) {
|
||||||
|
virConnectPtr conn = ctxt->_private;
|
||||||
|
|
||||||
|
if (conn &&
|
||||||
|
conn->err.code == VIR_ERR_NONE &&
|
||||||
|
ctxt->lastError.level == XML_ERR_FATAL &&
|
||||||
|
ctxt->lastError.message != NULL) {
|
||||||
|
virNetworkReportError (conn, VIR_ERR_XML_DETAIL,
|
||||||
|
_("at line %d: %s"),
|
||||||
|
ctxt->lastError.line,
|
||||||
|
ctxt->lastError.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virNetworkDefPtr virNetworkDefParseString(virConnectPtr conn,
|
virNetworkDefPtr virNetworkDefParseString(virConnectPtr conn,
|
||||||
const char *xmlStr)
|
const char *xmlStr)
|
||||||
{
|
{
|
||||||
xmlDocPtr xml;
|
xmlParserCtxtPtr pctxt;
|
||||||
|
xmlDocPtr xml = NULL;
|
||||||
xmlNodePtr root;
|
xmlNodePtr root;
|
||||||
virNetworkDefPtr def;
|
virNetworkDefPtr def = NULL;
|
||||||
|
|
||||||
if (!(xml = xmlReadDoc(BAD_CAST xmlStr, "network.xml", NULL,
|
/* Set up a parser context so we can catch the details of XML errors. */
|
||||||
XML_PARSE_NOENT | XML_PARSE_NONET |
|
pctxt = xmlNewParserCtxt ();
|
||||||
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
|
if (!pctxt || !pctxt->sax)
|
||||||
virNetworkReportError(conn, VIR_ERR_XML_ERROR, NULL);
|
goto cleanup;
|
||||||
return NULL;
|
pctxt->sax->error = catchXMLError;
|
||||||
|
pctxt->_private = conn;
|
||||||
|
|
||||||
|
if (conn) virResetError (&conn->err);
|
||||||
|
xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr, "network.xml", NULL,
|
||||||
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
||||||
|
XML_PARSE_NOWARNING);
|
||||||
|
if (!xml) {
|
||||||
|
if (conn && conn->err.code == VIR_ERR_NONE)
|
||||||
|
virNetworkReportError(conn, VIR_ERR_XML_ERROR,
|
||||||
|
_("failed to parse xml document"));
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((root = xmlDocGetRootElement(xml)) == NULL) {
|
if ((root = xmlDocGetRootElement(xml)) == NULL) {
|
||||||
virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
"%s", _("missing root element"));
|
"%s", _("missing root element"));
|
||||||
xmlFreeDoc(xml);
|
goto cleanup;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def = virNetworkDefParseNode(conn, xml, root);
|
def = virNetworkDefParseNode(conn, xml, root);
|
||||||
|
|
||||||
xmlFreeDoc(xml);
|
cleanup:
|
||||||
|
xmlFreeParserCtxt (pctxt);
|
||||||
|
xmlFreeDoc (xml);
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
virNetworkDefPtr virNetworkDefParseFile(virConnectPtr conn,
|
virNetworkDefPtr virNetworkDefParseFile(virConnectPtr conn,
|
||||||
const char *filename)
|
const char *filename)
|
||||||
{
|
{
|
||||||
xmlDocPtr xml;
|
xmlParserCtxtPtr pctxt;
|
||||||
|
xmlDocPtr xml = NULL;
|
||||||
xmlNodePtr root;
|
xmlNodePtr root;
|
||||||
virNetworkDefPtr def;
|
virNetworkDefPtr def = NULL;
|
||||||
|
|
||||||
if (!(xml = xmlReadFile(filename, NULL,
|
/* Set up a parser context so we can catch the details of XML errors. */
|
||||||
XML_PARSE_NOENT | XML_PARSE_NONET |
|
pctxt = xmlNewParserCtxt ();
|
||||||
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
|
if (!pctxt || !pctxt->sax)
|
||||||
virNetworkReportError(conn, VIR_ERR_XML_ERROR, NULL);
|
goto cleanup;
|
||||||
return NULL;
|
pctxt->sax->error = catchXMLError;
|
||||||
|
pctxt->_private = conn;
|
||||||
|
|
||||||
|
if (conn) virResetError (&conn->err);
|
||||||
|
xml = xmlCtxtReadFile (pctxt, filename, NULL,
|
||||||
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
||||||
|
XML_PARSE_NOWARNING);
|
||||||
|
if (!xml) {
|
||||||
|
if (conn && conn->err.code == VIR_ERR_NONE)
|
||||||
|
virNetworkReportError(conn, VIR_ERR_XML_ERROR,
|
||||||
|
_("failed to parse xml document"));
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((root = xmlDocGetRootElement(xml)) == NULL) {
|
if ((root = xmlDocGetRootElement(xml)) == NULL) {
|
||||||
virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
"%s", _("missing root element"));
|
"%s", _("missing root element"));
|
||||||
xmlFreeDoc(xml);
|
goto cleanup;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def = virNetworkDefParseNode(conn, xml, root);
|
def = virNetworkDefParseNode(conn, xml, root);
|
||||||
|
|
||||||
xmlFreeDoc(xml);
|
cleanup:
|
||||||
|
xmlFreeParserCtxt (pctxt);
|
||||||
|
xmlFreeDoc (xml);
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,22 +361,53 @@ virStoragePoolDefParseDoc(virConnectPtr conn,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Called from SAX on parsing errors in the XML. */
|
||||||
|
static void
|
||||||
|
catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
|
||||||
|
{
|
||||||
|
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
|
||||||
|
|
||||||
|
if (ctxt) {
|
||||||
|
virConnectPtr conn = ctxt->_private;
|
||||||
|
|
||||||
|
if (conn &&
|
||||||
|
conn->err.code == VIR_ERR_NONE &&
|
||||||
|
ctxt->lastError.level == XML_ERR_FATAL &&
|
||||||
|
ctxt->lastError.message != NULL) {
|
||||||
|
virStorageReportError (conn, VIR_ERR_XML_DETAIL,
|
||||||
|
_("at line %d: %s"),
|
||||||
|
ctxt->lastError.line,
|
||||||
|
ctxt->lastError.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virStoragePoolDefPtr
|
virStoragePoolDefPtr
|
||||||
virStoragePoolDefParse(virConnectPtr conn,
|
virStoragePoolDefParse(virConnectPtr conn,
|
||||||
const char *xmlStr,
|
const char *xmlStr,
|
||||||
const char *filename) {
|
const char *filename) {
|
||||||
virStoragePoolDefPtr ret = NULL;
|
virStoragePoolDefPtr ret = NULL;
|
||||||
|
xmlParserCtxtPtr pctxt;
|
||||||
xmlDocPtr xml = NULL;
|
xmlDocPtr xml = NULL;
|
||||||
xmlNodePtr node = NULL;
|
xmlNodePtr node = NULL;
|
||||||
xmlXPathContextPtr ctxt = NULL;
|
xmlXPathContextPtr ctxt = NULL;
|
||||||
|
|
||||||
if (!(xml = xmlReadDoc(BAD_CAST xmlStr,
|
/* Set up a parser context so we can catch the details of XML errors. */
|
||||||
filename ? filename : "storage.xml",
|
pctxt = xmlNewParserCtxt ();
|
||||||
NULL,
|
if (!pctxt || !pctxt->sax)
|
||||||
XML_PARSE_NOENT | XML_PARSE_NONET |
|
goto cleanup;
|
||||||
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
|
pctxt->sax->error = catchXMLError;
|
||||||
virStorageReportError(conn, VIR_ERR_XML_ERROR,
|
pctxt->_private = conn;
|
||||||
"%s", _("malformed xml document"));
|
|
||||||
|
if (conn) virResetError (&conn->err);
|
||||||
|
xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr,
|
||||||
|
filename ? filename : "storage.xml", NULL,
|
||||||
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
||||||
|
XML_PARSE_NOWARNING);
|
||||||
|
if (!xml) {
|
||||||
|
if (conn && conn->err.code == VIR_ERR_NONE)
|
||||||
|
virStorageReportError(conn, VIR_ERR_XML_ERROR,
|
||||||
|
_("failed to parse xml document"));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,12 +427,14 @@ virStoragePoolDefParse(virConnectPtr conn,
|
|||||||
|
|
||||||
ret = virStoragePoolDefParseDoc(conn, ctxt, node);
|
ret = virStoragePoolDefParseDoc(conn, ctxt, node);
|
||||||
|
|
||||||
|
xmlFreeParserCtxt (pctxt);
|
||||||
xmlXPathFreeContext(ctxt);
|
xmlXPathFreeContext(ctxt);
|
||||||
xmlFreeDoc(xml);
|
xmlFreeDoc(xml);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
xmlFreeParserCtxt (pctxt);
|
||||||
xmlXPathFreeContext(ctxt);
|
xmlXPathFreeContext(ctxt);
|
||||||
xmlFreeDoc(xml);
|
xmlFreeDoc(xml);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -725,15 +758,27 @@ virStorageVolDefParse(virConnectPtr conn,
|
|||||||
const char *xmlStr,
|
const char *xmlStr,
|
||||||
const char *filename) {
|
const char *filename) {
|
||||||
virStorageVolDefPtr ret = NULL;
|
virStorageVolDefPtr ret = NULL;
|
||||||
|
xmlParserCtxtPtr pctxt;
|
||||||
xmlDocPtr xml = NULL;
|
xmlDocPtr xml = NULL;
|
||||||
xmlNodePtr node = NULL;
|
xmlNodePtr node = NULL;
|
||||||
xmlXPathContextPtr ctxt = NULL;
|
xmlXPathContextPtr ctxt = NULL;
|
||||||
|
|
||||||
if (!(xml = xmlReadDoc(BAD_CAST xmlStr, filename ? filename : "storage.xml", NULL,
|
/* Set up a parser context so we can catch the details of XML errors. */
|
||||||
XML_PARSE_NOENT | XML_PARSE_NONET |
|
pctxt = xmlNewParserCtxt ();
|
||||||
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
|
if (!pctxt || !pctxt->sax)
|
||||||
virStorageReportError(conn, VIR_ERR_XML_ERROR,
|
goto cleanup;
|
||||||
"%s", _("malformed xml document"));
|
pctxt->sax->error = catchXMLError;
|
||||||
|
pctxt->_private = conn;
|
||||||
|
|
||||||
|
if (conn) virResetError (&conn->err);
|
||||||
|
xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr,
|
||||||
|
filename ? filename : "storage.xml", NULL,
|
||||||
|
XML_PARSE_NOENT | XML_PARSE_NONET |
|
||||||
|
XML_PARSE_NOWARNING);
|
||||||
|
if (!xml) {
|
||||||
|
if (conn && conn->err.code == VIR_ERR_NONE)
|
||||||
|
virStorageReportError(conn, VIR_ERR_XML_ERROR,
|
||||||
|
_("failed to parse xml document"));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -753,12 +798,14 @@ virStorageVolDefParse(virConnectPtr conn,
|
|||||||
|
|
||||||
ret = virStorageVolDefParseDoc(conn, pool, ctxt, node);
|
ret = virStorageVolDefParseDoc(conn, pool, ctxt, node);
|
||||||
|
|
||||||
|
xmlFreeParserCtxt (pctxt);
|
||||||
xmlXPathFreeContext(ctxt);
|
xmlXPathFreeContext(ctxt);
|
||||||
xmlFreeDoc(xml);
|
xmlFreeDoc(xml);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
xmlFreeParserCtxt (pctxt);
|
||||||
xmlXPathFreeContext(ctxt);
|
xmlXPathFreeContext(ctxt);
|
||||||
xmlFreeDoc(xml);
|
xmlFreeDoc(xml);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user