[libvirt] [PATCH v3 1/2] network: Introduce network hooks

Daniel P. Berrange berrange at redhat.com
Tue Feb 11 09:54:05 UTC 2014


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 :|




More information about the libvir-list mailing list