diff -r c44f1d969809 src/virtManager/details.py
--- a/src/virtManager/details.py	Wed Oct 22 16:53:28 2008 -0400
+++ b/src/virtManager/details.py	Fri Oct 24 14:45:26 2008 +0900
@@ -95,6 +95,8 @@ class vmmDetails(gobject.GObject):
                             gobject.TYPE_NONE, []),
         "action-view-manager": (gobject.SIGNAL_RUN_FIRST,
                                 gobject.TYPE_NONE, []),
+        "action-migrate-domain": (gobject.SIGNAL_RUN_FIRST,
+                                  gobject.TYPE_NONE, (str,str,str)),
         }
 
 
@@ -131,6 +133,13 @@ class vmmDetails(gobject.GObject):
         menu = gtk.Menu()
         self.window.get_widget("control-shutdown").set_menu(menu)
         
+        self.migrate_menu_items = {}
+
+        self.migrate_menu_items["(None)"] = gtk.ImageMenuItem(_("(None)"))
+        self.migrate_menu_items["(None)"].show()
+        self.migrate_menu_items["(None)"].set_sensitive(False)
+        self.window.get_widget("details-menu-migrate_menu").add(self.migrate_menu_items["(None)"])
+
         rebootimg = gtk.Image()
         rebootimg.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file_at_size(self.config.get_icon_dir() + "/icon_shutdown.png", 18, 18))
         shutdownimg = gtk.Image()
@@ -656,6 +665,32 @@ class vmmDetails(gobject.GObject):
     def control_vm_destroy(self, src):
         self.emit("action-destroy-domain", self.vm.get_connection().get_uri(), self.vm.get_uuid())
 
+    def control_vm_migrate(self, src):
+        # get selected submenu(destination hostname)
+        hostname = self.window.get_widget("details-menu-migrate_menu").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
+        self.emit("action-migrate-domain", self.vm.get_connection().get_uri(), self.vm.get_uuid(), host_uri)
+
+    def set_migrate_menu(self):
+        menu = self.window.get_widget("details-menu-migrate_menu")
+        # clear migrate-submenu
+        for submenu_item in menu.get_children():
+            submenu_item_name = submenu_item.get_image().get_stock()[0]
+            menu.remove(self.migrate_menu_items[submenu_item_name])
+
+        available_migrate_hostnames = self.engine.get_available_migrate_hostnames()
+        if len(available_migrate_hostnames) == 0:
+            menu.add(self.migrate_menu_items["(None)"])
+        else:
+            for hostname in available_migrate_hostnames.values():
+                self.migrate_menu_items[hostname] = gtk.ImageMenuItem(hostname)
+                self.migrate_menu_items[hostname].show()
+                self.migrate_menu_items[hostname].connect("activate", self.control_vm_migrate)
+                menu.add(self.migrate_menu_items[hostname])
+
     def set_pause_widget_states(self, state):
         try:
             self.ignorePause = True
@@ -701,6 +736,13 @@ class vmmDetails(gobject.GObject):
             self.window.get_widget("control-shutdown").set_sensitive(True)
             self.window.get_widget("details-menu-shutdown").set_sensitive(True)
             self.window.get_widget("details-menu-save").set_sensitive(True)
+
+        # Currently, the condition that "Migrate" become insensitive is only "readonly".
+        if vm.is_read_only():
+            self.window.get_widget("details-menu-migrate").set_sensitive(False)
+        else:
+            self.window.get_widget("details-menu-migrate").set_sensitive(True)
+            self.set_migrate_menu()
 
         if status in [ libvirt.VIR_DOMAIN_SHUTOFF ,libvirt.VIR_DOMAIN_CRASHED ]:
             if self.window.get_widget("console-pages").get_current_page() != PAGE_UNAVAILABLE:
diff -r c44f1d969809 src/virtManager/domain.py
--- a/src/virtManager/domain.py	Wed Oct 22 16:53:28 2008 -0400
+++ b/src/virtManager/domain.py	Fri Oct 24 14:45:26 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 c44f1d969809 src/virtManager/engine.py
--- a/src/virtManager/engine.py	Wed Oct 22 16:53:28 2008 -0400
+++ b/src/virtManager/engine.py	Fri Oct 24 14:45:26 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()
 
@@ -279,6 +281,7 @@ class vmmEngine(gobject.GObject):
                 details.connect("action-reboot-domain", self._do_reboot_domain)
                 details.connect("action-exit-app", self._do_exit_app)
                 details.connect("action-view-manager", self._do_show_manager)
+                details.connect("action-migrate-domain", self._do_migrate_domain)
 
             except Exception, e:
                 self.err.show_err(_("Error bringing up domain details: %s") % str(e),
@@ -296,6 +299,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 +532,64 @@ 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)
+        resp = self.err.yes_no(_("%s will be migrated from %s to %s, are you sure?") % \
+                    (vm.get_name(), conn.get_hostname(), destconn.get_hostname()))
+        if resp:
+            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 will be migrated from %s to %s." % \
+                                            (vmname, hostname, desthostname)))
+        migrate_progress.set_title(" ")
+        return migrate_progress
+
+    def get_available_migrate_hostnames(self):
+        hostname = self.windowManager.current_connection().get_hostname()
+        driver = self.windowManager.current_connection().get_driver()
+        available_migrate_hostnames = {}
+
+        # 1. connected(ACTIVE, INACTIVE) host
+        for key in self.connections.keys():
+            if self.connections[key].has_key("connection") is True \
+            and (self.get_connection(key).get_state() == vmmConnection.STATE_ACTIVE or self.get_connection(key).get_state() == vmmConnection.STATE_INACTIVE):
+                available_migrate_hostnames[key] = self.get_connection(key).get_hostname()
+
+        # 2. remove source host
+        for key in available_migrate_hostnames.keys():
+            if available_migrate_hostnames[key] == hostname:
+                del available_migrate_hostnames[key]
+
+        # 3. remove a different host of hypervisor
+        for key in available_migrate_hostnames.keys():
+            if self.get_connection(key).get_driver() != driver:
+                del available_migrate_hostnames[key]
+
+        return available_migrate_hostnames
 
 
 gobject.type_register(vmmEngine)
diff -r c44f1d969809 src/virtManager/manager.py
--- a/src/virtManager/manager.py	Wed Oct 22 16:53:28 2008 -0400
+++ b/src/virtManager/manager.py	Fri Oct 24 14:45:26 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,33 @@ 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:
+            self.emit("action-migrate-domain", vm.get_connection().get_uri(), vm.get_uuid(), host_uri)
+
+    def set_migrate_submenu(self):
+        # clear migrate-submenu
+        for submenu_item in self.vmmenumigrate.get_children():
+            submenu_item_name = submenu_item.get_image().get_stock()[0]
+            self.vmmenumigrate.remove(self.vmmenumigrate_items[submenu_item_name])
+
+        available_migrate_hostnames = self.engine.get_available_migrate_hostnames()
+        if len(available_migrate_hostnames) == 0:
+            self.vmmenumigrate.add(self.vmmenumigrate_items["(None)"])
+        else:
+            for hostname in available_migrate_hostnames.values():
+                self.vmmenumigrate_items[hostname] = gtk.ImageMenuItem(hostname)
+                self.vmmenumigrate_items[hostname].show()
+                self.vmmenumigrate_items[hostname].connect("activate", self.migrate)
+                self.vmmenumigrate.add(self.vmmenumigrate_items[hostname])
+
     def _add_connection(self, engine, conn):
         conn.connect("vm-added", self.vm_added)
         conn.connect("vm-removed", self.vm_removed)
diff -r c44f1d969809 src/vmm-details.glade
--- a/src/vmm-details.glade	Wed Oct 22 16:53:28 2008 -0400
+++ b/src/vmm-details.glade	Fri Oct 24 14:45:26 2008 +0900
@@ -162,6 +162,27 @@
 
 		  <child>
 		    <widget class="GtkSeparatorMenuItem" id="separator11">
+		      <property name="visible">True</property>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkMenuItem" id="details-menu-migrate">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">_Migrate</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="on_details_menu_migrate_activate"/>
+
+		      <child>
+			<widget class="GtkMenu" id="details-menu-migrate_menu">
+
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkSeparatorMenuItem" id="separator12">
 		      <property name="visible">True</property>
 		    </widget>
 		  </child>
