This patch adds a migrate() function for libvirt, which is a encapsulation for 
"virsh migrate" command.

Signed-off-by: Tang Chen <tangc...@cn.fujitsu.com>
---
 client/virt/libvirt_vm.py |  212 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 212 insertions(+), 0 deletions(-)

diff --git a/client/virt/libvirt_vm.py b/client/virt/libvirt_vm.py
index c825661..773e170 100644
--- a/client/virt/libvirt_vm.py
+++ b/client/virt/libvirt_vm.py
@@ -293,6 +293,36 @@ def virsh_domain_exists(name, uri = ""):
         logging.warning("VM %s does not exist", name)
         return False
 
+def virsh_migrate(name, migrate_cmd, params = None, uri = ""):
+    """
+    Migrate a guest to another host.
+
+    @params name: VM name
+    @params migrate_cmd: Migrate command to be executed
+    @param params: A dict containing VM params
+    """
+    uri_arg = ""
+    if uri:
+        uri_arg = "-c " + uri
+    destpwd = params.get("destpwd")
+    destuser = params.get("destuser")
+    try:
+        cmd = "virsh %s %s" % (uri_arg, migrate_cmd)
+        session = aexpect.ShellSession(cmd, linesep="\n")
+        virt_utils._remote_login(session, destuser, destpwd, "", timeout=60)
+        return True
+    # If migration succeeds, migrate command will terminate the session 
+    # automically. So we have to catch the LoginProcessTerminatedError.
+    except virt_utils.LoginProcessTerminatedError, e:
+        logging.info("%s", e)
+        session.close()
+        if str(e).find("status: 0") >= 0:
+            return True
+        else:
+            return False
+    except error.CmdError:
+        logging.error("Migrating VM %s failed", name)
+        return False
 
 class VM(virt_vm.BaseVM):
     """
@@ -978,6 +1008,188 @@ class VM(virt_vm.BaseVM):
             fcntl.lockf(lockfile, fcntl.LOCK_UN)
             lockfile.close()
 
+    def __make_migrate_command(self, name=None, params=None):
+        """
+        Generate a migrate command line.
+
+        @param name: The name of the object
+        @param params: A dict containing VM params
+
+        @note: The params dict should contain:
+               live -- yes/no
+               method -- direct/p2p/p2p_tunnelled
+               persistent -- yes/no
+               undefinesource -- yes/no
+               suspend -- yes/no
+               copy-storage -- all/inc
+               change-protection -- yes/no
+               verbose -- /yes/no
+               domain -- VM name
+               desturi -- Destination URI
+               migrateuri -- Migration URI
+               dname -- VM name on destination
+               timeout -- timeout > 0
+               xml -- Path to xml file to be used on destination
+        """
+        def add_live():
+            return " --live"
+
+        def add_method(method):
+            if method == "direct":
+                return " --direct"
+            elif method == "p2p":
+                return " --p2p"
+            # Cannot use --tunnelled without --p2p.
+            elif method == "p2p_tunnelled":
+                return " --p2p --tunnelled"
+            else:
+                logging.warning("Unknown migrate method, using default.")
+                return ""
+
+        def add_persistent():
+            return " --persistent"
+
+        def add_undefinesource():
+            return " --undefinesource"
+
+        def add_suspend():
+            return " --suspend"
+
+        def add_copy_storage(copy_storage_mode):
+            if copy_storage_mode == "all":
+                return " --copy-storage-all"
+            elif copy_storage_mode == "inc":
+                return " --copy-storage-inc"
+            else:
+                logging.warning("Unknown copy storage mode, using default.")
+                return ""
+
+        def add_change_protection():
+            return " --change-protection"
+
+        def add_verbose():
+            return " --verbose"
+
+        # Domain name must be specified.
+        def add_domain(domain_name):
+            if virsh_domain_exists(domain_name):
+                return " --domain %s" % domain_name
+            else:
+                raise virt_vm.VMMigrateError("Wrong domain name.")
+
+        # Destination uri must be specified.
+        def add_desturi(desturi):
+            if desturi:
+                return " --desturi %s" % desturi
+            else:
+                raise virt_vm.VMMigrateError("Wrong destination uri.")
+
+        def add_migrateuri(migrateuri):
+            if migrateuri:
+                return " --migrateuri %s" % migrateuri
+            else:
+                return ""
+
+        def add_dname(dname):
+            if dname:
+                return " --dname %s" % dname
+            else:
+                return ""
+
+        def add_timeout(timeout):
+            if int(timeout) > 0:
+                return " --timeout %s" % timeout
+            else:
+                logging.warning("Invalid timeout value. Ingoring it.")
+                return ""
+
+        def add_xml(xml_file):
+            if os.path.isfile(xml_file):
+                return " --xml %s" % xml_file
+            else:
+                logging.warning("%s: No such xml file is found. Ingoring it.", 
xml_file)
+                return ""
+
+        migrate_cmd = "migrate "
+
+        if name is None:
+            name = self.name
+        if params is None:
+            params = self.params
+
+        live = params.get("live")
+        if live == "yes":
+            migrate_cmd += add_live()
+
+        method = params.get("method")
+        if method:
+            migrate_cmd += add_method(method)
+
+        persistent = params.get("persistent")
+        if persistent == "yes":
+            migrate_cmd += add_persistent()
+
+        undefinesource = params.get("undefinesource")
+        if undefinesource == "yes":
+            migrate_cmd += add_undefinesource()
+
+        suspend = params.get("suspend")
+        if suspend == "yes":
+            migrate_cmd += add_suspend()
+
+        copy_storage_mode = params.get("copy_storage_mode")
+        if copy_storage_mode:
+            migrate_cmd += add_copy_storage(copy_storage_mode)
+
+        change_protection = params.get("change_protection")
+        if change_protection == "yes":
+            migrate_cmd += add_change_protection()
+
+        verbose = params.get("verbose")
+        if verbose == "yes":
+            migrate_cmd += add_verbose()
+
+        # --domain and --desturi must be specified.
+        domain_name = params.get("main_vm")
+        if domain_name:
+            migrate_cmd += add_domain(domain_name)
+
+        desturi = params.get("desturi")
+        if desturi:
+            migrate_cmd += add_desturi(desturi)
+
+        migrateuri = params.get("migrateuri")
+        if migrateuri:
+            migrate_cmd += add_migrateuri(migrateuri)
+
+        dname = params.get("dname")
+        if dname:
+            migrate_cmd += add_dname(dname)
+
+        timeout = params.get("timeout")
+        if timeout:
+            migrate_cmd += add_timeout(timeout)
+
+        xml_file = params.get("xml_file")
+        if xml_file:
+            migrate_cmd += add_xml(xml_file)
+
+        logging.info("Migrate command: %s" % migrate_cmd)
+        return migrate_cmd
+
+    def migrate(self, name=None):
+        """
+        Migrate a VM to a remote host.
+        """
+        migrate_cmd = ""
+
+        migrate_cmd = self.__make_migrate_command(name, self.params)
+
+        ret = virsh_migrate(self.name, migrate_cmd, self.params, 
self.connect_uri)
+        if ret == True:
+            return True
+        else:
+            return False
 
     def destroy(self, gracefully=True, free_mac_addresses=True):
         """
-- 
1.7.3.1



-- 
Best Regards,
Tang chen
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to