[virt-tools-list] [PATCH] Allow unsafe migrations in virt-manager

Charles Arnold carnold at suse.com
Tue Dec 10 21:33:12 UTC 2013


Normally, setting cache=none is required in order to ensure a consistent view
of storage between the source and destination migration hosts. However, some
configurations have that quality without resorting to the use of an O_DIRECT
open (which is what cache=none does), and hence cache=none wouldn't be
necessary.

Unfortunately, libvirt is not able to determine on it's own all the
configurations which require cache=none for migration but in the interest of
safety enforces it when it isn't otherwise able to determine migration safety.

For this reason the libvirt api has an 'unsafe' option which allows the user
to override the safety migration checks.

This patch adds a checkbox to allow unsafe migration to the 'Advanced options'
portion of the migration dialog.

Signed-off-by: Charles Arnold <carnold at suse.com>

diff --git a/ui/migrate.ui b/ui/migrate.ui
index 3b81fbb..cbbbc5c 100644
--- a/ui/migrate.ui
+++ b/ui/migrate.ui
@@ -296,6 +296,53 @@
                           </packing>
                         </child>
                         <child>
+                          <object class="GtkAlignment" id="alignment7">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="left_padding">6</property>
+                            <child>
+                              <object class="GtkHBox" id="migrate-unsafe-box">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="spacing">6</property>
+                                <child>
+                                  <object class="GtkLabel" id="label17">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" translatable="yes">_Allow unsafe migration:</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">migrate-unsafe</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkCheckButton" id="migrate-unsafe">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">False</property>
+                                    <property name="use_action_appearance">False</property>
+                                    <property name="draw_indicator">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
                           <object class="GtkHBox" id="migrate-maxdowntime-box">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
@@ -408,7 +455,7 @@
                           <packing>
                             <property name="expand">True</property>
                             <property name="fill">True</property>
-                            <property name="position">1</property>
+                            <property name="position">2</property>
                           </packing>
                         </child>
                         <child>
@@ -659,7 +706,7 @@
                           <packing>
                             <property name="expand">False</property>
                             <property name="fill">True</property>
-                            <property name="position">2</property>
+                            <property name="position">3</property>
                           </packing>
                         </child>
                       </object>
diff --git a/virtManager/domain.py b/virtManager/domain.py
index 2fc869a..b0acd93 100644
--- a/virtManager/domain.py
+++ b/virtManager/domain.py
@@ -1323,7 +1323,7 @@ class vmmDomain(vmmLibvirtObject):
         self._backend.migrateSetMaxDowntime(max_downtime, flag)
 
     def migrate(self, destconn, interface=None, rate=0,
-                live=False, secure=False, meter=None):
+                live=False, secure=False, unsafe=False, meter=None):
         self._install_abort = True
 
         newname = None
@@ -1336,6 +1336,9 @@ class vmmDomain(vmmLibvirtObject):
             flags |= libvirt.VIR_MIGRATE_PEER2PEER
             flags |= libvirt.VIR_MIGRATE_TUNNELLED
 
+        if unsafe:
+            flags |= libvirt.VIR_MIGRATE_UNSAFE
+
         destconn = destconn.get_backend().libvirtconn
         logging.debug("Migrating: conn=%s flags=%s dname=%s uri=%s rate=%s",
                       destconn, flags, newname, interface, rate)
diff --git a/virtManager/migrate.py b/virtManager/migrate.py
index 75dce35..f32dcf1 100644
--- a/virtManager/migrate.py
+++ b/virtManager/migrate.py
@@ -141,6 +141,7 @@ class vmmMigrateDialog(vmmGObjectUI):
 
         self.widget("migrate-rate").set_value(0)
         self.widget("migrate-secure").set_active(False)
+        self.widget("migrate-unsafe").set_active(False)
 
         downtime_box = self.widget("migrate-maxdowntime-box")
         support_downtime = self.vm.support_downtime()
@@ -168,6 +169,16 @@ class vmmMigrateDialog(vmmGObjectUI):
         secure_box.set_sensitive(support_secure)
         secure_box.set_tooltip_text(secure_tooltip)
 
+        unsafe_box = self.widget("migrate-unsafe-box")
+        support_unsafe = hasattr(libvirt, "VIR_MIGRATE_UNSAFE")
+        unsafe_tooltip = ""
+        if not support_unsafe:
+            unsafe_tooltip = _("Libvirt version does not support unsafe "
+                               "migration.")
+
+        unsafe_box.set_sensitive(support_unsafe)
+        unsafe_box.set_tooltip_text(unsafe_tooltip)
+
         self.rebuild_dest_rows()
 
     def set_state(self, vm):
@@ -228,6 +239,9 @@ class vmmMigrateDialog(vmmGObjectUI):
     def get_config_secure(self):
         return self.widget("migrate-secure").get_active()
 
+    def get_config_unsafe(self):
+        return self.widget("migrate-unsafe").get_active()
+
     def get_config_max_downtime_enabled(self):
         return self.widget("migrate-max-downtime").get_sensitive()
 
@@ -464,6 +478,7 @@ class vmmMigrateDialog(vmmGObjectUI):
             max_downtime = self.get_config_max_downtime()
             live = not self.get_config_offline()
             secure = self.get_config_secure()
+            unsafe = self.get_config_unsafe()
             uri = self.build_migrate_uri(destconn, srcuri)
             rate = self.get_config_rate()
             if rate:
@@ -485,7 +500,7 @@ class vmmMigrateDialog(vmmGObjectUI):
 
         progWin = vmmAsyncJob(
             self._async_migrate,
-            [self.vm, destconn, uri, rate, live, secure, max_downtime],
+            [self.vm, destconn, uri, rate, live, secure, unsafe, max_downtime],
             self._finish_cb, [destconn],
             _("Migrating VM '%s'" % self.vm.get_name()),
             (_("Migrating VM '%s' from %s to %s. This may take a while.") %
@@ -525,7 +540,7 @@ class vmmMigrateDialog(vmmGObjectUI):
 
     def _async_migrate(self, asyncjob,
                        origvm, origdconn, migrate_uri, rate, live,
-                       secure, max_downtime):
+                       secure, unsafe, max_downtime):
         meter = asyncjob.get_meter()
 
         srcconn = origvm.conn
@@ -545,6 +560,6 @@ class vmmMigrateDialog(vmmGObjectUI):
             timer = self.timeout_add(100, self._async_set_max_downtime,
                                      vm, max_downtime, current_thread)
 
-        vm.migrate(dstconn, migrate_uri, rate, live, secure, meter=meter)
+        vm.migrate(dstconn, migrate_uri, rate, live, secure, unsafe, meter=meter)
         if timer:
             self.idle_add(GLib.source_remove, timer)





More information about the virt-tools-list mailing list