[libvirt] [PATCH 5/5] qemu: hook: Provide hook when restoring a domain save image

Peter Krempa pkrempa at redhat.com
Wed Sep 17 15:18:39 UTC 2014


---
 docs/hooks.html.in     | 11 ++++++++
 src/qemu/qemu_driver.c | 69 +++++++++++++++++++++++++++++++++++++++++++++-----
 src/util/virhook.c     |  3 ++-
 src/util/virhook.h     |  1 +
 4 files changed, 76 insertions(+), 8 deletions(-)

diff --git a/docs/hooks.html.in b/docs/hooks.html.in
index 07b9d49..265dbb7 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 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
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 1d82e93..2dd2e48 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5636,20 +5636,23 @@ 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;
     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)
@@ -5658,12 +5661,29 @@ 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;

-        virDomainDefFree(def);
-        def = newdef;
+        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;
+            hook_taint = true;
+        }
     }

     if (!(vm = virDomainObjListAdd(driver->domains, def,
@@ -5679,6 +5699,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;

@@ -5697,6 +5722,8 @@ qemuDomainRestoreFlags(virConnectPtr conn,
  cleanup:
     virDomainDefFree(def);
     VIR_FORCE_CLOSE(fd);
+    VIR_FREE(xml);
+    VIR_FREE(xmlout);
     virFileWrapperFdFree(wrapperFd);
     if (vm)
         virObjectUnlock(vm);
@@ -5834,12 +5861,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)
@@ -5847,6 +5877,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];
@@ -5870,6 +5923,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




More information about the libvir-list mailing list