Allow unsafe migrations in virt-manager
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@suse.com>
This commit is contained in:
parent
e57cd46904
commit
1124043151
|
@ -295,6 +295,53 @@
|
|||
<property name="position">0</property>
|
||||
</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>
|
||||
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue