diff --git a/qemu/cfg/host-kernel.cfg b/qemu/cfg/host-kernel.cfg index 6742b85006d9f461044314323512e013f89577eb..346ac1420d2a083a273b7b81c8c2ce229b10d2f1 100644 --- a/qemu/cfg/host-kernel.cfg +++ b/qemu/cfg/host-kernel.cfg @@ -54,3 +54,22 @@ variants: - 3: host_kernel_ver_str += ".3" requires_kernel = [">= 2.6.32-279", "< 2.6.32-280"] + - 7: + # RHEL-7 pointer + host_kernel_ver_str += ".7" + netdev_peer_re = "\s{2,}(.*?):.*?peer=(.*?)\n" + drive_mirror: + block_mirror_cmd = "drive-mirror" + block_reopen_cmd = "block-job-complete" + check_event = yes + ksm_base: + status_query_cmd = "cat /sys/kernel/mm/ksm/run" + setup_cmd = "echo 1 > /sys/kernel/mm/ksm/run" + query_cmd = "cat /sys/kernel/mm/ksm/pages_sharing" + virtio_net: + vhost = "vhost=on" + variants: + - 0: + host_kernel_ver_str += ".0" + requires_kernel = [">= 3.2.1-0.8"] + machine_type = "pc" diff --git a/qemu/tests/block_copy.py b/qemu/tests/block_copy.py index cb05f663d6eb81c218598494599a135903109ebe..ed584b2174112993e606556427e0cb3b155d2f9b 100644 --- a/qemu/tests/block_copy.py +++ b/qemu/tests/block_copy.py @@ -122,9 +122,10 @@ class BlockCopy(object): cancel active job on given image; """ def is_cancelled(): + ret = not bool(self.get_status()) if self.vm.monitor.protocol == "qmp": - return self.vm.monitor.get_event("BLOCK_JOB_CANCELLED") - return not self.get_status() + ret &= bool(self.vm.monitor.get_event("BLOCK_JOB_CANCELLED")) + return ret error.context("cancel block copy job", logging.info) params = self.parser_test_args() @@ -133,10 +134,10 @@ class BlockCopy(object): if self.vm.monitor.protocol == "qmp": self.vm.monitor.clear_events() self.vm.cancel_block_job(self.device) - cancelled = utils_misc.wait_for(is_cancelled, timeout=timeout, - text="wait job cancelled in %ss" % timeout) + cancelled = utils_misc.wait_for(is_cancelled, timeout=timeout) if not cancelled: - raise error.TestFail("Job still running after %ss" % timeout) + msg = "Cancel block job timeout in %ss" % timeout + raise error.TestFail(msg) @error.context_aware diff --git a/qemu/tests/cfg/drive_mirror.cfg b/qemu/tests/cfg/drive_mirror.cfg new file mode 100644 index 0000000000000000000000000000000000000000..be58c994aea87ad66230b4aef154ba0b8d935f18 --- /dev/null +++ b/qemu/tests/cfg/drive_mirror.cfg @@ -0,0 +1,96 @@ +- drive_mirror: + no Host_RHEL.5 + no Host_RHEL.6.1 + no Host_RHEL.6.2 + only qcow2 + type = drive_mirror + monitor_type = qmp + monitors = qmpmonitor1 + main_monitor = qmpmonitor1 + backup_image_before_testing = yes + restore_image_after_testing = yes + block_mirror_cmd = "__com.redhat_drive-mirror" + block_reopen_cmd = "__com.redhat_drive-reopen" + wait_timeout = 3600 + # wait_timeout: wait xx seconds for block mirror job go into steady status, aka offset equal image length + source_images = "image1" + # source_images: set which image will be mirroring to target, now only a image at one time; + full_copy_image1 = "full" + #for full image or top most + default_speed_image1 = 0 + # default speed unit is B/s, for 10MB/s please set speed to '10M' + target_format_image1 = "qcow2" + create_mode_image1 = "absolute-paths" + target_image_image1 = "/tmp/target1" + check_event = no + variants: + - simple: + type = drive_mirror_simple + repeat_times = 3 + cancel_timeout = 3 + variants: + - cancel: + before_steady = "cancel" + - set_speed: + max_speed_image1 = 10M + before_steady = "set_speed" + - reset_speed: + default_speed_image1 = 10M + max_speed_image1 = 1M + before_steady = "set_speed" + - query: + before_steady = "query_status" + default_speed_image1 = 3M + max_speed_image1 = 10M + - with_stress: + type = drive_mirror_stress + reopen_timeout = 360 + variants: + - heavyload: + tmp_dir = "/tmp" + download_link = http://weather.ou.edu/~apw/projects/stress/stress-1.0.4.tar.gz + md5sum = a607afa695a511765b40993a64c6e2f4 + install_cmd = "tar -xzvf %s/stress-1.0.4.tar.gz -C ./ && cd stress-1.0.4 && ./configure --prefix=/usr && make && make install " + config_cmd = "" + app_check_cmd = "stress --help" + start_cmd = "stress --cpu 4 --io 4 --vm 2 --vm-bytes 256M --quiet &" + check_cmd = 'pidof -s stress' + stop_cmd = "killall -g stress" + variants: + - stress: + before_start = "load_stress" + when_steady = "reopen" + after_reopen = "reboot verify_alive" + - stop: + before_start = "load_stress" + before_steady = "stop" + when_steady = "reopen resume" + after_reopen = "reboot verify_alive" + - check_steady: + before_start = "load_stress" + when_steady = "verify_steady" + #seconds to verify offset not decrease when guest in steady status + hold_on_timeout = 300 + after_reopen = "reboot verify_alive" + - dd: + app_check_cmd = "dd --help" + start_cmd = "(dd if=/dev/urandom of=/tmp/tmp.img bs=4k count=500000 oflag=direct &)" + check_cmd = "pidof dd" + stop_cmd = "killall -g dd;rm -f /tmp/tmp.img" + before_start = "load_stress" + when_steady = "reopen" + after_reopen = "reboot verify_alive" + - reboot: + type = drive_mirror_reboot + when_steady = "reopen stop_reset" + after_reopen = "reboot verify_alive" + - powerdown: + type = drive_mirror_powerdown + app_check_cmd = "uname" + start_cmd = 'sh -c "wget -c https://www.kernel.org/pub/linux/kernel/v2.6/longterm/v2.6.35/linux-2.6.35.14.tar.gz -O /mnt/Linux.tgz && ' + start_cmd += 'tar -xzvf /mnt/Linux.tgz -C /mnt && cd /mnt/linux-2.6.35.14 && make defconfig && make && make modules"' + check_cmd = 'pidof -s make' + stop_cmd = 'pkill sh;rm -rf /mnt/linux-2.6.35.14' + before_start = "load_stress" + when_steady = "powerdown" + after_reopen ="verify_alive" diff --git a/qemu/tests/drive_mirror.py b/qemu/tests/drive_mirror.py new file mode 100644 index 0000000000000000000000000000000000000000..90416353c538a9f31e8361631bd2dba5ea5ffab6 --- /dev/null +++ b/qemu/tests/drive_mirror.py @@ -0,0 +1,130 @@ +import logging, time +from autotest.client.shared import error +from virttest import utils_misc +from qemu.tests import block_copy + +class DriveMirror(block_copy.BlockCopy): + """ + base class for block mirror tests; + """ + + def __init__(self, test, params, env, tag): + super(DriveMirror, self).__init__(test, params, env, tag) + + def parser_test_args(self): + """ + paraser test args and set default value; + """ + params = super(DriveMirror, self).parser_test_args() + params["create_mode"] = params.get("create_mode", "absolute-path") + params["target_format"] = params.get("target_format", "qcow2") + params["reopen_timeout"] = int(params.get("reopen_timeout", 60)) + params["full_copy"] = params.get("full_copy", "").lower() + params["check_event"] = params.get("check_event", "no").lower() + cmd = params.get("block_mirror_cmd", "__com.redhat.drive-mirror") + if cmd.startswith("__com.redhat"): + params["full_copy"] = (params["full_copy"] == "full") + return params + + @error.context_aware + def start(self): + """ + start block device mirroring job; + """ + params = self.parser_test_args() + target_image = params.get("target_image") + default_speed = params.get("default_speed") + full_copy = params.get("full_copy") + create_mode = params.get("create_mode") + target_format = params.get("target_format") + + error.context("start to mirror block device", logging.info) + self.vm.block_mirror(self.device, target_image, default_speed, + full_copy, target_format, create_mode) + time.sleep(0.5) + started = self.get_status() + if not started: + raise error.TestFail("No active mirror job found") + self.trash.append(target_image) + + @error.context_aware + def reopen(self): + """ + reopen target image, then check if image file of the device is + target images; + """ + + params = self.parser_test_args() + target_image = params.get("target_image") + target_format = params.get("target_format") + reopen_timeout = params.get("reopen_timeout") + + def is_opened(): + device = self.vm.get_block({"file": target_image}) + ret = (device == self.device) + if self.vm.monitor.protocol == "qmp": + ret &= bool(self.vm.monitor.get_event("BLOCK_JOB_COMPLETED")) + return ret + + error.context("reopen new target image", logging.info) + if self.vm.monitor.protocol == "qmp": + self.vm.monitor.clear_events() + self.vm.block_reopen(self.device, target_image, target_format) + opened = utils_misc.wait_for(is_opened, timeout=reopen_timeout) + if not opened: + msg = "Wait open new image timeout(%ss)" % reopen_timeout + raise error.TestFail(msg) + + def is_steady(self): + """ + check block device mirroring job is steady status or not; + """ + params = self.parser_test_args() + info = self.get_status() + ret = (info["len"] == info["offset"]) + if self.vm.monitor.protocol == "qmp": + check_event = params.get("check_event") + if check_event == "yes": + ret &= bool(self.vm.monitor.get_event("BLOCK_JOB_READY")) + return ret + + def wait_for_steady(self): + """ + check block device mirroring status, utils timeout; if still not go + into steady status, raise TestFail exception; + """ + params = self.parser_test_args() + timeout = params.get("wait_timeout") + steady =utils_misc.wait_for(self.is_steady, + step=2.0, timeout=timeout) + if not steady: + raise error.TestFail("wait job goin ready status" + "timeout in %ss" % timeout) + + def action_before_start(self): + """ + run steps before job in steady status; + """ + return self.do_steps("before_start") + + def action_before_steady(self): + """ + run steps before job in steady status; + """ + return self.do_steps("before_steady") + + def action_when_steady(self): + """ + run steps when job in steady status; + """ + self.wait_for_steady() + return self.do_steps("when_steady") + + def action_after_reopen(self): + """ + run steps after reopened new target image; + """ + return self.do_steps("after_reopen") + +def run_drive_mirror(test, params, env): + pass diff --git a/qemu/tests/drive_mirror_powerdown.py b/qemu/tests/drive_mirror_powerdown.py new file mode 100644 index 0000000000000000000000000000000000000000..c42c7e06f6300f3739373d69aecc5fccb817d868 --- /dev/null +++ b/qemu/tests/drive_mirror_powerdown.py @@ -0,0 +1,75 @@ +import logging +from virttest import storage, data_dir +from autotest.client.shared import error, utils +from qemu.tests import drive_mirror_stress + +class DriveMirrorPowerdown(drive_mirror_stress.DriveMirrorStress): + + def __init__(self, test, params, env, tag): + super(DriveMirrorPowerdown, self).__init__(test, params, env, tag) + params = self.params.object_params(self.tag) + image_file = storage.get_image_filename(params, + data_dir.get_data_dir()) + self.params["image_file"] = image_file + + @error.context_aware + def powerdown(self): + """ + power down guest via quit qemu; + """ + params = self.parser_test_args() + error.context("powerdown vm", logging.info) + self.vm.destroy() + error.context("backup base image", logging.info) + image_file = params.get("image_file") + cmd = "mv %s %s-bak" % (image_file, image_file) + utils.system(cmd) + return + + @error.context_aware + def powerup(self): + """ + bootup guest with target image, same as reopen new image; + steps are: + 1). backup base image, move target image as base image + 2). bootup guest with target image; + """ + params = self.parser_test_args() + image_file = params.get("image_file") + target_image = params.get("target_image") + cmd = "yes|mv %s %s" % (target_image, image_file) + error.context("copy target image") + utils.system(cmd) + error.context("powerup vm with target image", logging.info) + self.vm.create() + + def clean(self): + params = self.parser_test_args() + image_file = params.get("image_file") + super(DriveMirrorPowerdown, self).clean() + cmd = "yes|mv %s-bak %s" % (image_file, image_file) + utils.system(cmd) + +def run_drive_mirror_powerdown(test, params, env): + """ + drive_mirror_powerdown test: + 1). boot guest, do kernel build + 3). mirror disk to target image + 4). wait go into steady status, then quit qemu + 5). bootup guest with target image + 6). check guest can response correctly + + @param test: QEMU test object + @param params: Dictionary with the test parameters + @param env: Dictionary with test environment. + """ + tag = params.get("source_images", "image1") + powerdown_test = DriveMirrorPowerdown(test, params, env, tag) + try: + powerdown_test.action_before_start() + powerdown_test.start() + powerdown_test.action_when_steady() + powerdown_test.powerup() + powerdown_test.action_after_reopen() + finally: + powerdown_test.clean() diff --git a/qemu/tests/drive_mirror_reboot.py b/qemu/tests/drive_mirror_reboot.py new file mode 100644 index 0000000000000000000000000000000000000000..7120a6082bc751ef2a6789a8da7ee34924afa0cf --- /dev/null +++ b/qemu/tests/drive_mirror_reboot.py @@ -0,0 +1,56 @@ +import time, random, logging +from autotest.client.shared import error, utils +from qemu.tests import drive_mirror + +class DriveMirrorReboot(drive_mirror.DriveMirror): + + STOP = False + + def __init__(self, test, params, env, tag): + super(DriveMirrorReboot, self).__init__(test, params, env, tag) + + @error.context_aware + def start_reset(self): + """ + Reset guest with system_reset in loop; + """ + reboot_method = self.params.get("reboot_method", "system_reset") + error.context("reset/restart guest in loop", logging.info) + while not self.STOP: + self.reboot(method=reboot_method) + random_sleep =random.randint(3, 20) + time.sleep(random_sleep) + return None + + @error.context_aware + def stop_reset(self): + """ + stop reset guest loop; + """ + error.context("stop reset/restart guest loop", logging.info) + self.STOP = True + + +def run_drive_mirror_reboot(test, params, env): + """ + drive_mirror_reboot test: + 1). boot guest, do system_reset in loop + 2). start mirroring, wait go into steady status + 3). reopen new image and stop system_reset, then reboot guest + 4). check guest alive + + @param test: QEMU test object + @param params: Dictionary with the test parameters + @param env: Dictionary with test environment. + """ + tag = params.get("source_images", "image1") + reboot_test = DriveMirrorReboot(test, params, env, tag) + try: + bg = utils.InterruptedThread(reboot_test.start_reset) + bg.start() + reboot_test.start() + reboot_test.action_when_steady() + bg.join() + reboot_test.action_after_reopen() + finally: + reboot_test.clean() diff --git a/qemu/tests/drive_mirror_simple.py b/qemu/tests/drive_mirror_simple.py new file mode 100644 index 0000000000000000000000000000000000000000..2e4e916b9f9c79bb7714bba379e6134f109f53d8 --- /dev/null +++ b/qemu/tests/drive_mirror_simple.py @@ -0,0 +1,44 @@ +import logging, time, random +from autotest.client.shared import error +from qemu.tests import drive_mirror + +class DriveMirrorSimple(drive_mirror.DriveMirror): + + def __init__(self, test, params, env, tag): + super(DriveMirrorSimple, self).__init__(test, params, env, tag) + + @error.context_aware + def query_status(self): + """ + query runing block mirroring job info; + """ + error.context("query job status", logging.info) + if not self.get_status(): + raise error.TestFail("No active job") + + +def run_drive_mirror_simple(test, params, env): + """ + drive_mirror_simple test: + 1). launch block mirroring job w/o max speed + 2). query job status on the device before steady status(optinal) + 3). reset max job speed before steady status(optional) + 4). cancel active job on the device before steady status(optional) + + @param test: QEMU test object + @param params: Dictionary with the test parameters + @param env: Dictionary with test environment. + """ + tag = params.get("source_images", "image1") + repeats = int(params.get("repeat_times", 3)) + simple_test = DriveMirrorSimple(test, params, env, tag) + try: + for i in range(repeats): + v_max,v_min = int(params.get("login_timeout", 360)) / 4, 0 + time.sleep(random.randint(v_min, v_max)) + simple_test.start() + simple_test.action_before_steady() + if simple_test.get_status(): + simple_test.cancel() + finally: + simple_test.clean() diff --git a/qemu/tests/drive_mirror_stress.py b/qemu/tests/drive_mirror_stress.py new file mode 100644 index 0000000000000000000000000000000000000000..e850a390d76f579bcbef9aed271c6647640737fc --- /dev/null +++ b/qemu/tests/drive_mirror_stress.py @@ -0,0 +1,124 @@ +import time, logging +from autotest.client.shared import error +from autotest.client import utils +from virttest import utils_misc +from qemu.tests import drive_mirror + +class DriveMirrorStress(drive_mirror.DriveMirror): + + def __init__(self, test, params, env, tag): + super(DriveMirrorStress, self).__init__(test, params, env, tag) + + @error.context_aware + def install_stress_app(self): + error.context("install stress app in guest") + params = self.parser_test_args() + session = self.get_session() + installed = session.cmd_status(params.get("app_check_cmd")) == 0 + if installed: + return + link = params.get("download_link") + md5sum = params.get("md5sum") + tmp_dir = params.get("tmp_dir") + install_cmd = params.get("install_cmd") % tmp_dir + config_cmd = params.get("config_cmd") + pkg = utils.unmap_url_cache(self.test.tmpdir, link, md5sum) + self.vm.copy_files_to(pkg, tmp_dir) + s, o = session.cmd_status_output(install_cmd, timeout=300) + if s != 0: + raise error.TestError("Fail to install stress app(%s)" % o) + s, o = session.cmd_status_output(config_cmd, timeout=300) + if s != 0: + raise error.TestError("Fail to conifg stress app(%s)" % o) + + + @error.context_aware + def load_stress(self): + """ + load IO/CPU/Memoery stress in guest; + """ + params = self.parser_test_args() + self.install_stress_app() + cmd = params.get("start_cmd") + session = self.get_session() + error.context("lanuch stress app in guest", logging.info) + session.sendline(cmd) + logging.info("Command: %s" % cmd) + runing = utils_misc.wait_for(self.app_runing, first=0.5, timeout=300) + if not runing: + raise error.TestFail("stress app isn't running") + return None + + @error.context_aware + def unload_stress(self): + """ + stop stress app + """ + def _unload_stress(): + params = self.parser_test_args() + session = self.get_session() + cmd = params.get("stop_cmd") + session.sendline(cmd) + if not self.app_runing(): + return True + return False + + error.context("stop stress app in guest", logging.info) + utils_misc.wait_for(_unload_stress, first=2.0, + text="wait stress app quit", step=1.0, timeout=120) + + def app_runing(self): + """ + check stress app really run in background; + """ + session = self.get_session() + params = self.parser_test_args() + cmd = params.get("check_cmd") + status = session.cmd_status(cmd, timeout=120) + return status == 0 + + @error.context_aware + def verify_steady(self): + """ + verify offset not decreased, after block mirror job in steady status; + """ + error.context("verify offset not decreased", logging.info) + params = self.parser_test_args() + timeout = int(params.get("hold_on_timeout", 600)) + offset = self.get_status()["offset"] + start = time.time() + while time.time() < start + timeout: + _offset = self.get_status()["offset"] + if _offset < offset: + msg = "offset decreased, offset last: %s" % offset + msg += "offset now: %s" % _offset + raise error.TestFail(msg) + offset = _offset + + +def run_drive_mirror_stress(test, params, env): + """ + drive_mirror_stress test: + 1). load stress in guest + 2). mirror block device + 3). stop vm when mirroring job really run(optional) + 4). wait for block job in steady status + 5). check offset not decreased(optional) + 6). reopen new target image(optional) + 7). quit stress app, reboot guest(optional); + 8). verify guest can response correctly + + @param test: QEMU test object + @param params: Dictionary with the test parameters + @param env: Dictionary with test environment. + """ + tag = params.get("source_image", "image1") + stress_test = DriveMirrorStress(test, params, env, tag) + try: + stress_test.action_before_start() + stress_test.start() + stress_test.action_before_steady() + stress_test.action_when_steady() + stress_test.action_after_reopen() + finally: + stress_test.clean()