]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
API: Add api to set and get domain metadata
authorPeter Krempa <pkrempa@redhat.com>
Wed, 1 Feb 2012 13:03:50 +0000 (14:03 +0100)
committerEric Blake <eblake@redhat.com>
Wed, 1 Feb 2012 22:01:38 +0000 (15:01 -0700)
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

include/libvirt/libvirt.h.in
include/libvirt/virterror.h
src/driver.h
src/libvirt.c
src/libvirt_public.syms
src/remote/remote_driver.c
src/remote/remote_protocol.x
src/remote_protocol-structs
src/util/virterror.c

index cf53cf260d3d8b6b843724f63b002fdbd9e21ff1..07d03fa160a86867cba47720e60a7292efff4ad9 100644 (file)
@@ -1496,6 +1496,30 @@ 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;
+
+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
  */
index 9844cbe23f1f076888294b3f8ad00fc73239e82a..9dbadfe63f47a078dd35de404fe8bc7d09226acc 100644 (file)
@@ -244,6 +244,7 @@ typedef enum {
     VIR_ERR_OPERATION_ABORTED = 78,     /* operation on a domain was
                                            canceled/aborted by user */
     VIR_ERR_AUTH_CANCELLED = 79,        /* authentication cancelled */
+    VIR_ERR_NO_DOMAIN_METADATA = 80,    /* The metadata is not present */
 } virErrorNumber;
 
 /**
index 9ff5edf18fc076b962bec61fb94d5e9118f1df4f..d6ee60f4982fe33668c1e4e069fe9f1688aed030 100644 (file)
@@ -816,6 +816,20 @@ typedef int
                                  unsigned int maxerrors,
                                  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:
  *
@@ -988,6 +1002,8 @@ struct _virDriver {
     virDrvDomainGetBlockIoTune domainGetBlockIoTune;
     virDrvDomainGetCPUStats domainGetCPUStats;
     virDrvDomainGetDiskErrors domainGetDiskErrors;
+    virDrvDomainSetMetadata domainSetMetadata;
+    virDrvDomainGetMetadata domainGetMetadata;
 };
 
 typedef int
index fc41a3fad2ac103acfbae9066d54db0ef09b6f29..659e5db4e4968876e3ffb872e7ff70972ec192b4 100644 (file)
@@ -8886,6 +8886,184 @@ error:
     return -1;
 }
 
+/**
+ * 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 no
+ * newlines are permitted, and should be short (although the length is
+ * not enforced). For these two options @key and @uri are irrelevant and
+ * must 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='%s', key='%s', uri='%s', flags=%x",
+                     type, NULLSTR(metadata), NULLSTR(key), NULLSTR(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;
+    }
+
+    switch (type) {
+    case VIR_DOMAIN_METADATA_TITLE:
+        if (metadata && strchr(metadata, '\n')) {
+                virLibDomainError(VIR_ERR_INVALID_ARG, "%s",
+                                  _("Domain title can't contain newlines"));
+                goto error;
+        }
+        /* fallthrough */
+    case VIR_DOMAIN_METADATA_DESCRIPTION:
+        if (uri || key) {
+            virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+            goto error;
+        }
+        break;
+    case VIR_DOMAIN_METADATA_ELEMENT:
+        if (!uri || !key) {
+            virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+            goto error;
+        }
+        break;
+    default:
+        /* For future expansion */
+        break;
+    }
+
+    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, otherwise must be NULL.
+ *
+ * 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='%s', flags=%x",
+                     type, NULLSTR(uri), flags);
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        goto error;
+    }
+
+    if ((flags & VIR_DOMAIN_AFFECT_LIVE) &&
+        (flags & VIR_DOMAIN_AFFECT_CONFIG)) {
+        virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+        goto error;
+    }
+
+    switch (type) {
+    case VIR_DOMAIN_METADATA_TITLE:
+    case VIR_DOMAIN_METADATA_DESCRIPTION:
+        if (uri) {
+            virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+            goto error;
+        }
+        break;
+    case VIR_DOMAIN_METADATA_ELEMENT:
+        if (!uri) {
+            virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+            goto error;
+        }
+        break;
+    default:
+        /* For future expansion */
+        break;
+    }
+
+    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
index ced9fb3969ffac7e302522e39a94a3fd3b70c361..9bbd3082f60f09020a5ca4fbd7a528e691f3b99a 100644 (file)
@@ -520,7 +520,9 @@ LIBVIRT_0.9.10 {
     global:
         virDomainGetCPUStats;
         virDomainGetDiskErrors;
+        virDomainGetMetadata;
         virDomainPMSuspendForDuration;
+        virDomainSetMetadata;
         virDomainShutdownFlags;
         virStorageVolResize;
         virStorageVolWipePattern;
index 09b5ace66675e294c66751abc8680cd621b14211..34816ad44002bf460c39f6bade704fb6e72c08c8 100644 (file)
@@ -4917,6 +4917,8 @@ static virDriver remote_driver = {
     .domainGetNumaParameters = remoteDomainGetNumaParameters, /* 0.9.9 */
     .domainGetCPUStats = remoteDomainGetCPUStats, /* 0.9.10 */
     .domainGetDiskErrors = remoteDomainGetDiskErrors, /* 0.9.10 */
+    .domainSetMetadata = remoteDomainSetMetadata, /* 0.9.10 */
+    .domainGetMetadata = remoteDomainGetMetadata, /* 0.9.10 */
 };
 
 static virNetworkDriver network_driver = {
index 10fd2940a885961f12beeb4441dea519448f18bb..efb209a23ebdfde3971252e3b48b7cb6dac90a9b 100644 (file)
@@ -1123,6 +1123,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_nonnull_string metadata;
+};
+
 struct remote_domain_block_job_abort_args {
     remote_nonnull_domain dom;
     remote_nonnull_string path;
@@ -2729,7 +2749,9 @@ enum remote_procedure {
 
     REMOTE_PROC_DOMAIN_PM_SUSPEND_FOR_DURATION = 261, /* autogen autogen */
     REMOTE_PROC_DOMAIN_GET_CPU_STATS = 262, /* skipgen skipgen */
-    REMOTE_PROC_DOMAIN_GET_DISK_ERRORS = 263 /* skipgen skipgen */
+    REMOTE_PROC_DOMAIN_GET_DISK_ERRORS = 263, /* skipgen skipgen */
+    REMOTE_PROC_DOMAIN_SET_METADATA = 264, /* autogen autogen */
+    REMOTE_PROC_DOMAIN_GET_METADATA = 265 /* autogen autogen */
 
     /*
      * Notice how the entries are grouped in sets of 10 ?
index ee2207ca5261a4247610c44ec08f70532b39bf44..8b66a5fbea96a5175acd664c2c8bed1320356415 100644 (file)
@@ -788,6 +788,23 @@ struct remote_domain_set_autostart_args {
         remote_nonnull_domain      dom;
         int                        autostart;
 };
+struct remote_domain_set_metadata_args {
+        remote_nonnull_domain      dom;
+        int                        type;
+        remote_string              metadata;
+        remote_string              key;
+        remote_string              uri;
+        u_int                      flags;
+};
+struct remote_domain_get_metadata_args {
+        remote_nonnull_domain      dom;
+        int                        type;
+        remote_string              uri;
+        u_int                      flags;
+};
+struct remote_domain_get_metadata_ret {
+        remote_nonnull_string      metadata;
+};
 struct remote_domain_block_job_abort_args {
         remote_nonnull_domain      dom;
         remote_nonnull_string      path;
@@ -2146,4 +2163,6 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_PM_SUSPEND_FOR_DURATION = 261,
         REMOTE_PROC_DOMAIN_GET_CPU_STATS = 262,
         REMOTE_PROC_DOMAIN_GET_DISK_ERRORS = 263,
+        REMOTE_PROC_DOMAIN_SET_METADATA = 264,
+        REMOTE_PROC_DOMAIN_GET_METADATA = 265,
 };
index 31ddd9d2d3c8be11c9ceabae111b6241e03c3a57..edd5198640b35bf9aab9174a7a25f235b30da048 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * virterror.c: implements error handling and reporting code for libvirt
  *
- * Copy:  Copyright (C) 2006, 2008-2011 Red Hat, Inc.
+ * Copy:  Copyright (C) 2006, 2008-2012 Red Hat, Inc.
  *
  * See COPYING.LIB for the License of this software
  *
@@ -1226,6 +1226,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: %s");
+            break;
     }
     return (errmsg);
 }