
On Mon, Feb 10, 2014 at 07:52:34PM +0100, Michal Privoznik wrote:
@@ -3583,6 +3639,48 @@ validate: } }
+ /* finally we can call the 'plugged' hook script if any */ + if (virHookPresent(VIR_HOOK_DRIVER_NETWORK)) { + /* the XML construction is a bit complicated here, + * as we want to pass both domain XML and network XML */ + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *xml, *net_xml, *dom_xml; + int hookret; + + net_xml = virNetworkDefFormat(netdef, 0); + dom_xml = virDomainDefFormat(dom, 0); + + if (!net_xml || !dom_xml) { + VIR_FREE(net_xml); + VIR_FREE(dom_xml); + goto error; + } + + virBufferAdd(&buf, net_xml, -1); + virBufferAdd(&buf, dom_xml, -1);
This isn't very easy for applications to consume. With all the other things you can just pass stdin straight to your XML parser and process it. When you concatenate 2 XML docs this way it becomes much harder, since you have to split the two docs which means parsing them without an XML parser. Usually you'd want to place the 2 docs within a parent XML doc so the overall result is still a single wellformed XML doc.
+ + VIR_FREE(net_xml); + VIR_FREE(dom_xml); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + goto error; + } + + xml = virBufferContentAndReset(&buf); + + hookret = virHookCall(VIR_HOOK_DRIVER_NETWORK, network->def->name, + VIR_HOOK_NETWORK_OP_IFACE_PLUGGED, + VIR_HOOK_SUBOP_BEGIN, NULL, xml, NULL); + VIR_FREE(xml); + + /* + * If the script raised an error abort the allocation + */ + if (hookret < 0) + goto error; + } + if (dev) { /* we are now assured of success, so mark the allocation */ dev->connections++; @@ -3618,6 +3716,7 @@ error: }
/* networkNotifyActualDevice: + * @dom: domain definition that @iface belongs to * @iface: the domain's NetDef with an "actual" device already filled in. * * Called to notify the network driver when libvirtd is restarted and @@ -3628,7 +3727,8 @@ error: * Returns 0 on success, -1 on failure. */ int -networkNotifyActualDevice(virDomainNetDefPtr iface) +networkNotifyActualDevice(virDomainDefPtr dom, + virDomainNetDefPtr iface) { virNetworkDriverStatePtr driver = driverState; enum virDomainNetType actualType = virDomainNetGetActualType(iface); @@ -3781,6 +3881,48 @@ networkNotifyActualDevice(virDomainNetDefPtr iface) }
success: + /* finally we can call the 'plugged' hook script if any */ + if (virHookPresent(VIR_HOOK_DRIVER_NETWORK)) { + /* the XML construction is a bit complicated here, + * as we want to pass both domain XML and network XML */ + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *xml, *net_xml, *dom_xml; + int hookret; + + net_xml = virNetworkDefFormat(netdef, 0); + dom_xml = virDomainDefFormat(dom, 0); + + if (!net_xml || !dom_xml) { + VIR_FREE(net_xml); + VIR_FREE(dom_xml); + goto error; + } + + virBufferAdd(&buf, net_xml, -1); + virBufferAdd(&buf, dom_xml, -1); + + VIR_FREE(net_xml); + VIR_FREE(dom_xml); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + goto error; + } + + xml = virBufferContentAndReset(&buf); + + hookret = virHookCall(VIR_HOOK_DRIVER_NETWORK, network->def->name, + VIR_HOOK_NETWORK_OP_IFACE_PLUGGED, + VIR_HOOK_SUBOP_BEGIN, NULL, xml, NULL); + VIR_FREE(xml); + + /* + * If the script raised an error abort the allocation + */ + if (hookret < 0) + goto error; + } + netdef->connections++; VIR_DEBUG("Using network %s, %d connections", netdef->name, netdef->connections); @@ -3796,6 +3938,7 @@ error:
/* networkReleaseActualDevice: + * @dom: domain definition that @iface belongs to * @iface: a domain's NetDef (interface definition) * * Given a domain <interface> element that previously had its <actual> @@ -3806,7 +3949,8 @@ error: * Returns 0 on success, -1 on failure. */ int -networkReleaseActualDevice(virDomainNetDefPtr iface) +networkReleaseActualDevice(virDomainDefPtr dom, + virDomainNetDefPtr iface) { virNetworkDriverStatePtr driver = driverState; enum virDomainNetType actualType = virDomainNetGetActualType(iface); @@ -3925,6 +4069,42 @@ networkReleaseActualDevice(virDomainNetDefPtr iface) success: if (iface->data.network.actual) netdef->connections--; + + /* finally we can call the 'unplugged' hook script if any */ + if (virHookPresent(VIR_HOOK_DRIVER_NETWORK)) { + /* the XML construction is a bit complicated here, + * as we want to pass both domain XML and network XML */ + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *xml, *net_xml, *dom_xml; + + net_xml = virNetworkDefFormat(netdef, 0); + dom_xml = virDomainDefFormat(dom, 0); + + if (!net_xml || !dom_xml) { + VIR_FREE(net_xml); + VIR_FREE(dom_xml); + goto error; + } + + virBufferAdd(&buf, net_xml, -1); + virBufferAdd(&buf, dom_xml, -1); + + VIR_FREE(net_xml); + VIR_FREE(dom_xml); + + if (virBufferError(&buf)) { + virBufferFreeAndReset(&buf); + goto error; + } + + xml = virBufferContentAndReset(&buf); + + virHookCall(VIR_HOOK_DRIVER_NETWORK, network->def->name, + VIR_HOOK_NETWORK_OP_IFACE_UNPLUGGED, + VIR_HOOK_SUBOP_BEGIN, NULL, xml, NULL); + VIR_FREE(xml); + } + VIR_DEBUG("Releasing network %s, %d connections", netdef->name, netdef->connections);
There's alot of repeated code patterns throughout this file. Seems this would be shorter if we had a helper method for doing all the hook presence check / xml formatting hook invocation. Each usage would then just be a single line function call. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|