[libvirt] [PATCH 2/2] qemu: Add pre-migration hook

Jiri Denemark jdenemar at redhat.com
Tue Feb 28 21:49:10 UTC 2012


This hook is called during the Prepare phase on destination host and may
be used for changing domain XML.
---
 docs/hooks.html.in        |   35 +++++++++++++++++++++++------------
 src/qemu/qemu_migration.c |   40 ++++++++++++++++++++++++++++++++++++++++
 src/util/hooks.c          |    3 ++-
 src/util/hooks.h          |    1 +
 4 files changed, 66 insertions(+), 13 deletions(-)

diff --git a/docs/hooks.html.in b/docs/hooks.html.in
index 890359e..6c82c6d 100644
--- a/docs/hooks.html.in
+++ b/docs/hooks.html.in
@@ -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 to, e.g., 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 any of these hook script executions returns indicating success
+          (error code 0), the migration continues.  Any other return 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/>
 
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 7df2d4f..d00bd61 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -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,43 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
             goto cleanup;
     }
 
+    /* Let migration hook filter domain XML */
+    if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
+        char *xml = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE);
+        int hookret;
+
+        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 +1283,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]);
diff --git a/src/util/hooks.c b/src/util/hooks.c
index 8c16a3a..b0c15fd 100644
--- a/src/util/hooks.c
+++ b/src/util/hooks.c
@@ -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",
diff --git a/src/util/hooks.h b/src/util/hooks.h
index a53ac2c..7fd29f6 100644
--- a/src/util/hooks.h
+++ b/src/util/hooks.h
@@ -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,
 };
-- 
1.7.8.5




More information about the libvir-list mailing list