[virt-tools-list] [PATCH] virt-manager: Add block migration support
Eiichi Tsukata
devel at etsukata.com
Sat Oct 5 14:59:36 UTC 2013
This patch adds block migration support. There are two modes: full
disk copy and incremental disk copy, which correspond to libvirt
virDomainMigrate API's flags, VIR_MIGRATE_NON_SHARED_DISK and
VIR_MIGRATE_NON_SHARED_INC. These flags are mutually exclusive,
so GUI is implemented by ComboBox.
Signed-off-by: Eiichi Tsukata <devel at etsukata.com>
---
ui/migrate.ui | 61 ++++++++++++++++++++++++++++++++++++++++++++++--
virtManager/domain.py | 7 +++++-
virtManager/migrate.py | 41 +++++++++++++++++++++++++++++---
virtManager/uihelpers.py | 20 ++++++++++++++++
4 files changed, 123 insertions(+), 6 deletions(-)
diff --git a/ui/migrate.ui b/ui/migrate.ui
index 3b81fbb..d2b5b76 100644
--- a/ui/migrate.ui
+++ b/ui/migrate.ui
@@ -296,6 +296,63 @@
</packing>
</child>
<child>
+ <object class="GtkAlignment" id="alignment5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="left_padding">6</property>
+ <child>
+ <object class="GtkHBox" id="migrate-block-box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Block migration:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">migrate-set-block</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-set-block">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_migrate_set_block_toggled" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="migrate-block">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="position">2</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 +465,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 +716,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 4dc8a8a..6ec1beb 100644
--- a/virtManager/domain.py
+++ b/virtManager/domain.py
@@ -1322,7 +1322,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, block=None, meter=None):
self._install_abort = True
newname = None
@@ -1335,6 +1335,11 @@ class vmmDomain(vmmLibvirtObject):
flags |= libvirt.VIR_MIGRATE_PEER2PEER
flags |= libvirt.VIR_MIGRATE_TUNNELLED
+ if block == "full":
+ flags |= libvirt.VIR_MIGRATE_NON_SHARED_DISK
+ elif block == "incremental":
+ flags |= libvirt.VIR_MIGRATE_NON_SHARED_INC
+
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..fd39457 100644
--- a/virtManager/migrate.py
+++ b/virtManager/migrate.py
@@ -31,6 +31,7 @@ from gi.repository import Gtk
import libvirt
from virtinst import util
+from virtManager import uihelpers
from virtManager.baseclass import vmmGObjectUI
from virtManager.asyncjob import vmmAsyncJob
from virtManager.domain import vmmDomain
@@ -68,6 +69,7 @@ class vmmMigrateDialog(vmmGObjectUI):
"on_migrate_set_interface_toggled" : self.toggle_set_interface,
"on_migrate_set_port_toggled" : self.toggle_set_port,
"on_migrate_set_maxdowntime_toggled" : self.toggle_set_maxdowntime,
+ "on_migrate_set_block_toggled" : self.toggle_set_block,
})
self.bind_escape_key_close()
@@ -116,6 +118,9 @@ class vmmMigrateDialog(vmmGObjectUI):
self.engine.connect("conn-removed", self.dest_remove_conn)
self.destconn_changed(dest_combo)
+ block_combo = self.widget("migrate-block")
+ uihelpers.build_block_migration_combo(block_combo)
+
def reset_state(self):
title_str = ("<span size='large' color='white'>%s '%s'</span>" %
(_("Migrate"), util.xml_escape(self.vm.get_name())))
@@ -141,6 +146,7 @@ class vmmMigrateDialog(vmmGObjectUI):
self.widget("migrate-rate").set_value(0)
self.widget("migrate-secure").set_active(False)
+ self.widget("migrate-set-block").set_active(False)
downtime_box = self.widget("migrate-maxdowntime-box")
support_downtime = self.vm.support_downtime()
@@ -168,6 +174,19 @@ class vmmMigrateDialog(vmmGObjectUI):
secure_box.set_sensitive(support_secure)
secure_box.set_tooltip_text(secure_tooltip)
+ block_box = self.widget("migrate-block-box")
+ support_block = (hasattr(libvirt, "VIR_MIGRATE_NON_SHARED_DISK")
+ and hasattr(libvirt, "VIR_MIGRATE_NON_SHARED_DISK"))
+ block_tooltip = ""
+ if not support_block:
+ secure_tooltip = _("Libvirt version does not support block "
+ "migration.")
+
+ block_box.set_sensitive(support_block)
+ block_box.set_tooltip_text(block_tooltip)
+ block_combo = self.widget("migrate-block")
+ uihelpers.populate_block_migration_combo(block_combo)
+
self.rebuild_dest_rows()
def set_state(self, vm):
@@ -199,6 +218,10 @@ class vmmMigrateDialog(vmmGObjectUI):
enable = src.get_active()
self.widget("migrate-max-downtime").set_sensitive(enable)
+ def toggle_set_block(self, src):
+ enable = src.get_active()
+ self.widget("migrate-block").set_sensitive(enable)
+
def toggle_set_port(self, src):
enable = src.get_active()
self.widget("migrate-port").set_sensitive(enable)
@@ -228,9 +251,20 @@ class vmmMigrateDialog(vmmGObjectUI):
def get_config_secure(self):
return self.widget("migrate-secure").get_active()
+ def get_config_block(self):
+ if not self.get_config_block_enabled():
+ return 0
+ combo = self.widget("migrate-block")
+ model = combo.get_model()
+ idx = combo.get_active()
+ return model[idx][0]
+
def get_config_max_downtime_enabled(self):
return self.widget("migrate-max-downtime").get_sensitive()
+ def get_config_block_enabled(self):
+ return self.widget("migrate-block").get_sensitive()
+
def get_config_rate_enabled(self):
return self.widget("migrate-rate").get_sensitive()
def get_config_rate(self):
@@ -464,6 +498,7 @@ class vmmMigrateDialog(vmmGObjectUI):
max_downtime = self.get_config_max_downtime()
live = not self.get_config_offline()
secure = self.get_config_secure()
+ block = self.get_config_block()
uri = self.build_migrate_uri(destconn, srcuri)
rate = self.get_config_rate()
if rate:
@@ -485,7 +520,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, max_downtime, block],
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 +560,7 @@ class vmmMigrateDialog(vmmGObjectUI):
def _async_migrate(self, asyncjob,
origvm, origdconn, migrate_uri, rate, live,
- secure, max_downtime):
+ secure, max_downtime, block):
meter = asyncjob.get_meter()
srcconn = origvm.conn
@@ -545,6 +580,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, block, meter=meter)
if timer:
self.idle_add(GLib.source_remove, timer)
diff --git a/virtManager/uihelpers.py b/virtManager/uihelpers.py
index 81308a2..5d1fe78 100644
--- a/virtManager/uihelpers.py
+++ b/virtManager/uihelpers.py
@@ -1096,6 +1096,26 @@ def build_keycombo_menu(cb):
return menu
+#########################
+# Block migration combo #
+#########################
+
+def build_block_migration_combo(combo):
+ model = Gtk.ListStore(str)
+ combo.set_model(model)
+ set_combo_text_column(combo, 0)
+
+
+def populate_block_migration_combo(combo):
+ model = combo.get_model()
+ model.clear()
+
+ model.append(["full"])
+ model.append(["incremental"])
+
+ combo.set_active(0)
+
+
#############
# Misc bits #
#############
--
1.8.3.1
More information about the virt-tools-list
mailing list