There might be some use cases, where user wants to prepare the host or its environment prior to starting a network and do some cleanup after the network has been shut down. Consider all the functionality that libvirt doesn't currently have as an example what a hook script can possibly do. Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- docs/hooks.html.in | 43 +++++++++++++++++++++++++++++-------------- src/network/bridge_driver.c | 29 +++++++++++++++++++++++++++++ src/util/virhook.c | 10 +++++++++- src/util/virhook.h | 8 ++++++++ 4 files changed, 75 insertions(+), 15 deletions(-) diff --git a/docs/hooks.html.in b/docs/hooks.html.in index f0f692b..b950031 100644 --- a/docs/hooks.html.in +++ b/docs/hooks.html.in @@ -16,6 +16,7 @@ configuration<br/><br/></li> <li>A QEMU guest is started or stopped<br/><br/></li> <li>An LXC guest is started or stopped<br/><br/></li> + <li>A network is started or stopped<br/><br/></li> </ul> <h2><a name="location">Script location</a></h2> @@ -44,6 +45,8 @@ Executed when a QEMU guest is started, stopped, or migrated<br/><br/></li> <li><code>/etc/libvirt/hooks/lxc</code><br /><br/> Executed when an LXC guest is started or stopped</li> + <li><code>/etc/libvirt/hooks/network</code><br /><br/> + Executed when a network is started or stopped</li> </ul> <br/> @@ -62,10 +65,11 @@ <h2><a name="arguments">Script arguments</a></h2> <p>The hook scripts are called with specific command line arguments, depending upon the script, and the operation being performed.</p> - <p>The guest hook scripts, qemu and lxc, are also given the <b>full</b> - XML description for the domain on their stdin. This includes items - such the UUID of the domain and its storage information, and is - intended to provide all the libvirt information the script needs.</p> + <p>The guest hook scripts, qemu and lxc, or network hook script are + also given the <b>full</b> XML description for the domain on their + stdin. This includes items such as the UUID of the domain or network, + domain storage information, etc. and is intended to provide all the + libvirt information the script needs.</p> <p>The command line arguments take this approach:</p> <ol> @@ -181,23 +185,34 @@ <pre>/etc/libvirt/hooks/lxc guest_name reconnect begin -</pre> </li> </ul> + + <h5><a name="network">/etc/libvirt/hooks/network</a></h5> + <ul> + <li><span class="since">Since 1.2.2</span>, when a network is started, + this script is called as:<br/> + <pre>/etc/libvirt/hooks/network network_name start - start</pre></li> + <li>When a network is shut down, this script is called as:<br/> + <pre>/etc/libvirt/hooks/network network_name shutdown - shutdown</pre></li> + </ul> + <br/> <h2><a name="execution">Script execution</a></h2> <ul> - <li>The "start" operation for the guest hook scripts, qemu and lxc, + <li>The "start" operation for the guest and network hook scripts, executes <b>prior</b> to the guest being created. This allows the - guest start operation to be aborted if the script returns indicating - failure.<br/><br/></li> - <li>The "shutdown" operation for the guest hook scripts, qemu and lxc, - executes <b>after</b> the guest has stopped. If the hook script - indicates failure in its return, the shut down of the guest cannot - be aborted because it has already been performed.<br/><br/></li> + guest or network start operation to be aborted if the script returns + indicating failure.<br/><br/></li> + <li>The "shutdown" operation for the guest and network hook scripts, + executes <b>after</b> the guest or network has stopped. If the hook + script indicates failure in its return, the shut down of the guest + or network cannot be aborted because it has already been performed. + <br/><br/></li> <li>Hook scripts execute in a synchronous fashion. Libvirt waits for them to return before continuing the given operation.<br/><br/> - This is most noticeable with the guest start operation, as a lengthy - operation in the hook script can mean an extended wait for the guest - to be available to end users.<br/><br/></li> + This is most noticeable with the guest or network start operation, + as a lengthy operation in the hook script can mean an extended wait + for the guest or network to be available to end users.<br/><br/></li> <li>For a hook script to be utilised, it must have its execute bit set (ie. chmod o+rx <i>qemu</i>), and must be present when the libvirt daemon is started.<br/><br/></li> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 53c2274..2bca5bc 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -71,6 +71,7 @@ #include "virstring.h" #include "viraccessapicheck.h" #include "network_event.h" +#include "virhook.h" #define VIR_FROM_THIS VIR_FROM_NETWORK @@ -2011,6 +2012,23 @@ networkStartNetwork(virNetworkDriverStatePtr driver, if (virNetworkObjSetDefTransient(network, true) < 0) goto cleanup; + /* Run an early hook to set-up missing devices */ + if (virHookPresent(VIR_HOOK_DRIVER_NETWORK)) { + char *xml = virNetworkDefFormat(network->def, 0); + int hookret; + + hookret = virHookCall(VIR_HOOK_DRIVER_NETWORK, network->def->name, + VIR_HOOK_NETWORK_OP_START, VIR_HOOK_SUBOP_BEGIN, + NULL, xml, NULL); + VIR_FREE(xml); + + /* + * If the script raised an error abort the launch + */ + if (hookret < 0) + goto cleanup; + } + switch (network->def->forward.type) { case VIR_NETWORK_FORWARD_NONE: @@ -2090,6 +2108,17 @@ static int networkShutdownNetwork(virNetworkDriverStatePtr driver, break; } + /* now that we know it's stopped call the hook if present */ + if (virHookPresent(VIR_HOOK_DRIVER_NETWORK)) { + char *xml = virNetworkDefFormat(network->def, 0); + + /* we can't stop the operation even if the script raised an error */ + virHookCall(VIR_HOOK_DRIVER_NETWORK, network->def->name, + VIR_HOOK_NETWORK_OP_STOPPED, VIR_HOOK_SUBOP_END, + NULL, xml, NULL); + VIR_FREE(xml); + } + network->active = 0; virNetworkObjUnsetDefTransient(network); return ret; diff --git a/src/util/virhook.c b/src/util/virhook.c index 159efdb..5206810 100644 --- a/src/util/virhook.c +++ b/src/util/virhook.c @@ -48,12 +48,14 @@ VIR_ENUM_DECL(virHookDaemonOp) VIR_ENUM_DECL(virHookSubop) VIR_ENUM_DECL(virHookQemuOp) VIR_ENUM_DECL(virHookLxcOp) +VIR_ENUM_DECL(virHookNetworkOp) VIR_ENUM_IMPL(virHookDriver, VIR_HOOK_DRIVER_LAST, "daemon", "qemu", - "lxc") + "lxc", + "network") VIR_ENUM_IMPL(virHookDaemonOp, VIR_HOOK_DAEMON_OP_LAST, "start", @@ -83,6 +85,10 @@ VIR_ENUM_IMPL(virHookLxcOp, VIR_HOOK_LXC_OP_LAST, "started", "reconnect") +VIR_ENUM_IMPL(virHookNetworkOp, VIR_HOOK_NETWORK_OP_LAST, + "start", + "stopped") + static int virHooksFound = -1; /** @@ -246,6 +252,8 @@ virHookCall(int driver, case VIR_HOOK_DRIVER_LXC: opstr = virHookLxcOpTypeToString(op); break; + case VIR_HOOK_DRIVER_NETWORK: + opstr = virHookNetworkOpTypeToString(op); } if (opstr == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, diff --git a/src/util/virhook.h b/src/util/virhook.h index 96bf4cf..05ed3b5 100644 --- a/src/util/virhook.h +++ b/src/util/virhook.h @@ -30,6 +30,7 @@ enum virHookDriverType { VIR_HOOK_DRIVER_DAEMON = 0, /* Daemon related events */ VIR_HOOK_DRIVER_QEMU, /* QEmu domains related events */ VIR_HOOK_DRIVER_LXC, /* LXC domains related events */ + VIR_HOOK_DRIVER_NETWORK, /* network related events */ VIR_HOOK_DRIVER_LAST, }; @@ -74,6 +75,13 @@ enum virHookLxcOpType { VIR_HOOK_LXC_OP_LAST, }; +enum virHookNetworkOpType { + VIR_HOOK_NETWORK_OP_START, /* network is about to start */ + VIR_HOOK_NETWORK_OP_STOPPED, /* network has stopped */ + + VIR_HOOK_NETWORK_OP_LAST, +}; + int virHookInitialize(void); int virHookPresent(int driver); -- 1.8.5.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list