---
docs/hooks.html.in | 11 ++++++++
src/qemu/qemu_driver.c | 70 +++++++++++++++++++++++++++++++++++++++++++++-----
src/util/virhook.c | 3 ++-
src/util/virhook.h | 1 +
4 files changed, 78 insertions(+), 7 deletions(-)
diff --git a/docs/hooks.html.in b/docs/hooks.html.in
index 07b9d49..1aae00c 100644
--- a/docs/hooks.html.in
+++ b/docs/hooks.html.in
@@ -177,6 +177,17 @@
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 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
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ee542bf..e73d4f9 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5644,20 +5644,24 @@ qemuDomainRestoreFlags(virConnectPtr conn,
unsigned int flags)
{
virQEMUDriverPtr driver = conn->privateData;
+ qemuDomainObjPrivatePtr priv = NULL;
virDomainDefPtr def = NULL;
- virDomainDefPtr newdef = NULL;
virDomainObjPtr vm = NULL;
+ char *xml = NULL;
+ char *xmlout = NULL;
+ const char *newxml = dxml;
int fd = -1;
int ret = -1;
virQEMUSaveHeader header;
virFileWrapperFdPtr wrapperFd = NULL;
+ bool hook_taint = false;
virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
VIR_DOMAIN_SAVE_RUNNING |
VIR_DOMAIN_SAVE_PAUSED, -1);
- fd = qemuDomainSaveImageOpen(driver, path, &def, &header, NULL,
+ fd = qemuDomainSaveImageOpen(driver, path, &def, &header, &xml,
(flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) != 0,
&wrapperFd, false, false);
if (fd < 0)
@@ -5666,12 +5670,31 @@ qemuDomainRestoreFlags(virConnectPtr conn,
if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
goto cleanup;
- if (dxml) {
- if (!(newdef = qemuDomainSaveImageUpdateDef(driver, def, dxml)))
+ if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
+ int hookret;
+
+ if ((hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, def->name,
+ VIR_HOOK_QEMU_OP_RESTORE,
+ VIR_HOOK_SUBOP_BEGIN,
+ NULL,
+ dxml ? dxml : xml,
+ &xmlout)) < 0)
+ goto cleanup;
+
+ if (hookret == 0 && xmlout) {
+ VIR_DEBUG("Using hook-filtered domain XML: %s", xmlout);
+ hook_taint = true;
+ newxml = xmlout;
+ }
+ }
+
+ if (newxml) {
+ virDomainDefPtr tmp;
+ if (!(tmp = qemuDomainSaveImageUpdateDef(driver, def, newxml)))
goto cleanup;
virDomainDefFree(def);
- def = newdef;
+ def = tmp;
}
if (!(vm = virDomainObjListAdd(driver->domains, def,
@@ -5687,6 +5710,11 @@ qemuDomainRestoreFlags(virConnectPtr conn,
else if (flags & VIR_DOMAIN_SAVE_PAUSED)
header.was_running = 0;
+ if (hook_taint) {
+ priv = vm->privateData;
+ priv->hookRun = true;
+ }
+
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
goto cleanup;
@@ -5705,6 +5733,8 @@ qemuDomainRestoreFlags(virConnectPtr conn,
cleanup:
virDomainDefFree(def);
VIR_FORCE_CLOSE(fd);
+ VIR_FREE(xml);
+ VIR_FREE(xmlout);
virFileWrapperFdFree(wrapperFd);
if (vm)
virObjectUnlock(vm);
@@ -5842,12 +5872,15 @@ qemuDomainObjRestore(virConnectPtr conn,
bool bypass_cache)
{
virDomainDefPtr def = NULL;
+ qemuDomainObjPrivatePtr priv = vm->privateData;
int fd = -1;
int ret = -1;
+ char *xml = NULL;
+ char *xmlout = NULL;
virQEMUSaveHeader header;
virFileWrapperFdPtr wrapperFd = NULL;
- fd = qemuDomainSaveImageOpen(driver, path, &def, &header, NULL,
+ fd = qemuDomainSaveImageOpen(driver, path, &def, &header, &xml,
bypass_cache, &wrapperFd, false, true);
if (fd < 0) {
if (fd == -3)
@@ -5855,6 +5888,29 @@ qemuDomainObjRestore(virConnectPtr conn,
goto cleanup;
}
+ if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
+ int hookret;
+
+ if ((hookret = virHookCall(VIR_HOOK_DRIVER_QEMU, def->name,
+ VIR_HOOK_QEMU_OP_RESTORE,
+ VIR_HOOK_SUBOP_BEGIN,
+ NULL, xml, &xmlout)) < 0)
+ goto cleanup;
+
+ if (hookret == 0 && xmlout) {
+ virDomainDefPtr tmp;
+
+ VIR_DEBUG("Using hook-filtered domain XML: %s", xmlout);
+
+ if (!(tmp = qemuDomainSaveImageUpdateDef(driver, def, xmlout)))
+ goto cleanup;
+
+ virDomainDefFree(def);
+ def = tmp;
+ priv->hookRun = true;
+ }
+ }
+
if (STRNEQ(vm->def->name, def->name) ||
memcmp(vm->def->uuid, def->uuid, VIR_UUID_BUFLEN)) {
char vm_uuidstr[VIR_UUID_STRING_BUFLEN];
@@ -5878,6 +5934,8 @@ qemuDomainObjRestore(virConnectPtr conn,
VIR_WARN("Failed to close %s", path);
cleanup:
+ VIR_FREE(xml);
+ VIR_FREE(xmlout);
virDomainDefFree(def);
VIR_FORCE_CLOSE(fd);
virFileWrapperFdFree(wrapperFd);
diff --git a/src/util/virhook.c b/src/util/virhook.c
index ac7b40f..25d0783 100644
--- a/src/util/virhook.c
+++ b/src/util/virhook.c
@@ -77,7 +77,8 @@ VIR_ENUM_IMPL(virHookQemuOp, VIR_HOOK_QEMU_OP_LAST,
"migrate",
"started",
"reconnect",
- "attach")
+ "attach",
+ "restore")
VIR_ENUM_IMPL(virHookLxcOp, VIR_HOOK_LXC_OP_LAST,
"start",
diff --git a/src/util/virhook.h b/src/util/virhook.h
index 5bc0a5f..550ef84 100644
--- a/src/util/virhook.h
+++ b/src/util/virhook.h
@@ -60,6 +60,7 @@ typedef enum {
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_RESTORE, /* domain is being restored */
VIR_HOOK_QEMU_OP_LAST,
} virHookQemuOpType;
--
2.1.0