This patch adds API to modify domain metadata for running and stopped domains. The api supports changing description, title as well as the newly added <metadata> element. The API has support for storing data in the metadata element using xml namespaces. * include/libvirt/libvirt.h.in * src/libvirt_public.syms - add function headers - add enum to select metadata to operate on - export functions * src/libvirt.c - add public api implementation * src/driver.h - add driver support * src/remote/remote_driver.c * src/remote/remote_protocol.x - wire up the remote protocol * include/libvirt/virterror.h * src/util/virterror.c - add a new error message note that metadata for domain are missing --- This is a major rework based on Eric's and Daniels comments. include/libvirt/libvirt.h.in | 25 ++++++++ include/libvirt/virterror.h | 1 + src/driver.h | 15 +++++ src/libvirt.c | 125 ++++++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 2 + src/remote/remote_driver.c | 2 + src/remote/remote_protocol.x | 25 ++++++++- src/util/virterror.c | 6 ++ 8 files changed, 200 insertions(+), 1 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 9a51c4f..ab6b90d 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1474,12 +1474,37 @@ int virDomainGetMaxVcpus (virDomainPtr domain); int virDomainGetSecurityLabel (virDomainPtr domain, virSecurityLabelPtr seclabel); +typedef enum { + VIR_DOMAIN_METADATA_DESCRIPTION = 0, /* Operate on <description> */ + VIR_DOMAIN_METADATA_TITLE = 1, /* Operate on <title> */ + VIR_DOMAIN_METADATA_ELEMENT = 2, /* Operate on <metadata> */ + +#ifdef VIR_ENUM_SENTINELS + VIR_DOMAIN_METADATA_LAST +#endif +} virDomainMetadataType; + /** * VIR_DOMAIN_TITLE_LENGTH: * * Maximum length of the string in the title field. */ #define VIR_DOMAIN_TITLE_LENGTH 40 + +int +virDomainSetMetadata(virDomainPtr domain, + int type, + const char *metadata, + const char *key, + const char *uri, + unsigned int flags); + +char * +virDomainGetMetadata(virDomainPtr domain, + int type, + const char *uri, + unsigned int flags); + /* * XML domain description */ diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index e896d67..4395637 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -243,6 +243,7 @@ typedef enum { risky domain snapshot revert */ VIR_ERR_OPERATION_ABORTED = 78, /* operation on a domain was canceled/aborted by user */ + VIR_ERR_NO_DOMAIN_METADATA = 79, /* The metadata is not present */ } virErrorNumber; /** diff --git a/src/driver.h b/src/driver.h index df2aa60..153a5eb 100644 --- a/src/driver.h +++ b/src/driver.h @@ -797,6 +797,19 @@ typedef int (*virDrvDomainShutdownFlags)(virDomainPtr domain, unsigned int flags); +typedef int + (*virDrvDomainSetMetadata)(virDomainPtr dom, + int type, + const char *metadata, + const char *key, + const char *uri, + unsigned int flags); + +typedef char * + (*virDrvDomainGetMetadata)(virDomainPtr dom, + int type, + const char *uri, + unsigned int flags); /** * _virDriver: @@ -967,6 +980,8 @@ struct _virDriver { virDrvNodeSuspendForDuration nodeSuspendForDuration; virDrvDomainSetBlockIoTune domainSetBlockIoTune; virDrvDomainGetBlockIoTune domainGetBlockIoTune; + virDrvDomainSetMetadata domainSetMetadata; + virDrvDomainGetMetadata domainGetMetadata; }; typedef int diff --git a/src/libvirt.c b/src/libvirt.c index e9d638b..d1a59de 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -8826,6 +8826,131 @@ error: } /** + * virDomainSetMetadata: + * @domain: a domain object + * @type: type of description, from virDomainMetadataType + * @metadata: new metadata text + * @key: XML namespace key, or NULL + * @uri: XML namespace URI, or NULL + * @flags: bitwise-OR of virDomainModificationImpact + * + * Sets the appropriate domain element given by @type to the + * value of @description. A @type of VIR_DOMAIN_METADATA_DESCRIPTION + * is free-form text; VIR_DOMAIN_METADATA_TITLE is free-form but + * length-limited to 40 bytes. For these two options @key and @uri are + * irelevant and can be set to NULL. + * + * For type VIR_DOMAIN_METADATA_ELEMENT @metadata must be well-formed + * XML belonging to namespace defined by @uri with local name @key. + * + * Passing NULL for @metadata says to remove that element from the + * domain XML (passing the empty string leaves the element present). + * + * The resulting metadata will be present in virDomainGetXMLDesc(), + * as well as quick access through virDomainGetMetadata(). + * + * @flags controls whether the live domain, persistent configuration, + * or both will be modified. + * + * Returns 0 on success, -1 in case of failure. + */ +int +virDomainSetMetadata(virDomainPtr domain, + int type, + const char *metadata, + const char *key, + const char *uri, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "type=%d, metadata=%p, key=%p, uri=%p flags=%x", + type, metadata, key, uri, flags); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->flags & VIR_CONNECT_RO) { + virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->driver->domainSetMetadata) { + int ret; + ret = conn->driver->domainSetMetadata(domain, type, metadata, key, uri, + flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return -1; +} + +/** + * virDomainGetMetadata: + * @domain: a domain object + * @type: type of description, from virDomainMetadataType + * @uri: XML namespace identifier + * @flags: bitwise-OR of virDomainModificationImpact + * + * Retrieves the appropriate domain element given by @type. + * If VIR_DOMAIN_METADATA_ELEMENT is requested parameter @uri + * must be set to the name of the namespace the requested elements + * belong to. + * + * If an element of the domain XML is not present, the resulting + * error will be VIR_ERR_NO_DOMAIN_METADATA. This method forms + * a shortcut for seeing information from virDomainSetMetadata() + * without having to go through virDomainGetXMLDesc(). + * + * @flags controls whether the live domain or persistent + * configuration will be queried. + * + * Returns the metadata string on success (caller must free), + * or NULL in case of failure. + */ +char * +virDomainGetMetadata(virDomainPtr domain, + int type, + const char *uri, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(domain, "type=%d, uri=%p, flags=%x", + type, uri, flags); + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); + goto error; + } + + conn = domain->conn; + + if (conn->driver->domainGetMetadata) { + char *ret; + if (!(ret = conn->driver->domainGetMetadata(domain, type, uri, flags))) + goto error; + return ret; + } + + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(domain->conn); + return NULL; +} + +/** * virNodeGetSecurityModel: * @conn: a connection object * @secmodel: pointer to a virSecurityModel structure diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 1340b0c..f71ba22 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -520,6 +520,8 @@ LIBVIRT_0.9.10 { global: virDomainShutdownFlags; virStorageVolWipePattern; + virDomainSetMetadata; + virDomainGetMetadata; } LIBVIRT_0.9.9; # .... define new API here using predicted next version number .... diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index f79f53e..c70f5a6 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -4751,6 +4751,8 @@ static virDriver remote_driver = { .domainGetBlockIoTune = remoteDomainGetBlockIoTune, /* 0.9.8 */ .domainSetNumaParameters = remoteDomainSetNumaParameters, /* 0.9.9 */ .domainGetNumaParameters = remoteDomainGetNumaParameters, /* 0.9.9 */ + .domainSetMetadata = remoteDomainSetMetadata, /* 0.9.10 */ + .domainGetMetadata = remoteDomainGetMetadata, /* 0.9.10 */ }; static virNetworkDriver network_driver = { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 0f354bb..b4d2035 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -1096,6 +1096,26 @@ struct remote_domain_set_autostart_args { int autostart; }; +struct remote_domain_set_metadata_args { + remote_nonnull_domain dom; + int type; + remote_string metadata; + remote_string key; + remote_string uri; + unsigned int flags; +}; + +struct remote_domain_get_metadata_args { + remote_nonnull_domain dom; + int type; + remote_string uri; + unsigned int flags; +}; + +struct remote_domain_get_metadata_ret { + remote_string metadata; +}; + struct remote_domain_block_job_abort_args { remote_nonnull_domain dom; remote_nonnull_string path; @@ -2667,7 +2687,10 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_SET_INTERFACE_PARAMETERS = 256, /* autogen autogen */ REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257, /* skipgen skipgen */ REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS = 258, /* autogen autogen */ - REMOTE_PROC_STORAGE_VOL_WIPE_PATTERN = 259 /* autogen autogen */ + REMOTE_PROC_STORAGE_VOL_WIPE_PATTERN = 259, /* autogen autogen */ + REMOTE_PROC_DOMAIN_SET_METADATA = 260, /* autogen autogen */ + + REMOTE_PROC_DOMAIN_GET_METADATA = 261 /* autogen autogen */ /* * Notice how the entries are grouped in sets of 10 ? diff --git a/src/util/virterror.c b/src/util/virterror.c index 85eec8d..5bcfe79 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -1220,6 +1220,12 @@ virErrorMsg(virErrorNumber error, const char *info) else errmsg = _("operation aborted: %s"); break; + case VIR_ERR_NO_DOMAIN_METADATA: + if (info == NULL) + errmsg = _("metadata not found"); + else + errmsg = _("metadata not found"); + break; } return (errmsg); } -- 1.7.3.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list