Hi Michael and Lucas,
Would you please give me some comments/suggestions based on
my initial design of it? Thanks in advance. :)
============ KVM server-side migration design =================
1 for generating migration test dicts, two methods:
1.1 use existent framework of kvm client test
1.2 new a script named kvm_migration.py under dir kvm, initial version could be:
kvm_migration.py
--------
import sys, os, time, logging, commands
from autotest_lib.client.bin import test
from autotest_lib.client.common_lib import error
import kvm_utils, kvm_preprocessing, common, kvm_vm, kvm_test_utils
class kvm_migration(test.test):
"""
KVM migration test.
@copyright: Red Hat 2008-2009
@see: http://www.linux-kvm.org/page/KVM-Autotest/Client_Install
(Online doc - Getting started with KVM testing)
"""
version = 1
def initialize(self):
pass
def setup(self):
"""
Setup environment like NFS mount etc.
"""
pass
def run_once(self, params):
"""
Setup remote machine and then execute migration.
"""
# Check whether remote machine is ready
dsthost = params.get("dsthost")
srchost = params.get("srchost")
image_path = os.path.join(self.bindir, "images")
rootdir = params.get("rootdir")
iso = os.path.join(rootdir, 'iso')
images = os.path.join(rootdir, 'images')
qemu = os.path.join(rootdir, 'qemu')
qemu_img = os.path.join(rootdir, 'qemu-img')
def link_if_not_exist(ldir, target, link_name):
t = target
l = os.path.join(ldir, link_name)
if not os.path.exists(l):
os.symlink(t,l)
link_if_not_exist(self.bindir, '../../', 'autotest')
link_if_not_exist(self.bindir, iso, 'isos')
link_if_not_exist(self.bindir, images, 'images')
link_if_not_exist(self.bindir, qemu, 'qemu')
link_if_not_exist(self.bindir, qemu_img, 'qemu-img')
try:
image_real_path = os.readlink(image_path)
except OSError:
raise error.TestError("Readlink of image dir failed")
def setup_dest(srchost, path):
"""
Mount NFS directory from source host.
"""
cmd = "mount |grep -q %s" % srchost
if os.system(cmd):
mnt_cmd = "mount %s:%s %s" % (srchost,
path,
path)
s, o = commands.getstatusoutput(mnt_cmd)
if s != 0:
raise error.TestError("Mount srchost failed: %s" % o)
def setup_source(path):
"""
Setup NFS mount point.
"""
export_string = "%s *(rw,no_root_squash)" % path
export_file = '/etc/exports'
f = open(export_file)
if not export_string in f.read().strip():
try:
f.write(export_string)
except IOError:
raise error.TestError("Failed to write to exports file")
cmd = "service nfs restart && exportfs -a"
if os.system(cmd):
raise error.TestError("Failed to restart NFS on source")
if params.get("role") == "dest":
setup_dest(srchost, image_real_path)
elif params.get("role") == "source":
setup_source(image_real_path)
# Report the parameters we've received and write them as keyvals
logging.debug("Test parameters:")
keys = params.keys()
keys.sort()
for key in keys:
logging.debug(" %s = %s", key, params[key])
self.write_test_keyval({key: params[key]})
# Open the environment file
env_filename = os.path.join(self.bindir, params.get("env", "env"))
env = kvm_utils.load_env(env_filename, {})
logging.debug("Contents of environment: %s" % str(env))
# Preprocess
kvm_preprocessing.preprocess(self, params, env)
kvm_utils.dump_env(env, env_filename)
try:
try:
# Get the living VM
vm = kvm_test_utils.get_living_vm(env, params.get("main_vm"))
if params.get("role") == "source":
s, o = vm.send_monitor_cmd("help info")
if not "info migrate" in o:
raise error.TestError("Migration is not supported")
session = kvm_test_utils.wait_for_login(vm)
migration_test_command =
params.get("migration_test_command")
reference_output =
session.get_command_output(migration_test_command)
kvm_test_utils.migrate(vm, dsthost, vm.migration_port, env)
session.close()
elif params.get("role") == "dest":
try:
mig_timeout = int(params.get("mig_timeout"))
session = kvm_test_utils.wait_for_login(vm,
timeout=mig_timeout)
except:
raise error.TestFail("Could not log into migrated
guest")
except Exception, e:
logging.error("Test failed: %s", e)
logging.debug("Postprocessing on error...")
kvm_preprocessing.postprocess_on_error(self, params, env)
kvm_utils.dump_env(env, env_filename)
raise
finally:
# Postprocess
kvm_preprocessing.postprocess(self, params, env)
logging.debug("Contents of environment: %s", str(env))
kvm_utils.dump_env(env, env_filename)
--------
But there will be a problem: where can we edit the config file
to generate differnt dicts for migration test? Hard code the parameters in
control.srv?
It will be easier to resolve the problem of making up kvm_tests.cfg for both
client
machines.
2 just pass 'start_vm_for_migration = yes' to dest host
3 source host will wait until dest host telling it's ready using socket
communication (any existent implement/function in autotest framework? )
4 and then change the role of 'source machine' and 'dest machine' to implement
ping-pong
migrate.
Initial version of control.srv for server-migration:
-----
AUTHOR = "Yolkfull Chow <[email protected]>"
TIME = "SHORT"
NAME = "Migration across Multi-machine"
TEST_CATEGORY = "Functional"
TEST_CLASS = 'Virtualization'
TEST_TYPE = "Server"
DOC = """
Migrate KVM guest between two hosts.
Arguments to run_test:
@dict - a dictionary containing all parameters that migration need.
"""
import sys, os, commands
from autotest_lib.server import utils
KVM_DIR = os.path.join('/root/devel/upstream/server-mig', 'client/tests/kvm')
sys.path.insert(0, KVM_DIR)
import kvm_config
rootdir = '/tmp/kvm_autotest_root'
def run(pair):
print "KVM migration running on srchost [%s] and desthost [%s]\n" % (
pair[0], pair[1])
source = hosts.create_host(pair[0])
dest = hosts.create_host(pair[1])
source_at = autotest.Autotest(source)
source_at.install(source)
dest_at = autotest.Autotest(dest)
dest_at.install(dest)
# ----------------------------------------------------------
# Get test set (dictionary list) from the configuration file
# ----------------------------------------------------------
filename = os.path.join(KVM_DIR, "kvm_tests.cfg")
cfg = kvm_config.config(filename)
# Make only dictionaries that migration needs
cfg.parse_string("only migrate")
filename = os.path.join(KVM_DIR, "kvm_address_pools.cfg")
if os.path.exists(filename):
cfg.parse_file(filename)
hostname = os.uname()[1].split(".")[0]
if cfg.filter("^" + hostname):
cfg.parse_string("only ^%s" % hostname)
else:
cfg.parse_string("only ^default_host")
list = cfg.get_list()
# Control file template for client machine
control_string = "job.run_test('kvm_migration', params=%s)"
for vm_dict in list:
vm_dict['srchost'] = source.ip
vm_dict['dsthost'] = dest.ip
vm_dict['display'] = 'vnc'
vm_dict['rootdir'] = rootdir
source_dict = vm_dict.copy()
dest_dict = vm_dict.copy()
source_dict['role'] = "source"
dest_dict['role'] = "dest"
dest_dict['start_vm_for_migration'] = "yes"
# Report the parameters we've received
print "Test parameters:"
keys = vm_dict.keys()
keys.sort()
for key in keys:
print " " + str(key) + " = " + str(vm_dict[key])
source_control_file = ''.join([control_string % source_dict])
dest_control_file = ''.join([control_string % dest_dict])
dest_command = subcommand(dest_at.run,
[dest_control_file, dest.hostname])
source_command = subcommand(source_at.run,
[source_control_file, source.hostname])
parallel([dest_command, source_command])
# grab the pairs (and failures)
(pairs, failures) = utils.form_ntuples_from_machines(machines, 2)
# log the failures
for failure in failures:
job.record("FAIL", failure[0], "kvm", failure[1])
# now run through each pair and run
job.parallel_simple(run, pairs, log=False)
--------
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html