[virt-tools-list] [RFC Patch] force guest to suspend at timeout

Wen Congyang wency at cn.fujitsu.com
Mon Jan 10 08:54:04 UTC 2011


# 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.

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