def run(test, params, env): """ A 'qemu-img' resize test. 1.create a raw image 2.change the raw image size * n 3.verify resize * n :param test: Qemu test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def _sum_size_changes(size_changes): """ Sum the list of size changes. :param size_changes: list of size changes """ res = [] for change in size_changes: s = int(utils_numeric.normalize_data_size( change, "B")) * (-1 if '-' in change else 1) res.append(s) return sum(res) def _verify_resize(img_size, expected_size): """Verify the image size is as expected after resize.""" logging.info("Verify the size of %s is %s." % (img.image_filename, expected_size)) if img_size != expected_size: test.fail("Got image virtual size: %s, should be: %s." % (img_size, expected_size)) def _resize(size_changes): """Resize the image and verify its size.""" for idx, size in enumerate(size_changes): logging.info("Resize the raw image %s %s." % (img.image_filename, size)) shrink = True if "-" in size else False img.resize(size, shrink=shrink) img_size = json.loads(img.info(output="json"))["virtual-size"] expected_size = (int( utils_numeric.normalize_data_size(params["image_size_test"], "B")) + _sum_size_changes(size_changes[:idx + 1])) _verify_resize(img_size, expected_size) img_param = params.object_params('test') img = QemuImg(img_param, data_dir.get_data_dir(), 'test') size_changes = params["size_changes"].split() logging.info("Create a raw image %s." % img.image_filename) img.create(img_param) _resize(size_changes)
def run(test, params, env): """ qemu-img supports 'discard' for raw block target images. 1. Create source image via dd with all zero. 2. Modprobe a 1G scsi_debug disk with writesame_16 mode. 3. Trace the system calls while converting the zero image to the scsi_debug block device, then check whether 'fallocate' system call results work in the log. :param test: Qemu test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def _check_output(strace_event, strace_output, match_str): """Check whether the value is good in the output file.""" logging.debug("Check the output file '%s'.", strace_output) with open(strace_output) as fd: m = re.findall(match_str + r', \d+, \d+', fd.read()) if not m: test.fail("The result of system call '%s' is not right, " "check '%s' for more details." % (strace_event, strace_output)) last_lst = m[-1].split(',') sum_size = int(last_lst[-1]) + int(last_lst[-2]) # get the source image size in byte unit byte_image_size = int( utils_numeric.normalize_data_size(image_size, "B")) if sum_size != byte_image_size: test.fail( "The target allocated size '%s' is different from the source image size, " "check '%s' for more details." % (str(sum_size), strace_output)) src_image = params["images"] image_size = params["image_size_test"] root_dir = data_dir.get_data_dir() source = QemuImg(params.object_params(src_image), root_dir, src_image) strace_event = params["strace_event"] strace_events = strace_event.split() strace_output_file = os.path.join(test.debugdir, "convert_to_block.log") source.create(source.params) # Generate the target scsi block file. tgt_disk = process.system_output("lsscsi | grep '%s' | awk '{print $NF}'" % params["scsi_mod"], shell=True).decode() params["image_name_target"] = tgt_disk logging.debug( "Convert from %s to %s with cache mode none, strace log: %s.", source.image_filename, tgt_disk, strace_output_file) with strace(source, strace_events, strace_output_file, trace_child=True): fail_on((process.CmdError, ))(source.convert)( params.object_params(src_image), root_dir, cache_mode="none") _check_output(strace_event, strace_output_file, "FALLOC_FL_PUNCH_HOLE")
def run(test, params, env): """ A 'qemu-img' resize test. 1.create a raw image 2.change the raw image size * n 3.verify resize * n :param test: Qemu test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def _sum_size_changes(size_changes): """ Sum the list of size changes. :param size_changes: list of size changes """ res = [] for change in size_changes: s = int(utils_numeric.normalize_data_size(change, "B") ) * (-1 if '-' in change else 1) res.append(s) return sum(res) def _verify_resize(img_size, expected_size): """Verify the image size is as expected after resize.""" logging.info("Verify the size of %s is %s." % (img.image_filename, expected_size)) if img_size != expected_size: test.fail("Got image virtual size: %s, should be: %s." % (img_size, expected_size)) def _resize(size_changes): """Resize the image and verify its size.""" for idx, size in enumerate(size_changes): logging.info("Resize the raw image %s %s." % (img.image_filename, size)) shrink = True if "-" in size else False img.resize(size, shrink=shrink) img_size = json.loads(img.info(output="json"))["virtual-size"] expected_size = (int(utils_numeric.normalize_data_size( params["image_size_test"], "B")) + _sum_size_changes(size_changes[:idx + 1])) _verify_resize(img_size, expected_size) img_param = params.object_params('test') img = QemuImg(img_param, data_dir.get_data_dir(), 'test') size_changes = params["size_changes"].split() logging.info("Create a raw image %s." % img.image_filename) img.create(img_param) _resize(size_changes)
def run(test, params, env): """ Negative test. Verify that qemu-img supports to check the options used for creating external snapshot, and raise accurate error when specifying a wrong option. 1. It should be failed to create the snapshot when specifying a wrong format for backing file. 2. It should be failed to create the snapshot when specifying a non-existing backing file. 3. It should be failed to create the snapshot when specifying an empty string for backing file. :param test: Qemu test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def _check_command(cmds): """run the command and check the output""" cmds = cmds.split(";") for qemu_img_cmd in cmds: if qemu_img_cmd_agrs: qemu_img_cmd %= qemu_img_cmd_agrs cmd_result = process.run(qemu_img_cmd, ignore_status=True, shell=True) if not re.search(err_info, cmd_result.stderr.decode(), re.I | re.M): test.fail("Failed to get error information. The actual error " "information is %s." % cmd_result.stderr.decode()) def run_cmd_with_incorrect_format(): cmds = params.get("cmd_with_incorrect_format") _check_command(cmds) def run_cmd_with_non_existing_backing_file(): cmds = params.get("cmd_with_non_existing_backing_file") _check_command(cmds) def run_cmd_with_empty_string_for_backing_file(): cmds = params.get("cmd_with_empty_string_for_backing_file") _check_command(cmds) qemu_img_cmd_agrs = "" image_stg = params["images"] if image_stg == "stg": root_dir = data_dir.get_data_dir() stg = QemuImg(params.object_params(image_stg), root_dir, image_stg) stg.create(stg.params) qemu_img_cmd_agrs = stg.image_filename err_info = params["err_info"] test_scenario = params["test_scenario"] locals()[test_scenario]()
def run(test, params, env): """ Convert a image to a virtual block device. 1. Create source and middle images. 2. Setup loop device with the middle image. 3. Convert the source image to the loop device. :param test: Qemu test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def setup_loop_dev(image_path): """ Setup a loop device with a file image. :param image_path: The path to the image used to setup loop device :return: The loop device under /dev """ cmd_result = process.run("losetup -f %s --show" % image_path) return cmd_result.stdout_text.strip() def free_loop_dev(loop_dev): """ Free a loop device. :param loop_dev: The loop device will be free """ process.run("losetup -d %s" % loop_dev) src_img = params["images"].split()[0] mid_img = params["images"].split()[-1] root_dir = data_dir.get_data_dir() source = QemuImg(params.object_params(src_img), root_dir, src_img) middle = QemuImg(params.object_params(mid_img), root_dir, mid_img) mid_filename = middle.image_filename logging.info("Create the test image files.") source.create(source.params) middle.create(middle.params) logging.info("Setup target loop device via 'losetup'.") target = setup_loop_dev(mid_filename) params["image_name_target"] = target logging.debug("Convert from %s to %s with cache mode none.", source.image_filename, mid_filename) try: fail_on((process.CmdError,))(source.convert)( params.object_params(src_img), root_dir, cache_mode="none") finally: logging.info("Clean the loop device.") free_loop_dev(target)
def _create_tmpfs_data_disk(): """ Create a tmpfs data disk """ logging.info("Create tmpfs data disk") disk_name_key = params["disk_name_key"] tmp_dir = data_dir.get_tmp_dir() tmpfs_dir = os.path.join(tmp_dir, "tmpfs") if not os.path.isdir(tmpfs_dir): os.makedirs(tmpfs_dir) params[disk_name_key] = os.path.join(tmpfs_dir, "data") tmpfs_image_name = params["tmpfs_image_name"] img_param = params.object_params(tmpfs_image_name) img = QemuImg(img_param, data_dir.get_data_dir(), tmpfs_image_name) img.create(img_param)
def run(test, params, env): """ qemu-img supports 'discard' for raw block target images. 1. Create source image via dd with all zero. 2. Modprobe a 1G scsi_debug disk with writesame_16 mode. 3. Trace the system calls while converting the zero image to the scsi_debug block device, then check whether 'fallocate' system call works in the log. :param test: Qemu test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def check_output(strace_event, strace_output, match_str): """Check whether the value is good in the output file.""" logging.debug("Check the output file '%s'.", strace_output) with open(strace_output) as fd: if match_str not in fd.read(): test.fail("The system call of '%s' is not right, " "check '%s' for more details." % (strace_event, strace_output)) src_image = params["images"] root_dir = data_dir.get_data_dir() source = QemuImg(params.object_params(src_image), root_dir, src_image) strace_event = params["strace_event"] strace_events = strace_event.split() strace_output_file = os.path.join(test.debugdir, "convert_to_block.log") source.create(source.params) # Generate the target scsi block file. tgt_disk = process.system_output("lsscsi | grep '%s' | awk '{print $NF}'" % params["scsi_mod"], shell=True).decode() params["image_name_target"] = tgt_disk logging.debug( "Convert from %s to %s with cache mode none, strace log: %s.", source.image_filename, tgt_disk, strace_output_file) with strace(source, strace_events, strace_output_file, trace_child=True): fail_on((process.CmdError, ))(source.convert)( params.object_params(src_image), root_dir, cache_mode="none") check_output(strace_event, strace_output_file, "FALLOC_FL_PUNCH_HOLE, 0, 1073741824")
def run(test, params, env): """ Creating a raw image with large size on different file systems. 1. Create a raw image with large size on XFS and check the output info. 2. Setup EXT4 filesystem. 3. Create a raw image with large size on the EXT4 file system and check the output info. :param test: VT test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ large_img = params["images"] root_dir = data_dir.get_data_dir() loop_img = os.path.join(root_dir, "loop.img") loop_size = int(params["loop_file_size"]) file_sys = params["file_sys"] err_info = params["err_info"].split(";") mnt_dir = os.path.join(root_dir, "tmp") large = QemuImg(params.object_params(large_img), mnt_dir, large_img) # Setup file system env part = p.Partition(loop_img, loop_size=loop_size, mountpoint=mnt_dir) part.mkfs(file_sys) part.mount() logging.info("Test creating an image with large size over %s.", file_sys) try: large.create(large.params) except TestError as err: for info in err_info: if info in six.text_type(err): break else: test.fail("CML failed with unexpected output: %s" % err) else: test.fail("There is no error when creating an image with large size.") finally: part.unmount() os.rmdir(mnt_dir) os.remove(loop_img)
def run(test, params, env): """ qemu-img supports to create a raw image file. 1. Create test image, and write 1M "1" into the test image via qemu-io. 2. Check the image virtual and actual size info. :param test: Qemu test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def _qemu_io(img, cmd): """Run qemu-io cmd to a given img.""" logging.info("Run qemu-io %s" % img.image_filename) try: QemuIOSystem(test, params, img.image_filename).cmd_output(cmd, 120) except process.CmdError as err: test.fail("qemu-io to '%s' failed: %s." % (img.image_filename, err)) def _check_img_size(img_info, defined_sizes, size_keys): """Check the size info of the image""" for defined_size, size_key in zip(defined_sizes, size_keys): logging.info("Check the '%s' size info of %s" % (size_key, source.image_filename)) defined_size = normalize_data_size(defined_size, "B") get_size = img_info[size_key] if int(defined_size) != int(get_size): test.fail("Got unexpected size '%s', expected size is '%s'" % (get_size, defined_size)) src_image = params["images"] img_dir = data_dir.get_data_dir() write_size = params["write_size"] source = QemuImg(params.object_params(src_image), img_dir, src_image) source.create(source.params) _qemu_io(source, 'write -P 1 0 %s' % write_size) src_info = json.loads(source.info(output="json")) _check_img_size(src_info, [write_size, params["image_size_test"]], ["actual-size", "virtual-size"])
def run(test, params, env): """ 'qemu-img check' should report the end offset of the image. 1. Create a test qcow2 image. 2. Check there is image end offset and the value with both "humam" and "json" output. :param test: Qemu test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def _check_result(key, offset, output): """Check the keywords and the value from the output.""" if key not in output or int(offset) != int(output[key]): test.fail("The keyword/value is no correct. Check please.") report = params["images"] root_dir = data_dir.get_data_dir() report = QemuImg(params.object_params(report), root_dir, report) offset = params["image_end_offset"] human_key = params["human_key"] json_key = params["json_key"] logging.info("Create the test image file.") report.create(report.params) # 'qemu-img check' the image and check the output info. check_result = report.check(report.params, root_dir, output="human").stdout.decode() if not check_result: test.error("There is no output of check command, check please.") logging.debug("The check output with human output format: %s", check_result) result_dict = dict(re.findall(r'(.+):\s(.+)', check_result)) _check_result(human_key, offset, result_dict) check_result = report.check(report.params, root_dir, output="json").stdout.decode() if not check_result: test.error("There is no output of check command, check please.") logging.debug("The check output with json output format: %s", check_result) _check_result(json_key, offset, json.loads(check_result))
def create_image(self): """ Create a image. """ image_name = self.params.get("image_name") self.params['image_name_snapshot'] = image_name + "-snap" snapshot_params = self.params.object_params("snapshot") base_dir = self.params.get("images_base_dir", data_dir.get_data_dir()) image_io = QemuImg(snapshot_params, base_dir, image_name) image_name, _ = image_io.create(snapshot_params) return image_name
def run(test, params, env): """ qemu-img supports convert with copy-offloading. 1. create source image, and write "1" into the half of source image via qemu-io 2. trace the system calls for qemu-img convert with copy-offloading and inspect whether there is copy_file_range 3. compare the sourc and target images :param test: Qemu test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def _qemu_io(img, cmd): """Run qemu-io cmd to a given img.""" logging.info("Run qemu-io %s", img.image_filename) QemuIOSystem(test, params, img.image_filename).cmd_output(cmd, 120) def _convert_with_copy_offloading_and_verify(src, tgt): """Verify whether copy_offloading works.""" logging.info("Verify whether copy_offloading works for commit.") cmd = ("strace -e trace=copy_file_range -f qemu-img convert -C -f " "%s %s -O %s %s " % (src.image_format, src.image_filename, tgt.image_format, tgt.image_filename)) sts, text = process.getstatusoutput(cmd, verbose=True) if sts != 0: test.fail("Convert with copy_offloading failed: %s." % text) src_image = params["src_image"] tgt_image = params["tgt_image"] img_dir = data_dir.get_data_dir() source = QemuImg(params.object_params(src_image), img_dir, src_image) source.create(source.params) _qemu_io(source, 'write -P 1 0 %s' % params["write_size"]) target = QemuImg(params.object_params(tgt_image), img_dir, tgt_image) _convert_with_copy_offloading_and_verify(source, target)
def run(test, params, env): """ Creating image with large size. 1. Create a qcow2 image with large size and check the output info. 2. Create a qcow2 with a normal size. 3. Increase a large size to the qcow2 image and check the output info. :param test: VT test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ large_img, small_img = params["images"].split() root_dir = data_dir.get_data_dir() large = QemuImg(params.object_params(large_img), root_dir, large_img) small = QemuImg(params.object_params(small_img), root_dir, small_img) large_filename = large.image_filename size_increases = params["size_changes"] create_err_info = params["create_err_info"] resize_err_info = params["resize_err_info"] logging.info("Test creating an image with large size.") try: large.create(large.params) except exceptions.TestError as err: if create_err_info not in str(err) or large_filename not in str(err): test.fail("CML failed with unexpected output: %s" % err) else: test.fail("There is no error when creating an image with large size.") logging.info("Test resizing an image with large size.") small.create(small.params) result = small.resize(size_increases) status, output = result.exit_status, result.stderr_text if status == 0: test.fail("There is no error when resizing an image with large size.") elif resize_err_info not in output: test.fail("CML failed with unexpected output: %s" % output)
def run(test, params, env): """ Run qcow2 performance tests: 1. Create image with given parameters 2. Write to the image to prepare a certain size image 3. Do one operations to the image and measure the time 4. Record the results :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ image_chain = params.get("image_chain") test_image = int(params.get("test_image", "0")) interval_size = params.get("interval_szie", "64k") write_round = int(params.get("write_round", "16384")) op_type = params.get("op_type") new_base = params.get("new_base") writecmd = params.get("writecmd") iocmd = params.get("iocmd") opcmd = params.get("opcmd") io_options = params.get("io_options", "n") cache_mode = params.get("cache_mode") image_dir = data_dir.get_data_dir() if not re.match("\d+", interval_size[-1]): write_unit = interval_size[-1] interval_size = int(interval_size[:-1]) else: interval_size = int(interval_size) write_unit = "" error.context("Init images for testing", logging.info) sn_list = [] for img in re.split("\s+", image_chain.strip()): image_params = params.object_params(img) sn_tmp = QemuImg(image_params, image_dir, img) sn_tmp.create(image_params) sn_list.append((sn_tmp, image_params)) # Write to the test image error.context("Prepare the image with write a certain size block", logging.info) dropcache = 'echo 3 > /proc/sys/vm/drop_caches && sleep 5' snapshot_file = sn_list[test_image][0].image_filename if op_type != "writeoffset1": offset = 0 writecmd0 = writecmd % (write_round, offset, interval_size, write_unit, interval_size, write_unit) iocmd0 = iocmd % (writecmd0, io_options, snapshot_file) logging.info("writecmd-offset-0: %s", writecmd0) utils.run(dropcache) output = utils.run(iocmd0) else: offset = 1 writecmd1 = writecmd % (write_round, offset, interval_size, write_unit, interval_size, write_unit) iocmd1 = iocmd % (writecmd1, io_options, snapshot_file) logging.info("writecmd-offset-1: %s", writecmd1) utils.run(dropcache) output = utils.run(iocmd1) error.context("Do one operations to the image and measure the time", logging.info) if op_type == "read": readcmd = opcmd % (io_options, snapshot_file) logging.info("read: %s", readcmd) utils.run(dropcache) output = utils.run(readcmd) elif op_type == "commit": commitcmd = opcmd % (cache_mode, snapshot_file) logging.info("commit: %s", commitcmd) utils.run(dropcache) output = utils.run(commitcmd) elif op_type == "rebase": new_base_img = QemuImg(params.object_params(new_base), image_dir, new_base) new_base_img.create(params.object_params(new_base)) rebasecmd = opcmd % (new_base_img.image_filename, cache_mode, snapshot_file) logging.info("rebase: %s", rebasecmd) utils.run(dropcache) output = utils.run(rebasecmd) elif op_type == "convert": convertname = sn_list[test_image][0].image_filename + "_convert" convertcmd = opcmd % (snapshot_file, cache_mode, convertname) logging.info("convert: %s", convertcmd) utils.run(dropcache) output = utils.run(convertcmd) error.context("Result recording", logging.info) result_file = open( "%s/%s_%s_results" % (test.resultsdir, "qcow2perf", op_type), 'w') result_file.write("%s:%s\n" % (op_type, output)) logging.info("%s takes %s" % (op_type, output)) result_file.close()
def run_qemu_io_blkdebug(test, params, env): """ Run qemu-io blkdebug tests: 1. Create image with given parameters 2. Write the blkdebug config file 3. Try to do operate in image with qemu-io and get the error message 4. Get the error message from perror by error number set in config file 5. Compare the error message @param test: kvm test object @param params: Dictionary with the test parameters @param env: Dictionary with test environment. """ tmp_dir = params.get("tmp_dir", "/tmp") blkdebug_cfg = utils_misc.get_path( tmp_dir, params.get("blkdebug_cfg", "blkdebug.cfg")) err_command = params["err_command"] err_event = params["err_event"] errn_list = re.split("\s+", params["errn_list"].strip()) re_std_msg = params["re_std_msg"] test_timeout = int(params.get("test_timeout", "60")) pre_err_commands = params.get("pre_err_commands") image = params.get("images") blkdebug_default = params.get("blkdebug_default") error.context("Create image", logging.info) image_io = QemuImg(params.object_params(image), test.bindir, image) image_name, _ = image_io.create(params.object_params(image)) template_name = utils_misc.get_path(test.virtdir, blkdebug_default) template = ConfigParser.ConfigParser() template.read(template_name) for errn in errn_list: log_filename = utils_misc.get_path(test.outputdir, "qemu-io-log-%s" % errn) error.context("Write the blkdebug config file", logging.info) template.set("inject-error", "event", '"%s"' % err_event) template.set("inject-error", "errno", '"%s"' % errn) error.context("Write blkdebug config file", logging.info) blkdebug = None try: blkdebug = open(blkdebug_cfg, 'w') template.write(blkdebug) finally: if blkdebug is not None: blkdebug.close() error.context("Operate in qemu-io to trigger the error", logging.info) session = qemu_io.QemuIOShellSession(test, params, image_name, blkdebug_cfg=blkdebug_cfg, log_filename=log_filename) if pre_err_commands: for cmd in re.split(",", pre_err_commands.strip()): session.cmd_output(cmd, timeout=test_timeout) output = session.cmd_output(err_command, timeout=test_timeout) error.context("Get error message from command perror", logging.info) perror_cmd = "perror %s" % errn std_msg = utils.system_output(perror_cmd) std_msg = re.findall(re_std_msg, std_msg) if std_msg: std_msg = std_msg[0] else: std_msg = "" logging.warning("Can not find error message from perror") session.close() error.context("Compare the error message", logging.info) if std_msg: if std_msg in output: logging.info("Error message is correct in qemu-io") else: fail_log = "The error message is mismatch:" fail_log += "qemu-io reports: '%s'," % output fail_log += "perror reports: '%s'" % std_msg raise error.TestFail(fail_log) else: logging.warning("Can not find error message from perror." " The output from qemu-io is %s" % output)
def run(test, params, env): """ Test if VM paused when image NFS shutdown, the drive option 'werror' should be stop, the drive option 'cache' should be none. 1) Setup NFS service on host 2) Boot up a VM using another disk on NFS server and write the disk by dd 3) Check if VM status is 'running' 4) Reject NFS connection on host 5) Check if VM status is 'paused' 6) Accept NFS connection on host and continue VM by monitor command 7) Check if VM status is 'running' :param test: kvm test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ def get_nfs_devname(params, session): """ Get the possbile name of nfs storage dev name in guest. :param params: Test params dictionary. :param session: An SSH session object. """ image1_type = params.object_params("image1").get("drive_format") stg_type = params.object_params("stg").get("drive_format") cmd = "" # Seems we can get correct 'stg' devname even if the 'stg' image # has a different type from main image (we call it 'image1' in # config file) with these 'if' sentences. if image1_type == stg_type: cmd = "ls /dev/[hsv]d[a-z]" elif stg_type == "virtio": cmd = "ls /dev/vd[a-z]" else: cmd = "ls /dev/[sh]d[a-z]" cmd += " | tail -n 1" return session.cmd_output(cmd).rstrip() def check_vm_status(vm, status): """ Check if VM has the given status or not. :param vm: VM object. :param status: String with desired status. :return: True if VM status matches our desired status. :return: False if VM status does not match our desired status. """ try: vm.verify_status(status) except (virt_vm.VMStatusError, qemu_monitor.MonitorLockError): return False else: return True error_context.context("Setup NFS Server on local host", logging.info) host_ip = utils_net.get_host_ip_address(params) try: config = NFSCorruptConfig(test, params, host_ip) config.setup() except NFSCorruptError as e: test.error(str(e)) image_stg_dir = config.mnt_dir stg_params = params.object_params("stg") stg_img = QemuImg(stg_params, image_stg_dir, "stg") stg_img.create(stg_params) error_context.context("Boot vm with image on NFS server", logging.info) image_name = os.path.join(image_stg_dir, "nfs_corrupt") params["image_name_stg"] = image_name vm = env.get_vm(params["main_vm"]) try: vm.create(params=params) except Exception: stg_img.remove() config.cleanup() test.error("failed to create VM") session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360))) nfs_devname = get_nfs_devname(params, session) # Write disk on NFS server error_context.context("Write disk that image on NFS", logging.info) write_disk_cmd = "dd if=/dev/zero of=%s oflag=direct" % nfs_devname logging.info("dd with command: %s", write_disk_cmd) session.sendline(write_disk_cmd) try: # Read some command output, it will timeout session.read_up_to_prompt(timeout=30) except Exception: pass try: error_context.context("Make sure guest is running before test", logging.info) vm.resume() vm.verify_status("running") try: error_context.context("Reject NFS connection on host", logging.info) process.system(config.iptables_rule_gen('A')) error_context.context("Check if VM status is 'paused'", logging.info) if not utils_misc.wait_for( lambda: check_vm_status(vm, "paused"), int(params.get('wait_paused_timeout', 240))): test.error("Guest is not paused after stop NFS") finally: error_context.context("Accept NFS connection on host", logging.info) process.system(config.iptables_rule_gen('D')) error_context.context("Ensure nfs is resumed", logging.info) nfs_resume_timeout = int(params.get('nfs_resume_timeout', 240)) if not utils_misc.wait_for(config.is_mounted_dir_acessible, nfs_resume_timeout): test.error("NFS connection does not resume") error_context.context("Continue guest", logging.info) vm.resume() error_context.context("Check if VM status is 'running'", logging.info) if not utils_misc.wait_for(lambda: check_vm_status(vm, "running"), 20): test.error("Guest does not restore to 'running' status") finally: session.close() vm.destroy(gracefully=True) stg_img.check_image(params, image_stg_dir) stg_img.remove() config.cleanup()
def run_qemu_io_blkdebug(test, params, env): """ Run qemu-io blkdebug tests: 1. Create image with given parameters 2. Write the blkdebug config file 3. Try to do operate in image with qemu-io and get the error message 4. Get the error message from perror by error number set in config file 5. Compare the error message @param test: kvm test object @param params: Dictionary with the test parameters @param env: Dictionary with test environment. """ tmp_dir = params.get("tmp_dir", "/tmp") blkdebug_cfg = utils_misc.get_path(tmp_dir, params.get("blkdebug_cfg", "blkdebug.cfg")) err_command = params["err_command"] err_event = params["err_event"] errn_list = re.split("\s+", params["errn_list"].strip()) re_std_msg = params["re_std_msg"] test_timeout = int(params.get("test_timeout", "60")) pre_err_commands = params.get("pre_err_commands") image = params.get("images") blkdebug_default = params.get("blkdebug_default") error.context("Create image", logging.info) image_io = QemuImg(params.object_params(image), test.bindir, image) image_name = image_io.create(params.object_params(image)) template_name = utils_misc.get_path(test.virtdir, blkdebug_default) template = ConfigParser.ConfigParser() template.read(template_name) for errn in errn_list: log_filename = utils_misc.get_path(test.outputdir, "qemu-io-log-%s" % errn) error.context("Write the blkdebug config file", logging.info) template.set("inject-error", "event", '"%s"' % err_event) template.set("inject-error", "errno", '"%s"' % errn) error.context("Write blkdebug config file", logging.info) blkdebug = None try: blkdebug = open(blkdebug_cfg, 'w') template.write(blkdebug) finally: if blkdebug is not None: blkdebug.close() error.context("Operate in qemu-io to trigger the error", logging.info) session = qemu_io.QemuIOShellSession(test, params, image_name, blkdebug_cfg=blkdebug_cfg, log_filename=log_filename) if pre_err_commands: for cmd in re.split(",", pre_err_commands.strip()): session.cmd_output(cmd, timeout=test_timeout) output = session.cmd_output(err_command, timeout=test_timeout) error.context("Get error message from command perror", logging.info) perror_cmd = "perror %s" % errn std_msg = utils.system_output(perror_cmd) std_msg = re.findall(re_std_msg, std_msg) if std_msg: std_msg = std_msg[0] else: std_msg = "" logging.warning("Can not find error message from perror") session.close() error.context("Compare the error message", logging.info) if std_msg: if std_msg in output: logging.info("Error message is correct in qemu-io") else: fail_log = "The error message is mismatch:" fail_log += "qemu-io reports: '%s'," % output fail_log += "perror reports: '%s'" % std_msg raise error.TestFail(fail_log) else: logging.warning("Can not find error message from perror." " The output from qemu-io is %s" % output)
def run(test, params, env): """ Run qemu-io blkdebug tests: 1. Create image with given parameters 2. Write the blkdebug config file 3. Try to do operate in image with qemu-io and get the error message 4. Get the error message from os.strerror by error number set in config file 5. Compare the error message :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ if params.get("blkdebug_event_name_separator") == 'underscore': blkdebug_event = params.get('err_event') if "." in blkdebug_event: params['err_event'] = blkdebug_event.replace(".", "_") tmp_dir = params.get("tmp_dir", "/tmp") blkdebug_cfg = utils_misc.get_path(tmp_dir, params.get("blkdebug_cfg", "blkdebug.cfg")) err_command = params["err_command"] err_event = params["err_event"] errn_list = re.split(r"\s+", params["errn_list"].strip()) test_timeout = int(params.get("test_timeout", "60")) pre_err_commands = params.get("pre_err_commands") image = params.get("images") blkdebug_default = params.get("blkdebug_default") session_reload = params.get("session_reload", "no") == "yes" pre_snapshot = params.get("pre_snapshot", "no") == "yes" del_snapshot = params.get("del_snapshot", "no") == "yes" error_context.context("Create image", logging.info) image_io = QemuImg( params.object_params(image), data_dir.get_data_dir(), image) image_name, _ = image_io.create(params.object_params(image)) template_name = utils_misc.get_path(test.virtdir, blkdebug_default) template = ConfigParser() template.read(template_name) for errn in errn_list: log_filename = utils_misc.get_path(test.outputdir, "qemu-io-log-%s" % errn) error_context.context("Write the blkdebug config file", logging.info) template.set("inject-error", "event", '"%s"' % err_event) template.set("inject-error", "errno", '"%s"' % errn) error_context.context("Write blkdebug config file", logging.info) blkdebug = None try: blkdebug = open(blkdebug_cfg, 'w') template.write(blkdebug) finally: if blkdebug is not None: blkdebug.close() error_context.context("Create image", logging.info) image_io = QemuImg(params.object_params( image), data_dir.get_data_dir(), image) image_name = image_io.create(params.object_params(image))[0] error_context.context("Operate in qemu-io to trigger the error", logging.info) session = qemu_io.QemuIOShellSession(test, params, image_name, blkdebug_cfg=blkdebug_cfg, log_filename=log_filename) if pre_err_commands: for cmd in re.split(",", pre_err_commands.strip()): session.cmd_output(cmd, timeout=test_timeout) if session_reload or pre_snapshot: session.close() if pre_snapshot: image_io.snapshot_create() image_sn = image_io.snapshot_tag session = qemu_io.QemuIOShellSession(test, params, image_name, blkdebug_cfg=blkdebug_cfg, log_filename=log_filename) if not del_snapshot: output = session.cmd_output(err_command, timeout=test_timeout) session.close() else: session.close() try: image_io.snapshot_del(blkdebug_cfg=blkdebug_cfg) output = "" except process.CmdError as err: output = err.result.stderr # Remove the snapshot and base image after a round of test image_io.remove() if pre_snapshot and not del_snapshot: params_sn = params.object_params(image_sn) image_snapshot = QemuImg( params_sn, data_dir.get_data_dir(), image_sn) image_snapshot.remove() error_context.context("Get error message", logging.info) try: std_msg = os.strerror(int(errn)) except ValueError: test.error("Can not find error message:\n" " error code is %s" % errn) session.close() error_context.context("Compare the error message", logging.info) if std_msg in output: logging.info("Error message is correct in qemu-io") else: fail_log = "The error message is mismatch:\n" fail_log += " qemu-io reports: '%s',\n" % output fail_log += " os.strerror reports: '%s'" % std_msg test.fail(fail_log)
def run(test, params, env): """ Run qemu-io blkdebug tests: 1. Create image with given parameters 2. Write the blkdebug config file 3. Try to do operate in image with qemu-io and get the error message 4. Get the error message from os.strerror by error number set in config file 5. Compare the error message :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ if params.get("blkdebug_event_name_separator") == 'underscore': blkdebug_event = params.get('err_event') if "." in blkdebug_event: params['err_event'] = blkdebug_event.replace(".", "_") tmp_dir = params.get("tmp_dir", "/tmp") blkdebug_cfg = utils_misc.get_path(tmp_dir, params.get("blkdebug_cfg", "blkdebug.cfg")) err_command = params["err_command"] err_event = params["err_event"] errn_list = re.split("\s+", params["errn_list"].strip()) test_timeout = int(params.get("test_timeout", "60")) pre_err_commands = params.get("pre_err_commands") image = params.get("images") blkdebug_default = params.get("blkdebug_default") session_reload = params.get("session_reload", "no") == "yes" pre_snapshot = params.get("pre_snapshot", "no") == "yes" del_snapshot = params.get("del_snapshot", "no") == "yes" error.context("Create image", logging.info) image_io = QemuImg( params.object_params(image), data_dir.get_data_dir(), image) image_name, _ = image_io.create(params.object_params(image)) template_name = utils_misc.get_path(test.virtdir, blkdebug_default) template = ConfigParser.ConfigParser() template.read(template_name) for errn in errn_list: log_filename = utils_misc.get_path(test.outputdir, "qemu-io-log-%s" % errn) error.context("Write the blkdebug config file", logging.info) template.set("inject-error", "event", '"%s"' % err_event) template.set("inject-error", "errno", '"%s"' % errn) error.context("Write blkdebug config file", logging.info) blkdebug = None try: blkdebug = open(blkdebug_cfg, 'w') template.write(blkdebug) finally: if blkdebug is not None: blkdebug.close() error.context("Create image", logging.info) image_io = QemuImg(params.object_params( image), data_dir.get_data_dir(), image) image_name = image_io.create(params.object_params(image))[0] error.context("Operate in qemu-io to trigger the error", logging.info) session = qemu_io.QemuIOShellSession(test, params, image_name, blkdebug_cfg=blkdebug_cfg, log_filename=log_filename) if pre_err_commands: for cmd in re.split(",", pre_err_commands.strip()): session.cmd_output(cmd, timeout=test_timeout) if session_reload or pre_snapshot: session.close() if pre_snapshot: image_io.snapshot_create() image_sn = image_io.snapshot_tag session = qemu_io.QemuIOShellSession(test, params, image_name, blkdebug_cfg=blkdebug_cfg, log_filename=log_filename) if not del_snapshot: output = session.cmd_output(err_command, timeout=test_timeout) session.close() else: session.close() try: image_io.snapshot_del(blkdebug_cfg=blkdebug_cfg) output = "" except process.CmdError, err: output = err.result.stderr # Remove the snapshot and base image after a round of test image_io.remove() if pre_snapshot and not del_snapshot: params_sn = params.object_params(image_sn) image_snapshot = QemuImg( params_sn, data_dir.get_data_dir(), image_sn) image_snapshot.remove() error.context("Get error message", logging.info) try: std_msg = os.strerror(int(errn)) except ValueError: raise error.TestError("Can not find error message:\n" " error code is %s" % errn) session.close() error.context("Compare the error message", logging.info) if std_msg in output: logging.info("Error message is correct in qemu-io") else: fail_log = "The error message is mismatch:\n" fail_log += " qemu-io reports: '%s',\n" % output fail_log += " os.strerror reports: '%s'" % std_msg raise error.TestFail(fail_log)
def run(test, params, env): """ Run qcow2 performance tests: 1. Create image with given parameters 2. Write to the image to prepare a certain size image 3. Do one operations to the image and measure the time 4. Record the results :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ image_chain = params.get("image_chain") test_image = int(params.get("test_image", "0")) interval_size = params.get("interval_szie", "64k") write_round = int(params.get("write_round", "16384")) op_type = params.get("op_type") new_base = params.get("new_base") writecmd = params.get("writecmd") iocmd = params.get("iocmd") opcmd = params.get("opcmd") io_options = params.get("io_options", "n") cache_mode = params.get("cache_mode") image_dir = data_dir.get_data_dir() if not re.match("\d+", interval_size[-1]): write_unit = interval_size[-1] interval_size = int(interval_size[:-1]) else: interval_size = int(interval_size) write_unit = "" error.context("Init images for testing", logging.info) sn_list = [] for img in re.split("\s+", image_chain.strip()): image_params = params.object_params(img) sn_tmp = QemuImg(image_params, image_dir, img) sn_tmp.create(image_params) sn_list.append((sn_tmp, image_params)) # Write to the test image error.context("Prepare the image with write a certain size block", logging.info) dropcache = 'echo 3 > /proc/sys/vm/drop_caches && sleep 5' snapshot_file = sn_list[test_image][0].image_filename if op_type != "writeoffset1": offset = 0 writecmd0 = writecmd % (write_round, offset, interval_size, write_unit, interval_size, write_unit) iocmd0 = iocmd % (writecmd0, io_options, snapshot_file) logging.info("writecmd-offset-0: %s", writecmd0) utils.run(dropcache) output = utils.run(iocmd0) else: offset = 1 writecmd1 = writecmd % (write_round, offset, interval_size, write_unit, interval_size, write_unit) iocmd1 = iocmd % (writecmd1, io_options, snapshot_file) logging.info("writecmd-offset-1: %s", writecmd1) utils.run(dropcache) output = utils.run(iocmd1) error.context("Do one operations to the image and measure the time", logging.info) if op_type == "read": readcmd = opcmd % (io_options, snapshot_file) logging.info("read: %s", readcmd) utils.run(dropcache) output = utils.run(readcmd) elif op_type == "commit": commitcmd = opcmd % (cache_mode, snapshot_file) logging.info("commit: %s", commitcmd) utils.run(dropcache) output = utils.run(commitcmd) elif op_type == "rebase": new_base_img = QemuImg(params.object_params(new_base), image_dir, new_base) new_base_img.create(params.object_params(new_base)) rebasecmd = opcmd % (new_base_img.image_filename, cache_mode, snapshot_file) logging.info("rebase: %s", rebasecmd) utils.run(dropcache) output = utils.run(rebasecmd) elif op_type == "convert": convertname = sn_list[test_image][0].image_filename + "_convert" convertcmd = opcmd % (snapshot_file, cache_mode, convertname) logging.info("convert: %s", convertcmd) utils.run(dropcache) output = utils.run(convertcmd) error.context("Result recording", logging.info) result_file = open("%s/%s_%s_results" % (test.resultsdir, "qcow2perf", op_type), 'w') result_file.write("%s:%s\n" % (op_type, output)) logging.info("%s takes %s" % (op_type, output)) result_file.close()
logging.info("Enable virt NFS SELinux boolean on target host.") seLinuxBool = SELinuxBoolean(params) seLinuxBool.setup() subdriver = utils_test.get_image_info(shared_storage)['format'] extra_attach = ("--config --driver qemu --subdriver %s --cache %s" % (subdriver, disk_cache)) # Attach a scsi device for special testcases if attach_scsi_disk: shared_dir = os.path.dirname(shared_storage) # This is a workaround. It does not take effect to specify # this parameter in config file params["image_name"] = "scsi_test" scsi_qemuImg = QemuImg(params, shared_dir, '') scsi_disk, _ = scsi_qemuImg.create(params) s_attach = virsh.attach_disk(vm_name, scsi_disk, "sdb", extra_attach, debug=True) if s_attach.exit_status != 0: logging.error("Attach another scsi disk failed.") # Get vcpu and memory info of guest for numa related tests if enable_numa: numa_dict_list = [] vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) vcpu = vmxml.vcpu max_mem = vmxml.max_mem max_mem_unit = vmxml.max_mem_unit
def run(test, params, env): """ A 'qemu-img' resize test. 1.create a raw/qcow2/luks image 2.change the raw/qcow2/luks image size * n 3.verify resize * n :param test: Qemu test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def _sum_size_changes(size_changes): """ Sum the list of size changes. :param size_changes: list of size changes """ res = [] for change in size_changes: s = int(utils_numeric.normalize_data_size( change, "B")) * (-1 if '-' in change else 1) res.append(s) return sum(res) def _verify_resize_image(img_size, expected_size): """Verify the image size is as expected after resize.""" logging.info("Verify the size of %s is %s.", img.image_filename, expected_size) if img_size != expected_size: test.fail("Got image virtual size: %s, should be: %s." % (img_size, expected_size)) def _verify_resize_disk(disk_size, expected_size): """ Verify the disk size is as expected after resize. """ logging.info("Verify the disk size of the image %s is %sG.", img.image_filename, expected_size) if disk_size != expected_size: test.fail("Got image actual size: %sG, should be: %sG." % (disk_size, expected_size)) def _resize(size_changes, preallocation): """Resize the image and verify its size.""" for idx, size in enumerate(size_changes): logging.info("Resize the raw image %s %s with preallocation %s.", img.image_filename, size, preallocation) shrink = True if "-" in size else False img.resize(size, shrink=shrink, preallocation=preallocation) if preallocation in ["full", "falloc"]: disk_size = json.loads(img.info(output="json"))["actual-size"] # Set the magnitude order to GiB, allow some bytes deviation disk_size = float( utils_numeric.normalize_data_size(str(disk_size), "G")) expected_disk_size = size[1] _verify_resize_disk(int(disk_size), int(expected_disk_size)) img_size = json.loads(img.info(output="json"))["virtual-size"] expected_size = (int( utils_numeric.normalize_data_size(params["image_size_test"], "B")) + _sum_size_changes(size_changes[:idx + 1])) _verify_resize_image(img_size, expected_size) img_param = params.object_params('test') img = QemuImg(img_param, data_dir.get_data_dir(), 'test') size_changes = params["size_changes"].split() preallocation = params.get("preallocation") logging.info("Create a raw image %s.", img.image_filename) img.create(img_param) _resize(size_changes, preallocation)
logging.info("Enable virt NFS SELinux boolean on target host.") seLinuxBool = SELinuxBoolean(params) seLinuxBool.setup() subdriver = utils_test.get_image_info(shared_storage)['format'] extra_attach = ("--config --driver qemu --subdriver %s --cache %s" % (subdriver, disk_cache)) # Attach a scsi device for special testcases if attach_scsi_disk: shared_dir = os.path.dirname(shared_storage) # This is a workaround. It does not take effect to specify # this parameter in config file params["image_name"] = "scsi_test" scsi_qemuImg = QemuImg(params, shared_dir, '') scsi_disk, _ = scsi_qemuImg.create(params) s_attach = virsh.attach_disk(vm_name, scsi_disk, "sdb", extra_attach, debug=True) if s_attach.exit_status != 0: logging.error("Attach another scsi disk failed.") # Get vcpu and memory info of guest for numa related tests if enable_numa: numa_dict_list = [] vmxml = vm_xml.VMXML.new_from_dumpxml(vm.name) vcpu = vmxml.vcpu max_mem = vmxml.max_mem max_mem_unit = vmxml.max_mem_unit if vcpu < 1: raise error.TestError("%s not having even 1 vcpu" % vm.name)