Based on a patch from Zeeshan Ali (Khattak) <zeeshanak@xxxxxxxxx> --- libvirt-gconfig/libvirt-gconfig-domain.c | 60 +++++++++++++++++++++ libvirt-gconfig/libvirt-gconfig-domain.h | 7 +++ libvirt-gconfig/libvirt-gconfig-helpers-private.h | 1 + libvirt-gconfig/libvirt-gconfig-helpers.c | 23 ++++++++- libvirt-gconfig/libvirt-gconfig-object-private.h | 4 ++ libvirt-gconfig/libvirt-gconfig-object.c | 32 +++++++++++ libvirt-gconfig/libvirt-gconfig.sym | 2 + 7 files changed, 128 insertions(+), 1 deletions(-) diff --git a/libvirt-gconfig/libvirt-gconfig-domain.c b/libvirt-gconfig/libvirt-gconfig-domain.c index 61af625..d943099 100644 --- a/libvirt-gconfig/libvirt-gconfig-domain.c +++ b/libvirt-gconfig/libvirt-gconfig-domain.c @@ -449,3 +449,63 @@ GList *gvir_config_domain_get_devices(GVirConfigDomain *domain) return data.devices; } + +gboolean gvir_config_domain_set_custom_xml(GVirConfigDomain *domain, + const gchar *xml, + const gchar *ns, + const gchar *ns_uri, + GError **error) +{ + GVirConfigObject *metadata; + GVirConfigObject *custom_xml; + + g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), FALSE); + g_return_val_if_fail(xml != NULL, FALSE); + g_return_val_if_fail(error == NULL || *error == NULL, FALSE); + + metadata = gvir_config_object_add_child(GVIR_CONFIG_OBJECT(domain), "metadata"); + + custom_xml = gvir_config_object_new_from_xml(GVIR_CONFIG_TYPE_OBJECT, NULL, NULL, xml, error); + if (error != NULL && *error != NULL) + return FALSE; + + gvir_config_object_set_namespace(custom_xml, ns, ns_uri, TRUE); + + gvir_config_object_attach_replace(metadata, custom_xml); + + return TRUE; +} + +struct LookupNamespacedNodeData { + const char *ns_uri; + xmlNodePtr node; +}; + +static gboolean lookup_namespaced_node(xmlNodePtr node, gpointer opaque) +{ + struct LookupNamespacedNodeData* data = opaque; + + if (node->ns == NULL) + return TRUE; + + if (g_strcmp0((char *)node->ns->href, data->ns_uri) == 0) { + data->node = node; + return FALSE; + } + + return TRUE; +} + +gchar *gvir_config_domain_get_custom_xml(GVirConfigDomain *domain, + const gchar *ns_uri) +{ + struct LookupNamespacedNodeData data = { NULL, NULL }; + + g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN(domain), NULL); + g_return_val_if_fail(ns_uri != NULL, NULL); + + data.ns_uri = ns_uri; + gvir_config_object_foreach_child(GVIR_CONFIG_OBJECT(domain), "metadata", + lookup_namespaced_node, &data); + return gvir_config_xml_node_to_string(data.node); +} diff --git a/libvirt-gconfig/libvirt-gconfig-domain.h b/libvirt-gconfig/libvirt-gconfig-domain.h index 6cdaec9..769d2f0 100644 --- a/libvirt-gconfig/libvirt-gconfig-domain.h +++ b/libvirt-gconfig/libvirt-gconfig-domain.h @@ -126,6 +126,13 @@ GList *gvir_config_domain_get_devices(GVirConfigDomain *domain); void gvir_config_domain_set_lifecycle(GVirConfigDomain *domain, GVirConfigDomainLifecycleEvent event, GVirConfigDomainLifecycleAction action); +gboolean gvir_config_domain_set_custom_xml(GVirConfigDomain *domain, + const gchar *xml, + const gchar *ns, + const gchar *ns_uri, + GError **error); +gchar *gvir_config_domain_get_custom_xml(GVirConfigDomain *domain, + const gchar *ns_uri); G_END_DECLS diff --git a/libvirt-gconfig/libvirt-gconfig-helpers-private.h b/libvirt-gconfig/libvirt-gconfig-helpers-private.h index 96ec02e..514aeb0 100644 --- a/libvirt-gconfig/libvirt-gconfig-helpers-private.h +++ b/libvirt-gconfig/libvirt-gconfig-helpers-private.h @@ -56,6 +56,7 @@ char *gvir_config_xml_get_child_element_content_glib (xmlNode *node, const char *child_name); xmlChar *gvir_config_xml_get_attribute_content(xmlNodePtr node, const char *attr_name); +char *gvir_config_xml_node_to_string(xmlNodePtr node); char *gvir_config_xml_get_attribute_content_glib(xmlNodePtr node, const char *attr_name); const char *gvir_config_genum_get_nick (GType enum_type, gint value); diff --git a/libvirt-gconfig/libvirt-gconfig-helpers.c b/libvirt-gconfig/libvirt-gconfig-helpers.c index c406a49..6500439 100644 --- a/libvirt-gconfig/libvirt-gconfig-helpers.c +++ b/libvirt-gconfig/libvirt-gconfig-helpers.c @@ -148,7 +148,8 @@ gvir_config_xml_parse(const char *xml, const char *root_node, GError **err) "Unable to parse configuration"); return NULL; } - if ((!doc->children) || (strcmp((char *)doc->children->name, root_node) != 0)) { + if ((!doc->children) || + (g_strcmp0((char *)doc->children->name, root_node) != 0)) { g_set_error(err, GVIR_CONFIG_OBJECT_ERROR, 0, @@ -306,3 +307,23 @@ gvir_config_genum_get_value (GType enum_type, const char *nick, g_return_val_if_reached(default_value); } + +G_GNUC_INTERNAL char * +gvir_config_xml_node_to_string(xmlNodePtr node) +{ + xmlBufferPtr xmlbuf; + char *xml; + + if (node == NULL) + return NULL; + + xmlbuf = xmlBufferCreate(); + if (xmlNodeDump(xmlbuf, node->doc, node, 0, 0) < 0) + return NULL; + else + xml = g_strndup((gchar *)xmlBufferContent(xmlbuf), xmlBufferLength(xmlbuf)); + + xmlBufferFree(xmlbuf); + + return xml; +} diff --git a/libvirt-gconfig/libvirt-gconfig-object-private.h b/libvirt-gconfig/libvirt-gconfig-object-private.h index 781e1a3..8fc9a08 100644 --- a/libvirt-gconfig/libvirt-gconfig-object-private.h +++ b/libvirt-gconfig/libvirt-gconfig-object-private.h @@ -90,6 +90,10 @@ void gvir_config_object_foreach_child(GVirConfigObject *object, const char *parent_name, GVirConfigXmlNodeIterator iter_func, gpointer opaque); +gboolean gvir_config_object_set_namespace(GVirConfigObject *object, + const char *ns, + const char *ns_uri, + gboolean recursive); G_END_DECLS diff --git a/libvirt-gconfig/libvirt-gconfig-object.c b/libvirt-gconfig/libvirt-gconfig-object.c index 2e28208..5449bd6 100644 --- a/libvirt-gconfig/libvirt-gconfig-object.c +++ b/libvirt-gconfig/libvirt-gconfig-object.c @@ -846,3 +846,35 @@ gvir_config_object_remove_attribute(GVirConfigObject *object, status = xmlUnsetProp(object->priv->node, (xmlChar *)attr_name); } while (status == 0); } + +static void set_namespace_on_tree(xmlNodePtr node, xmlNsPtr namespace) +{ + xmlNodePtr child; + + xmlSetNs(node, namespace); + + for (child = node->children; child != NULL; child = child->next) + set_namespace_on_tree(child, namespace); +} + +G_GNUC_INTERNAL gboolean +gvir_config_object_set_namespace(GVirConfigObject *object, const char *ns, + const char *ns_uri, gboolean recursive) +{ + xmlNsPtr namespace; + + g_return_val_if_fail(GVIR_CONFIG_IS_OBJECT(object), FALSE); + g_return_val_if_fail(ns != NULL, FALSE); + g_return_val_if_fail(ns_uri != NULL, FALSE); + + namespace = xmlNewNs(object->priv->node, + (xmlChar *)ns_uri, (xmlChar *)ns); + if (namespace == NULL) + return FALSE; + if (recursive) { + set_namespace_on_tree(object->priv->node, namespace); + } else { + xmlSetNs(object->priv->node, namespace); + } + return TRUE; +} diff --git a/libvirt-gconfig/libvirt-gconfig.sym b/libvirt-gconfig/libvirt-gconfig.sym index 88aef57..ab2c7bf 100644 --- a/libvirt-gconfig/libvirt-gconfig.sym +++ b/libvirt-gconfig/libvirt-gconfig.sym @@ -14,6 +14,8 @@ LIBVIRT_GCONFIG_0.0.4 { gvir_config_domain_new; gvir_config_domain_new_from_xml; gvir_config_domain_set_clock; + gvir_config_domain_set_custom_xml; + gvir_config_domain_get_custom_xml; gvir_config_domain_get_description; gvir_config_domain_set_description; gvir_config_domain_get_devices; -- 1.7.7.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list