conf: Add support for requesting of XML metadata via the API

The virDomainGetMetadata function was designed to support also retrieval
of app specific metadata from the <metadata> element. This functionality
was never implemented originally.
This commit is contained in:
Peter Krempa 2013-09-06 17:34:43 +02:00
parent 01b03f59e7
commit ac38bff077
4 changed files with 140 additions and 9 deletions

View File

@ -18542,7 +18542,6 @@ virDomainObjGetMetadata(virDomainObjPtr vm,
unsigned int flags) unsigned int flags)
{ {
virDomainDefPtr def; virDomainDefPtr def;
char *field = NULL;
char *ret = NULL; char *ret = NULL;
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
@ -18557,16 +18556,20 @@ virDomainObjGetMetadata(virDomainObjPtr vm,
switch ((virDomainMetadataType) type) { switch ((virDomainMetadataType) type) {
case VIR_DOMAIN_METADATA_DESCRIPTION: case VIR_DOMAIN_METADATA_DESCRIPTION:
field = def->description; if (VIR_STRDUP(ret, def->description) < 0)
goto cleanup;
break; break;
case VIR_DOMAIN_METADATA_TITLE: case VIR_DOMAIN_METADATA_TITLE:
field = def->title; if (VIR_STRDUP(ret, def->title) < 0)
goto cleanup;
break; break;
case VIR_DOMAIN_METADATA_ELEMENT: case VIR_DOMAIN_METADATA_ELEMENT:
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", if (!def->metadata)
_("<metadata> element is not yet supported")); break;
if (virXMLExtractNamespaceXML(def->metadata, uri, &ret) < 0)
goto cleanup; goto cleanup;
break; break;
@ -18577,12 +18580,10 @@ virDomainObjGetMetadata(virDomainObjPtr vm,
break; break;
} }
if (!field) if (!ret)
virReportError(VIR_ERR_NO_DOMAIN_METADATA, "%s", virReportError(VIR_ERR_NO_DOMAIN_METADATA, "%s",
_("Requested metadata element is not present")); _("Requested metadata element is not present"));
ignore_value(VIR_STRDUP(ret, field));
cleanup: cleanup:
return ret; return ret;
} }

View File

@ -2092,6 +2092,7 @@ virUUIDParse;
# util/virxml.h # util/virxml.h
virXMLChildElementCount; virXMLChildElementCount;
virXMLExtractNamespaceXML;
virXMLNodeToString; virXMLNodeToString;
virXMLParseHelper; virXMLParseHelper;
virXMLPickShellSafeComment; virXMLPickShellSafeComment;

View File

@ -928,3 +928,125 @@ cleanup:
return ret; return ret;
} }
typedef int (*virXMLForeachCallback)(xmlNodePtr node,
void *opaque);
static int
virXMLForeachNode(xmlNodePtr root,
virXMLForeachCallback cb,
void *opaque);
static int
virXMLForeachNode(xmlNodePtr root,
virXMLForeachCallback cb,
void *opaque)
{
xmlNodePtr next;
int ret;
for (next = root; next; next = next->next) {
if ((ret = cb(next, opaque)) != 0)
return ret;
/* recurse into children */
if (next->children) {
if ((ret = virXMLForeachNode(next->children, cb, opaque)) != 0)
return ret;
}
}
return 0;
}
static int
virXMLRemoveElementNamespace(xmlNodePtr node,
void *opaque)
{
const char *uri = opaque;
if (node->ns &&
STREQ_NULLABLE((const char *)node->ns->href, uri))
xmlSetNs(node, NULL);
return 0;
}
xmlNodePtr
virXMLFindChildNodeByNs(xmlNodePtr root,
const char *uri)
{
xmlNodePtr next;
for (next = root->children; next; next = next->next) {
if (next->ns &&
STREQ_NULLABLE((const char *) next->ns->href, uri))
return next;
}
return NULL;
}
/**
* virXMLExtractNamespaceXML: extract a sub-namespace of XML as string
*/
int
virXMLExtractNamespaceXML(xmlNodePtr root,
const char *uri,
char **doc)
{
xmlNodePtr node;
xmlNodePtr nodeCopy = NULL;
xmlNsPtr actualNs;
xmlNsPtr prevNs = NULL;
char *xmlstr = NULL;
int ret = -1;
if (!(node = virXMLFindChildNodeByNs(root, uri))) {
/* node not found */
ret = 1;
goto cleanup;
}
/* copy the node so that we can modify the namespace */
if (!(nodeCopy = xmlCopyNode(node, 1))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Failed to copy XML node"));
goto cleanup;
}
virXMLForeachNode(nodeCopy, virXMLRemoveElementNamespace,
(void *)uri);
/* remove the namespace declaration
* - it's only a single linked list ... doh */
for (actualNs = nodeCopy->nsDef; actualNs; actualNs = actualNs->next) {
if (STREQ_NULLABLE((const char *)actualNs->href, uri)) {
/* unlink */
if (prevNs)
prevNs->next = actualNs->next;
else
nodeCopy->nsDef = actualNs->next;
/* discard */
xmlFreeNs(actualNs);
break;
}
prevNs = actualNs;
}
if (!(xmlstr = virXMLNodeToString(nodeCopy->doc, nodeCopy)))
goto cleanup;
ret = 0;
cleanup:
if (doc)
*doc = xmlstr;
xmlFreeNode(nodeCopy);
return ret;
}

View File

@ -165,4 +165,11 @@ int virXMLSaveFile(const char *path,
char *virXMLNodeToString(xmlDocPtr doc, xmlNodePtr node); char *virXMLNodeToString(xmlDocPtr doc, xmlNodePtr node);
xmlNodePtr virXMLFindChildNodeByNs(xmlNodePtr root,
const char *uri);
int virXMLExtractNamespaceXML(xmlNodePtr root,
const char *uri,
char **doc);
#endif /* __VIR_XML_H__ */ #endif /* __VIR_XML_H__ */