[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