Add virDomainSetMigrateMaxDowntime support
This commit is contained in:
parent
5a8523fc03
commit
febecf4089
1
AUTHORS
1
AUTHORS
|
@ -67,6 +67,7 @@ Further patches have been submitted by:
|
|||
Marc Deslauriers <marc.deslauriers-at-ubuntu-dot-com>
|
||||
Matthias Fulz <olz1983-at-googlemail-dot-com>
|
||||
Niels de Vos <ndevos-at-redhat-dot-com>
|
||||
Wen Congyang <wency-at-cn-dot-fujitsu-dot-com>
|
||||
|
||||
<...send a patch & get your name here...>
|
||||
|
||||
|
|
|
@ -857,6 +857,12 @@ class vmmDomain(vmmDomainBase):
|
|||
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()
|
||||
|
||||
|
@ -997,6 +1003,9 @@ class vmmDomain(vmmDomainBase):
|
|||
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
|
||||
|
|
|
@ -23,6 +23,7 @@ import gtk.glade
|
|||
|
||||
import traceback
|
||||
import logging
|
||||
import threading
|
||||
|
||||
import virtinst
|
||||
import libvirt
|
||||
|
@ -78,6 +79,7 @@ class vmmMigrateDialog(gobject.GObject):
|
|||
"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 @@ class vmmMigrateDialog(gobject.GObject):
|
|||
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 @@ class vmmMigrateDialog(gobject.GObject):
|
|||
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 @@ class vmmMigrateDialog(gobject.GObject):
|
|||
|
||||
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 @@ class vmmMigrateDialog(gobject.GObject):
|
|||
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 @@ class vmmMigrateDialog(gobject.GObject):
|
|||
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 @@ class vmmMigrateDialog(gobject.GObject):
|
|||
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 @@ class vmmMigrateDialog(gobject.GObject):
|
|||
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 libvirt.libvirtError, 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 @@ class vmmMigrateDialog(gobject.GObject):
|
|||
|
||||
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())))
|
||||
|
|
|
@ -245,6 +245,99 @@
|
|||
<property name="position">0</property>
|
||||
</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>
|
||||
|
@ -471,7 +564,7 @@
|
|||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
|
|
Loading…
Reference in New Issue