mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-28 19:41:16 +00:00
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:
parent
01b03f59e7
commit
ac38bff077
@ -18542,7 +18542,6 @@ virDomainObjGetMetadata(virDomainObjPtr vm,
|
||||
unsigned int flags)
|
||||
{
|
||||
virDomainDefPtr def;
|
||||
char *field = NULL;
|
||||
char *ret = NULL;
|
||||
|
||||
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
|
||||
@ -18557,16 +18556,20 @@ virDomainObjGetMetadata(virDomainObjPtr vm,
|
||||
|
||||
switch ((virDomainMetadataType) type) {
|
||||
case VIR_DOMAIN_METADATA_DESCRIPTION:
|
||||
field = def->description;
|
||||
if (VIR_STRDUP(ret, def->description) < 0)
|
||||
goto cleanup;
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_METADATA_TITLE:
|
||||
field = def->title;
|
||||
if (VIR_STRDUP(ret, def->title) < 0)
|
||||
goto cleanup;
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_METADATA_ELEMENT:
|
||||
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
||||
_("<metadata> element is not yet supported"));
|
||||
if (!def->metadata)
|
||||
break;
|
||||
|
||||
if (virXMLExtractNamespaceXML(def->metadata, uri, &ret) < 0)
|
||||
goto cleanup;
|
||||
break;
|
||||
|
||||
@ -18577,12 +18580,10 @@ virDomainObjGetMetadata(virDomainObjPtr vm,
|
||||
break;
|
||||
}
|
||||
|
||||
if (!field)
|
||||
if (!ret)
|
||||
virReportError(VIR_ERR_NO_DOMAIN_METADATA, "%s",
|
||||
_("Requested metadata element is not present"));
|
||||
|
||||
ignore_value(VIR_STRDUP(ret, field));
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
@ -2092,6 +2092,7 @@ virUUIDParse;
|
||||
|
||||
# util/virxml.h
|
||||
virXMLChildElementCount;
|
||||
virXMLExtractNamespaceXML;
|
||||
virXMLNodeToString;
|
||||
virXMLParseHelper;
|
||||
virXMLPickShellSafeComment;
|
||||
|
@ -928,3 +928,125 @@ cleanup:
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -165,4 +165,11 @@ int virXMLSaveFile(const char *path,
|
||||
|
||||
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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user