Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx> --- docs/hooks.html.in | 406 ----------------------------------- docs/hooks.rst | 518 +++++++++++++++++++++++++++++++++++++++++++++ docs/meson.build | 2 +- 3 files changed, 519 insertions(+), 407 deletions(-) delete mode 100644 docs/hooks.html.in create mode 100644 docs/hooks.rst diff --git a/docs/hooks.html.in b/docs/hooks.html.in deleted file mode 100644 index bbbc414dc4..0000000000 --- a/docs/hooks.html.in +++ /dev/null @@ -1,406 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html> -<html xmlns="http://www.w3.org/1999/xhtml"> - <body> - <h1>Hooks for specific system management</h1> - - <ul id="toc"></ul> - - <h2><a id="intro">Custom event scripts</a></h2> - <p>Beginning with libvirt 0.8.0, specific events on a host system will - trigger custom scripts.</p> - <p>These custom <b>hook</b> scripts are executed when any of the following - actions occur:</p> - <ul> - <li>The libvirt daemon starts, stops, or reloads its - configuration - (<span class="since">since 0.8.0</span>)<br/><br/></li> - <li>A QEMU guest is started or stopped - (<span class="since">since 0.8.0</span>)<br/><br/></li> - <li>An LXC guest is started or stopped - (<span class="since">since 0.8.0</span>)<br/><br/></li> - <li>A libxl-handled Xen guest is started or stopped - (<span class="since">since 2.1.0</span>)<br/><br/></li> - <li>A network is started or stopped or an interface is - plugged/unplugged to/from the network - (<span class="since">since 1.2.2</span>)<br/><br/></li> - </ul> - - <h2><a id="location">Script location</a></h2> - <p>The libvirt hook scripts are located in the directory - <code>$SYSCONFDIR/libvirt/hooks/</code>.</p> - <ul> - <li>In Linux distributions such as Fedora and RHEL, this is - <code>/etc/libvirt/hooks/</code>. Other Linux distributions may do - this differently.</li> - <li>If your installation of libvirt has instead been compiled from - source, it is likely to be - <code>/usr/local/etc/libvirt/hooks/</code>.</li> - <li><span class="since">Since 6.5.0</span>, you can also place several - hook scripts in the directories - <code>/etc/libvirt/hooks/<driver>.d/</code>.</li> - </ul> - <p>To use hook scripts, you will need to create this <code>hooks</code> - directory manually, place the desired hook scripts inside, then make - them executable.</p> - <br/> - - <h2><a id="names">Script names</a></h2> - <p>At present, there are five hook scripts that can be called:</p> - <ul> - <li><code>/etc/libvirt/hooks/daemon</code><br/><br/> - Executed when the libvirt daemon is started, stopped, or reloads - its configuration<br/><br/></li> - <li><code>/etc/libvirt/hooks/qemu</code><br/><br/> - 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/libxl</code><br/><br/> - Executed when a libxl-handled Xen guest is started, stopped, or - migrated<br/><br/></li> - <li><code>/etc/libvirt/hooks/network</code><br/><br/> - Executed when a network is started or stopped or an - interface is plugged/unplugged to/from the network</li> - </ul> - <p><span class="since">Since 6.5.0</span>, you can also have - several scripts with any name in the directories - <code>/etc/libvirt/hooks/<driver>.d/</code>. They are - executed in alphabetical order after main script.</p> - <br/> - - <h2><a id="structure">Script structure</a></h2> - <p>The hook scripts are executed using standard Linux process creation - functions. Therefore, they must begin with the declaration of the - command interpreter to use.</p> - <p>For example:</p> - <pre>#!/bin/bash</pre> - <p>or:</p> - <pre>#!/usr/bin/python</pre> - <p>Other command interpreters are equally valid, as is any executable - binary, so you are welcome to use your favourite languages.</p> - <br/> - - <h2><a id="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>For all cases, stdin of the network hook script is provided with the - full XML description of the network status in the following form:</p> - -<pre><hookData> - <network> - <name>$network_name</name> - <uuid>afca425a-2c3a-420c-b2fb-dd7b4950d722</uuid> - ... - </network> -</hookData></pre> - - <p>In the case of an network port being created / deleted, the network - XML will be followed with the full XML description of the port:</p> - -<pre><hookData> - <network> - <name>$network_name</name> - <uuid>afca425a-2c3a-420c-b2fb-dd7b4950d722</uuid> - ... - </network> - <networkport> - <uuid>5d744f21-ba4a-4d6e-bdb2-30a35ff3207d</uuid> - ... - <plug type='direct' dev='ens3' mode='vepa'/> - </networkport> -</hookData></pre> - - <p>Please note that this approach is different from other cases such as - <code>daemon</code>, <code>qemu</code> or <code>lxc</code> hook scripts, - because two XMLs may be passed here, while in the other cases only a single - XML is passed.</p> - - <p>The command line arguments take this approach:</p> - <ol> - <li>The first argument is the name of the <b>object</b> involved in the - operation, or '-' if there is none.<br/><br/> - For example, the name of a guest being started.<br/><br/></li> - <li>The second argument is the name of the <b>operation</b> being - performed.<br/><br/> - For example, "start" if a guest is being started.<br/><br/></li> - <li>The third argument is a <b>sub-operation</b> indication, or '-' if there - is none.<br/><br/></li> - <li>The last argument is an <b>extra argument</b> string, or '-' if there is - none.</li> - </ol> - - <h4><a id="arguments_specifics">Specifics</a></h4> - <p>This translates to the following specifics for each hook script:</p> - - <h5><a id="daemon">/etc/libvirt/hooks/daemon</a></h5> - <ul> - <li>When the libvirt daemon is started, this script is called as:<br/> - <pre>/etc/libvirt/hooks/daemon - start - start</pre></li> - <li>When the libvirt daemon is shut down, this script is called as:<br/> - <pre>/etc/libvirt/hooks/daemon - shutdown - shutdown</pre></li> - <li>When the libvirt daemon receives the SIGHUP signal, it reloads its - configuration and triggers the hook script as:<br/> - <pre>/etc/libvirt/hooks/daemon - reload begin SIGHUP</pre></li> - </ul> - <p>Please note that when the libvirt daemon is restarted, the <i>daemon</i> - hook script is called once with the "shutdown" operation, and then once - with the "start" operation. There is no specific operation to indicate - a "restart" is occurring.</p> - - <h5><a id="qemu">/etc/libvirt/hooks/qemu</a></h5> - <ul> - <li>Before a QEMU guest is started, the qemu hook script is - called in three locations; if any location fails, the guest - is not started. The first location, <span class="since">since - 0.9.0</span>, is before libvirt performs any resource - labeling, and the hook can allocate resources not managed by - libvirt such as DRBD or missing bridges. This is called as:<br/> - <pre>/etc/libvirt/hooks/qemu guest_name prepare begin -</pre> - The second location, available <span class="since">Since - 0.8.0</span>, occurs after libvirt has finished labeling - all resources, but has not yet started the guest, called as:<br/> - <pre>/etc/libvirt/hooks/qemu guest_name start begin -</pre> - The third location, <span class="since">0.9.13</span>, - occurs after the QEMU process has successfully started up:<br/> - <pre>/etc/libvirt/hooks/qemu guest_name started begin -</pre> - </li> - <li>When a QEMU guest is stopped, the qemu hook script is called - in two locations, to match the startup. - First, <span class="since">since 0.8.0</span>, the hook is - called before libvirt restores any labels:<br/> - <pre>/etc/libvirt/hooks/qemu guest_name stopped end -</pre> - Then, after libvirt has released all resources, the hook is - called again, <span class="since">since 0.9.0</span>, to allow - any additional resource cleanup:<br/> - <pre>/etc/libvirt/hooks/qemu guest_name release end -</pre></li> - <li><span class="since">Since 0.9.11</span>, the qemu hook script - is also called at the beginning of incoming migration. It is called - as: <pre>/etc/libvirt/hooks/qemu guest_name migrate begin -</pre> - with domain XML sent to standard input of the script. In this case, - the script acts as a filter and is supposed to modify the domain - XML and print it out on its standard output. Empty output is - identical to copying the input XML without changing it. In case the - script returns failure or the output XML is not valid, incoming - migration will be canceled. This hook may be used, e.g., to change - location of disk images for incoming domains.</li> - <li><span class="since">Since 1.2.9</span>, the qemu hook script is - also called when restoring a saved image either via the API or - automatically when restoring a managed save machine. It is called - as: <pre>/etc/libvirt/hooks/qemu guest_name restore begin -</pre> - with domain XML sent to standard input of the script. In this case, - the script acts as a filter and is supposed to modify the domain - XML and print it out on its standard output. Empty output is - identical to copying the input XML without changing it. In case the - script returns failure or the output XML is not valid, restore of the - image will be aborted. This hook may be used, e.g., to change - location of disk images for restored domains.</li> - <li><span class="since">Since 6.5.0</span>, you can also place several - hook scripts in the directory - <code>/etc/libvirt/hooks/qemu.d/</code>. They are executed in - alphabetical order after main script. In this case each script also - acts as filter and can modify the domain XML and print it out on - its standard output. This script output is passed to standard input - next script in order. Empty output from any script is also identical - to copying the input XML without changing it. - In case any script returns failure common process will be aborted, - but all scripts from the directory will are executed.</li> - <li><span class="since">Since 0.9.13</span>, the qemu hook script - is also called when the libvirtd daemon restarts and reconnects - to previously running QEMU processes. If the script fails, the - existing QEMU process will be killed off. It is called as: - <pre>/etc/libvirt/hooks/qemu guest_name reconnect begin -</pre> - </li> - <li><span class="since">Since 0.9.13</span>, the qemu hook script - is also called when the QEMU driver is told to attach to an - externally launched QEMU process. It is called as: - <pre>/etc/libvirt/hooks/qemu guest_name attach begin -</pre> - </li> - </ul> - - <h5><a id="lxc">/etc/libvirt/hooks/lxc</a></h5> - <ul> - <li>Before a LXC guest is started, the lxc hook script is - called in three locations; if any location fails, the guest - is not started. The first location, <span class="since">since - 0.9.13</span>, is before libvirt performs any resource - labeling, and the hook can allocate resources not managed by - libvirt such as DRBD or missing bridges. This is called as:<br/> - <pre>/etc/libvirt/hooks/lxc guest_name prepare begin -</pre> - The second location, available <span class="since">Since - 0.8.0</span>, occurs after libvirt has finished labeling - all resources, but has not yet started the guest, called as:<br/> - <pre>/etc/libvirt/hooks/lxc guest_name start begin -</pre> - The third location, <span class="since">0.9.13</span>, - occurs after the LXC process has successfully started up:<br/> - <pre>/etc/libvirt/hooks/lxc guest_name started begin -</pre> - </li> - <li>When a LXC guest is stopped, the lxc hook script is called - in two locations, to match the startup. - First, <span class="since">since 0.8.0</span>, the hook is - called before libvirt restores any labels:<br/> - <pre>/etc/libvirt/hooks/lxc guest_name stopped end -</pre> - Then, after libvirt has released all resources, the hook is - called again, <span class="since">since 0.9.0</span>, to allow - any additional resource cleanup:<br/> - <pre>/etc/libvirt/hooks/lxc guest_name release end -</pre></li> - <li><span class="since">Since 0.9.13</span>, the lxc hook script - is also called when the libvirtd daemon restarts and reconnects - to previously running LXC processes. If the script fails, the - existing LXC process will be killed off. It is called as: - <pre>/etc/libvirt/hooks/lxc guest_name reconnect begin -</pre> - </li> - </ul> - - <h5><a id="libxl">/etc/libvirt/hooks/libxl</a></h5> - <ul> - <li>Before a Xen guest is started using libxl driver, the libxl hook - script is called in three locations; if any location fails, the guest - is not started. The first location, <span class="since">since - 2.1.0</span>, is before libvirt performs any resource - labeling, and the hook can allocate resources not managed by - libvirt. This is called as:<br/> - <pre>/etc/libvirt/hooks/libxl guest_name prepare begin -</pre> - The second location, available <span class="since">Since - 2.1.0</span>, occurs after libvirt has finished labeling - all resources, but has not yet started the guest, called as:<br/> - <pre>/etc/libvirt/hooks/libxl guest_name start begin -</pre> - The third location, <span class="since">2.1.0</span>, - occurs after the domain has successfully started up:<br/> - <pre>/etc/libvirt/hooks/libxl guest_name started begin -</pre> - </li> - <li>When a libxl-handled Xen guest is stopped, the libxl hook script - is called in two locations, to match the startup. - First, <span class="since">since 2.1.0</span>, the hook is - called before libvirt restores any labels:<br/> - <pre>/etc/libvirt/hooks/libxl guest_name stopped end -</pre> - Then, after libvirt has released all resources, the hook is - called again, <span class="since">since 2.1.0</span>, to allow - any additional resource cleanup:<br/> - <pre>/etc/libvirt/hooks/libxl guest_name release end -</pre></li> - <li><span class="since">Since 2.1.0</span>, the libxl hook script - is also called at the beginning of incoming migration. It is called - as: <pre>/etc/libvirt/hooks/libxl guest_name migrate begin -</pre> - with domain XML sent to standard input of the script. In this case, - the script acts as a filter and is supposed to modify the domain - XML and print it out on its standard output. Empty output is - identical to copying the input XML without changing it. In case the - script returns failure or the output XML is not valid, incoming - migration will be canceled. This hook may be used, e.g., to change - location of disk images for incoming domains.</li> - <li><span class="since">Since 6.5.0</span>, you can also place several - hook scripts in the directory - <code>/etc/libvirt/hooks/libxl.d/</code>. They are executed in - alphabetical order after main script. In this case each script also - acts as filter and can modify the domain XML and print it out on - its standard output. This script output is passed to standard input - next script in order. Empty output from any script is also identical - to copying the input XML without changing it. - In case any script returns failure common process will be aborted, - but all scripts from the directory will are executed.</li> - <li><span class="since">Since 2.1.0</span>, the libxl hook script - is also called when the libvirtd daemon restarts and reconnects - to previously running Xen domains. If the script fails, the - existing Xen domains will be killed off. It is called as: - <pre>/etc/libvirt/hooks/libxl guest_name reconnect begin -</pre> - </li> - </ul> - - <h5><a id="network">/etc/libvirt/hooks/network</a></h5> - <ul> - <li><span class="since">Since 1.2.2</span>, before a network is started, - this script is called as:<br/> - <pre>/etc/libvirt/hooks/network network_name start begin -</pre></li> - <li>After the network is started, up & running, the script is - called as:<br/> - <pre>/etc/libvirt/hooks/network network_name started begin -</pre></li> - <li>When a network is shut down, this script is called as:<br/> - <pre>/etc/libvirt/hooks/network network_name stopped end -</pre></li> - <li>Later, when network is started and there's an interface from a - domain to be plugged into the network, the hook script is called as:<br/> - <pre>/etc/libvirt/hooks/network network_name port-created begin -</pre> - Please note, that in this case, the script is passed both network and - port XMLs on its stdin.</li> - <li>When network is updated, the hook script is called as:<br/> - <pre>/etc/libvirt/hooks/network network_name updated begin -</pre></li> - <li>When the domain from previous case is shutting down, the interface - is unplugged. This leads to another script invocation:<br/> - <pre>/etc/libvirt/hooks/network network_name port-deleted begin -</pre> - And again, as in previous case, both network and port XMLs are passed - onto script's stdin.</li> - </ul> - - <br/> - - <h2><a id="execution">Script execution</a></h2> - <ul> - <li>The "start" operation for the guest and network hook scripts, - executes <b>prior</b> to the object (guest or network) being created. - This allows the object start operation to be aborted if the script - returns indicating failure.<br/><br/></li> - <li>The "stopped" operation for the guest and network hook scripts, - executes <b>after</b> the object (guest or network) has stopped. If - the hook script indicates failure in its return, the shut down of the - object 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 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 - (e.g. chmod o+rx <i>qemu</i>), and must be present when the libvirt - daemon is started.<br/><br/></li> - <li>If a hook script is added to a host after the libvirt daemon is - already running, it won't be used until the libvirt daemon - next starts.</li> - </ul> - <br/> - - <h2><a id="qemu_migration">QEMU guest migration</a></h2> - <p>Migration of a QEMU guest involves running hook scripts on both the - source and destination hosts:</p> - <ol> - <li>At the beginning of the migration, the <i>qemu</i> hook script on - the <b>destination</b> host is executed with the "migrate" - operation.</li> - <li>Before QEMU process is spawned, the two operations ("prepare" and - "start") called for domain start are executed on - <b>destination</b> host.</li> - <li>If both of these hook script executions exit successfully (exit - status 0), the migration continues. Any other exit code indicates - failure, and the migration is aborted.</li> - <li>The QEMU guest is then migrated to the destination host.</li> - <li>Unless an error occurs during the migration process, the <i>qemu</i> - hook script on the <b>source</b> host is then executed with the - "stopped" and "release" operations to indicate it is no longer - running on this host. Regardless of the return codes, the - migration is not aborted as it has already been performed.</li> - </ol> - <br/> - - <h2><a id="recursive">Calling libvirt functions from within a hook script</a></h2> - <p><b>DO NOT DO THIS!</b></p> - <p>A hook script must not call back into libvirt, as the libvirt daemon - is already waiting for the script to exit.</p> - <p>A deadlock is likely to occur.</p> - <br/> - - <h2><a id="return_codes">Return codes and logging</a></h2> - <p>If a hook script returns with an exit code of 0, the libvirt daemon - regards this as successful and performs no logging of it.</p> - <p>However, if a hook script returns with a non zero exit code, the libvirt - daemon regards this as a failure, logs its return code, and - additionally logs anything on stderr the hook script returns.</p> - <p>For example, a hook script might use this code to indicate failure, - and send a text string to stderr:</p> - <pre>echo "Could not find required XYZZY" >&2 -exit 1</pre> - <p>The resulting entry in the libvirt log will appear as:</p> - <pre>20:02:40.297: error : virHookCall:285 : Hook script execution failed: internal error Child process (LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - HOME=/root USER=root LOGNAME=root /etc/libvirt/hooks/qemu qemu prepare begin -) unexpected exit status 1: Could not find required XYZZY</pre> - </body> -</html> diff --git a/docs/hooks.rst b/docs/hooks.rst new file mode 100644 index 0000000000..9c5f3ff456 --- /dev/null +++ b/docs/hooks.rst @@ -0,0 +1,518 @@ +.. role:: since + +==================================== +Hooks for specific system management +==================================== + +.. contents:: + +Custom event scripts +-------------------- + +Beginning with libvirt 0.8.0, specific events on a host system will trigger +custom scripts. + +These custom **hook** scripts are executed when any of the following actions +occur: + +- The libvirt daemon starts, stops, or reloads its configuration ( + :since:`since 0.8.0` ) +- A QEMU guest is started or stopped ( :since:`since 0.8.0` ) +- An LXC guest is started or stopped ( :since:`since 0.8.0` ) +- A libxl-handled Xen guest is started or stopped ( :since:`since 2.1.0` ) +- A network is started or stopped or an interface is plugged/unplugged to/from + the network ( :since:`since 1.2.2` ) + +Script location +--------------- + +The libvirt hook scripts are located in the directory +``$SYSCONFDIR/libvirt/hooks/``. + +- In Linux distributions such as Fedora and RHEL, this is + ``/etc/libvirt/hooks/``. Other Linux distributions may do this differently. +- If your installation of libvirt has instead been compiled from source, it is + likely to be ``/usr/local/etc/libvirt/hooks/``. +- :since:`Since 6.5.0` , you can also place several hook scripts in the + directories ``/etc/libvirt/hooks/<driver>.d/``. + +To use hook scripts, you will need to create this ``hooks`` directory manually, +place the desired hook scripts inside, then make them executable. + +Script names +------------ + +At present, there are five hook scripts that can be called: + +- ``/etc/libvirt/hooks/daemon`` + Executed when the libvirt daemon is started, stopped, or reloads its + configuration +- ``/etc/libvirt/hooks/qemu`` + Executed when a QEMU guest is started, stopped, or migrated +- ``/etc/libvirt/hooks/lxc`` + Executed when an LXC guest is started or stopped +- ``/etc/libvirt/hooks/libxl`` + Executed when a libxl-handled Xen guest is started, stopped, or migrated +- ``/etc/libvirt/hooks/network`` + Executed when a network is started or stopped or an interface is + plugged/unplugged to/from the network + +:since:`Since 6.5.0` , you can also have several scripts with any name in the +directories ``/etc/libvirt/hooks/<driver>.d/``. They are executed in +alphabetical order after main script. + +Script structure +---------------- + +The hook scripts are executed using standard Linux process creation functions. +Therefore, they must begin with the declaration of the command interpreter to +use. + +For example: + +:: + + #!/bin/bash + +or: + +:: + + #!/usr/bin/python + +Other command interpreters are equally valid, as is any executable binary, so +you are welcome to use your favourite languages. + +Script arguments +---------------- + +The hook scripts are called with specific command line arguments, depending upon +the script, and the operation being performed. + +The guest hook scripts, qemu and lxc, are also given the **full** 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. + +For all cases, stdin of the network hook script is provided with the full XML +description of the network status in the following form: + +:: + + <hookData> + <network> + <name>$network_name</name> + <uuid>afca425a-2c3a-420c-b2fb-dd7b4950d722</uuid> + ... + </network> + </hookData> + +In the case of an network port being created / deleted, the network XML will be +followed with the full XML description of the port: + +:: + + <hookData> + <network> + <name>$network_name</name> + <uuid>afca425a-2c3a-420c-b2fb-dd7b4950d722</uuid> + ... + </network> + <networkport> + <uuid>5d744f21-ba4a-4d6e-bdb2-30a35ff3207d</uuid> + ... + <plug type='direct' dev='ens3' mode='vepa'/> + </networkport> + </hookData> + +Please note that this approach is different from other cases such as ``daemon``, +``qemu`` or ``lxc`` hook scripts, because two XMLs may be passed here, while in +the other cases only a single XML is passed. + +The command line arguments take this approach: + +#. The first argument is the name of the **object** involved in the operation, + or '-' if there is none. + For example, the name of a guest being started. +#. The second argument is the name of the **operation** being performed. + For example, "start" if a guest is being started. +#. The third argument is a **sub-operation** indication, or '-' if there is + none. +#. The last argument is an **extra argument** string, or '-' if there is none. + +Specifics +~~~~~~~~~ + +This translates to the following specifics for each hook script: + +/etc/libvirt/hooks/daemon +^^^^^^^^^^^^^^^^^^^^^^^^^ + +- | When the libvirt daemon is started, this script is called as: + + :: + + /etc/libvirt/hooks/daemon - start - start + +- | When the libvirt daemon is shut down, this script is called as: + + :: + + /etc/libvirt/hooks/daemon - shutdown - shutdown + +- | When the libvirt daemon receives the SIGHUP signal, it reloads its + configuration and triggers the hook script as: + + :: + + /etc/libvirt/hooks/daemon - reload begin SIGHUP + +Please note that when the libvirt daemon is restarted, the *daemon* hook script +is called once with the "shutdown" operation, and then once with the "start" +operation. There is no specific operation to indicate a "restart" is occurring. + +/etc/libvirt/hooks/qemu +^^^^^^^^^^^^^^^^^^^^^^^ + +- | Before a QEMU guest is started, the qemu hook script is called in three + locations; if any location fails, the guest is not started. The first + location, :since:`since 0.9.0` , is before libvirt performs any resource + labeling, and the hook can allocate resources not managed by libvirt such + as DRBD or missing bridges. This is called as: + + :: + + /etc/libvirt/hooks/qemu guest_name prepare begin - + + | The second location, available :since:`Since 0.8.0` , occurs after libvirt + has finished labeling all resources, but has not yet started the guest, + called as: + + :: + + /etc/libvirt/hooks/qemu guest_name start begin - + + | The third location, :since:`0.9.13` , occurs after the QEMU process has + successfully started up: + + :: + + /etc/libvirt/hooks/qemu guest_name started begin - + +- | When a QEMU guest is stopped, the qemu hook script is called in two + locations, to match the startup. First, :since:`since 0.8.0` , the hook is + called before libvirt restores any labels: + + :: + + /etc/libvirt/hooks/qemu guest_name stopped end - + + | Then, after libvirt has released all resources, the hook is called again, + :since:`since 0.9.0` , to allow any additional resource cleanup: + + :: + + /etc/libvirt/hooks/qemu guest_name release end - + +- :since:`Since 0.9.11` , the qemu hook script is also called at the beginning + of incoming migration. It is called as: + + :: + + /etc/libvirt/hooks/qemu guest_name migrate begin - + + with domain XML sent to standard input of the script. In this case, the + script acts as a filter and is supposed to modify the domain XML and print it + out on its standard output. Empty output is identical to copying the input + XML without changing it. In case the script returns failure or the output XML + is not valid, incoming migration will be canceled. This hook may be used, + e.g., to change location of disk images for incoming domains. + +- :since:`Since 1.2.9` , the qemu hook script is also called when restoring a + saved image either via the API or automatically when restoring a managed save + machine. It is called as: + + :: + + /etc/libvirt/hooks/qemu guest_name restore begin - + + with domain XML sent to standard input of the script. In this case, the + script acts as a filter and is supposed to modify the domain XML and print it + out on its standard output. Empty output is identical to copying the input + XML without changing it. In case the script returns failure or the output XML + is not valid, restore of the image will be aborted. This hook may be used, + e.g., to change location of disk images for restored domains. + +- :since:`Since 6.5.0` , you can also place several hook scripts in the + directory ``/etc/libvirt/hooks/qemu.d/``. They are executed in alphabetical + order after main script. In this case each script also acts as filter and can + modify the domain XML and print it out on its standard output. This script + output is passed to standard input next script in order. Empty output from + any script is also identical to copying the input XML without changing it. In + case any script returns failure common process will be aborted, but all + scripts from the directory will are executed. + +- :since:`Since 0.9.13` , the qemu hook script is also called when the libvirtd + daemon restarts and reconnects to previously running QEMU processes. If the + script fails, the existing QEMU process will be killed off. It is called as: + + :: + + /etc/libvirt/hooks/qemu guest_name reconnect begin - + +- :since:`Since 0.9.13` , the qemu hook script is also called when the QEMU + driver is told to attach to an externally launched QEMU process. It is called + as: + + :: + + /etc/libvirt/hooks/qemu guest_name attach begin - + +/etc/libvirt/hooks/lxc +^^^^^^^^^^^^^^^^^^^^^^ + +- | Before a LXC guest is started, the lxc hook script is called in three + locations; if any location fails, the guest is not started. The first + location, :since:`since 0.9.13` , is before libvirt performs any resource + labeling, and the hook can allocate resources not managed by libvirt such + as DRBD or missing bridges. This is called as: + + :: + + /etc/libvirt/hooks/lxc guest_name prepare begin - + + | The second location, available :since:`Since 0.8.0` , occurs after libvirt + has finished labeling all resources, but has not yet started the guest, + called as: + + :: + + /etc/libvirt/hooks/lxc guest_name start begin - + + | The third location, :since:`0.9.13` , occurs after the LXC process has + successfully started up: + + :: + + /etc/libvirt/hooks/lxc guest_name started begin - + +- | When a LXC guest is stopped, the lxc hook script is called in two + locations, to match the startup. First, :since:`since 0.8.0` , the hook is + called before libvirt restores any labels: + + :: + + /etc/libvirt/hooks/lxc guest_name stopped end - + + | Then, after libvirt has released all resources, the hook is called again, + :since:`since 0.9.0` , to allow any additional resource cleanup: + + :: + + /etc/libvirt/hooks/lxc guest_name release end - + +- :since:`Since 0.9.13` , the lxc hook script is also called when the libvirtd + daemon restarts and reconnects to previously running LXC processes. If the + script fails, the existing LXC process will be killed off. It is called as: + + :: + + /etc/libvirt/hooks/lxc guest_name reconnect begin - + +/etc/libvirt/hooks/libxl +^^^^^^^^^^^^^^^^^^^^^^^^ + +- | Before a Xen guest is started using libxl driver, the libxl hook script is + called in three locations; if any location fails, the guest is not started. + The first location, :since:`since 2.1.0` , is before libvirt performs any + resource labeling, and the hook can allocate resources not managed by + libvirt. This is called as: + + :: + + /etc/libvirt/hooks/libxl guest_name prepare begin - + + | The second location, available :since:`Since 2.1.0` , occurs after libvirt + has finished labeling all resources, but has not yet started the guest, + called as: + + :: + + /etc/libvirt/hooks/libxl guest_name start begin - + + | The third location, :since:`2.1.0` , occurs after the domain has + successfully started up: + + :: + + /etc/libvirt/hooks/libxl guest_name started begin - + +- | When a libxl-handled Xen guest is stopped, the libxl hook script is called + in two locations, to match the startup. First, :since:`since 2.1.0` , the + hook is called before libvirt restores any labels: + + :: + + /etc/libvirt/hooks/libxl guest_name stopped end - + + | Then, after libvirt has released all resources, the hook is called again, + :since:`since 2.1.0` , to allow any additional resource cleanup: + + :: + + /etc/libvirt/hooks/libxl guest_name release end - + +- :since:`Since 2.1.0` , the libxl hook script is also called at the beginning + of incoming migration. It is called as: + + :: + + /etc/libvirt/hooks/libxl guest_name migrate begin - + + with domain XML sent to standard input of the script. In this case, the + script acts as a filter and is supposed to modify the domain XML and print it + out on its standard output. Empty output is identical to copying the input + XML without changing it. In case the script returns failure or the output XML + is not valid, incoming migration will be canceled. This hook may be used, + e.g., to change location of disk images for incoming domains. + +- :since:`Since 6.5.0` , you can also place several hook scripts in the + directory ``/etc/libvirt/hooks/libxl.d/``. They are executed in alphabetical + order after main script. In this case each script also acts as filter and can + modify the domain XML and print it out on its standard output. This script + output is passed to standard input next script in order. Empty output from + any script is also identical to copying the input XML without changing it. In + case any script returns failure common process will be aborted, but all + scripts from the directory will are executed. + +- :since:`Since 2.1.0` , the libxl hook script is also called when the libvirtd + daemon restarts and reconnects to previously running Xen domains. If the + script fails, the existing Xen domains will be killed off. It is called as: + + :: + + /etc/libvirt/hooks/libxl guest_name reconnect begin - + +/etc/libvirt/hooks/network +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- | :since:`Since 1.2.2` , before a network is started, this script is called + as: + + :: + + /etc/libvirt/hooks/network network_name start begin - + +- | After the network is started, up & running, the script is called as: + + :: + + /etc/libvirt/hooks/network network_name started begin - + +- | When a network is shut down, this script is called as: + + :: + + /etc/libvirt/hooks/network network_name stopped end - + +- | Later, when network is started and there's an interface from a domain to be + plugged into the network, the hook script is called as: + + :: + + /etc/libvirt/hooks/network network_name port-created begin - + + Please note, that in this case, the script is passed both network and port + XMLs on its stdin. + +- | When network is updated, the hook script is called as: + + :: + + /etc/libvirt/hooks/network network_name updated begin - + +- | When the domain from previous case is shutting down, the interface is + unplugged. This leads to another script invocation: + + :: + + /etc/libvirt/hooks/network network_name port-deleted begin - + + And again, as in previous case, both network and port XMLs are passed onto + script's stdin. + +Script execution +---------------- + +- The "start" operation for the guest and network hook scripts, executes + **prior** to the object (guest or network) being created. This allows the + object start operation to be aborted if the script returns indicating + failure. +- The "stopped" operation for the guest and network hook scripts, executes + **after** the object (guest or network) has stopped. If the hook script + indicates failure in its return, the shut down of the object cannot be + aborted because it has already been performed. +- Hook scripts execute in a synchronous fashion. Libvirt waits for them to + return before continuing the given operation. + 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. +- For a hook script to be utilised, it must have its execute bit set (e.g. + chmod o+rx *qemu*), and must be present when the libvirt daemon is started. +- If a hook script is added to a host after the libvirt daemon is already + running, it won't be used until the libvirt daemon next starts. + +QEMU guest migration +-------------------- + +Migration of a QEMU guest involves running hook scripts on both the source and +destination hosts: + +#. At the beginning of the migration, the *qemu* hook script on the + **destination** host is executed with the "migrate" operation. +#. Before QEMU process is spawned, the two operations ("prepare" and "start") + called for domain start are executed on **destination** host. +#. If both of these hook script executions exit successfully (exit status 0), + the migration continues. Any other exit code indicates failure, and the + migration is aborted. +#. The QEMU guest is then migrated to the destination host. +#. Unless an error occurs during the migration process, the *qemu* hook script + on the **source** host is then executed with the "stopped" and "release" + operations to indicate it is no longer running on this host. Regardless of + the return codes, the migration is not aborted as it has already been + performed. + +Calling libvirt functions from within a hook script +--------------------------------------------------- + +**DO NOT DO THIS!** + +A hook script must not call back into libvirt, as the libvirt daemon is already +waiting for the script to exit. + +A deadlock is likely to occur. + +Return codes and logging +------------------------ + +If a hook script returns with an exit code of 0, the libvirt daemon regards this +as successful and performs no logging of it. + +However, if a hook script returns with a non zero exit code, the libvirt daemon +regards this as a failure, logs its return code, and additionally logs anything +on stderr the hook script returns. + +For example, a hook script might use this code to indicate failure, and send a +text string to stderr: + +:: + + echo "Could not find required XYZZY" >&2 + exit 1 + +The resulting entry in the libvirt log will appear as: + +:: + + 20:02:40.297: error : virHookCall:285 : Hook script execution failed: internal error Child process (LC_ALL=C PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + HOME=/root USER=root LOGNAME=root /etc/libvirt/hooks/qemu qemu prepare begin -) unexpected exit status 1: Could not find required XYZZY diff --git a/docs/meson.build b/docs/meson.build index 22eca7d8bd..a0e96e2453 100644 --- a/docs/meson.build +++ b/docs/meson.build @@ -25,7 +25,6 @@ docs_html_in_files = [ 'formatnetwork', 'formatnode', 'formatnwfilter', - 'hooks', 'index', 'internals', 'java', @@ -92,6 +91,7 @@ docs_rst_files = [ 'goals', 'governance', 'hacking', + 'hooks', 'libvirt-go', 'libvirt-go-xml', 'macos', -- 2.35.1