atom feed14 messages in com.redhat.et-mgmt-toolsRe: [et-mgmt-tools] [RFC]Re: [libvirt...
FromSent OnAttachments
S.SakamotoSep 19, 2008 2:43 am.jpg, .jpg
Daniel P. BerrangeSep 19, 2008 3:07 am 
S.SakamotoOct 1, 2008 2:48 am 
S.SakamotoOct 9, 2008 2:10 am.patch
Atsushi SAKAIOct 14, 2008 9:20 pm 
S.SakamotoOct 14, 2008 10:04 pm.patch
Atsushi SAKAIOct 16, 2008 6:43 am 
Cole RobinsonOct 16, 2008 8:05 am 
S.SakamotoOct 20, 2008 1:44 am.patch
S.SakamotoOct 24, 2008 1:29 am 
Cole RobinsonOct 28, 2008 8:25 am 
S.SakamotoOct 29, 2008 5:21 pm.patch
Cole RobinsonOct 30, 2008 2:18 pm.patch
S.SakamotoOct 30, 2008 6:29 pm 
Subject:Re: [et-mgmt-tools] [RFC]Re: [libvirt] [RFC][PATCH] virt-managercallsmigration API
From:Cole Robinson (crob@redhat.com)
Date:Oct 16, 2008 8:05:00 am
List:com.redhat.et-mgmt-tools

S.Sakamoto wrote:

Hi,

I make the prototype patch.

This patch is displayed destination host in a sub-menu, as follows.

right-click | +- Run Pause Shutdown -------- Migrate ----> host1.example.com host2.example.com host3.example.com

The item that display in a sub-menu is the host which is a state of ACTIVE or INACTIVE besides the source host. When the host which is a state of ACTIVE or INACTIVE besides a source host
doesn't exist, "(None)" that is insensitive is displayed, as follows.

right-click | +- Run Pause Shutdown -------- Migrate ----> (None)

domain.py | 6 ++++ engine.py | 36 ++++++++++++++++++++++++++++ manager.py | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 117 insertions(+), 3 deletions(-)

Thanks, Shigeki Sakamoto.

Hi, patch generally looks good. One issue though: how does this handle connections using different hypervisors? Say a local xen and a remote qemu. Obviously we shouldn't be able to migrate between the two but I think this code would allow it.

Maybe have the connection list look something like:

migrate -> hostname1 (qemu) -> hostname2 (xen)

If the hypervisors don't match the entry would be disabled.

Also, having the migrate option only available as a right click menu item doesn't seem too transparent. Maybe also list it as an option under the 'Virtual Machine' menu in the individual VM view. If you go this route, you'll want to offload most of the logic to engine.py like is done for shutdown, pause, etc.

diff -r 270e1697b81a src/virtManager/domain.py --- a/src/virtManager/domain.py Mon Oct 06 13:21:06 2008 -0400 +++ b/src/virtManager/domain.py Wed Oct 08 16:38:05 2008 +0900 @@ -972,4 +972,10 @@ class vmmDomain(gobject.GObject): # Invalidate cached xml self.xml = None

+ def migrate(self, dictcon): + flags = 0 + if self.lastStatus == libvirt.VIR_DOMAIN_RUNNING: + flags = libvirt.VIR_MIGRATE_LIVE + self.vm.migrate(self.connection.vmm, flags, None, dictcon.get_short_hostname(), 0) + gobject.type_register(vmmDomain) diff -r 270e1697b81a src/virtManager/engine.py --- a/src/virtManager/engine.py Mon Oct 06 13:21:06 2008 -0400 +++ b/src/virtManager/engine.py Wed Oct 08 16:38:05 2008 +0900 @@ -202,6 +202,8 @@ class vmmEngine(gobject.GObject): self.shutdown_domain(src, uri, uuid) def _do_reboot_domain(self, src, uri, uuid): self.reboot_domain(src, uri, uuid) + def _do_migrate_domain(self, src, uri, uuid, desturi): + self.migrate_domain(uri, uuid, desturi) def _do_exit_app(self, src): self.exit_app()

@@ -296,6 +298,7 @@ class vmmEngine(gobject.GObject): self.windowManager.connect("action-shutdown-domain", self._do_shutdown_domain) self.windowManager.connect("action-reboot-domain", self._do_reboot_domain) self.windowManager.connect("action-destroy-domain", self._do_destroy_domain) + self.windowManager.connect("action-migrate-domain", self._do_migrate_domain) self.windowManager.connect("action-show-console", self._do_show_console) self.windowManager.connect("action-show-details", self._do_show_details) self.windowManager.connect("action-show-preferences", self._do_show_preferences) @@ -528,6 +531,39 @@ class vmmEngine(gobject.GObject): else: logging.warning("Reboot requested, but machine is already shutting down / shutoff")

+ def migrate_domain(self, uri, uuid, desturi): + conn = self.get_connection(uri, False) + vm = conn.get_vm(uuid) + destconn = self.get_connection(desturi, False) + migrate_progress = None + try: + # show progress dialog + migrate_progress = self.get_migrate_progress(vm.get_name(), conn.get_short_hostname(), destconn.get_short_hostname()) + migrate_progress.show() + while gtk.events_pending(): + gtk.main_iteration() + # call virDomainMigrate + vm.migrate(destconn) + # close progress dialog + migrate_progress.destroy() + except Exception, e: + migrate_progress.destroy() + self.err.show_err(_("Error migrating domain: %s") % str(e), + "".join(traceback.format_exc())) + + self.windowManager.conn_refresh_resources(conn) + self.windowManager.conn_refresh_resources(destconn) + + def get_migrate_progress(self, vmname, hostname, desthostname): + migrate_progress = None + migrate_progress = gtk.MessageDialog(None, \ + gtk.DIALOG_DESTROY_WITH_PARENT, \ + gtk.MESSAGE_INFO, \ + gtk.BUTTONS_NONE, \ + _("%s is migrating from %s to %s." % \ + (vmname, hostname, desthostname))) + migrate_progress.set_title(" ") + return migrate_progress

gobject.type_register(vmmEngine) diff -r 270e1697b81a src/virtManager/manager.py --- a/src/virtManager/manager.py Mon Oct 06 13:21:06 2008 -0400 +++ b/src/virtManager/manager.py Wed Oct 08 16:38:05 2008 +0900 @@ -101,6 +101,8 @@ class vmmManager(gobject.GObject): gobject.TYPE_NONE, [str]), "action-show-help": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [str]), + "action-migrate-domain": (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, (str,str,str)), "action-exit-app": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, []),}

@@ -154,6 +156,8 @@ class vmmManager(gobject.GObject): self.vmmenushutdown = gtk.Menu() self.vmmenu_items = {} self.vmmenushutdown_items = {} + self.vmmenumigrate = gtk.Menu() + self.vmmenumigrate_items = {}

self.vmmenu_items["run"] = gtk.ImageMenuItem("_Run") self.vmmenu_items["run"].set_image(self.vmmenu_icons["run"]) @@ -198,9 +202,23 @@ class vmmManager(gobject.GObject):

self.vmmenushutdown_items["forcepoweroff"].connect("activate", self.destroy_vm)

self.vmmenushutdown.add(self.vmmenushutdown_items["forcepoweroff"])

- self.vmmenu_items["hsep"] = gtk.SeparatorMenuItem() - self.vmmenu_items["hsep"].show(); - self.vmmenu.add(self.vmmenu_items["hsep"]) + self.vmmenu_items["hsep1"] = gtk.SeparatorMenuItem() + self.vmmenu_items["hsep1"].show(); + self.vmmenu.add(self.vmmenu_items["hsep1"]) + + self.vmmenu_items["migrate"] = gtk.ImageMenuItem("_Migrate") + self.vmmenu_items["migrate"].set_submenu(self.vmmenumigrate) + self.vmmenu_items["migrate"].show() + self.vmmenu.add(self.vmmenu_items["migrate"]) + + self.vmmenumigrate_items["(None)"] = gtk.ImageMenuItem(_("(None)")) + self.vmmenumigrate_items["(None)"].show() + self.vmmenumigrate_items["(None)"].set_sensitive(False) + self.vmmenumigrate.add(self.vmmenumigrate_items["(None)"]) + + self.vmmenu_items["hsep2"] = gtk.SeparatorMenuItem() + self.vmmenu_items["hsep2"].show(); + self.vmmenu.add(self.vmmenu_items["hsep2"])

self.vmmenu_items["open"] = gtk.ImageMenuItem(gtk.STOCK_OPEN) self.vmmenu_items["open"].connect("activate", self.open_vm_console) @@ -698,6 +716,7 @@ class vmmManager(gobject.GObject): self.vmmenu_items["resume"].hide() self.vmmenu_items["resume"].set_sensitive(False) self.vmmenu_items["shutdown"].set_sensitive(False) + self.vmmenu_items["migrate"].set_sensitive(False) else: if vm.status() == libvirt.VIR_DOMAIN_SHUTOFF: self.vmmenu_items["run"].set_sensitive(True) @@ -706,6 +725,8 @@ class vmmManager(gobject.GObject): self.vmmenu_items["resume"].hide() self.vmmenu_items["resume"].set_sensitive(False)

self.vmmenu_items["shutdown"].set_sensitive(False) + self.vmmenu_items["migrate"].set_sensitive(True) + self.set_migrate_submenu() elif vm.status() == libvirt.VIR_DOMAIN_RUNNING: self.vmmenu_items["run"].set_sensitive(False) self.vmmenu_items["pause"].set_sensitive(True) @@ -713,6 +734,8 @@ class vmmManager(gobject.GObject): self.vmmenu_items["resume"].hide() self.vmmenu_items["resume"].set_sensitive(False) self.vmmenu_items["shutdown"].set_sensitive(True) + self.vmmenu_items["migrate"].set_sensitive(True) + self.set_migrate_submenu() elif vm.status() == libvirt.VIR_DOMAIN_PAUSED: self.vmmenu_items["run"].set_sensitive(False) self.vmmenu_items["pause"].hide() @@ -720,6 +743,8 @@ class vmmManager(gobject.GObject): self.vmmenu_items["resume"].show() self.vmmenu_items["resume"].set_sensitive(True) self.vmmenu_items["shutdown"].set_sensitive(True) + self.vmmenu_items["migrate"].set_sensitive(True) + self.set_migrate_submenu() self.vmmenu.popup(None, None, None, 0, event.time) return False else: @@ -1007,6 +1032,53 @@ class vmmManager(gobject.GObject): if vm is not None: self.emit("action-resume-domain", vm.get_connection().get_uri(), vm.get_uuid())

+ def migrate(self, ignore): + vm = self.current_vm() + # get selected submenu(destination hostname) + hostname = self.vmmenumigrate.get_active().get_image().get_stock()[0] + for key in self.engine.connections.keys(): + if self.engine.get_connection(key).get_hostname() == hostname: + host_uri = key + break + if vm is not None: + result = self.err.yes_no(_("%s is migrated from %s to %s, are you sure?") % \

Change "is migrated from" to "will be migrated from"

The rest looks fine.

Thanks, Cole