[libvirt] [PATCH 2/4] API: Add api to set and get domain metadata

Peter Krempa pkrempa at redhat.com
Fri Jan 27 17:22:17 UTC 2012


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




More information about the libvir-list mailing list