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@xxxxxxxxxxxx> --- 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 _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list