mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 21:34:54 +03:00
docs: significant expansion of custom hook script information
This commit is contained in:
parent
0890a70a19
commit
bf3211c95a
@ -2,69 +2,184 @@
|
|||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<h1>Hooks for specific system management</h1>
|
<h1>Hooks for specific system management</h1>
|
||||||
<p>Libvirt includes synchronous hooks, starting from version 0.8.0, as a
|
|
||||||
way to tie in specific tailored system actions at a specific time.
|
<ul id="toc"></ul>
|
||||||
If these scripts are present on the host where the hypervisor
|
|
||||||
is running, then they are called when the libvirt daemon is doingi
|
<h2><a name="intro">Custom event scripts</a></h2>
|
||||||
some significant action.</p>
|
<p>Beginning with libvirt 0.8.0, specific events on a host system will
|
||||||
<p>The scripts are expected to execute quickly, return a zero exit
|
trigger custom scripts.</p>
|
||||||
status if all conditions are set for the daemon to continue the
|
<p>These custom <b>hook</b> scripts are executed when any of the following
|
||||||
action (non zero will be considered a failure which may
|
actions occur:</p>
|
||||||
be ignored but in general will stop the ongoing operation).
|
|
||||||
The script also should not call back into libvirt as the daemon
|
|
||||||
is waiting for the script exit and deadlock is likely to occur.</p>
|
|
||||||
<p>The scripts are stored in the directory <code>/etc/libvirt/hooks/</code>
|
|
||||||
when using a standard installation path
|
|
||||||
(<code>$SYSCONF_DIR/libvirt/hooks/</code> in general).</p>
|
|
||||||
<p>Each script is given the following command line arguments:</p>
|
|
||||||
<ul>
|
|
||||||
<li> the first argument is the name of the object involved in the
|
|
||||||
operation, or '-' if there is none.
|
|
||||||
<li> the second argument is the name of the operation.
|
|
||||||
<li> the third argument is a suboperation indication like 'start' or
|
|
||||||
'end', or '-' if there is none.
|
|
||||||
<li> the last argument is an extra argument string or '-' if there
|
|
||||||
is none.
|
|
||||||
</ul>
|
|
||||||
<p>There are currently scripts for 3 domains of operation:
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><p><code>/etc/libvirt/hooks/daemon</code> script if
|
<li>The libvirt daemon starts, stops, or reloads its
|
||||||
present is called at 3 points in time:</p>
|
configuration<br/><br/></li>
|
||||||
<p>at daemon startup, typically started with the following
|
<li>A QEMU guest is started or stopped<br/><br/></li>
|
||||||
arguments:</p>
|
<li>An LXC guest is started or stopped<br/><br/></li>
|
||||||
<pre>/etc/libvirt/hooks/daemon - start - start</pre>
|
|
||||||
<p>at daemon shutdown when it is about to exit, with the following
|
|
||||||
arguments:</p>
|
|
||||||
<pre>/etc/libvirt/hooks/daemon - shutdown - shutdown</pre>
|
|
||||||
<p>When the daemon is asked to reload its driver state when
|
|
||||||
receiving the SIGHUP signal, arguments are:</p>
|
|
||||||
<pre>/etc/libvirt/hooks/daemon - reload begin SIGHUP</pre>
|
|
||||||
</li>
|
|
||||||
<li><p><code>/etc/libvirt/hooks/qemu</code> script and <br/>
|
|
||||||
<code>/etc/libvirt/hooks/lxc</code> associate hooks for domain
|
|
||||||
operation on the respective QEmu/KVM and LXC drivers.</p>
|
|
||||||
<p> The domain related hooks also receive the full XML description
|
|
||||||
for the concerned domain on their stdin, which allows them to get
|
|
||||||
all the information from the domain, including UUID or storage
|
|
||||||
if that is needed for the script operation.</p>
|
|
||||||
<p> Currently only domain startup and domain end operations
|
|
||||||
involve the hook, the first one just before the domain gets
|
|
||||||
created.
|
|
||||||
For example if starting a QEmu domain named <code>test</code>
|
|
||||||
the following script will get called:</p>
|
|
||||||
<pre>/etc/libvirt/hooks/qemu test start begin -</pre>
|
|
||||||
<p> note that a non-zero return value from the script will abort the
|
|
||||||
domain startup operation, and if an error string is passed on
|
|
||||||
stderr by the hook script, it will be provided back to the user
|
|
||||||
at the libvirt API level.</p>
|
|
||||||
<p> For domain shutdown, the script will be called just after the
|
|
||||||
domain has finished execution, and the script will get:</p>
|
|
||||||
<pre>/etc/libvirt/hooks/qemu test stopped end -</pre>
|
|
||||||
<p> It is expected that other operations will be associated to hooks
|
|
||||||
but at the time of 0.8.0 only those 2 are associated to the
|
|
||||||
domains life cycle</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<p></p>
|
|
||||||
|
<h2><a name="location">Script location</a></h2>
|
||||||
|
<p>The libvirt hook scripts are located in the directory
|
||||||
|
<code>$SYSCONF_DIR/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>
|
||||||
|
</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 name="names">Script names</a></h2>
|
||||||
|
<p>At present, there are three 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>
|
||||||
|
</ul>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<h2><a name="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 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 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 name="arguments_specifics">Specifics</a></h4>
|
||||||
|
<p>This translates to the following specifics for each hook script:</p>
|
||||||
|
|
||||||
|
<h5><a name="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>qemu</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 name="qemu">/etc/libvirt/hooks/qemu</a></h5>
|
||||||
|
<ul>
|
||||||
|
<li>When a QEMU guest is started, the qemu hook script is called as:<br/>
|
||||||
|
<pre>/etc/libvirt/hooks/qemu guest_name start begin -</pre></li>
|
||||||
|
<li>When a QEMU guest is stopped, the qemu hook script is called
|
||||||
|
as:<br/>
|
||||||
|
<pre>/etc/libvirt/hooks/qemu guest_name stopped end -</pre></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h5><a name="lxc">/etc/libvirt/hooks/lxc</a></h5>
|
||||||
|
<ul>
|
||||||
|
<li>When an LXC guest is started, the lxc hook script is called as:<br/>
|
||||||
|
<pre>/etc/libvirt/hooks/lxc guest_name start begin -</pre></li>
|
||||||
|
<li>When a LXC guest is stopped, the lxc hook script is called
|
||||||
|
as:<br/>
|
||||||
|
<pre>/etc/libvirt/hooks/lxc guest_name stopped end -</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,
|
||||||
|
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>
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
<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 name="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 "start"
|
||||||
|
operation.<br/><br/></li>
|
||||||
|
<li>If this hook script returns indicating success (error code 0), the
|
||||||
|
migration continues. Any other return code indicates failure, and
|
||||||
|
the migration is aborted.<br/><br/></li>
|
||||||
|
<li>The QEMU guest is then migrated to the destination host.<br/>
|
||||||
|
<br/></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"
|
||||||
|
operation, to indicate it is no longer running on this
|
||||||
|
host.<br/><br/>
|
||||||
|
Regardless of the return code from this hook script, the migration
|
||||||
|
is not aborted as it has already been performed.</li>
|
||||||
|
</ol>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<h2><a name="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 name="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 it with return code 256, 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:416 : Hook script execution failed: Hook script /etc/libvirt/hooks/qemu qemu failed with error code 256:Could not find required XYZZY</pre>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
Reference in New Issue
Block a user