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)
|
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,17 +18556,21 @@ 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;
|
||||||
goto cleanup;
|
|
||||||
|
if (virXMLExtractNamespaceXML(def->metadata, uri, &ret) < 0)
|
||||||
|
goto cleanup;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -2092,6 +2092,7 @@ virUUIDParse;
|
|||||||
|
|
||||||
# util/virxml.h
|
# util/virxml.h
|
||||||
virXMLChildElementCount;
|
virXMLChildElementCount;
|
||||||
|
virXMLExtractNamespaceXML;
|
||||||
virXMLNodeToString;
|
virXMLNodeToString;
|
||||||
virXMLParseHelper;
|
virXMLParseHelper;
|
||||||
virXMLPickShellSafeComment;
|
virXMLPickShellSafeComment;
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user