[libvirt] [gconfig v6 1/5] gconfig: Add gvir_config_object_has_child

From: Christophe Fergeau <cfergeau@redhat.com> --- libvirt-gconfig/libvirt-gconfig-object-private.h | 2 ++ libvirt-gconfig/libvirt-gconfig-object.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/libvirt-gconfig/libvirt-gconfig-object-private.h b/libvirt-gconfig/libvirt-gconfig-object-private.h index e91c4ef..7a0d21f 100644 --- a/libvirt-gconfig/libvirt-gconfig-object-private.h +++ b/libvirt-gconfig/libvirt-gconfig-object-private.h @@ -117,6 +117,8 @@ GVirConfigObject *gvir_config_object_get_child(GVirConfigObject *object, GVirConfigObject *gvir_config_object_get_child_with_type(GVirConfigObject *object, const gchar *child_name, GType child_type); +gboolean gvir_config_object_has_child(GVirConfigObject *object, + const gchar *child_name); G_END_DECLS diff --git a/libvirt-gconfig/libvirt-gconfig-object.c b/libvirt-gconfig/libvirt-gconfig-object.c index bf328f3..6225de2 100644 --- a/libvirt-gconfig/libvirt-gconfig-object.c +++ b/libvirt-gconfig/libvirt-gconfig-object.c @@ -970,3 +970,16 @@ gvir_config_object_get_child(GVirConfigObject *object, child_name, GVIR_CONFIG_TYPE_OBJECT); } + +G_GNUC_INTERNAL gboolean +gvir_config_object_has_child(GVirConfigObject *object, const gchar *child_name) +{ + xmlNodePtr node; + + g_return_val_if_fail(GVIR_CONFIG_IS_OBJECT(object), FALSE); + g_return_val_if_fail(child_name != NULL, FALSE); + + node = gvir_config_xml_get_element(object->priv->node, child_name, NULL); + + return (node != NULL); +} -- 2.7.4

Add API to read and write domain/devices/hostdev nodes. This patch only adds the baseclass and hence is not useful on it's own. A more specific subclass to represent PCI devices will be added in a following patch. --- libvirt-gconfig/Makefile.am | 2 + .../libvirt-gconfig-domain-device-private.h | 3 + libvirt-gconfig/libvirt-gconfig-domain-device.c | 2 +- libvirt-gconfig/libvirt-gconfig-domain-hostdev.c | 190 +++++++++++++++++++++ libvirt-gconfig/libvirt-gconfig-domain-hostdev.h | 76 +++++++++ libvirt-gconfig/libvirt-gconfig.h | 1 + libvirt-gconfig/libvirt-gconfig.sym | 10 ++ 7 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 libvirt-gconfig/libvirt-gconfig-domain-hostdev.c create mode 100644 libvirt-gconfig/libvirt-gconfig-domain-hostdev.h diff --git a/libvirt-gconfig/Makefile.am b/libvirt-gconfig/Makefile.am index f308539..a7c6c4e 100644 --- a/libvirt-gconfig/Makefile.am +++ b/libvirt-gconfig/Makefile.am @@ -50,6 +50,7 @@ GCONFIG_HEADER_FILES = \ libvirt-gconfig-domain-graphics-sdl.h \ libvirt-gconfig-domain-graphics-spice.h \ libvirt-gconfig-domain-graphics-vnc.h \ + libvirt-gconfig-domain-hostdev.h \ libvirt-gconfig-domain-input.h \ libvirt-gconfig-domain-interface.h \ libvirt-gconfig-domain-interface-bridge.h \ @@ -141,6 +142,7 @@ GCONFIG_SOURCE_FILES = \ libvirt-gconfig-domain-graphics-sdl.c \ libvirt-gconfig-domain-graphics-spice.c \ libvirt-gconfig-domain-graphics-vnc.c \ + libvirt-gconfig-domain-hostdev.c \ libvirt-gconfig-domain-input.c \ libvirt-gconfig-domain-interface.c \ libvirt-gconfig-domain-interface-bridge.c \ diff --git a/libvirt-gconfig/libvirt-gconfig-domain-device-private.h b/libvirt-gconfig/libvirt-gconfig-domain-device-private.h index 062c0e2..c45e1df 100644 --- a/libvirt-gconfig/libvirt-gconfig-domain-device-private.h +++ b/libvirt-gconfig/libvirt-gconfig-domain-device-private.h @@ -43,6 +43,9 @@ GVirConfigDomainDevice * gvir_config_domain_graphics_new_from_tree(GVirConfigXmlDoc *doc, xmlNodePtr tree); GVirConfigDomainDevice * +gvir_config_domain_hostdev_new_from_tree(GVirConfigXmlDoc *doc, + xmlNodePtr tree); +GVirConfigDomainDevice * gvir_config_domain_interface_new_from_tree(GVirConfigXmlDoc *doc, xmlNodePtr tree); GVirConfigDomainDevice * diff --git a/libvirt-gconfig/libvirt-gconfig-domain-device.c b/libvirt-gconfig/libvirt-gconfig-domain-device.c index 3d2b9b3..8a75cea 100644 --- a/libvirt-gconfig/libvirt-gconfig-domain-device.c +++ b/libvirt-gconfig/libvirt-gconfig-domain-device.c @@ -66,7 +66,7 @@ gvir_config_domain_device_new_from_tree(GVirConfigXmlDoc *doc, } else if (xmlStrEqual(tree->name, (xmlChar*)"lease")) { goto unimplemented; } else if (xmlStrEqual(tree->name, (xmlChar*)"hostdev")) { - goto unimplemented; + return gvir_config_domain_hostdev_new_from_tree(doc, tree); } else if (xmlStrEqual(tree->name, (xmlChar*)"redirdev")) { type = GVIR_CONFIG_TYPE_DOMAIN_REDIRDEV; } else if (xmlStrEqual(tree->name, (xmlChar*)"smartcard")) { diff --git a/libvirt-gconfig/libvirt-gconfig-domain-hostdev.c b/libvirt-gconfig/libvirt-gconfig-domain-hostdev.c new file mode 100644 index 0000000..ce5f8aa --- /dev/null +++ b/libvirt-gconfig/libvirt-gconfig-domain-hostdev.c @@ -0,0 +1,190 @@ +/* + * libvirt-gconfig-domain-hostdev.c: libvirt domain hostdev configuration + * + * Copyright (C) 2016 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Authors: Zeeshan Ali (Khattak) <zeeshanak@gnome.org> + * Christophe Fergeau <cfergeau@redhat.com> + */ + +#include <config.h> + +#include "libvirt-gconfig/libvirt-gconfig.h" +#include "libvirt-gconfig/libvirt-gconfig-private.h" + +#define GVIR_CONFIG_DOMAIN_HOSTDEV_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV, GVirConfigDomainHostdevPrivate)) + +struct _GVirConfigDomainHostdevPrivate +{ + gboolean unused; +}; + +G_DEFINE_ABSTRACT_TYPE(GVirConfigDomainHostdev, gvir_config_domain_hostdev, GVIR_CONFIG_TYPE_DOMAIN_DEVICE); + + +static void gvir_config_domain_hostdev_class_init(GVirConfigDomainHostdevClass *klass) +{ + g_type_class_add_private(klass, sizeof(GVirConfigDomainHostdevPrivate)); +} + + +static void gvir_config_domain_hostdev_init(GVirConfigDomainHostdev *hostdev) +{ + hostdev->priv = GVIR_CONFIG_DOMAIN_HOSTDEV_GET_PRIVATE(hostdev); +} + +G_GNUC_INTERNAL GVirConfigDomainDevice * +gvir_config_domain_hostdev_new_from_tree(GVirConfigXmlDoc *doc, + xmlNodePtr tree) +{ + const char *type; + GType gtype; + + type = gvir_config_xml_get_attribute_content(tree, "type"); + if (type == NULL) + return NULL; + + if (g_str_equal(type, "usb")) { + goto unimplemented; + } else if (g_str_equal(type, "pci")) { + goto unimplemented; + } else if (g_str_equal(type, "scsi")) { + goto unimplemented; + } else { + g_debug("Unknown domain hostdev node: %s", type); + return NULL; + } + + return GVIR_CONFIG_DOMAIN_DEVICE(gvir_config_object_new_from_tree(gtype, doc, NULL, tree)); + +unimplemented: + g_debug("Parsing of '%s' domain hostdev nodes is unimplemented", type); + return NULL; +} + +/** + * gvir_config_domain_hostdev_set_boot_order: + * @hostdev: the host device + * @order: the boot order + * + * If a positive integer is passed as @order, @hostdev is marked bootable and + * boot order set to @order, otherwise @hostdev is marked to be unbootable. + */ +void gvir_config_domain_hostdev_set_boot_order(GVirConfigDomainHostdev *hostdev, + gint order) +{ + g_return_if_fail(GVIR_CONFIG_IS_DOMAIN_HOSTDEV(hostdev)); + + if (order >= 0) { + char *order_str = g_strdup_printf("%u", order); + + gvir_config_object_replace_child_with_attribute(GVIR_CONFIG_OBJECT(hostdev), + "boot", + "order", + order_str); + g_free(order_str); + } else { + gvir_config_object_delete_child(GVIR_CONFIG_OBJECT(hostdev), + "boot", + NULL); + } +} + +/** + * gvir_config_domain_hostdev_get_boot_order: + * @hostdev: the host device + * + * Returns: The boot order if @hostdev is bootable, otherwise a negative integer. + */ +gint gvir_config_domain_hostdev_get_boot_order(GVirConfigDomainHostdev *hostdev) +{ + return gvir_config_object_get_attribute_uint64(GVIR_CONFIG_OBJECT(hostdev), + "boot", "order", -1); +} + +/** + * gvir_config_domain_hostdev_set_readonly: + * @hostdev: the host device + * @readonly: the new readonly status + * + * Set the readonly status of @hostdev to @readonly. + */ +void gvir_config_domain_hostdev_set_readonly(GVirConfigDomainHostdev *hostdev, + gboolean readonly) +{ + g_return_if_fail(GVIR_CONFIG_IS_DOMAIN_HOSTDEV(hostdev)); + + if (readonly) { + GVirConfigObject *node; + + node = gvir_config_object_replace_child(GVIR_CONFIG_OBJECT(hostdev), + "readonly"); + g_object_unref(node); + } else { + gvir_config_object_delete_child(GVIR_CONFIG_OBJECT(hostdev), + "readonly", NULL); + } +} + +/** + * gvir_config_domain_hostdev_get_readonly: + * @hostdev: the host device + * + * Returns: %TRUE if @hostdev is readonly, %FALSE otherwise. + */ +gboolean gvir_config_domain_hostdev_get_readonly(GVirConfigDomainHostdev *hostdev) +{ + return gvir_config_object_has_child(GVIR_CONFIG_OBJECT(hostdev), + "readonly"); +} + +/** + * gvir_config_domain_hostdev_set_shareable: + * @hostdev: the host device + * @shareable: the new shareable status + * + * Set whether or not @hostdev is shared between domains. + */ +void gvir_config_domain_hostdev_set_shareable(GVirConfigDomainHostdev *hostdev, + gboolean shareable) +{ + g_return_if_fail(GVIR_CONFIG_IS_DOMAIN_HOSTDEV(hostdev)); + + if (shareable) { + GVirConfigObject *node; + + node = gvir_config_object_replace_child(GVIR_CONFIG_OBJECT(hostdev), + "shareable"); + g_object_unref(node); + } else { + gvir_config_object_delete_child(GVIR_CONFIG_OBJECT(hostdev), + "shareable", NULL); + } +} + +/** + * gvir_config_domain_hostdev_get_shareable: + * @hostdev: the host device + * + * Returns: %TRUE if @hostdev is shared between domains, %FALSE otherwise. + */ +gboolean gvir_config_domain_hostdev_get_shareable(GVirConfigDomainHostdev *hostdev) +{ + return gvir_config_object_has_child(GVIR_CONFIG_OBJECT(hostdev), + "shareable"); +} diff --git a/libvirt-gconfig/libvirt-gconfig-domain-hostdev.h b/libvirt-gconfig/libvirt-gconfig-domain-hostdev.h new file mode 100644 index 0000000..1372552 --- /dev/null +++ b/libvirt-gconfig/libvirt-gconfig-domain-hostdev.h @@ -0,0 +1,76 @@ +/* + * libvirt-gconfig-domain-hostdev.h: libvirt domain hostdev configuration + * + * Copyright (C) 2016 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Authors: Zeeshan Ali (Khattak) <zeeshanak@gnome.org> + * Christophe Fergeau <cfergeau@redhat.com> + */ + +#if !defined(__LIBVIRT_GCONFIG_H__) && !defined(LIBVIRT_GCONFIG_BUILD) +#error "Only <libvirt-gconfig/libvirt-gconfig.h> can be included directly." +#endif + +#ifndef __LIBVIRT_GCONFIG_DOMAIN_HOSTDEV_H__ +#define __LIBVIRT_GCONFIG_DOMAIN_HOSTDEV_H__ + +G_BEGIN_DECLS + +#define GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV (gvir_config_domain_hostdev_get_type ()) +#define GVIR_CONFIG_DOMAIN_HOSTDEV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV, GVirConfigDomainHostdev)) +#define GVIR_CONFIG_DOMAIN_HOSTDEV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV, GVirConfigDomainHostdevClass)) +#define GVIR_CONFIG_IS_DOMAIN_HOSTDEV(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV)) +#define GVIR_CONFIG_IS_DOMAIN_HOSTDEV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV)) +#define GVIR_CONFIG_DOMAIN_HOSTDEV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV, GVirConfigDomainHostdevClass)) + +typedef struct _GVirConfigDomainHostdev GVirConfigDomainHostdev; +typedef struct _GVirConfigDomainHostdevPrivate GVirConfigDomainHostdevPrivate; +typedef struct _GVirConfigDomainHostdevClass GVirConfigDomainHostdevClass; + +struct _GVirConfigDomainHostdev +{ + GVirConfigDomainDevice parent; + + GVirConfigDomainHostdevPrivate *priv; + + /* Do not add fields to this struct */ +}; + +struct _GVirConfigDomainHostdevClass +{ + GVirConfigDomainDeviceClass parent_class; + + gpointer padding[20]; +}; + +GType gvir_config_domain_hostdev_get_type(void); + +void gvir_config_domain_hostdev_set_boot_order(GVirConfigDomainHostdev *hostdev, + gint order); +gint gvir_config_domain_hostdev_get_boot_order(GVirConfigDomainHostdev *hostdev); + +void gvir_config_domain_hostdev_set_readonly(GVirConfigDomainHostdev *hostdev, + gboolean readonly); +gboolean gvir_config_domain_hostdev_get_readonly(GVirConfigDomainHostdev *hostdev); + +void gvir_config_domain_hostdev_set_shareable(GVirConfigDomainHostdev *hostdev, + gboolean shareable); +gboolean gvir_config_domain_hostdev_get_shareable(GVirConfigDomainHostdev *hostdev); + +G_END_DECLS + +#endif /* __LIBVIRT_GCONFIG_DOMAIN_HOSTDEV_H__ */ diff --git a/libvirt-gconfig/libvirt-gconfig.h b/libvirt-gconfig/libvirt-gconfig.h index 4624003..cfa9dd3 100644 --- a/libvirt-gconfig/libvirt-gconfig.h +++ b/libvirt-gconfig/libvirt-gconfig.h @@ -67,6 +67,7 @@ #include <libvirt-gconfig/libvirt-gconfig-domain-graphics-sdl.h> #include <libvirt-gconfig/libvirt-gconfig-domain-graphics-spice.h> #include <libvirt-gconfig/libvirt-gconfig-domain-graphics-vnc.h> +#include <libvirt-gconfig/libvirt-gconfig-domain-hostdev.h> #include <libvirt-gconfig/libvirt-gconfig-domain-input.h> #include <libvirt-gconfig/libvirt-gconfig-domain-interface.h> #include <libvirt-gconfig/libvirt-gconfig-domain-interface-bridge.h> diff --git a/libvirt-gconfig/libvirt-gconfig.sym b/libvirt-gconfig/libvirt-gconfig.sym index df6dd3a..3607554 100644 --- a/libvirt-gconfig/libvirt-gconfig.sym +++ b/libvirt-gconfig/libvirt-gconfig.sym @@ -734,7 +734,17 @@ global: } LIBVIRT_GCONFIG_0.2.1; LIBVIRT_GCONFIG_0.2.4 { +global: gvir_config_domain_graphics_spice_set_gl; + + gvir_config_domain_hostdev_get_boot_order; + gvir_config_domain_hostdev_get_readonly; + gvir_config_domain_hostdev_get_shareable; + gvir_config_domain_hostdev_get_type; + gvir_config_domain_hostdev_set_boot_order; + gvir_config_domain_hostdev_set_readonly; + gvir_config_domain_hostdev_set_shareable; + gvir_config_domain_video_get_model; gvir_config_domain_video_set_accel3d; } LIBVIRT_GCONFIG_0.2.2; -- 2.7.4

Add API to read and write PCI hostdev nodes. --- libvirt-gconfig/Makefile.am | 2 + .../libvirt-gconfig-domain-hostdev-pci.c | 232 +++++++++++++++++++++ .../libvirt-gconfig-domain-hostdev-pci.h | 81 +++++++ libvirt-gconfig/libvirt-gconfig-domain-hostdev.c | 2 +- libvirt-gconfig/libvirt-gconfig.h | 1 + libvirt-gconfig/libvirt-gconfig.sym | 11 + 6 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 libvirt-gconfig/libvirt-gconfig-domain-hostdev-pci.c create mode 100644 libvirt-gconfig/libvirt-gconfig-domain-hostdev-pci.h diff --git a/libvirt-gconfig/Makefile.am b/libvirt-gconfig/Makefile.am index a7c6c4e..0400343 100644 --- a/libvirt-gconfig/Makefile.am +++ b/libvirt-gconfig/Makefile.am @@ -51,6 +51,7 @@ GCONFIG_HEADER_FILES = \ libvirt-gconfig-domain-graphics-spice.h \ libvirt-gconfig-domain-graphics-vnc.h \ libvirt-gconfig-domain-hostdev.h \ + libvirt-gconfig-domain-hostdev-pci.h \ libvirt-gconfig-domain-input.h \ libvirt-gconfig-domain-interface.h \ libvirt-gconfig-domain-interface-bridge.h \ @@ -143,6 +144,7 @@ GCONFIG_SOURCE_FILES = \ libvirt-gconfig-domain-graphics-spice.c \ libvirt-gconfig-domain-graphics-vnc.c \ libvirt-gconfig-domain-hostdev.c \ + libvirt-gconfig-domain-hostdev-pci.c \ libvirt-gconfig-domain-input.c \ libvirt-gconfig-domain-interface.c \ libvirt-gconfig-domain-interface-bridge.c \ diff --git a/libvirt-gconfig/libvirt-gconfig-domain-hostdev-pci.c b/libvirt-gconfig/libvirt-gconfig-domain-hostdev-pci.c new file mode 100644 index 0000000..c173a8e --- /dev/null +++ b/libvirt-gconfig/libvirt-gconfig-domain-hostdev-pci.c @@ -0,0 +1,232 @@ +/* + * libvirt-gconfig-domain-hostdev.c: libvirt domain hostdev configuration + * + * Copyright (C) 2016 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Authors: Zeeshan Ali (Khattak) <zeeshanak@gnome.org> + * Christophe Fergeau <cfergeau@redhat.com> + */ + +#include <config.h> + +#include "libvirt-gconfig/libvirt-gconfig.h" +#include "libvirt-gconfig/libvirt-gconfig-private.h" + +#define GVIR_CONFIG_DOMAIN_HOSTDEV_PCI_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV_PCI, GVirConfigDomainHostdevPciPrivate)) + +struct _GVirConfigDomainHostdevPciPrivate +{ + gboolean unused; +}; + +G_DEFINE_TYPE(GVirConfigDomainHostdevPci, gvir_config_domain_hostdev_pci, GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV); + +static void gvir_config_domain_hostdev_pci_class_init(GVirConfigDomainHostdevPciClass *klass) +{ + g_type_class_add_private(klass, sizeof(GVirConfigDomainHostdevPciPrivate)); +} + + +static void gvir_config_domain_hostdev_pci_init(GVirConfigDomainHostdevPci *hostdev) +{ + hostdev->priv = GVIR_CONFIG_DOMAIN_HOSTDEV_PCI_GET_PRIVATE(hostdev); +} + +/** + * gvir_config_domain_hostdev_pci_new: + * + * Creates a new #GVirConfigDomainHostdevPci. + * + * Returns: (transfer full): a new #GVirConfigDomainHostdevPci. The returned + * object should be unreffed with g_object_unref() when no longer needed. + */ +GVirConfigDomainHostdevPci *gvir_config_domain_hostdev_pci_new(void) +{ + GVirConfigObject *object; + + object = gvir_config_object_new(GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV_PCI, + "hostdev", NULL); + gvir_config_object_set_attribute(object, "mode", "subsystem", NULL); + gvir_config_object_set_attribute(object, "type", "pci", NULL); + + return GVIR_CONFIG_DOMAIN_HOSTDEV_PCI(object); +} + +/** + * gvir_config_domain_hostdev_pci_new_from_xml: + * @xml: xml data to create the host device from + * @error: return location for a #GError, or NULL + * + * Creates a new #GVirConfigDomainHostdevPci. The host device object will be + * created using the XML description stored in @xml. This is a fragment of + * libvirt domain XML whose root node is <hostdev>. + * + * Returns: (transfer full): a new #GVirConfigDomainHostdevPci, or NULL if @xml + * failed to be parsed. The returned object should be unreffed with + * g_object_unref() when no longer needed. + */ +GVirConfigDomainHostdevPci *gvir_config_domain_hostdev_pci_new_from_xml(const gchar *xml, + GError **error) +{ + GVirConfigObject *object; + + object = gvir_config_object_new_from_xml(GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV_PCI, + "hostdev", NULL, xml, error); + if (object == NULL) + return NULL; + + if (g_strcmp0(gvir_config_object_get_attribute(object, NULL, "type"), "pci") != 0) { + g_object_unref(G_OBJECT(object)); + g_return_val_if_reached(NULL); + } + + return GVIR_CONFIG_DOMAIN_HOSTDEV_PCI(object); +} + +void gvir_config_domain_hostdev_pci_set_address(GVirConfigDomainHostdevPci *hostdev, + GVirConfigDomainAddressPci *address) +{ + GVirConfigObject *source; + xmlNodePtr node; + xmlAttrPtr attr; + + g_return_if_fail(GVIR_CONFIG_IS_DOMAIN_HOSTDEV_PCI(hostdev)); + g_return_if_fail(GVIR_CONFIG_IS_DOMAIN_ADDRESS_PCI(address)); + node = gvir_config_object_get_xml_node(GVIR_CONFIG_OBJECT(address)); + g_return_if_fail(node != NULL); + + source = gvir_config_object_replace_child(GVIR_CONFIG_OBJECT(hostdev), + "source"); + /* Because of https://bugzilla.redhat.com/show_bug.cgi?id=1327577, we can't + * just use GVirConfigDomainAddressPci's node, as is, since it contains + * a 'type' attribute, which is not accepted by libvirt. So we create a + * copy for our use and just delete the 'type' attribute from it. + */ + node = xmlCopyNode(node, 1); + for (attr = node->properties; attr; attr = attr->next) { + if (g_strcmp0 ("type", (char *)attr->name) == 0) { + xmlRemoveProp (attr); + break; + } + } + gvir_config_object_set_child(source, node); + g_object_unref(source); +} + +/** + * gvir_config_domain_hostdev_pci_get_address: + * @hostdev: A #GVirConfigDomainHostdevPci object. + * + * Gets the address associated with @hostdev. + * + * Returns: (transfer full): a new #GVirConfigDomainAddressPci, or NULL if no + * address is associated with @hostdev. The returned object should be unreffed + * with g_object_unref() when no longer needed. + */ +GVirConfigDomainAddressPci *gvir_config_domain_hostdev_pci_get_address(GVirConfigDomainHostdevPci *hostdev) +{ + GVirConfigObject *source; + GVirConfigObject* address; + + g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN_HOSTDEV_PCI(hostdev), NULL); + + source = gvir_config_object_get_child(GVIR_CONFIG_OBJECT(hostdev), "source"); + if (source == NULL) + return NULL; + + address = gvir_config_object_get_child_with_type(source, + "address", + GVIR_CONFIG_TYPE_DOMAIN_ADDRESS_PCI); + g_object_unref(source); + return GVIR_CONFIG_DOMAIN_ADDRESS_PCI(address); +} + +void gvir_config_domain_hostdev_pci_set_managed(GVirConfigDomainHostdevPci *hostdev, + gboolean managed) +{ + g_return_if_fail(GVIR_CONFIG_IS_DOMAIN_HOSTDEV_PCI(hostdev)); + + gvir_config_object_set_attribute_with_type(GVIR_CONFIG_OBJECT(hostdev), + "managed", + G_TYPE_BOOLEAN, + managed, + NULL); +} + +gboolean gvir_config_domain_hostdev_pci_get_managed(GVirConfigDomainHostdevPci *hostdev) +{ + g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN_HOSTDEV_PCI(hostdev), FALSE); + + return gvir_config_object_get_attribute_boolean(GVIR_CONFIG_OBJECT(hostdev), + NULL, + "managed", + FALSE); +} + +void gvir_config_domain_hostdev_pci_set_rom_file(GVirConfigDomainHostdevPci *hostdev, + const gchar *file) +{ + GVirConfigObject *rom; + + g_return_if_fail(GVIR_CONFIG_IS_DOMAIN_HOSTDEV_PCI(hostdev)); + + rom = gvir_config_object_add_child(GVIR_CONFIG_OBJECT(hostdev), "rom"); + gvir_config_object_set_attribute(rom, + "file", file, + NULL); + g_object_unref(rom); +} + +void gvir_config_domain_hostdev_pci_set_rom_bar(GVirConfigDomainHostdevPci *hostdev, + gboolean bar) +{ + GVirConfigObject *rom; + + g_return_if_fail(GVIR_CONFIG_IS_DOMAIN_HOSTDEV_PCI(hostdev)); + + rom = gvir_config_object_add_child(GVIR_CONFIG_OBJECT(hostdev), "rom"); + gvir_config_object_set_attribute(rom, + "bar", bar? "on" : "off", + NULL); + g_object_unref(rom); +} + +const gchar *gvir_config_domain_hostdev_pci_get_rom_file(GVirConfigDomainHostdevPci *hostdev) +{ + return gvir_config_object_get_attribute(GVIR_CONFIG_OBJECT(hostdev), "rom", "file"); +} + +gboolean gvir_config_domain_hostdev_pci_get_rom_bar(GVirConfigDomainHostdevPci *hostdev) +{ + xmlNodePtr hostdev_node; + xmlNodePtr rom_node; + const gchar *bar_str; + + g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN_HOSTDEV_PCI(hostdev), FALSE); + + hostdev_node = gvir_config_object_get_xml_node(GVIR_CONFIG_OBJECT(hostdev)); + g_return_val_if_fail(hostdev_node != NULL, FALSE); + + rom_node = gvir_config_xml_get_element(hostdev_node, "rom", NULL); + if (!rom_node || !(rom_node->children)) + /* When containing rom node is missing, default value is TRUE for newer Qemu */ + return TRUE; + + bar_str = gvir_config_xml_get_attribute_content(rom_node, "bar"); + return (g_strcmp0(bar_str, "on")); +} diff --git a/libvirt-gconfig/libvirt-gconfig-domain-hostdev-pci.h b/libvirt-gconfig/libvirt-gconfig-domain-hostdev-pci.h new file mode 100644 index 0000000..51378aa --- /dev/null +++ b/libvirt-gconfig/libvirt-gconfig-domain-hostdev-pci.h @@ -0,0 +1,81 @@ +/* + * libvirt-gconfig-domain-hostdev.h: libvirt domain hostdev configuration + * + * Copyright (C) 2016 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Authors: Zeeshan Ali (Khattak) <zeeshanak@gnome.org> + * Christophe Fergeau <cfergeau@redhat.com> + */ + +#if !defined(__LIBVIRT_GCONFIG_H__) && !defined(LIBVIRT_GCONFIG_BUILD) +#error "Only <libvirt-gconfig/libvirt-gconfig.h> can be included directly." +#endif + +#ifndef __LIBVIRT_GCONFIG_DOMAIN_HOSTDEV_PCI_H__ +#define __LIBVIRT_GCONFIG_DOMAIN_HOSTDEV_PCI_H__ + +G_BEGIN_DECLS + +#define GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV_PCI (gvir_config_domain_hostdev_pci_get_type ()) +#define GVIR_CONFIG_DOMAIN_HOSTDEV_PCI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV_PCI, GVirConfigDomainHostdevPci)) +#define GVIR_CONFIG_DOMAIN_HOSTDEV_PCI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV_PCI, GVirConfigDomainHostdevPciClass)) +#define GVIR_CONFIG_IS_DOMAIN_HOSTDEV_PCI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV_PCI)) +#define GVIR_CONFIG_IS_DOMAIN_HOSTDEV_PCI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV_PCI)) +#define GVIR_CONFIG_DOMAIN_HOSTDEV_PCI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV_PCI, GVirConfigDomainHostdevPciClass)) + +typedef struct _GVirConfigDomainHostdevPci GVirConfigDomainHostdevPci; +typedef struct _GVirConfigDomainHostdevPciPrivate GVirConfigDomainHostdevPciPrivate; +typedef struct _GVirConfigDomainHostdevPciClass GVirConfigDomainHostdevPciClass; + +struct _GVirConfigDomainHostdevPci +{ + GVirConfigDomainHostdev parent; + + GVirConfigDomainHostdevPciPrivate *priv; + + /* Do not add fields to this struct */ +}; + +struct _GVirConfigDomainHostdevPciClass +{ + GVirConfigDomainHostdevClass parent_class; + + gpointer padding[20]; +}; + +GType gvir_config_domain_hostdev_pci_get_type(void); + +GVirConfigDomainHostdevPci *gvir_config_domain_hostdev_pci_new(void); +GVirConfigDomainHostdevPci *gvir_config_domain_hostdev_pci_new_from_xml(const gchar *xml, + GError **error); +void gvir_config_domain_hostdev_pci_set_address(GVirConfigDomainHostdevPci *hostdev, + GVirConfigDomainAddressPci *address); +GVirConfigDomainAddressPci *gvir_config_domain_hostdev_pci_get_address(GVirConfigDomainHostdevPci *hostdev); + +void gvir_config_domain_hostdev_pci_set_managed(GVirConfigDomainHostdevPci *hostdev, + gboolean managed); +gboolean gvir_config_domain_hostdev_pci_get_managed(GVirConfigDomainHostdevPci *hostdev); +void gvir_config_domain_hostdev_pci_set_rom_file(GVirConfigDomainHostdevPci *hostdev, + const gchar *file); +const gchar *gvir_config_domain_hostdev_pci_get_rom_file(GVirConfigDomainHostdevPci *hostdev); +void gvir_config_domain_hostdev_pci_set_rom_bar(GVirConfigDomainHostdevPci *hostdev, + gboolean bar); +gboolean gvir_config_domain_hostdev_pci_get_rom_bar(GVirConfigDomainHostdevPci *hostdev); + +G_END_DECLS + +#endif /* __LIBVIRT_GCONFIG_DOMAIN_HOSTDEV_PCI_H__ */ diff --git a/libvirt-gconfig/libvirt-gconfig-domain-hostdev.c b/libvirt-gconfig/libvirt-gconfig-domain-hostdev.c index ce5f8aa..459674d 100644 --- a/libvirt-gconfig/libvirt-gconfig-domain-hostdev.c +++ b/libvirt-gconfig/libvirt-gconfig-domain-hostdev.c @@ -62,7 +62,7 @@ gvir_config_domain_hostdev_new_from_tree(GVirConfigXmlDoc *doc, if (g_str_equal(type, "usb")) { goto unimplemented; } else if (g_str_equal(type, "pci")) { - goto unimplemented; + gtype = GVIR_CONFIG_TYPE_DOMAIN_HOSTDEV_PCI; } else if (g_str_equal(type, "scsi")) { goto unimplemented; } else { diff --git a/libvirt-gconfig/libvirt-gconfig.h b/libvirt-gconfig/libvirt-gconfig.h index cfa9dd3..6462154 100644 --- a/libvirt-gconfig/libvirt-gconfig.h +++ b/libvirt-gconfig/libvirt-gconfig.h @@ -68,6 +68,7 @@ #include <libvirt-gconfig/libvirt-gconfig-domain-graphics-spice.h> #include <libvirt-gconfig/libvirt-gconfig-domain-graphics-vnc.h> #include <libvirt-gconfig/libvirt-gconfig-domain-hostdev.h> +#include <libvirt-gconfig/libvirt-gconfig-domain-hostdev-pci.h> #include <libvirt-gconfig/libvirt-gconfig-domain-input.h> #include <libvirt-gconfig/libvirt-gconfig-domain-interface.h> #include <libvirt-gconfig/libvirt-gconfig-domain-interface-bridge.h> diff --git a/libvirt-gconfig/libvirt-gconfig.sym b/libvirt-gconfig/libvirt-gconfig.sym index 3607554..4d080b9 100644 --- a/libvirt-gconfig/libvirt-gconfig.sym +++ b/libvirt-gconfig/libvirt-gconfig.sym @@ -741,6 +741,17 @@ global: gvir_config_domain_hostdev_get_readonly; gvir_config_domain_hostdev_get_shareable; gvir_config_domain_hostdev_get_type; + gvir_config_domain_hostdev_pci_get_address; + gvir_config_domain_hostdev_pci_get_managed; + gvir_config_domain_hostdev_pci_get_rom_bar; + gvir_config_domain_hostdev_pci_get_rom_file; + gvir_config_domain_hostdev_pci_get_type; + gvir_config_domain_hostdev_pci_new; + gvir_config_domain_hostdev_pci_new_from_xml; + gvir_config_domain_hostdev_pci_set_address; + gvir_config_domain_hostdev_pci_set_managed; + gvir_config_domain_hostdev_pci_set_rom_bar; + gvir_config_domain_hostdev_pci_set_rom_file; gvir_config_domain_hostdev_set_boot_order; gvir_config_domain_hostdev_set_readonly; gvir_config_domain_hostdev_set_shareable; -- 2.7.4

From: Christophe Fergeau <cfergeau@redhat.com> They will be useful to do more checks in the GVirDomainDeviceHostdev unit test. --- .../libvirt-gconfig-domain-address-pci.c | 45 ++++++++++++++++++++++ .../libvirt-gconfig-domain-address-pci.h | 5 +++ libvirt-gconfig/libvirt-gconfig.sym | 6 +++ 3 files changed, 56 insertions(+) diff --git a/libvirt-gconfig/libvirt-gconfig-domain-address-pci.c b/libvirt-gconfig/libvirt-gconfig-domain-address-pci.c index 4bf94cc..0105402 100644 --- a/libvirt-gconfig/libvirt-gconfig-domain-address-pci.c +++ b/libvirt-gconfig/libvirt-gconfig-domain-address-pci.c @@ -92,30 +92,75 @@ static void set_attribute_hex(GVirConfigDomainAddressPci *address, g_free(format); } +int gvir_config_domain_address_pci_get_domain(GVirConfigDomainAddressPci *address) +{ + g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN_ADDRESS_PCI(address), -1); + + return gvir_config_object_get_attribute_uint64(GVIR_CONFIG_OBJECT(address), + NULL, "domain", + -1); +} + void gvir_config_domain_address_pci_set_domain(GVirConfigDomainAddressPci *address, guint16 pci_domain) { set_attribute_hex(address, "domain", pci_domain, 0, G_MAXUINT16, 4); } +int gvir_config_domain_address_pci_get_bus(GVirConfigDomainAddressPci *address) +{ + g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN_ADDRESS_PCI(address), -1); + + return gvir_config_object_get_attribute_uint64(GVIR_CONFIG_OBJECT(address), + NULL, "bus", + -1); +} + void gvir_config_domain_address_pci_set_bus(GVirConfigDomainAddressPci *address, guchar bus) { set_attribute_hex(address, "bus", bus, 0, G_MAXUINT8, 2); } +int gvir_config_domain_address_pci_get_slot(GVirConfigDomainAddressPci *address) +{ + g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN_ADDRESS_PCI(address), -1); + + return gvir_config_object_get_attribute_uint64(GVIR_CONFIG_OBJECT(address), + NULL, "slot", + -1); +} + void gvir_config_domain_address_pci_set_slot(GVirConfigDomainAddressPci *address, guchar slot) { set_attribute_hex(address, "slot", slot, 0, 0x1f, 2); } +int gvir_config_domain_address_pci_get_function(GVirConfigDomainAddressPci *address) +{ + g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN_ADDRESS_PCI(address), -1); + + return gvir_config_object_get_attribute_uint64(GVIR_CONFIG_OBJECT(address), + NULL, "function", + -1); +} + void gvir_config_domain_address_pci_set_function(GVirConfigDomainAddressPci *address, guchar function) { set_attribute_hex(address, "function", function, 0, 7, 1); } +gboolean gvir_config_domain_address_pci_get_multifunction(GVirConfigDomainAddressPci *address) +{ + g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN_ADDRESS_PCI(address), FALSE); + + return gvir_config_object_get_attribute_boolean(GVIR_CONFIG_OBJECT(address), + NULL, "multifunction", + FALSE); +} + void gvir_config_domain_address_pci_set_multifunction(GVirConfigDomainAddressPci *address, gboolean multifunction) { diff --git a/libvirt-gconfig/libvirt-gconfig-domain-address-pci.h b/libvirt-gconfig/libvirt-gconfig-domain-address-pci.h index 3b82624..cdef4a8 100644 --- a/libvirt-gconfig/libvirt-gconfig-domain-address-pci.h +++ b/libvirt-gconfig/libvirt-gconfig-domain-address-pci.h @@ -62,14 +62,19 @@ GVirConfigDomainAddressPci *gvir_config_domain_address_pci_new(void); GVirConfigDomainAddressPci *gvir_config_domain_address_pci_new_from_xml(const gchar *xml, GError **error); +int gvir_config_domain_address_pci_get_domain(GVirConfigDomainAddressPci *address); void gvir_config_domain_address_pci_set_domain(GVirConfigDomainAddressPci *address, guint16 pci_domain); +int gvir_config_domain_address_pci_get_bus(GVirConfigDomainAddressPci *address); void gvir_config_domain_address_pci_set_bus(GVirConfigDomainAddressPci *address, guchar bus); +int gvir_config_domain_address_pci_get_slot(GVirConfigDomainAddressPci *address); void gvir_config_domain_address_pci_set_slot(GVirConfigDomainAddressPci *address, guchar slot); +int gvir_config_domain_address_pci_get_function(GVirConfigDomainAddressPci *address); void gvir_config_domain_address_pci_set_function(GVirConfigDomainAddressPci *address, guchar function); +gboolean gvir_config_domain_address_pci_get_multifunction(GVirConfigDomainAddressPci *address); void gvir_config_domain_address_pci_set_multifunction(GVirConfigDomainAddressPci *address, gboolean multifunction); diff --git a/libvirt-gconfig/libvirt-gconfig.sym b/libvirt-gconfig/libvirt-gconfig.sym index 4d080b9..4ef4bf7 100644 --- a/libvirt-gconfig/libvirt-gconfig.sym +++ b/libvirt-gconfig/libvirt-gconfig.sym @@ -735,6 +735,12 @@ global: LIBVIRT_GCONFIG_0.2.4 { global: + gvir_config_domain_address_pci_get_bus; + gvir_config_domain_address_pci_get_domain; + gvir_config_domain_address_pci_get_function; + gvir_config_domain_address_pci_get_multifunction; + gvir_config_domain_address_pci_get_slot; + gvir_config_domain_graphics_spice_set_gl; gvir_config_domain_hostdev_get_boot_order; -- 2.7.4

--- tests/test-gconfig.c | 43 +++++++++++++++++++++++++ tests/xml/gconfig-domain-device-pci-hostdev.xml | 11 +++++++ 2 files changed, 54 insertions(+) create mode 100644 tests/xml/gconfig-domain-device-pci-hostdev.xml diff --git a/tests/test-gconfig.c b/tests/test-gconfig.c index be55ef9..a26bb5f 100644 --- a/tests/test-gconfig.c +++ b/tests/test-gconfig.c @@ -709,6 +709,47 @@ static void test_domain_device_usb_redir(void) g_object_unref(G_OBJECT(domain)); } +static void test_domain_device_pci_hostdev(void) +{ + GVirConfigDomain *domain; + GVirConfigDomainAddressPci *address; + GVirConfigDomainHostdevPci *hostdev; + + domain = gvir_config_domain_new(); + + hostdev = gvir_config_domain_hostdev_pci_new(); + gvir_config_domain_hostdev_set_boot_order(GVIR_CONFIG_DOMAIN_HOSTDEV(hostdev), 1); + g_assert_cmpint(gvir_config_domain_hostdev_get_boot_order(GVIR_CONFIG_DOMAIN_HOSTDEV(hostdev)), ==, 1); + gvir_config_domain_hostdev_pci_set_managed(hostdev, TRUE); + g_assert(gvir_config_domain_hostdev_pci_get_managed(hostdev) == TRUE); + gvir_config_domain_hostdev_pci_set_rom_bar(hostdev, TRUE); + gvir_config_domain_hostdev_pci_set_rom_file(hostdev, "/etc/fake/boot.bin"); + g_assert_cmpstr(gvir_config_domain_hostdev_pci_get_rom_file(hostdev), ==, "/etc/fake/boot.bin"); + g_assert(gvir_config_domain_hostdev_pci_get_rom_bar(hostdev)); + + address = gvir_config_domain_address_pci_new(); + gvir_config_domain_address_pci_set_domain(address, 1); + gvir_config_domain_address_pci_set_bus(address, 2); + gvir_config_domain_address_pci_set_slot(address, 3); + gvir_config_domain_address_pci_set_function(address, 4); + gvir_config_domain_hostdev_pci_set_address(hostdev, address); + g_object_unref(G_OBJECT(address)); + + address = gvir_config_domain_hostdev_pci_get_address(hostdev); + g_assert(address != NULL); + g_assert_cmpint(gvir_config_domain_address_pci_get_domain(address), ==, 1); + g_assert_cmpint(gvir_config_domain_address_pci_get_bus(address), ==, 2); + g_assert_cmpint(gvir_config_domain_address_pci_get_slot(address), ==, 3); + g_assert_cmpint(gvir_config_domain_address_pci_get_function(address), ==, 4); + g_object_unref(G_OBJECT(address)); + + gvir_config_domain_add_device(domain, GVIR_CONFIG_DOMAIN_DEVICE (hostdev)); + g_object_unref(G_OBJECT(hostdev)); + + check_xml(domain, "gconfig-domain-device-pci-hostdev.xml"); + + g_object_unref(G_OBJECT(domain)); +} int main(int argc, char **argv) { @@ -739,6 +780,8 @@ int main(int argc, char **argv) test_domain_device_channel); g_test_add_func("/libvirt-gconfig/domain-device-usb-redir", test_domain_device_usb_redir); + g_test_add_func("/libvirt-gconfig/domain-device-pci-hostdev", + test_domain_device_pci_hostdev); return g_test_run(); } diff --git a/tests/xml/gconfig-domain-device-pci-hostdev.xml b/tests/xml/gconfig-domain-device-pci-hostdev.xml new file mode 100644 index 0000000..70e32ac --- /dev/null +++ b/tests/xml/gconfig-domain-device-pci-hostdev.xml @@ -0,0 +1,11 @@ +<domain> + <devices> + <hostdev mode="subsystem" type="pci" managed="yes"> + <boot order="1"/> + <rom bar="on" file="/etc/fake/boot.bin"/> + <source> + <address domain="0x0001" bus="0x02" slot="0x03" function="0x4"/> + </source> + </hostdev> + </devices> +</domain> -- 2.7.4
participants (1)
-
Zeeshan Ali (Khattak)