mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-01 17:35:17 +00:00
Add some missing hook functions
A core use case of the hook scripts is to be able to do things to a guest's network configuration. It is possible to hook into the 'start' operation for a QEMU guest which runs just before the guest is started. The TAP devices will exist at this point, but the QEMU process will not. It can be desirable to have a 'started' hook too, which runs once QEMU has started. If libvirtd is restarted it will re-populate firewall rules, but there is no QEMU hook to trigger for existing domains. This is solved with a 'reconnect' hook. Finally, if attaching to an external QEMU process there needs to be an 'attach' hook script. This all also applies to the LXC driver * docs/hooks.html.in: Document new operations * src/util/hooks.c, src/util/hooks.c: Add 'started', 'reconnect' and 'attach' operations for QEMU. Add 'prepare', 'started', 'release' and 'reconnect' operations for LXC * src/lxc/lxc_driver.c: Add hooks for 'prepare', 'started', 'release' and 'reconnect' operations * src/qemu/qemu_process.c: Add hooks for 'started', 'reconnect' and 'reconnect' operations
This commit is contained in:
parent
5d490603a6
commit
6510c97bf5
@ -101,7 +101,7 @@
|
||||
<h5><a name="qemu">/etc/libvirt/hooks/qemu</a></h5>
|
||||
<ul>
|
||||
<li>Before a QEMU guest is started, the qemu hook script is
|
||||
called in two locations; if either location fails, the guest
|
||||
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
|
||||
@ -110,7 +110,11 @@
|
||||
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></li>
|
||||
<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
|
||||
@ -130,15 +134,51 @@
|
||||
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 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 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>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
|
||||
as:<br/>
|
||||
<pre>/etc/libvirt/hooks/lxc guest_name stopped end -</pre></li>
|
||||
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>
|
||||
<br/>
|
||||
|
||||
|
@ -1152,6 +1152,17 @@ static void lxcVmCleanup(lxc_driver_t *driver,
|
||||
virCgroupFree(&cgroup);
|
||||
}
|
||||
|
||||
/* now that we know it's stopped call the hook if present */
|
||||
if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
|
||||
char *xml = virDomainDefFormat(vm->def, 0);
|
||||
|
||||
/* we can't stop the operation even if the script raised an error */
|
||||
virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
|
||||
VIR_HOOK_LXC_OP_RELEASE, VIR_HOOK_SUBOP_END,
|
||||
NULL, xml, NULL);
|
||||
VIR_FREE(xml);
|
||||
}
|
||||
|
||||
if (vm->newDef) {
|
||||
virDomainDefFree(vm->def);
|
||||
vm->def = vm->newDef;
|
||||
@ -1625,23 +1636,6 @@ lxcBuildControllerCmd(lxc_driver_t *driver,
|
||||
virCommandAddArgList(cmd, "--veth", veths[i], NULL);
|
||||
}
|
||||
|
||||
/* now that we know it is about to start call the hook if present */
|
||||
if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
|
||||
char *xml = virDomainDefFormat(vm->def, 0);
|
||||
int hookret;
|
||||
|
||||
hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
|
||||
VIR_HOOK_LXC_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;
|
||||
}
|
||||
|
||||
virCommandPreserveFD(cmd, handshakefd);
|
||||
|
||||
return cmd;
|
||||
@ -1803,6 +1797,23 @@ static int lxcVmStart(virConnectPtr conn,
|
||||
if (virDomainObjSetDefTransient(driver->caps, vm, true) < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* Run an early hook to set-up missing devices */
|
||||
if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
|
||||
char *xml = virDomainDefFormat(vm->def, 0);
|
||||
int hookret;
|
||||
|
||||
hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
|
||||
VIR_HOOK_LXC_OP_PREPARE, VIR_HOOK_SUBOP_BEGIN,
|
||||
NULL, xml, NULL);
|
||||
VIR_FREE(xml);
|
||||
|
||||
/*
|
||||
* If the script raised an error abort the launch
|
||||
*/
|
||||
if (hookret < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Here we open all the PTYs we need on the host OS side.
|
||||
* The LXC controller will open the guest OS side PTYs
|
||||
* and forward I/O between them.
|
||||
@ -1887,6 +1898,23 @@ static int lxcVmStart(virConnectPtr conn,
|
||||
virCommandSetOutputFD(cmd, &logfd);
|
||||
virCommandSetErrorFD(cmd, &logfd);
|
||||
|
||||
/* now that we know it is about to start call the hook if present */
|
||||
if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
|
||||
char *xml = virDomainDefFormat(vm->def, 0);
|
||||
int hookret;
|
||||
|
||||
hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
|
||||
VIR_HOOK_LXC_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;
|
||||
}
|
||||
|
||||
/* Log timestamp */
|
||||
if ((timestamp = virTimeStringNow()) == NULL) {
|
||||
virReportOOMError();
|
||||
@ -1965,6 +1993,23 @@ static int lxcVmStart(virConnectPtr conn,
|
||||
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
|
||||
goto error;
|
||||
|
||||
/* finally we can call the 'started' hook script if any */
|
||||
if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
|
||||
char *xml = virDomainDefFormat(vm->def, 0);
|
||||
int hookret;
|
||||
|
||||
hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
|
||||
VIR_HOOK_LXC_OP_STARTED, VIR_HOOK_SUBOP_BEGIN,
|
||||
NULL, xml, NULL);
|
||||
VIR_FREE(xml);
|
||||
|
||||
/*
|
||||
* If the script raised an error abort the launch
|
||||
*/
|
||||
if (hookret < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
cleanup:
|
||||
@ -2512,6 +2557,21 @@ lxcReconnectVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
|
||||
if (virSecurityManagerReserveLabel(driver->securityManager,
|
||||
vm->def, vm->pid) < 0)
|
||||
goto error;
|
||||
|
||||
/* now that we know it's reconnected call the hook if present */
|
||||
if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
|
||||
char *xml = virDomainDefFormat(vm->def, 0);
|
||||
int hookret;
|
||||
|
||||
/* we can't stop the operation even if the script raised an error */
|
||||
hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
|
||||
VIR_HOOK_LXC_OP_RECONNECT, VIR_HOOK_SUBOP_BEGIN,
|
||||
NULL, xml, NULL);
|
||||
VIR_FREE(xml);
|
||||
if (hookret < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
} else {
|
||||
vm->def->id = -1;
|
||||
VIR_FORCE_CLOSE(priv->monitor);
|
||||
|
@ -3108,6 +3108,23 @@ qemuProcessReconnect(void *opaque)
|
||||
if (virDomainSaveStatus(driver->caps, driver->stateDir, obj) < 0)
|
||||
goto error;
|
||||
|
||||
/* Run an hook to allow admins to do some magic */
|
||||
if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
|
||||
char *xml = qemuDomainDefFormatXML(driver, obj->def, 0, false);
|
||||
int hookret;
|
||||
|
||||
hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, obj->def->name,
|
||||
VIR_HOOK_QEMU_OP_RECONNECT, VIR_HOOK_SUBOP_BEGIN,
|
||||
NULL, xml, NULL);
|
||||
VIR_FREE(xml);
|
||||
|
||||
/*
|
||||
* If the script raised an error abort the launch
|
||||
*/
|
||||
if (hookret < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (obj->def->id >= driver->nextvmid)
|
||||
driver->nextvmid = obj->def->id + 1;
|
||||
|
||||
@ -3770,6 +3787,23 @@ int qemuProcessStart(virConnectPtr conn,
|
||||
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* finally we can call the 'started' hook script if any */
|
||||
if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
|
||||
char *xml = qemuDomainDefFormatXML(driver, vm->def, 0, false);
|
||||
int hookret;
|
||||
|
||||
hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, vm->def->name,
|
||||
VIR_HOOK_QEMU_OP_STARTED, VIR_HOOK_SUBOP_BEGIN,
|
||||
NULL, xml, NULL);
|
||||
VIR_FREE(xml);
|
||||
|
||||
/*
|
||||
* If the script raised an error abort the launch
|
||||
*/
|
||||
if (hookret < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
virCommandFree(cmd);
|
||||
VIR_FORCE_CLOSE(logfile);
|
||||
|
||||
@ -4280,6 +4314,23 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* Run an hook to allow admins to do some magic */
|
||||
if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
|
||||
char *xml = qemuDomainDefFormatXML(driver, vm->def, 0, false);
|
||||
int hookret;
|
||||
|
||||
hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, vm->def->name,
|
||||
VIR_HOOK_QEMU_OP_ATTACH, VIR_HOOK_SUBOP_BEGIN,
|
||||
NULL, xml, NULL);
|
||||
VIR_FREE(xml);
|
||||
|
||||
/*
|
||||
* If the script raised an error abort the launch
|
||||
*/
|
||||
if (hookret < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VIR_FORCE_CLOSE(logfile);
|
||||
VIR_FREE(seclabel);
|
||||
|
||||
|
@ -74,11 +74,18 @@ VIR_ENUM_IMPL(virHookQemuOp, VIR_HOOK_QEMU_OP_LAST,
|
||||
"stopped",
|
||||
"prepare",
|
||||
"release",
|
||||
"migrate")
|
||||
"migrate",
|
||||
"started",
|
||||
"reconnect",
|
||||
"attach")
|
||||
|
||||
VIR_ENUM_IMPL(virHookLxcOp, VIR_HOOK_LXC_OP_LAST,
|
||||
"start",
|
||||
"stopped")
|
||||
"stopped",
|
||||
"prepare",
|
||||
"release",
|
||||
"started",
|
||||
"reconnect")
|
||||
|
||||
static int virHooksFound = -1;
|
||||
|
||||
|
@ -57,6 +57,9 @@ enum virHookQemuOpType {
|
||||
VIR_HOOK_QEMU_OP_PREPARE, /* domain startup initiated */
|
||||
VIR_HOOK_QEMU_OP_RELEASE, /* domain destruction is over */
|
||||
VIR_HOOK_QEMU_OP_MIGRATE, /* domain is being migrated */
|
||||
VIR_HOOK_QEMU_OP_STARTED, /* domain has started */
|
||||
VIR_HOOK_QEMU_OP_RECONNECT, /* domain is being reconnected by libvirt */
|
||||
VIR_HOOK_QEMU_OP_ATTACH, /* domain is being attached to be libvirt */
|
||||
|
||||
VIR_HOOK_QEMU_OP_LAST,
|
||||
};
|
||||
@ -64,6 +67,10 @@ enum virHookQemuOpType {
|
||||
enum virHookLxcOpType {
|
||||
VIR_HOOK_LXC_OP_START, /* domain is about to start */
|
||||
VIR_HOOK_LXC_OP_STOPPED, /* domain has stopped */
|
||||
VIR_HOOK_LXC_OP_PREPARE, /* domain startup initiated */
|
||||
VIR_HOOK_LXC_OP_RELEASE, /* domain destruction is over */
|
||||
VIR_HOOK_LXC_OP_STARTED, /* domain has started */
|
||||
VIR_HOOK_LXC_OP_RECONNECT, /* domain is being reconnected by libvirt */
|
||||
|
||||
VIR_HOOK_LXC_OP_LAST,
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user