def _qemu_img_info(tag, backing_tag=None): """Run qemu info to given image.""" img_param = params.object_params(tag) img = QemuImg(img_param, img_root_dir, tag) output = img.info(output="json") _verify_backing_file(output, backing_tag) return img
def run(test, params, env): """ qemu-img map an unaligned image. 1.create a raw file using truncate 2.write data into the raw file 3.verify the dumped mete-data using qemu-img map :param test: Qemu test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment """ def _generate_random_string(max_len=19): """Generate random alphabets string in the range of [1, max_len+1].""" random_str = ''.join(random.choice( string.ascii_lowercase) for _ in range(random.randint(1, max_len))) return random_str, len(random_str) def _verify_qemu_img_map(output, str_len): """Verify qemu-img map's output.""" logging.info("Verify the dumped mete-data of the unaligned image.") qemu_path = utils_misc.get_qemu_binary(params) qemu_version = env_process._get_qemu_version(qemu_path) match = re.search(r'[0-9]+\.[0-9]+\.[0-9]+(\-[0-9]+)?', qemu_version) host_qemu = match.group(0) if host_qemu in VersionInterval('[6.1.0,)'): expected = [ {"start": 0, "length": str_len, "depth": 0, "present": True, "zero": False, "data": True, "offset": 0}, {"start": str_len, "length": 512 - (str_len % 512), "depth": 0, "present": True, "zero": True, "data": False, "offset": str_len}] else: expected = [{"start": 0, "length": str_len, "depth": 0, "zero": False, "data": True, "offset": 0}, {"start": str_len, "length": 512 - (str_len % 512), "depth": 0, "zero": True, "data": False, "offset": str_len}] res = json.loads(output) if res != expected: test.fail("The dumped mete-data of the unaligned " "image '%s' is not correct." % img.image_filename) img_param = params.object_params("test") img = QemuImg(img_param, data_dir.get_data_dir(), "test") logging.info("Create a new file %s using truncate.", img.image_filename) process.run("rm -f %s" % img.image_filename) process.run("truncate -s 1G %s " % img.image_filename) random_str, str_len = _generate_random_string() logging.info("Write '%s' into the file %s.", random_str, img.image_filename) process.run("echo -n '%s' > %s" % (random_str, img.image_filename), shell=True) res = img.map(output="json") if res.exit_status != 0: test.fail("qemu-img map error: %s." % res.stderr_text) _verify_qemu_img_map(res.stdout_text, str_len)
def _qemu_img_info(info_img): error_context.context("Check qemu-img info with %s." % info_img, logging.info) img_param = params.object_params(info_img) img = QemuImg(img_param, data_dir.get_data_dir(), info_img) try: img.info() except process.CmdError: test.fail("qemu-img info %s failed." % info_img)
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): """ 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 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 _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 convert images with unaligned size. 1. create source image via truncate, and write 10k "1" into the source image via qemu-io 2. convert the source image to target, check whether there is error :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: test.fail("qemu-io to '%s' failed." % img.image_filename) src_image = params["images"] tgt_image = params["convert_target"] img_dir = data_dir.get_data_dir() source = QemuImg(params.object_params(src_image), img_dir, src_image) with open(source.image_filename, mode='wb') as fd: fd.truncate(int(params["truncate_size"])) _qemu_io(source, 'write -P 1 0 %s' % params["write_size"]) fail_on((process.CmdError, ))(source.convert)(source.params, img_dir, cache_mode="none", source_cache_mode="none") params["images"] += " " + tgt_image
def run(test, params, env): """ qemu-img map an unaligned image. 1.create a raw file using truncate 2.write data into the raw file 3.verify the dumped mete-data using qemu-img map :param test: Qemu test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment """ def _generate_random_string(max_len=19): """Generate random alphabets string in the range of [1, max_len+1].""" random_str = ''.join(random.choice( string.ascii_lowercase) for _ in range(random.randint(1, max_len))) return random_str, len(random_str) def _verify_qemu_img_map(output, str_len): """Verify qemu-img map's output.""" logging.info("Verify the dumped mete-data of the unaligned image.") expected = [{"start": 0, "length": str_len, "depth": 0, "zero": False, "data": True, "offset": 0}, {"start": str_len, "length": 512 - (str_len % 512), "depth": 0, "zero": True, "data": False, "offset": str_len}] res = json.loads(output) if res != expected: test.fail("The dumped mete-data of the unaligned " "image '%s' is not correct." % img.image_filename) img_param = params.object_params("test") img = QemuImg(img_param, data_dir.get_data_dir(), "test") logging.info("Create a new file %s using truncate." % img.image_filename) process.run("rm -f %s" % img.image_filename) process.run("truncate -s 1G %s " % img.image_filename) random_str, str_len = _generate_random_string() logging.info("Write '%s' into the file %s." % (random_str, img.image_filename)) process.run("echo -n '%s' > %s" % (random_str, img.image_filename), shell=True) res = img.map(output="json") if res.exit_status != 0: test.fail("qemu-img map error: %s." % res.stderr_text) _verify_qemu_img_map(res.stdout_text, str_len)
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 _verify_backing_file(output, backing_tag): """Verify backing file is as expected.""" if backing_tag is None: return backing_param = params.object_params(backing_tag) backing = QemuImg(backing_param, img_root_dir, backing_tag) if backing.image_filename not in json.loads( output)["backing-filename"]: test.fail("Backing file is not correct.")
def get_node_name(image_tag): """ Get the node name. """ img_params = params.object_params(image_tag) root_dir = data_dir.get_data_dir() img = QemuImg(img_params, root_dir, image_tag) filename = img.image_filename if img.image_format == 'luks': filename = get_image_json(image_tag, img_params, root_dir) return vm.get_block({"filename": filename})
def commit(self, t_params=None): """ commit snapshot to backing file; """ error_context.context("commit snapshot to backingfile", logging.info) params = self.params.object_params(self.tag) if t_params: params.update(t_params) cache_mode = params.get("cache_mode") return QemuImg.commit(self, params, cache_mode)
def run(test, params, env): """ Check the data after resizing short overlay over longer backing files. 1. Create a qcow2 base image. 2. Create a middle snapshot file with smaller size. 3. Create a top snapshot with the size as the same as the one of base. 4. Write '1' to the base image file. 5. Check the data of the top image file. 6. Commit top image file. 7. Check the data in the middle image file. :param test: VT 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)) images = params["image_chain"].split() root_dir = data_dir.get_data_dir() base = QemuImg(params.object_params(images[0]), root_dir, images[0]) mid = QemuImg(params.object_params(images[1]), root_dir, images[1]) top = QemuImg(params.object_params(images[-1]), root_dir, images[-1]) logging.info("Create base and snapshot files") for image in (base, mid, top): image.create(image.params) _qemu_io(base, params["base_cmd"]) top_cmd = params["top_cmd"] _qemu_io(top, top_cmd) logging.info("Commit %s image file." % top.image_filename) fail_on((process.CmdError, ))(top.commit)() _qemu_io(mid, top_cmd)
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 _verify_write_lock_err_msg(e, img_tag): error_context.context("Verify qemu-img write lock err msg.", logging.info) img_param = params.object_params(img_tag) img = QemuImg(img_param, data_dir.get_data_dir(), img_tag) msgs = [ '"write" lock', 'Is another process using the image', img.image_filename ] if not all(msg in e.result.stderr.decode() for msg in msgs): test.fail("Image lock information is not as expected.")
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 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): """ 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 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): """ qemu-img uses larger output buffer for "none" cache mode. 1. Create 100M source image with random data via 'dd'. 2. Trace the system calls while converting the source image to the a qcow2 target image, and check the maxim result of pwrite/pwrite64 should be 2M. :param test: Qemu test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ src_image = params["images"] tgt_image = params["convert_target"] 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_with_none.log") src_filename = source.image_filename process.run("dd if=/dev/urandom of=%s bs=1M count=100" % src_filename) logging.debug( "Convert from %s to %s with cache mode none, strace log: " "%s.", src_filename, tgt_image, 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") logging.debug("Check whether the max size of %s syscall is 2M in %s.", strace_event, strace_output_file) with open(strace_output_file) as fd: for line in fd.readlines(): if int(line.split()[-1]) == 2097152: break else: test.fail("The max size of '%s' is not 2M, check '%s' please.", strace_event, strace_output_file) params["images"] += " " + tgt_image
def run(test, params, env): """ Image creation locking should be properly released. 1. Create raw image and close it after 0.5 sec. 2. Check there is no lock error of the CML. :param test: Qemu test object. :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ lock_test = params["images"] root_dir = data_dir.get_data_dir() test_image = QemuImg(params.object_params(lock_test), root_dir, lock_test) test_filename = test_image.image_filename lock_err_info = 'Failed to get "consistent read" lock' try: process.run("qemu-img create -f raw -o preallocation=full %s 1G & " "sleep 0.5;qemu-io -c info -c close -r %s" % (test_filename, test_filename), shell=True) except process.CmdError as err: if lock_err_info in err.result.stderr.decode(): test.fail("Image lock not released: %s" % err) else: test.error("Command line failed: %s" % err)
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 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 _get_img_obj_and_params(tag): """Get an QemuImg object and its params based on the tag.""" img_param = params.object_params(tag) img = QemuImg(img_param, data_dir.get_data_dir(), tag) return img, img_param
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): """ change a removable media: 1) Boot VM with QMP/human monitor enabled. 2) Connect to QMP/human monitor server. 3) Eject original cdrom. 4) Eject original cdrom for second time. 5) Insert new image to cdrom. 6) Eject device after add new image by change command. 7) Insert original cdrom to cdrom. 8) Try to eject non-removable device w/o force option. :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment """ vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360))) logging.info("Wait until device is ready") time.sleep(10) def check_block(block): return True if block in str(vm.monitor.info("block")) else False orig_img_name = params.get("cdrom_cd1") p_dict = {"file": orig_img_name} device_name = vm.get_block(p_dict) if device_name is None: msg = "Fail to get device using image %s" % orig_img_name test.fail(msg) eject_check = QMPEventCheckCDEject(vm, device_name) change_check = QMPEventCheckCDChange(vm, device_name) # eject first time error_context.context("Eject original device.", logging.info) with eject_check: vm.eject_cdrom(device_name) if check_block(orig_img_name): test.fail("Fail to eject cdrom %s. " % orig_img_name) # eject second time error_context.context("Eject original device for second time", logging.info) with eject_check: vm.eject_cdrom(device_name) # change media new_img_name = params.get("new_img_name") error_context.context("Insert new image to device.", logging.info) with change_check: vm.change_media(device_name, new_img_name) if not check_block(new_img_name): test.fail("Fail to change cdrom to %s." % new_img_name) # eject after change error_context.context("Eject device after add new image by change command", logging.info) with eject_check: vm.eject_cdrom(device_name) if check_block(new_img_name): test.fail("Fail to eject cdrom %s." % orig_img_name) # change back to orig_img_name error_context.context( "Insert %s to device %s" % (orig_img_name, device_name), logging.info) with change_check: vm.change_media(device_name, orig_img_name) if not check_block(orig_img_name): test.fail("Fail to change cdrom to %s." % orig_img_name) # change again error_context.context( "Insert %s to device %s" % (new_img_name, device_name), logging.info) with change_check: vm.change_media(device_name, new_img_name) if not check_block(new_img_name): test.fail("Fail to change cdrom to %s." % new_img_name) # eject non-removable error_context.context("Try to eject non-removable device", logging.info) p_dict = {"removable": False} device_name = vm.get_block(p_dict) if vm.check_capability(Flags.BLOCKDEV): sys_image = QemuImg(params, data_dir.get_data_dir(), params['images'].split()[0]) device_name = vm.get_block({"filename": sys_image.image_filename}) if device_name is None: test.error("Could not find non-removable device") try: if params.get("force_eject", "no") == "yes": vm.eject_cdrom(device_name, force=True) else: vm.eject_cdrom(device_name) except Exception as e: if "is not removable" not in str(e): test.fail(e) logging.debug("Catch exception message: %s" % e) if not check_block(device_name): test.fail("Could remove non-removable device!") session.close()
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 _qemu_img_info(info_img, force_share=False): error_context.context("Check qemu-img info with %s." % info_img, logging.info) img_param = params.object_params(info_img) img = QemuImg(img_param, data_dir.get_data_dir(), info_img) img.info(force_share)
def run(test, params, env): """ KVM block resize test: 1) Start guest with data disk or system disk. 2) Do format disk in guest if needed. 3) Record md5 of test file on the data disk. Enlarge the data disk image from qemu monitor. 4) Extend data disk partition/file-system in guest. 5) Verify the data disk size match expected size. 6) Reboot the guest. 7) Do iozone test, compare the md5 of test file. 8) Shrink data disk partition/file-system in guest. 9) Shrink data disk image from qemu monitor. 10) Verify the data disk size match expected size. 11) Reboot the guest. 12) Do iozone test, compare the md5 of test file. :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def verify_disk_size(session, os_type, disk): """ Verify the current block size match with the expected size. """ global current_size current_size = utils_disk.get_disk_size(session, os_type, disk) accept_ratio = float(params.get("accept_ratio", 0)) if (current_size <= block_size and current_size >= block_size * (1 - accept_ratio)): logging.info( "Block Resizing Finished !!! \n" "Current size %s is same as the expected %s", current_size, block_size) return True def create_md5_file(filename): """ Create the file to verify md5 value. """ logging.debug("create md5 file %s" % filename) if os_type == 'windows': vm.copy_files_to(params["tmp_md5_file"], filename) else: session.cmd(params["dd_cmd"] % filename) def get_md5_of_file(filename): """ Get the md5 value of filename. """ ex_args = (mpoint, filename) if os_type == 'windows' else filename return session.cmd(md5_cmd % ex_args).split()[0] vm = env.get_vm(params["main_vm"]) vm.verify_alive() timeout = float(params.get("login_timeout", 240)) driver_name = params.get("driver_name") os_type = params["os_type"] fstype = params.get("fstype") labeltype = params.get("labeltype", "msdos") img_size = params.get("image_size_stg", "10G") mpoint = params.get("disk_letter", "C") disk = params.get("disk_index", 0) md5_cmd = params.get("md5_cmd", "md5sum %s") md5_file = params.get("md5_file", "md5.dat") data_image = params.get("images").split()[-1] data_image_params = params.object_params(data_image) data_image_filename = storage.get_image_filename(data_image_params, data_dir.get_data_dir()) data_image_dev = vm.get_block({'file': data_image_filename}) img = QemuImg(data_image_params, data_dir.get_data_dir(), data_image) block_virtual_size = json.loads(img.info(force_share=True, output="json"))["virtual-size"] session = vm.wait_for_login(timeout=timeout) if os_type == 'windows' and driver_name: session = utils_test.qemu.windrv_check_running_verifier( session, vm, test, driver_name, timeout) if params.get("format_disk") == "yes": if os_type == 'linux': disk = sorted(utils_disk.get_linux_disks(session).keys())[0] else: disk = utils_disk.get_windows_disks_index(session, img_size)[0] utils_disk.update_windows_disk_attributes(session, disk) error_context.context("Formatting disk", logging.info) mpoint = utils_disk.configure_empty_disk(session, disk, img_size, os_type, fstype=fstype, labeltype=labeltype)[0] partition = mpoint.replace('mnt', 'dev') if 'mnt' in mpoint else None for ratio in params.objects("disk_change_ratio"): block_size = int(int(block_virtual_size) * float(ratio)) # Record md5 if params.get('md5_test') == 'yes': junction = ":\\" if os_type == 'windows' else "/" md5_filename = mpoint + junction + md5_file create_md5_file(md5_filename) md5 = get_md5_of_file(md5_filename) logging.debug("Got md5 %s ratio:%s on %s" % (md5, ratio, disk)) # We need shrink the disk in guest first, than in monitor if float(ratio) < 1.0: error_context.context( "Shrink disk size to %s in guest" % block_size, logging.info) if os_type == 'windows': shr_size = utils_numeric.normalize_data_size( str( utils_disk.get_disk_size(session, os_type, disk) - block_size), 'M').split(".")[0] drive.shrink_volume(session, mpoint, shr_size) else: utils_disk.resize_filesystem_linux(session, partition, str(block_size)) utils_disk.resize_partition_linux(session, partition, str(block_size)) error_context.context("Change disk size to %s in monitor" % block_size, logging.info) if vm.check_capability(Flags.BLOCKDEV): args = (None, block_size, data_image_dev) else: args = (data_image_dev, block_size) vm.monitor.block_resize(*args) if params.get("guest_prepare_cmd", ""): session.cmd(params.get("guest_prepare_cmd")) # Update GPT due to size changed if os_type == "linux" and labeltype == "gpt": session.cmd("sgdisk -e /dev/%s" % disk) if params.get("need_reboot") == "yes": session = vm.reboot(session=session) if params.get("need_rescan") == "yes": drive.rescan_disks(session) # We need extend disk in monitor first than extend it in guest if float(ratio) > 1.0: error_context.context("Extend disk to %s in guest" % block_size, logging.info) if os_type == 'windows': drive.extend_volume(session, mpoint) else: utils_disk.resize_partition_linux(session, partition, str(block_size)) utils_disk.resize_filesystem_linux(session, partition, utils_disk.SIZE_AVAILABLE) global current_size current_size = 0 if not wait.wait_for(lambda: verify_disk_size(session, os_type, disk), 20, 0, 1, "Block Resizing"): test.fail("Block size get from guest is not same as expected.\n" "Reported: %s\nExpect: %s\n" % (current_size, block_size)) session = vm.reboot(session=session) if os_type == 'linux': if not utils_disk.is_mount( partition, dst=mpoint, fstype=fstype, session=session): utils_disk.mount(partition, mpoint, fstype=fstype, session=session) if params.get('iozone_test') == 'yes': iozone_timeout = float(params.get("iozone_timeout", 1800)) iozone_cmd_options = params.get("iozone_option") % mpoint io_test = generate_instance(params, vm, 'iozone') try: io_test.run(iozone_cmd_options, iozone_timeout) finally: io_test.clean() # Verify md5 if params.get('md5_test') == 'yes': new_md5 = get_md5_of_file(md5_filename) test.assertTrue(new_md5 == md5, "Unmatched md5: %s" % new_md5) session.close()
def run(test, params, env): """ Check the dump info of snapshot files over nbd. 1. Create a base image with 4 clusters of 64k. 3. Create a top snapshot based on the base image. 4. Write data to the first/second/third cluster of the base image file. 5. Write data to the second/third cluster of the top image. 6. Export the snapshot image over NBD. 7. Check the dump info of the snapshot over NBD. :param test: VT 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.""" 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, str(err))) images = params["image_chain"].split() base_img = images[0] top_img = images[1] root_dir = data_dir.get_data_dir() base = QemuImg(params.object_params(base_img), root_dir, base_img) top = QemuImg(params.object_params(top_img), root_dir, top_img) # write data to the base image _qemu_io(base, params["base_io_cmd_01"]) _qemu_io(base, params["base_io_cmd_02"]) _qemu_io(base, params["base_io_cmd_03"]) # write data to the top image _qemu_io(top, params["top_io_cmd_01"]) _qemu_io(top, params["top_io_cmd_02"]) # export the top image over nbd nbd_export = QemuNBDExportImage(params, top_img) nbd_export.export_image() nbd_image_tag = params['nbd_image_tag'] nbd_image_params = params.object_params(nbd_image_tag) localhost = socket.gethostname() nbd_image_params['nbd_server'] = localhost if localhost else 'localhost' qemu_img = qemu_storage.QemuImg(nbd_image_params, None, nbd_image_tag) nbd_image = qemu_img.image_filename map_cmd = params["map_cmd"] check_msg = params["check_msg"] logging.info("Dump the info of '%s'", nbd_image) try: result = process.run(map_cmd + " " + nbd_image, ignore_status=True, shell=True) if result.exit_status != 0: test.fail('Failed to execute the map command, error message: %s' % result.stderr.decode()) elif check_msg not in result.stdout.decode().strip(): test.fail("Message '%s' mismatched with '%s'" % (check_msg, result.stdout.decode())) finally: nbd_export.stop_export()
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("\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 if vcpu < 1: raise error.TestError("%s not having even 1 vcpu"