[et-mgmt-tools] [RFC]Re: [libvirt] [RFC][PATCH] virt-managercallsmigration API

Cole Robinson crobinso at redhat.com
Thu Oct 16 15:05:00 UTC 2008


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




More information about the et-mgmt-tools mailing list