[Libvirt-cim] [PATCH] (#2) Add a migration_tester.py tool

Kaitlin Rupert kaitlin at linux.vnet.ibm.com
Tue Feb 3 18:51:08 UTC 2009


# HG changeset patch
# User Kaitlin Rupert <karupert at us.ibm.com>
# Date 1232519221 28800
# Node ID 61209742da1d511a4b453d38432c2eeb35639a83
# Parent  189cc68a2f5a3251be1204bdaddfd90bb8740789
(#2) Add a migration_tester.py tool.

This can be used to drive migration between two different hosts.

How to call the tester:

python tools/migration_tester.py -u root -p pass -s fqdn:port -t fqdn -v virt_type guest_name --migration-type type

Ex:
python tools/migration_tester.py -u root -p pass -s source.myhost.com:5988 -t target.myhost.com -v Xen my_guest --migration-type live

Updates:
  -Added comment at the beginning of the tool that describes the usage
  -Improved the descriptions for username and password for the OptionParser
  -Fixed some errors in the usage description in the commit log

Signed-off-by: Kaitlin Rupert <karupert at us.ibm.com>

diff -r 189cc68a2f5a -r 61209742da1d tools/migration_tester.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/migration_tester.py	Tue Jan 20 22:27:01 2009 -0800
@@ -0,0 +1,310 @@
+#!/usr/bin/python
+#
+# Copyright IBM Corp. 2009
+#
+# Authors:
+#    Kaitlin Rupert <karupert at us.ibm.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+#
+# Usage:  python tools/migration_tester.py -u root -p pass 
+#          -s source.myhost.com:5988 -t target.myhost.com -v Xen guest 
+#          --migration-type live 
+#
+# Note:  Be sure you can authenticate via ssh into the target machine prior 
+#        to running the test.
+#
+#        You can set up ssh keys, or you will be prompted for the password 
+#        of the target machine
+
+import sys
+import time
+from optparse import OptionParser
+from pywbem import WBEMConnection, CIMInstanceName, CIMInstance, CIMError
+
+CIM_MIGRATE_OTHER=1
+CIM_MIGRATE_LIVE=2
+CIM_MIGRATE_RESUME=3
+CIM_MIGRATE_RESTART=4
+
+CIM_MIGRATE_URI_OTHER=1
+CIM_MIGRATE_URI_SSH=2
+CIM_MIGRATE_URI_TLS=3
+CIM_MIGRATE_URI_TLS_STRICT=4
+CIM_MIGRATE_URI_TCP=5
+CIM_MIGRATE_URI_UNIX=6
+
+CIM_JOBSTATE_COMPLETE=7
+
+class CIMClassMOF:
+
+    __supported_types = [int, str, bool]
+
+    def __init__(self, attrs = None):
+        """attrs should be dict
+        """
+
+        if attrs != None:
+            self.__dict__.update(attrs)
+
+    def mof(self):
+        """mof()
+
+        Return value is a string, containing the mof representation of the 
+        object.
+
+        Attribute types supported are : int, str, bool.
+
+        Attributes with unsupported types will be silently ignored when 
+        converting to mof representation.
+        """
+
+        mof_str = "instance of " + self.__class__.__name__ + " {\n"
+        for key, value in self.__dict__.items():
+            value_type = type(value)
+            if value_type not in self.__supported_types:
+                continue
+
+            mof_str += "%s = " % key
+            if value_type == int:
+                mof_str += "%d" % value
+            elif value_type == bool:
+                mof_str += str(value).lower()
+            else:
+                mof_str += '"%s"' % value
+            mof_str += ";\n"
+
+        mof_str += "};"
+        return mof_str
+
+    def __str__(self):
+        return self.mof()
+
+class CIM_VirtualSystemMigrationSettingData(CIMClassMOF):
+    def __init__(self, type, priority):
+        self.InstanceID = 'MigrationSettingData'
+        self.CreationClassName = self.__class__.__name__
+        self.MigrationType = type
+        self.Priority = priority
+
+class Xen_VirtualSystemMigrationSettingData(CIM_VirtualSystemMigrationSettingData):
+    def __init__(self, type, priority):
+        CIM_VirtualSystemMigrationSettingData.__init__(self, type, priority)
+
+class KVM_VirtualSystemMigrationSettingData(CIM_VirtualSystemMigrationSettingData):
+    def __init__(self, type, priority):
+        CIM_VirtualSystemMigrationSettingData.__init__(self, type, priority)
+
+def get_guest_ref(guest, virt):
+    guest_cn = "%s_ComputerSystem" % virt
+
+    keys = { 'Name' : guest,
+             'CreationClassName' : guest_cn
+           } 
+
+    try:
+        cs_ref = CIMInstanceName(guest_cn, keybindings=keys) 
+
+    except CIMError, (err_no, desc):
+        print err_no, desc
+        return None
+
+    return cs_ref
+
+def get_msd(mtype, virt):
+    if mtype == "live":
+        mtype = CIM_MIGRATE_LIVE
+    elif mtype == "resume":
+        mtype = CIM_MIGRATE_RESUME
+    elif mtype == "restart":
+        mtype = CIM_MIGRATE_RESTART
+    else:
+        mtype = CIM_MIGRATE_OTHER
+
+    try:
+        vsmsd_cn_base = "_VirtualSystemMigrationSettingData"
+        msd = eval(virt + vsmsd_cn_base)(type=mtype, priority=0)
+
+    except CIMError, (err_no, desc):
+        print err_no, desc
+        return None
+
+    return msd.mof()
+
+def check_migrate(s_conn, cs_ref, ip, msd, virt):
+    vsms_cn = "%s_VirtualSystemMigrationService" % virt
+    try:
+        if msd == None:
+            res = s_conn.InvokeMethod("CheckVirtualSystemIsMigratableToHost",
+                                      vsms_cn,
+                                      ComputerSystem=cs_ref,
+                                      DestinationHost=ip)
+        else:
+            res = s_conn.InvokeMethod("CheckVirtualSystemIsMigratableToHost",
+                                      vsms_cn,
+                                      ComputerSystem=cs_ref,
+                                      DestinationHost=ip,
+                                      MigrationSettingData=msd)
+
+        if res == None or res[1]['IsMigratable'] != True:
+            print "Migration check failed."
+            return 1
+
+    except CIMError, (err_no, desc):
+        print err_no, desc
+        return 1
+
+    return 0 
+
+def get_job_inst(s_conn, job_ref):
+    try:
+        inst = s_conn.GetInstance(job_ref) 
+
+    except CIMError, (err_no, desc):
+        print err_no, desc
+        return None
+
+    return inst
+
+def poll_for_job_status(s_conn, job_ref):
+
+    job_inst = get_job_inst(s_conn, job_ref)
+    if not job_inst:
+        print "Unable to get job instance" 
+        return 1
+
+    try:
+        while job_inst['JobState'] != CIM_JOBSTATE_COMPLETE:
+            time.sleep(3)
+            job_inst = get_job_inst(s_conn, job_ref)
+            if not job_inst:
+                print "Unable to get job instance" 
+                return 1
+            
+        if job_inst['Status'] != "Completed":
+            print "Migrate job failed: %s" % job_inst['Status']
+            return 1 
+    except KeyboardInterrupt:
+        print "Migrate job took too long"
+        return 1 
+
+    print "Migrate job succeeded: %s" % job_inst['Status']
+    return 0
+
+def migrate_host(s_conn, cs_ref, dest, msd, virt):
+    vsms_cn = "%s_VirtualSystemMigrationService" % virt
+
+    try:
+        if msd == None:
+            job = s_conn.InvokeMethod("MigrateVirtualSystemToHost",
+                                      vsms_cn,
+                                      ComputerSystem=cs_ref,
+                                      DestinationHost=dest)
+        else:
+            job = s_conn.InvokeMethod("MigrateVirtualSystemToHost",
+                                      vsms_cn,
+                                      ComputerSystem=cs_ref,
+                                      DestinationHost=dest,
+                                      MigrationSettingData=msd)
+
+        if len(job) < 1:
+            print "No job returned from migrate call" 
+            return 1
+
+        status = poll_for_job_status(s_conn, job[1]['Job'])
+
+    except CIMError, (err_no, desc):
+        print err_no, desc
+        return 1
+
+    return 0 
+
+def main():
+    usage = "usage: %prog [options] <target system>\nex: %prog my.target.com"
+    parser = OptionParser(usage)
+
+    parser.add_option("-s", "--src-url", dest="s_url", default="localhost:5988",
+                      help="URL of CIMOM to connect to (host:port)")
+    parser.add_option("-t", "--target-url", dest="t_url", 
+                      default="localhost:5988",
+                      help="URL of CIMOM to connect to (host:port)")
+    parser.add_option("-N", "--ns", dest="ns", default="root/virt",
+                      help="Namespace (default is root/virt)")
+    parser.add_option("-u", "--user", dest="username", default=None,
+                      help="Auth username for CIMOM on source system")
+    parser.add_option("-p", "--pass", dest="password", default=None,
+                      help="Auth password for CIMOM on source system")
+    parser.add_option("-v", "--virt-type", dest="virt", default=None,
+                      help="Virtualization type [ Xen | KVM ]")
+    parser.add_option("--migration-type", dest="type", default=None,
+                      help="Migration type: [ live | resume | restart ]")
+    parser.add_option("--disable-check", dest="disable_ck", action="store_true",
+                      help="Disable migration pre-check")
+
+    (options, args) = parser.parse_args()
+
+    if len(args) == 0:
+        print "Fatal: no guest specified."
+        sys.exit(1)
+
+    guest_name = args[0]
+
+    if ":" in options.s_url:
+        (sysname, port) = options.s_url.split(":")
+    else:
+        sysname = options.s_url
+
+    if ":" in options.t_url:
+        (t_sysname, port) = options.t_url.split(":")
+    else:
+        t_sysname = options.t_url
+
+    src_conn = WBEMConnection('http://%s' % sysname, 
+                              (options.username, options.password), options.ns)
+
+    guest_ref = get_guest_ref(guest_name, options.virt)
+    if guest_ref == None:
+        return 1
+
+    if options.virt == None:
+        print "Must specify virtualization type"
+        return 1
+
+    if options.virt != "Xen":
+        print "Only Xen migration is currently supported"
+        return 1
+
+    if options.type != None:
+        msd = get_msd(options.type, options.virt)
+        if msd == None:
+            return 1
+    else:
+        print "Using default MigrationSettingData"
+        msd = None
+
+    if not options.disable_ck:
+        status = check_migrate(src_conn, guest_ref, t_sysname, msd, 
+                               options.virt)
+        if status == 1:
+            return 1
+
+    print "Migrating %s.. this will take some time." % guest_name
+    status = migrate_host(src_conn, guest_ref, t_sysname, msd, options.virt)
+    return status
+
+if __name__=="__main__":
+    sys.exit(main())
+
+




More information about the Libvirt-cim mailing list