[libvirt] [glib PATCH 0/2] Add ns to the node's children when setting a custom XML

This work is preparing the field for adding and using metadata.libosinfo in GNOME Boxes (in a similar way that's already done for virt-manager) so we can have a cross-app schema for tracking libosinfo OS ID in the domain <metadata> XML. The tests added are from real cases as: - current Boxes' metadata (so, we ensure we won't break anything there); - the new Boxes' metadata.libosinfo; - Nova's XML example; Fabiano Fidêncio (2): object: Also add the ns to the node's children domain: Introduce gvir_config_domain_set_custom_xml_ns_children() libvirt-gconfig/libvirt-gconfig-domain.c | 41 ++++++++++++--- libvirt-gconfig/libvirt-gconfig-domain.h | 5 ++ .../libvirt-gconfig-object-private.h | 3 +- libvirt-gconfig/libvirt-gconfig-object.c | 51 +++++++++++++++---- libvirt-gconfig/libvirt-gconfig.sym | 5 ++ tests/test-gconfig.c | 3 ++ tests/xml/gconfig-domain.xml | 12 +++++ 7 files changed, 103 insertions(+), 17 deletions(-) -- 2.19.0

With the current code, we can only create a custom XML that looks like: <metadata> <boxes:gnome-boxes xmlns:boxes="https://wiki.gnome.org/Apps/Boxes"> <os-state>installed</os-state> <media-id>http://centos.org/centos/7.0:0</media-id> <media>/home/fidencio/Downloads/CentOS-7-x86_64-DVD-1804.iso</media> </boxes:gnome-boxes> </metadata> Although it works well for some use cases, there are use cases where we'd like to have something a bit more complex libosinfo or nova examples: <metadata> <libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0"> <libosinfo:os id="http://fedoraproject.org/fedora/17"/> </libosinfo:libosinfo> <nova:instance xmlns:nova="http://openstack.org/nova/instance/1"> <nova:flavor name="m1.small"> <nova:memory>512</nova:memory> <nova:disk>10</nova:disk> </nova:flavor> </nova:instance> </metadata> And for the latter case we'd have to go through the node's children and also set the namespace for each children. Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com> --- libvirt-gconfig/libvirt-gconfig-domain.c | 2 +- .../libvirt-gconfig-object-private.h | 3 +- libvirt-gconfig/libvirt-gconfig-object.c | 51 +++++++++++++++---- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/libvirt-gconfig/libvirt-gconfig-domain.c b/libvirt-gconfig/libvirt-gconfig-domain.c index 4fbbe67..a99f9ef 100644 --- a/libvirt-gconfig/libvirt-gconfig-domain.c +++ b/libvirt-gconfig/libvirt-gconfig-domain.c @@ -806,7 +806,7 @@ gboolean gvir_config_domain_set_custom_xml(GVirConfigDomain *domain, return FALSE; } - gvir_config_object_set_namespace(custom_xml, ns, ns_uri); + gvir_config_object_set_namespace(custom_xml, ns, ns_uri, FALSE); gvir_config_object_delete_children(metadata, NULL, ns_uri); gvir_config_object_attach_add(metadata, custom_xml); diff --git a/libvirt-gconfig/libvirt-gconfig-object-private.h b/libvirt-gconfig/libvirt-gconfig-object-private.h index 7a0d21f..02c704e 100644 --- a/libvirt-gconfig/libvirt-gconfig-object-private.h +++ b/libvirt-gconfig/libvirt-gconfig-object-private.h @@ -111,7 +111,8 @@ void gvir_config_object_foreach_child(GVirConfigObject *object, gpointer opaque); gboolean gvir_config_object_set_namespace(GVirConfigObject *object, const char *ns, - const char *ns_uri); + const char *ns_uri, + gboolean ns_children); GVirConfigObject *gvir_config_object_get_child(GVirConfigObject *object, const gchar *child_name); GVirConfigObject *gvir_config_object_get_child_with_type(GVirConfigObject *object, diff --git a/libvirt-gconfig/libvirt-gconfig-object.c b/libvirt-gconfig/libvirt-gconfig-object.c index fffbd21..eb8763e 100644 --- a/libvirt-gconfig/libvirt-gconfig-object.c +++ b/libvirt-gconfig/libvirt-gconfig-object.c @@ -928,26 +928,57 @@ gvir_config_object_remove_attribute(GVirConfigObject *object, } while (status == 0); } -G_GNUC_INTERNAL gboolean -gvir_config_object_set_namespace(GVirConfigObject *object, const char *ns, - const char *ns_uri) +static gboolean +gvir_config_object_set_xmlnode_namespace(xmlNodePtr node, const char *ns, + const char *ns_uri) { 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); + namespace = xmlNewNs(node, (xmlChar *)ns_uri, (xmlChar *)ns); if (namespace == NULL) return FALSE; - xmlSetNs(object->priv->node, namespace); + xmlSetNs(node, namespace); + return TRUE; +} + +static gboolean +gvir_config_object_set_namespace_recursively(xmlNodePtr node, + const char *ns, + const char *ns_uri) +{ + xmlNodePtr n; + + for (n = node; n != NULL; n = n->next) { + if (n->type == XML_ELEMENT_NODE) { + if (!gvir_config_object_set_xmlnode_namespace(n, ns, ns_uri)) + return FALSE; + } + + if (!gvir_config_object_set_namespace_recursively(n->children, ns, NULL)) + return FALSE; + } return TRUE; } +G_GNUC_INTERNAL gboolean +gvir_config_object_set_namespace(GVirConfigObject *object, const char *ns, + const char *ns_uri, gboolean ns_children) +{ + 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); + + if (!ns_children) { + return gvir_config_object_set_xmlnode_namespace(object->priv->node, + ns, ns_uri); + } + + return gvir_config_object_set_namespace_recursively(object->priv->node, + ns, ns_uri); +} + G_GNUC_INTERNAL GVirConfigObject * gvir_config_object_get_child_with_type(GVirConfigObject *object, const gchar *child_name, -- 2.19.0

gvir_config_domain_set_custom_xml_ns_children() basically has the same functionallity as gvir_config_domain_set_custom_xml() but also sets the namespace to the nodes' children. Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com> --- libvirt-gconfig/libvirt-gconfig-domain.c | 41 ++++++++++++++++++++---- libvirt-gconfig/libvirt-gconfig-domain.h | 5 +++ libvirt-gconfig/libvirt-gconfig.sym | 5 +++ tests/test-gconfig.c | 3 ++ tests/xml/gconfig-domain.xml | 12 +++++++ 5 files changed, 60 insertions(+), 6 deletions(-) diff --git a/libvirt-gconfig/libvirt-gconfig-domain.c b/libvirt-gconfig/libvirt-gconfig-domain.c index a99f9ef..ff5352a 100644 --- a/libvirt-gconfig/libvirt-gconfig-domain.c +++ b/libvirt-gconfig/libvirt-gconfig-domain.c @@ -782,11 +782,12 @@ 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) +static gboolean gvir_config_domain_set_custom_xml_helper(GVirConfigDomain *domain, + const gchar *xml, + const gchar *ns, + const gchar *ns_uri, + gboolean ns_children, + GError **error) { GVirConfigObject *metadata; GVirConfigObject *custom_xml; @@ -806,7 +807,7 @@ gboolean gvir_config_domain_set_custom_xml(GVirConfigDomain *domain, return FALSE; } - gvir_config_object_set_namespace(custom_xml, ns, ns_uri, FALSE); + gvir_config_object_set_namespace(custom_xml, ns, ns_uri, ns_children); gvir_config_object_delete_children(metadata, NULL, ns_uri); gvir_config_object_attach_add(metadata, custom_xml); @@ -816,6 +817,34 @@ gboolean gvir_config_domain_set_custom_xml(GVirConfigDomain *domain, return TRUE; } +gboolean gvir_config_domain_set_custom_xml(GVirConfigDomain *domain, + const gchar *xml, + const gchar *ns, + const gchar *ns_uri, + GError **error) +{ + return gvir_config_domain_set_custom_xml_helper(domain, + xml, + ns, + ns_uri, + FALSE, + error); +} + +gboolean gvir_config_domain_set_custom_xml_ns_children(GVirConfigDomain *domain, + const gchar *xml, + const gchar *ns, + const gchar *ns_uri, + GError **error) +{ + return gvir_config_domain_set_custom_xml_helper(domain, + xml, + ns, + ns_uri, + TRUE, + error); +} + struct LookupNamespacedNodeData { const char *ns_uri; xmlNodePtr node; diff --git a/libvirt-gconfig/libvirt-gconfig-domain.h b/libvirt-gconfig/libvirt-gconfig-domain.h index ed9be6b..822f500 100644 --- a/libvirt-gconfig/libvirt-gconfig-domain.h +++ b/libvirt-gconfig/libvirt-gconfig-domain.h @@ -137,6 +137,11 @@ 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_ns_children(GVirConfigDomain *domain, + const gchar *xml, + const gchar *ns, + const gchar *ns_uri, + GError **error); gboolean gvir_config_domain_set_custom_xml(GVirConfigDomain *domain, const gchar *xml, const gchar *ns, diff --git a/libvirt-gconfig/libvirt-gconfig.sym b/libvirt-gconfig/libvirt-gconfig.sym index 4ef4bf7..db69cba 100644 --- a/libvirt-gconfig/libvirt-gconfig.sym +++ b/libvirt-gconfig/libvirt-gconfig.sym @@ -766,4 +766,9 @@ global: gvir_config_domain_video_set_accel3d; } LIBVIRT_GCONFIG_0.2.2; +LIBVIRT_GCONFIG_1.0.1 { +global: + gvir_config_domain_set_custom_xml_ns_children; +} LIBVIRT_GCONFIG_0.2.4; + # .... define new API here using predicted next version number .... diff --git a/tests/test-gconfig.c b/tests/test-gconfig.c index 2c98c25..a64da26 100644 --- a/tests/test-gconfig.c +++ b/tests/test-gconfig.c @@ -114,6 +114,9 @@ static void test_domain(void) GVIR_CONFIG_DOMAIN_LIFECYCLE_ON_POWEROFF, GVIR_CONFIG_DOMAIN_LIFECYCLE_RESTART); + gvir_config_domain_set_custom_xml_ns_children(domain, "<libosinfo><os id=\"http://centos.org/centos/7\"/></libosinfo>", "libosinfo", "http://libosinfo.org/xmlns/libvirt/domain/1.0", NULL); + gvir_config_domain_set_custom_xml_ns_children(domain, "<instance><flavor name=\"m1.small\"><memory>512</memory><disk>10</disk></flavor></instance>", "nova", "http://openstack.org/nova/instance/1", NULL); + gvir_config_domain_set_custom_xml(domain, "<gnome-boxes><os-state>installed</os-state></gnome-boxes>", "boxes", "https://wiki.gnome.org/Apps/Boxes", NULL); gvir_config_domain_set_custom_xml(domain, "<foo/>", "ns", "http://foo", NULL); gvir_config_domain_set_custom_xml(domain, "<foo/>", "nsbar", "http://bar", NULL); gvir_config_domain_set_custom_xml(domain, "<foo/>", "ns", "http://bar", NULL); diff --git a/tests/xml/gconfig-domain.xml b/tests/xml/gconfig-domain.xml index 4118487..bfe0f53 100644 --- a/tests/xml/gconfig-domain.xml +++ b/tests/xml/gconfig-domain.xml @@ -9,6 +9,18 @@ </features> <on_poweroff>restart</on_poweroff> <metadata> + <libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0"> + <libosinfo:os id="http://centos.org/centos/7"/> + </libosinfo:libosinfo> + <nova:instance xmlns:nova="http://openstack.org/nova/instance/1"> + <nova:flavor name="m1.small"> + <nova:memory>512</nova:memory> + <nova:disk>10</nova:disk> + </nova:flavor> + </nova:instance> + <boxes:gnome-boxes xmlns:boxes="https://wiki.gnome.org/Apps/Boxes"> + <os-state>installed</os-state> + </boxes:gnome-boxes> <ns:foo xmlns:ns="http://bar"/> <ns:bar xmlns:ns="http://foo"/> </metadata> -- 2.19.0

On 10/03/2018 01:59 PM, Fabiano Fidêncio wrote:
This work is preparing the field for adding and using metadata.libosinfo in GNOME Boxes (in a similar way that's already done for virt-manager) so we can have a cross-app schema for tracking libosinfo OS ID in the domain <metadata> XML.
The tests added are from real cases as: - current Boxes' metadata (so, we ensure we won't break anything there); - the new Boxes' metadata.libosinfo; - Nova's XML example;
Fabiano Fidêncio (2): object: Also add the ns to the node's children domain: Introduce gvir_config_domain_set_custom_xml_ns_children()
libvirt-gconfig/libvirt-gconfig-domain.c | 41 ++++++++++++--- libvirt-gconfig/libvirt-gconfig-domain.h | 5 ++ .../libvirt-gconfig-object-private.h | 3 +- libvirt-gconfig/libvirt-gconfig-object.c | 51 +++++++++++++++---- libvirt-gconfig/libvirt-gconfig.sym | 5 ++ tests/test-gconfig.c | 3 ++ tests/xml/gconfig-domain.xml | 12 +++++ 7 files changed, 103 insertions(+), 17 deletions(-)
ACKed and pushed. Michal
participants (2)
-
Fabiano Fidêncio
-
Michal Privoznik