qemu: Add pre-migration hook

This hook is called during the Prepare phase on destination host and may
be used for changing domain XML.
This commit is contained in:
Jiri Denemark 2012-02-28 13:42:42 +01:00
parent 8ab785783f
commit 04dec5826d
4 changed files with 69 additions and 13 deletions

View File

@ -120,6 +120,16 @@
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>
</ul>
<h5><a name="lxc">/etc/libvirt/hooks/lxc</a></h5>
@ -161,19 +171,20 @@
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>
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"
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>
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/>

View File

@ -47,6 +47,7 @@
#include "rpc/virnetsocket.h"
#include "storage_file.h"
#include "viruri.h"
#include "hooks.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@ -1130,6 +1131,7 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
qemuMigrationCookiePtr mig = NULL;
bool tunnel = !!st;
char *origname = NULL;
char *xmlout = NULL;
if (virTimeMillisNow(&now) < 0)
return -1;
@ -1150,6 +1152,46 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
goto cleanup;
}
/* Let migration hook filter domain XML */
if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
char *xml;
int hookret;
if (!(xml = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE)))
goto cleanup;
hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, def->name,
VIR_HOOK_QEMU_OP_MIGRATE, VIR_HOOK_SUBOP_BEGIN,
NULL, xml, &xmlout);
VIR_FREE(xml);
if (hookret < 0) {
goto cleanup;
} else if (hookret == 0) {
if (!*xmlout) {
VIR_DEBUG("Migrate hook filter returned nothing; using the"
" original XML");
} else {
virDomainDefPtr newdef;
VIR_DEBUG("Using hook-filtered domain XML: %s", xmlout);
newdef = virDomainDefParseString(driver->caps, xmlout,
QEMU_EXPECTED_VIRT_TYPES,
VIR_DOMAIN_XML_INACTIVE);
if (!newdef)
goto cleanup;
if (!virDomainDefCheckABIStability(def, newdef)) {
virDomainDefFree(newdef);
goto cleanup;
}
virDomainDefFree(def);
def = newdef;
}
}
}
if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
goto cleanup;
@ -1244,6 +1286,7 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
cleanup:
VIR_FREE(origname);
VIR_FREE(xmlout);
virDomainDefFree(def);
VIR_FORCE_CLOSE(dataFD[0]);
VIR_FORCE_CLOSE(dataFD[1]);

View File

@ -73,7 +73,8 @@ VIR_ENUM_IMPL(virHookQemuOp, VIR_HOOK_QEMU_OP_LAST,
"start",
"stopped",
"prepare",
"release")
"release",
"migrate")
VIR_ENUM_IMPL(virHookLxcOp, VIR_HOOK_LXC_OP_LAST,
"start",

View File

@ -56,6 +56,7 @@ enum virHookQemuOpType {
VIR_HOOK_QEMU_OP_STOPPED, /* domain has stopped */
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_LAST,
};