[Ovirt-devel] [PATCH 2/2] Enables users to migrate virtual machines between hosts.

Darryl L. Pierce dpierce at redhat.com
Fri Dec 4 21:03:45 UTC 2009


Users select a virtual machine on their current libvirt host. They then
select a target machine, which must have been previously configured as a
connection. They confirm the migration and then it runs.
---
 Makefile.am                |    1 +
 nodeadmin/addhost.py       |   10 ++++-
 nodeadmin/libvirtworker.py |    6 +++
 nodeadmin/migratedomain.py |   81 ++++++++++++++++++++++++++++++++++++++++++++
 nodeadmin/nodemenu.py      |   28 +++++++++------
 nodeadmin/setup.py.in      |    1 +
 ovirt-node.spec.in         |    2 +
 7 files changed, 115 insertions(+), 14 deletions(-)
 create mode 100644 nodeadmin/migratedomain.py

diff --git a/Makefile.am b/Makefile.am
index e673aa4..c044d78 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -48,6 +48,7 @@ EXTRA_DIST =			\
   nodeadmin/listpools.py        \
   nodeadmin/mainmenu.py         \
   nodeadmin/menuscreen.py       \
+  nodeadmin/migratedomain.py    \
   nodeadmin/networkconfig.py    \
   nodeadmin/netmenu.py          \
   nodeadmin/nodeadmin.py        \
diff --git a/nodeadmin/addhost.py b/nodeadmin/addhost.py
index ef35b7d..ebcb4ea 100644
--- a/nodeadmin/addhost.py
+++ b/nodeadmin/addhost.py
@@ -59,7 +59,9 @@ class AddHostConfigScreen(ConfigScreen):
 
     def validate_input(self, page, errors):
         if page is DETAILS_PAGE:
-            if len(self.__hostname.value()) > 0:
+            if self.__connection.getSelection() is CONNECTION_LOCAL:
+                return True
+            elif len(self.__hostname.value()) > 0:
                 return True
             else:
                 errors.append("You must enter a remote hostname.")
@@ -115,8 +117,12 @@ class AddHostConfigScreen(ConfigScreen):
         grid.setField(Label(HYPERVISORS[self.__hypervisor.getSelection()]), 1, 0, anchorLeft = 1)
         grid.setField(Label("Connection:"), 0, 1, anchorRight = 1)
         grid.setField(Label(CONNECTIONS[self.__connection.getSelection()]), 1, 1, anchorLeft = 1)
+        if self.__connection.getSelection() is not CONNECTION_LOCAL:
+            hostname = self.__hostname.value()
+        else:
+            hostname = "local"
         grid.setField(Label("Hostname:"), 0, 2, anchorRight = 1)
-        grid.setField(Label(self.__hostname.value()), 1, 2, anchorLeft = 1)
+        grid.setField(Label(hostname), 1, 2, anchorLeft = 1)
         grid.setField(Label("Autoconnect on Startup:"), 0, 3, anchorRight = 1)
         label = "Yes"
         if not self.__autoconnect.value(): label = "No"
diff --git a/nodeadmin/libvirtworker.py b/nodeadmin/libvirtworker.py
index 15d1c58..b35509f 100644
--- a/nodeadmin/libvirtworker.py
+++ b/nodeadmin/libvirtworker.py
@@ -126,6 +126,12 @@ class LibvirtWorker:
         domain = self.get_domain(name)
         domain.undefine()
 
+    def migrate_domain(self, name, target):
+        '''Migrates the specified domain to the target machine.'''
+        target_conn = libvirt.open(target)
+        virtmachine = self.get_domain(name)
+        virtmachine.migrate(target_conn, libvirt.VIR_MIGRATE_LIVE, None, None, 0)
+
     def list_networks(self, defined = True, started = True):
         '''Lists all networks.'''
         result = []
diff --git a/nodeadmin/migratedomain.py b/nodeadmin/migratedomain.py
new file mode 100644
index 0000000..8c8c268
--- /dev/null
+++ b/nodeadmin/migratedomain.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+#
+# migratedomain.py - Copyright (C) 2009 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.  A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+from snack import *
+from libvirtworker import LibvirtWorker
+from configscreen import *
+
+LIST_DOMAINS  = 1
+SELECT_TARGET = 2
+CONFIRM_PAGE  = 3
+
+class MigrateDomainConfigScreen(DomainListConfigScreen):
+    def __init__(self):
+        DomainListConfigScreen.__init__(self, "Migrate Virtual Machine")
+        self.__configured = False
+
+    def get_elements_for_page(self, screen, page):
+        if   page is LIST_DOMAINS:  return self.get_domain_list_page(screen)
+        elif page is SELECT_TARGET: return self.get_target_page(screen)
+        elif page is CONFIRM_PAGE:  return self.get_confirm_page(screen)
+
+    def page_has_next(self, page):
+        if   page is LIST_DOMAINS: return self.has_selectable_domains()
+        else: return page < CONFIRM_PAGE
+
+    def page_has_back(self, page):
+        return page < CONFIRM_PAGE
+
+    def page_has_finish(self, page):
+        return page is CONFIRM_PAGE
+
+    def validate_input(self, page, errors):
+        if   page is LIST_DOMAINS: return self.get_selected_domain() is not None
+        elif page is SELECT_TARGET:
+            if self.__targets.current() is None:
+                errors.append("Please enter a target hostname or IP address.")
+                return False
+        elif page is CONFIRM_PAGE:
+            if not self.__confirm.value():
+                errors.append("You must confirm migrating this virtual machine to proceed.")
+                return False
+        return True
+
+    def process_input(self, page):
+        if page is CONFIRM_PAGE:
+            self.get_libvirt().migrate_domain(self.get_selected_domain(), self.__targets.current())
+            self.set_finished()
+
+    def get_target_page(self, screen):
+        self.__targets = Listbox(0)
+        for connection in self.get_virt_manager_config().get_connection_list():
+            self.__targets.append(connection, connection)
+        return [Label("Select A Target Host"),
+                self.__targets]
+
+    def get_confirm_page(self, screen):
+        self.__confirm = Checkbox("Confirm migrating this virtual machine.")
+        grid = Grid(1, 1)
+        grid.setField(self.__confirm, 0, 0)
+        return [grid]
+
+def MigrateDomain():
+    screen = MigrateDomainConfigScreen()
+    screen.start()
diff --git a/nodeadmin/nodemenu.py b/nodeadmin/nodemenu.py
index 16be89c..f213e09 100755
--- a/nodeadmin/nodemenu.py
+++ b/nodeadmin/nodemenu.py
@@ -26,17 +26,19 @@ from startdomain    import StartDomain
 from stopdomain     import StopDomain
 from removedomain   import RemoveDomain
 from listdomains    import ListDomains
+from migratedomain  import MigrateDomain
 from createuser     import CreateUser
 
 import utils
 import logging
 
-ADD_DOMAIN    = 1
-START_DOMAIN = 2
-STOP_DOMAIN   = 3
-REMOVE_DOMAIN = 4
-LIST_DOMAINS  = 5
-CREATE_USER   = 6
+ADD_DOMAIN     = 1
+START_DOMAIN   = 2
+STOP_DOMAIN    = 3
+REMOVE_DOMAIN  = 4
+LIST_DOMAINS   = 5
+MIGRATE_DOMAIN = 6
+CREATE_USER    = 7
 
 class NodeMenuScreen(MenuScreen):
     def __init__(self):
@@ -48,15 +50,17 @@ class NodeMenuScreen(MenuScreen):
                 ("Stop A Virtual Machine",    STOP_DOMAIN),
                 ("Remove A Virtual Machine",  REMOVE_DOMAIN),
                 ("List All Virtual Machines", LIST_DOMAINS),
+                ("Migrate Virtual Machine",   MIGRATE_DOMAIN),
                 ("Create A User",             CREATE_USER))
 
     def handle_selection(self, item):
-            if   item is ADD_DOMAIN:    AddDomain()
-            elif item is START_DOMAIN:  StartDomain()
-            elif item is STOP_DOMAIN:   StopDomain()
-            elif item is REMOVE_DOMAIN: RemoveDomain()
-            elif item is LIST_DOMAINS:  ListDomains()
-            elif item is CREATE_USER:   CreateUser()
+            if   item is ADD_DOMAIN:     AddDomain()
+            elif item is START_DOMAIN:   StartDomain()
+            elif item is STOP_DOMAIN:    StopDomain()
+            elif item is REMOVE_DOMAIN:  RemoveDomain()
+            elif item is LIST_DOMAINS:   ListDomains()
+            elif item is MIGRATE_DOMAIN: MigrateDomain()
+            elif item is CREATE_USER:    CreateUser()
 
 def NodeMenu():
     screen = NodeMenuScreen()
diff --git a/nodeadmin/setup.py.in b/nodeadmin/setup.py.in
index 17bfe93..0a95dcc 100644
--- a/nodeadmin/setup.py.in
+++ b/nodeadmin/setup.py.in
@@ -29,6 +29,7 @@ setup(name = "nodeadmin",
             'startvm     = nodeadmin.startdomain:StartDomain',
             'stopvm      = nodeadmin.stopdomain:StopDomain',
             'rmvm        = nodeadmin.removedomain:RemoveDomain',
+            'migratevm   = nodeadmin.migratedomain:MigradeDomain',
             'createuser  = nodeadmin.createuser:CreateUser',
             'listvms     = nodeadmin.listdomains:ListDomains',
             'definenet   = nodeadmin.definenet:DefineNetwork',
diff --git a/ovirt-node.spec.in b/ovirt-node.spec.in
index f056f3f..8815b1c 100644
--- a/ovirt-node.spec.in
+++ b/ovirt-node.spec.in
@@ -187,6 +187,7 @@ cd -
 %{__install} -p -m0755 nodeadmin/adddomain.py %{buildroot}%{python_sitelib}/nodeadmin
 %{__install} -p -m0644 nodeadmin/domainconfig.py %{buildroot}%{python_sitelib}/nodeadmin
 %{__install} -p -m0755 nodeadmin/listdomains.py %{buildroot}%{python_sitelib}/nodeadmin
+%{__install} -p -m0755 nodeadmin/migratedomain.py %{buildroot}%{python_sitelib}/nodeadmin
 %{__install} -p -m0755 nodeadmin/removedomain.py %{buildroot}%{python_sitelib}/nodeadmin
 %{__install} -p -m0755 nodeadmin/startdomain.py %{buildroot}%{python_sitelib}/nodeadmin
 %{__install} -p -m0755 nodeadmin/stopdomain.py %{buildroot}%{python_sitelib}/nodeadmin
@@ -383,6 +384,7 @@ fi
 %{_bindir}/stopvm
 %{_bindir}/rmvm
 %{_bindir}/listpools
+%{_bindir}/migratevm
 %{_bindir}/listvms
 %{_bindir}/rmpool
 %{_bindir}/rmvolume
-- 
1.6.5.2




More information about the ovirt-devel mailing list