
Hi,
+ */ +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 with a reference count of 1. + * 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: a new #GVirConfigDomainHostdevPci, or NULL if @xml failed to + * be parsed. + */ +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 (*error != 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; + GVirConfigObject *addr_object; + 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)); + addr_object = GVIR_CONFIG_OBJECT(address); + node = gvir_config_object_get_xml_node(addr_object); + g_return_if_fail(node != NULL); + + source = gvir_config_object_replace_child(GVIR_CONFIG_OBJECT(hostdev), + "source"); + /* We can't just use GVirConfigDomainAddressPci's node, as is, since it + * contains a 'type' attribute that's not valid in this context. So we + * create a copy for our use and just delete the 'type' node from it. + */
It took me a while to understand what this comment meant exactly, and why this was needed. If I followed correctly, in libvirt RelaxNG schema, the address for a PCI hostdev device is a 'pciaddress', which do not have a 'type' attribute contrary to most other addresses. This means that for the PCI address of a hostdev device, trying to set a 'type' attribute will trigger errors from libvirt when it tries to parse the domain XML.
Yeah, I tried tried with `virsh edit` and it tells me xml doesn't confirm to schema.
In my opinion, this is a libvirt bug that type="pci" is not accepted here as libvirt documentation says: « Device Addresses
Many devices have an optional <address> sub-element to describe where the device is placed on the virtual bus presented to the guest.[...]
Every address has a mandatory attribute type that describes which bus the device is on. »
Maybe here things are a bit special as this address is not a direct child of the <hostdev> element, but is contained within a <source> element, but I still think it would be nicer of libvirt, and more consistent to accept an optional type="pci" attribute here rather than rejecting it. This would have spared us the ugly workaround below :(
Yeah but even if it's resolved in libvirt, we'd still want to have a work around for older libvirt.
+ +const gchar *gvir_config_domain_hostdev_pci_get_rom(GVirConfigDomainHostdevPci *hostdev, + gboolean *bar) +{ + xmlNodePtr hostdev_node; + xmlNodePtr rom_node; + const gchar *bar_str; + + g_return_val_if_fail(GVIR_CONFIG_IS_DOMAIN_HOSTDEV_PCI(hostdev), NULL); + + hostdev_node = gvir_config_object_get_xml_node(GVIR_CONFIG_OBJECT(hostdev)); + g_return_val_if_fail(hostdev_node != NULL, NULL); + + rom_node = gvir_config_xml_get_element(hostdev_node, "rom", NULL); + if (!rom_node || !(rom_node->children)) + return NULL; + + bar_str = gvir_config_xml_get_attribute_content(rom_node, "bar"); + if (g_strcmp0(bar_str, "on")) + *bar = TRUE; + else + *bar = FALSE; + + return (const char *) rom_node->children->content;
The filename is in the file attribute, it's not in the node content (addressed in a patch I'm going to send by switching to using GVirConfigObject helpers).
Regarding the API, I don't think there are other places in libvirt-gconfig where we set (or get) 2 things with a single setter/getter. Are these 2 parameters tightly coupled together? It seems to me we could do something similar to the <os><type> attributes ('arch' and 'machine'). These 2 attributes are set by 2 separate helpers, but these helpers are in the GVirConfigOs class: gvir_config_domain_os_set_arch gvir_config_domain_os_set_machine
Both 'arch' and 'machine' are separate attributes on the 'type' node but "bar" is an attribute of "rom" node, that I think is unlikely to be used in isolation. If we keep this API, I think I should change 'rom' to be nullable. I see your point though and I don't have hard feeling either way. -- Regards, Zeeshan Ali (Khattak) ________________________________________ Befriend GNOME: http://www.gnome.org/friends/