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 _______________________________________________ et-mgmt-tools mailing list et-mgmt-tools@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/et-mgmt-tools