[virt-tools-list] [RFC Patch] force guest to suspend at timeout
Cole Robinson
crobinso at redhat.com
Thu Jan 13 17:17:12 UTC 2011
On 01/10/2011 03:54 AM, Wen Congyang wrote:
> # HG changeset patch
> # User Wen Congyang <wency at cn.fujitsu.com>
> # Date 1294645270 -28800
> # Node ID ac401f3556fa8a2cba588aa181f9e6f219cc9d99
> # Parent 5515384e667a6a93d548cbeec8cc7ff2f7ac28f0
> force guest to suspend at timeout
>
> If the memory of guest OS is changed constantly, the live migration
> can not be ended ever for ever.
>
> We can add maxdowntime to control the live migration. But the value
> of maxdowntime is diffcult to calculate because it depends on the
> transfer speed of network and constantly changing memroy size, and
> we can not modify maxdowntime during miration. We need a easy way
> to control the live migration.
>
Is not being able to change max downtime during migration a qemu
limitation, libvirt, or just virt-manager UI?
- Cole
> This patch adds the support of forcing guest to suspend at timeout.
> With this patch set, when we migrate the guest OS, we can specify a
> timeout. If the live migration timeouts, auto-suspend the guest OS,
> where the migration will complete offline.
>
> diff -r 5515384e667a -r ac401f3556fa src/virtManager/migrate.py
> --- a/src/virtManager/migrate.py Mon Jan 10 16:07:19 2011 +0800
> +++ b/src/virtManager/migrate.py Mon Jan 10 15:41:10 2011 +0800
> @@ -69,6 +69,8 @@
> "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_timeout_toggled" : self.toggle_set_timeout,
> + "on_migrate_set_offline" : self.toggle_set_offline,
> })
> util.bind_escape_key_close(self)
>
> @@ -127,6 +129,8 @@
> self.window.get_widget("migrate-set-port").set_active(False)
> self.window.get_widget("migrate-set-maxdowntime").set_active(False)
> self.window.get_widget("migrate-max-downtime").set_value(30)
> + self.window.get_widget("migrate-set-timeout").set_active(False)
> + self.window.get_widget("migrate-timeout").set_value(0)
>
> running = self.vm.is_active()
> self.window.get_widget("migrate-offline").set_active(not running)
> @@ -197,6 +201,17 @@
> enable = src.get_active()
> self.window.get_widget("migrate-port").set_sensitive(enable)
>
> + def toggle_set_timeout(self, src):
> + enable = src.get_active()
> + self.window.get_widget("migrate-timeout").set_sensitive(enable)
> +
> + def toggle_set_offline(self, src):
> + enable = src.get_active()
> + timeout_enable = self.window.get_widget("migrate-set-timeout").get_active()
> + self.window.get_widget("migrate-set-timeout").set_sensitive(not enable)
> + self.window.get_widget("migrate-timeout").set_sensitive(not enable and
> + timeout_enable)
> +
> def get_config_destconn(self):
> combo = self.window.get_widget("migrate-dest")
> model = combo.get_model()
> @@ -219,12 +234,20 @@
> return 0
> return int(self.window.get_widget("migrate-max-downtime").get_value())
>
> + def get_config_timeout(self):
> + if not self.get_config_timeout_enabled():
> + return 0
> + return int(self.window.get_widget("migrate-timeout").get_value())
> +
> def get_config_secure(self):
> return self.window.get_widget("migrate-secure").get_active()
>
> def get_config_max_downtime_enabled(self):
> return self.window.get_widget("migrate-max-downtime").get_property("sensitive")
>
> + def get_config_timeout_enabled(self):
> + return self.window.get_widget("migrate-timeout").get_property("sensitive")
> +
> def get_config_rate_enabled(self):
> return self.window.get_widget("migrate-rate").get_property("sensitive")
> def get_config_rate(self):
> @@ -398,6 +421,7 @@
> rate = self.get_config_rate()
> port = self.get_config_port()
> max_downtime = self.get_config_max_downtime()
> + timeout = self.get_config_timeout()
>
> if self.get_config_max_downtime_enabled() and max_downtime == 0:
> return self.err.val_err(_("max downtime must be greater than 0."))
> @@ -411,6 +435,9 @@
> if self.get_config_port_enabled() and port == 0:
> return self.err.val_err(_("Port must be greater than 0."))
>
> + if self.get_config_timeout_enabled() and timeout == 0:
> + return self.err.val_err(_("Timeout must be greater than 0."))
> +
> return True
>
> def finish(self, src_ignore):
> @@ -426,6 +453,7 @@
> secure = self.get_config_secure()
> uri = self.build_migrate_uri(destconn)
> rate = self.get_config_rate()
> + timeout = self.get_config_timeout()
> if rate:
> rate = int(rate)
> except Exception, e:
> @@ -446,7 +474,7 @@
>
> progWin = vmmAsyncJob(self._async_migrate,
> [self.vm, destconn, uri, rate, live, secure,
> - max_downtime],
> + max_downtime, timeout],
> _("Migrating VM '%s'" % self.vm.get_name()),
> (_("Migrating VM '%s' from %s to %s. "
> "This may take awhile.") %
> @@ -481,6 +509,19 @@
> logging.warning("Error setting migrate downtime: %s" % e)
> return False
>
> + def _async_set_offline(self, vm, migrate_thread):
> + logging.debug("pausing domain at timeout")
> + if not migrate_thread.isAlive():
> + return False
> + if not vm.is_pauseable():
> + return False
> + try:
> + vm.suspend()
> + return False
> + except Exception, e:
> + logging.warning("Error pausing domain: %s" % e)
> + return False
> +
> def cancel_migration(self, asyncjob, vm):
> logging.debug("Cancelling migrate job")
> if not vm:
> @@ -498,7 +539,7 @@
>
> def _async_migrate(self, asyncjob,
> origvm, origdconn, migrate_uri, rate, live,
> - secure, max_downtime):
> + secure, max_downtime, timeout):
> meter = vmmCreateMeter(asyncjob)
>
> srcconn = util.dup_conn(origvm.get_connection())
> @@ -510,18 +551,25 @@
> logging.debug("Migrating vm=%s from %s to %s", vm.get_name(),
> srcconn.get_uri(), dstconn.get_uri())
>
> - timer = None
> + max_downtime_timer = None
> + timeout_timer = None
> + current_thread = threading.currentThread()
> if max_downtime != 0:
> # 0 means that the spin box migrate-max-downtime does not
> # be enabled.
> - current_thread = threading.currentThread()
> - timer = util.safe_timeout_add(100,
> + max_downtime_timer = util.safe_timeout_add(100,
> self._async_set_max_downtime,
> vm, max_downtime,
> current_thread)
> + if timeout != 0:
> + timeout_timer = util.safe_timeout_add(timeout * 1000,
> + self._async_set_offline,
> + vm, current_thread)
>
> vm.migrate(dstconn, migrate_uri, rate, live, secure, meter=meter)
> - if timer:
> - gobject.source_remove(timer)
> + if max_downtime_timer:
> + gobject.source_remove(max_downtime_timer)
> + if timeout_timer:
> + gobject.source_remove(timeout_timer)
>
> vmmGObjectUI.type_register(vmmMigrateDialog)
> diff -r 5515384e667a -r ac401f3556fa src/vmm-migrate.glade
> --- a/src/vmm-migrate.glade Mon Jan 10 16:07:19 2011 +0800
> +++ b/src/vmm-migrate.glade Mon Jan 10 15:41:10 2011 +0800
> @@ -157,6 +157,7 @@
> <property name="receives_default">False</property>
> <property name="xalign">1</property>
> <property name="draw_indicator">True</property>
> + <signal name="toggled" handler="on_migrate_set_offline"/>
> </widget>
> <packing>
> <property name="expand">False</property>
> @@ -345,6 +346,106 @@
> </packing>
> </child>
> <child>
> + <widget class="GtkHBox" id="migrate-timeout-box">
> + <property name="visible">True</property>
> + <property name="spacing">3</property>
> + <child>
> + <widget class="GtkAlignment" id="alignment5">
> + <property name="visible">True</property>
> + <property name="left_padding">6</property>
> + <child>
> + <widget class="GtkLabel" id="label1">
> + <property name="visible">True</property>
> + <property name="xalign">1</property>
> + <property name="yalign">0.49000000953674316</property>
> + <property name="label" translatable="yes">Timeout:</property>
> + <property name="use_markup">True</property>
> + <property name="use_underline">True</property>
> + </widget>
> + </child>
> + </widget>
> + <packing>
> + <property name="expand">False</property>
> + <property name="fill">False</property>
> + <property name="position">0</property>
> + </packing>
> + </child>
> + <child>
> + <widget class="GtkCheckButton" id="migrate-set-timeout">
> + <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_timeout_toggled"/>
> + </widget>
> + <packing>
> + <property name="expand">False</property>
> + <property name="fill">False</property>
> + <property name="position">1</property>
> + </packing>
> + </child>
> + <child>
> + <widget class="GtkHBox" id="hbox5">
> + <property name="visible">True</property>
> + <property name="spacing">6</property>
> + <child>
> + <widget class="GtkHBox" id="hbox6">
> + <property name="visible">True</property>
> + <property name="spacing">6</property>
> + <child>
> + <widget class="GtkSpinButton" id="migrate-timeout">
> + <property name="visible">True</property>
> + <property name="sensitive">False</property>
> + <property name="can_focus">True</property>
> + <property name="invisible_char">â</property>
> + <property name="adjustment">0 0 1000000 1 60 0</property>
> + <property name="snap_to_ticks">True</property>
> + <property name="numeric">True</property>
> + </widget>
> + <packing>
> + <property name="expand">False</property>
> + <property name="position">0</property>
> + </packing>
> + </child>
> + <child>
> + <widget class="GtkLabel" id="label14">
> + <property name="visible">True</property>
> + <property name="xalign">0</property>
> + <property name="label" translatable="yes">s</property>
> + </widget>
> + <packing>
> + <property name="position">1</property>
> + </packing>
> + </child>
> + </widget>
> + <packing>
> + <property name="expand">False</property>
> + <property name="position">0</property>
> + </packing>
> + </child>
> + <child>
> + <widget class="GtkAlignment" id="alignment7">
> + <property name="visible">True</property>
> + <child>
> + <placeholder/>
> + </child>
> + </widget>
> + <packing>
> + <property name="position">1</property>
> + </packing>
> + </child>
> + </widget>
> + <packing>
> + <property name="expand">False</property>
> + <property name="position">2</property>
> + </packing>
> + </child>
> + </widget>
> + <packing>
> + <property name="position">2</property>
> + </packing>
> + </child>
> + <child>
> <widget class="GtkFrame" id="frame1">
> <property name="visible">True</property>
> <property name="label_xalign">0</property>
> @@ -570,7 +671,7 @@
> </widget>
> <packing>
> <property name="expand">False</property>
> - <property name="position">2</property>
> + <property name="position">3</property>
> </packing>
> </child>
> </widget>
More information about the virt-tools-list
mailing list