[virt-tools-list] [Patch V2] Add virDomainSetMigrateMaxDowntime support
Wen Congyang
wency at cn.fujitsu.com
Wed Nov 24 03:40:34 UTC 2010
# HG changeset patch
# User Wen Congyang <wency at cn.fujitsu.com>
# Date 1290569680 -28800
# Node ID 519e30777e538476c18a329984b44d37d27c39c9
# Parent 076759c3ada6fbb26c32d9181fb381097ed6bd0c
Add virDomainSetMigrateMaxDowntime support
diff -r 076759c3ada6 -r 519e30777e53 src/virtManager/domain.py
--- a/src/virtManager/domain.py Tue Nov 23 20:13:50 2010 -0500
+++ b/src/virtManager/domain.py Wed Nov 24 11:34:40 2010 +0800
@@ -944,6 +944,12 @@
def _XMLDesc(self, flags):
return self._backend.XMLDesc(flags)
+ def support_downtime(self):
+ # Note: this function has side effect
+ # if domain supports downtime, the downtime may be overriden to 30ms
+ return support.check_domain_support(self._backend,
+ support.SUPPORT_DOMAIN_MIGRATE_DOWNTIME)
+
def get_info(self):
return self._backend.info()
@@ -1090,6 +1096,9 @@
if self.get_autostart() != val:
self._backend.setAutostart(val)
+ def migrate_set_max_downtime(self, max_downtime, flag=0):
+ self._backend.migrateSetMaxDowntime(max_downtime, flag)
+
def migrate(self, destconn, interface=None, rate=0,
live=False, secure=False):
newname = None
diff -r 076759c3ada6 -r 519e30777e53 src/virtManager/migrate.py
--- a/src/virtManager/migrate.py Tue Nov 23 20:13:50 2010 -0500
+++ b/src/virtManager/migrate.py Wed Nov 24 11:34:40 2010 +0800
@@ -23,6 +23,7 @@
import traceback
import logging
+import threading
import virtinst
import libvirt
@@ -78,6 +79,7 @@
"on_migrate_set_rate_toggled" : self.toggle_set_rate,
"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,
})
util.bind_escape_key_close(self)
@@ -134,6 +136,8 @@
self.window.get_widget("migrate-set-interface").set_active(False)
self.window.get_widget("migrate-set-rate").set_active(False)
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)
running = self.vm.is_active()
self.window.get_widget("migrate-offline").set_active(not running)
@@ -187,6 +191,10 @@
self.window.get_widget("migrate-port").set_sensitive(enable and
port_enable)
+ def toggle_set_maxdowntime(self, src):
+ enable = src.get_active()
+ self.window.get_widget("migrate-max-downtime").set_sensitive(enable)
+
def toggle_set_port(self, src):
enable = src.get_active()
self.window.get_widget("migrate-port").set_sensitive(enable)
@@ -207,9 +215,18 @@
def get_config_offline(self):
return self.window.get_widget("migrate-offline").get_active()
+
+ def get_config_max_downtime(self):
+ if not self.get_config_max_downtime_enabled():
+ return 0
+ return int(self.window.get_widget("migrate-max-downtime").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_rate_enabled(self):
return self.window.get_widget("migrate-rate").get_property("sensitive")
def get_config_rate(self):
@@ -382,6 +399,10 @@
interface = self.get_config_interface()
rate = self.get_config_rate()
port = self.get_config_port()
+ max_downtime = self.get_config_max_downtime()
+
+ if self.get_config_max_downtime_enabled() and max_downtime == 0:
+ return self.err.val_err(_("max downtime must be greater than 0."))
if self.get_config_interface_enabled() and interface == None:
return self.err.val_err(_("An interface must be specified."))
@@ -402,6 +423,7 @@
destconn = self.get_config_destconn()
srchost = self.vm.get_connection().get_hostname()
dsthost = destconn.get_qualified_hostname()
+ max_downtime = self.get_config_max_downtime()
live = not self.get_config_offline()
secure = self.get_config_secure()
uri = self.build_migrate_uri(destconn)
@@ -418,7 +440,8 @@
self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
progWin = vmmAsyncJob(self.config, self._async_migrate,
- [self.vm, destconn, uri, rate, live, secure],
+ [self.vm, destconn, uri, rate, live, secure,
+ max_downtime],
title=_("Migrating VM '%s'" % self.vm.get_name()),
text=(_("Migrating VM '%s' from %s to %s. "
"This may take awhile.") %
@@ -437,8 +460,23 @@
destconn.tick(noStatsUpdate=True)
self.close()
+ def _async_set_max_downtime(self, vm, max_downtime, migrate_thread):
+ if not migrate_thread.isAlive():
+ return False
+ try:
+ vm.migrate_set_max_downtime(max_downtime, 0)
+ return False
+ except Exception, e:
+ if (isinstance(e, libvirt.libvirtError) and
+ e.get_error_code() == libvirt.VIR_ERR_OPERATION_INVALID):
+ # migration has not been started, wait 100 milliseconds
+ return True
+
+ logging.warning("Error setting migrate downtime: %s" % e)
+ return False
+
def _async_migrate(self, origvm, origdconn, migrate_uri, rate, live,
- secure, asyncjob):
+ secure, max_downtime, asyncjob):
errinfo = None
try:
try:
@@ -454,7 +492,22 @@
logging.debug("Migrating vm=%s from %s to %s", vm.get_name(),
srcconn.get_uri(), dstconn.get_uri())
+ timer = None
+ if max_downtime != 0 and vm.support_downtime():
+ # 0 means that the spin box migrate-max-downtime does not
+ # be enabled.
+ #
+ # We should check whether the domain supports downtime
+ # early, but vm.support_downtime() has side effect, so
+ # we check it only when user needs to modify downtime...
+ current_thread = threading.currentThread()
+ timer = util.safe_timeout_add(100,
+ self._async_set_max_downtime,
+ vm, max_downtime,
+ current_thread)
vm.migrate(dstconn, migrate_uri, rate, live, secure)
+ if timer:
+ gobject.source_remove(timer)
except Exception, e:
errinfo = (str(e), ("Unable to migrate guest:\n %s" %
"".join(traceback.format_exc())))
diff -r 076759c3ada6 -r 519e30777e53 src/vmm-migrate.glade
--- a/src/vmm-migrate.glade Tue Nov 23 20:13:50 2010 -0500
+++ b/src/vmm-migrate.glade Wed Nov 24 11:34:40 2010 +0800
@@ -250,6 +250,99 @@
</packing>
</child>
<child>
+ <widget class="GtkHBox" id="migrate-maxdowntime-box">
+ <property name="visible">True</property>
+ <property name="spacing">3</property>
+ <child>
+ <widget class="GtkLabel" id="label15">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Max downtime:</property>
+ <property name="use_markup">True</property>
+ <property name="use_underline">True</property>
+ </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-maxdowntime">
+ <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_maxdowntime_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="hbox8">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkHBox" id="hbox9">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkSpinButton" id="migrate-max-downtime">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="adjustment">30 0 1000000 1 1000 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="label16">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">ms</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="alignment6">
+ <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">1</property>
+ </packing>
+ </child>
+ <child>
<widget class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="label_xalign">0</property>
@@ -475,7 +568,7 @@
</widget>
<packing>
<property name="expand">False</property>
- <property name="position">1</property>
+ <property name="position">2</property>
</packing>
</child>
</widget>
More information about the virt-tools-list
mailing list