From 4f3c2e39e5c898c533ddf58b62b452a674df794d Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Wed, 17 Sep 2014 11:38:39 +0200 Subject: [PATCH] qemu: hook: Provide hook when restoring a domain save image --- 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 07b9d49986..1aae00c77b 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. +
  • 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 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 diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ee542bf882..e73d4f9178 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 ac7b40f498..25d0783bfb 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 5bc0a5f630..550ef84a38 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; -- GitLab