def summary_up_result(result_file, ignore, row_head, column_mark): """ Use to summary the monitor or other kinds of results. Now it calculates the average value for each item in the results. It fits to the records that are in matrix form. @result_file: files which need to calculate @ignore: pattern for the comment in results which need to through away @row_head: pattern for the items in row @column_mark: pattern for the first line in matrix which used to generate the items in column Return: A dictionary with the average value of results """ head_flag = False result_dict = {} column_list = {} row_list = [] fd = open(result_file, "r") for eachLine in fd: if len(re.findall(ignore, eachLine)) == 0: if len(re.findall(column_mark, eachLine)) != 0 and not head_flag: column = 0 _, row, eachLine = re.split(row_head, eachLine) for i in re.split("\s+", eachLine): if i: result_dict[i] = {} column_list[column] = i column += 1 head_flag = True elif len(re.findall(column_mark, eachLine)) == 0: column = 0 _, row, eachLine = re.split(row_head, eachLine) row_flag = False for i in row_list: if row == i: row_flag = True if row_flag is False: row_list.append(row) for i in result_dict: result_dict[i][row] = [] for i in re.split("\s+", eachLine): if i: result_dict[column_list[column]][row].append(i) column += 1 fd.close() # Calculate the average value average_list = {} for i in column_list: average_list[column_list[i]] = {} for j in row_list: average_list[column_list[i]][j] = {} check = result_dict[column_list[i]][j][0] if utils_misc.aton(check) or utils_misc.aton(check) == 0.0: count = 0 for k in result_dict[column_list[i]][j]: count += utils_misc.aton(k) average_list[column_list[i]][j] = "%.2f" % ( count / len(result_dict[column_list[i]][j])) return average_list
def summary_up_result(result_file, ignore, row_head, column_mark): """ Use to summary the monitor or other kinds of results. Now it calculates the average value for each item in the results. It fits to the records that are in matrix form. @result_file: files which need to calculate @ignore: pattern for the comment in results which need to through away @row_head: pattern for the items in row @column_mark: pattern for the first line in matrix which used to generate the items in column Return: A dictionary with the average value of results """ head_flag = False result_dict = {} column_list = {} row_list = [] fd = open(result_file, "r") for eachLine in fd: if len(re.findall(ignore, eachLine)) == 0: if len(re.findall(column_mark, eachLine)) != 0 and not head_flag: column = 0 _, row, eachLine = re.split(row_head, eachLine) for i in re.split("\s+", eachLine): if i: result_dict[i] = {} column_list[column] = i column += 1 head_flag = True elif len(re.findall(column_mark, eachLine)) == 0: column = 0 _, row, eachLine = re.split(row_head, eachLine) row_flag = False for i in row_list: if row == i: row_flag = True if row_flag is False: row_list.append(row) for i in result_dict: result_dict[i][row] = [] for i in re.split("\s+", eachLine): if i: result_dict[column_list[column]][row].append(i) column += 1 fd.close() # Calculate the average value average_list = {} for i in column_list: average_list[column_list[i]] = {} for j in row_list: average_list[column_list[i]][j] = {} check = result_dict[column_list[i]][j][0] if utils_misc.aton(check) or utils_misc.aton(check) == 0.0: count = 0 for k in result_dict[column_list[i]][j]: count += utils_misc.aton(k) average_list[column_list[i]][j] = "%.2f" % (count / len(result_dict[column_list[i]][j])) return average_list
def mpstat_ana(filename): """ Get the cpu usage from the mpstat summary file :param filename: filename of the mpstat summary file """ mpstat_result = open(filename, 'r') key_value = "%idle" index = 0 result = {} for line in mpstat_result.readlines(): if key_value in line: index = line.split().index(key_value) + 1 else: data = line.split() if data[0] == "all": vcpu = "all" else: vcpu = "vcpu%s" % data[0] cpu_use = "%20.2f" % (100 - utils_misc.aton(data[index])) result[vcpu] = cpu_use return result
def run(test, params, env): """ Test how KSM (Kernel Shared Memory) act when more than physical memory is used. In second part we also test how KVM handles a situation when the host runs out of memory (it is expected to pause the guest system, wait until some process returns memory and bring the guest back to life) :param test: QEMU test object. :param params: Dictionary with test parameters. :param env: Dictionary with the test environment. """ def _start_allocator(vm, session, timeout): """ Execute guest script and wait until it is initialized. :param vm: VM object. :param session: Remote session to a VM object. :param timeout: Timeout that will be used to verify if guest script started properly. """ logging.debug("Starting guest script on guest %s", vm.name) session.sendline("$(command -v python python3 | head -1) " "/tmp/ksm_overcommit_guest.py") try: _ = session.read_until_last_line_matches(["PASS:"******"FAIL:"], timeout) except aexpect.ExpectProcessTerminatedError as exc: test.fail("Command guest script on vm '%s' failed: %s" % (vm.name, str(exc))) def _execute_allocator(command, vm, session, timeout): """ Execute a given command on guest script main loop, indicating the vm the command was executed on. :param command: Command that will be executed. :param vm: VM object. :param session: Remote session to VM object. :param timeout: Timeout used to verify expected output. :return: Tuple (match index, data) """ logging.debug("Executing '%s' on guest script loop, vm: %s, timeout: " "%s", command, vm.name, timeout) session.sendline(command) try: (match, data) = session.read_until_last_line_matches( ["PASS:"******"FAIL:"], timeout) except aexpect.ExpectProcessTerminatedError as exc: e_str = ("Failed to execute command '%s' on guest script, " "vm '%s': %s" % (command, vm.name, str(exc))) test.fail(e_str) return (match, data) timeout = float(params.get("login_timeout", 240)) guest_script_overhead = int(params.get("guest_script_overhead", 5)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_login(timeout=timeout) # Prepare work in guest error_context.context("Turn off swap in guest", logging.info) session.cmd_status_output("swapoff -a") script_file_path = os.path.join(data_dir.get_root_dir(), "shared/scripts/ksm_overcommit_guest.py") vm.copy_files_to(script_file_path, "/tmp") test_type = params.get("test_type") shared_mem = int(params["shared_mem"]) get_free_mem_cmd = params.get("get_free_mem_cmd", "grep MemFree /proc/meminfo") free_mem = vm.get_memory_size(get_free_mem_cmd) max_mem = int(free_mem / (1 + TMPFS_OVERHEAD) - guest_script_overhead) # Keep test from OOM killer if max_mem < shared_mem: shared_mem = max_mem fill_timeout = int(shared_mem) / 10 query_cmd = params.get("query_cmd") query_regex = params.get("query_regex") random_bits = params.get("random_bits") seed = random.randint(0, 255) query_cmd = re.sub("QEMU_PID", str(vm.process.get_pid()), query_cmd) sharing_page_0 = decode_to_text(process.system_output(query_cmd, verbose=False, ignore_status=True, shell=True)) if query_regex: sharing_page_0 = re.findall(query_regex, sharing_page_0)[0] error_context.context("Start to allocate pages inside guest", logging.info) _start_allocator(vm, session, 60) error_context.context("Start to fill memory in guest", logging.info) mem_fill = "mem = MemFill(%s, 0, %s)" % (shared_mem, seed) _execute_allocator(mem_fill, vm, session, fill_timeout) cmd = "mem.value_fill()" _execute_allocator(cmd, vm, session, fill_timeout) time.sleep(120) sharing_page_1 = decode_to_text(process.system_output(query_cmd, verbose=False, ignore_status=True, shell=True)) if query_regex: sharing_page_1 = re.findall(query_regex, sharing_page_1)[0] error_context.context("Start to fill memory with random value in guest", logging.info) split = params.get("split") if split == "yes": if test_type == "negative": cmd = "mem.static_random_fill(%s)" % random_bits else: cmd = "mem.static_random_fill()" _execute_allocator(cmd, vm, session, fill_timeout) time.sleep(120) sharing_page_2 = decode_to_text(process.system_output(query_cmd, verbose=False, ignore_status=True, shell=True)) if query_regex: sharing_page_2 = re.findall(query_regex, sharing_page_2)[0] # clean up work in guest error_context.context("Clean up env in guest", logging.info) session.cmd_output("die()", 20) session.cmd_status_output("swapon -a") session.cmd_output("echo 3 > /proc/sys/vm/drop_caches") sharing_page = [sharing_page_0, sharing_page_1, sharing_page_2] for i in sharing_page: if re.findall("[A-Za-z]", i): data = i[0:-1] unit = i[-1] index = sharing_page.index(i) if unit == "g": sharing_page[index] = utils_misc.aton(data) * 1024 else: sharing_page[index] = utils_misc.aton(data) fail_type = 0 if test_type == "disable": if int(sharing_page[0]) != 0 and int(sharing_page[1]) != 0: fail_type += 1 else: if int(sharing_page[0]) >= int(sharing_page[1]): fail_type += 2 if int(sharing_page[1]) <= int(sharing_page[2]): fail_type += 4 fail = ["Sharing page increased abnormally", "Sharing page didn't increase", "Sharing page didn't split"] if fail_type != 0: turns = 0 while (fail_type > 0): if fail_type % 2 == 1: logging.error(fail[turns]) fail_type = fail_type / 2 turns += 1 test.fail("KSM test failed: %s %s %s" % (sharing_page_0, sharing_page_1, sharing_page_2)) session.close()
def run(test, params, env): """ Verify hotplug feature for char device """ vm_name = params.get("main_vm", "vm1") status_error = "yes" == params.get("status_error", "no") char_dev = params.get("char_dev", "file") hotplug_type = params.get("hotplug_type", "qmp") dup_charid = "yes" == params.get("dup_charid", "no") dup_devid = "yes" == params.get("dup_devid", "no") diff_devid = "yes" == params.get("diff_devid", "no") tmp_dir = os.path.join(test.tmpdir, "hotplug_serial") if not os.path.exists(tmp_dir): os.mkdir(tmp_dir) os.chmod(tmp_dir, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) vm_xml = VMXML.new_from_inactive_dumpxml(vm_name) vm_xml_backup = vm_xml.copy() # add controller for each char device devices = vm_xml.get_devices() controllers = vm_xml.get_devices(device_type="controller") for dev in controllers: if dev.type == "virtio-serial": devices.remove(dev) controller = Controller("controller") controller.type = "virtio-serial" controller.index = 0 devices.append(controller) vm_xml.set_devices(devices) vm_xml.sync() # start and login vm vm = env.get_vm(vm_name) vm.start() session = vm.wait_for_login() def prepare_channel_xml(to_file, char_type, id=0): params = {} mode = '' if char_type == "file": channel_type = char_type channel_path = os.path.join(tmp_dir, char_type) elif char_type == "socket": channel_type = 'unix' channel_path = os.path.join(tmp_dir, char_type) mode = 'bind' elif char_type == "pty": channel_type = char_type channel_path = ("/dev/pts/%s" % id) params = {'channel_type_name': channel_type, 'source_path': channel_path, 'source_mode': mode, 'target_type': 'virtio', 'target_name': char_type} channel_xml = utlv.create_channel_xml(params, alias=True, address=True) shutil.copyfile(channel_xml.xml, to_file) def hotplug_device(type, char_dev, id=0): tmp_file = os.path.join(tmp_dir, char_dev) if type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": char_add_opt += "file,path=%s,id=file" % tmp_file dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file" elif char_dev == "socket": char_add_opt += "socket,path=%s,server,nowait,id=socket" % tmp_file dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket" elif char_dev == "pty": char_add_opt += ("pty,path=/dev/pts/%s,id=pty" % id) dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty" result = virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") if result.exit_status: test.error('Failed to add chardev %s to %s. Result:\n %s' % (char_dev, vm_name, result)) result = virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") if result.exit_status: test.error('Failed to add device %s to %s. Result:\n %s' % (char_dev, vm_name, result)) elif type == "attach": xml_file = os.path.join(tmp_dir, "xml_%s" % char_dev) if char_dev in ["file", "socket"]: prepare_channel_xml(xml_file, char_dev) elif char_dev == "pty": prepare_channel_xml(xml_file, char_dev, id) result = virsh.attach_device(vm_name, xml_file) # serial device was introduced by the following commit, # http://libvirt.org/git/? # p=libvirt.git;a=commit;h=b63ea467617e3cbee4282ab2e5e780b4119cef3d if "unknown device type" in result.stderr: test.cancel('Failed to attach %s to %s. Result:\n %s' % (char_dev, vm_name, result)) return result def dup_hotplug(type, char_dev, id, dup_charid=False, dup_devid=False, diff_devid=False): tmp_file = os.path.join(tmp_dir, char_dev) if type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": if dup_charid: char_add_opt += "file,path=%s,id=file" % tmp_file if dup_devid: dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file" if diff_devid: dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file1" elif char_dev == "socket": if dup_charid: char_add_opt += "socket,path=%s,server,nowait,id=socket" % tmp_file if dup_devid: dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket" if diff_devid: dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket1" elif char_dev == "pty": if dup_charid: char_add_opt += "pty,path=/dev/pts/%s,id=pty" % id if dup_devid: dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty" if diff_devid: dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty1" if dup_charid: result = virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") if dup_devid or diff_devid: result = virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") elif type == "attach": if dup_devid: result = hotplug_device(type, char_dev, id) return result def confirm_hotplug_result(char_dev, id=0): tmp_file = os.path.join(tmp_dir, char_dev) serial_file = os.path.join("/dev/virtio-ports", char_dev) result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") h_o = result.stdout.strip() if not h_o.count("name = \"%s\"" % char_dev): test.fail("Cann't find device(%s) from:\n%s" % (char_dev, h_o)) if char_dev == "file": session.cmd("echo test > %s" % serial_file) with open(tmp_file, "r") as f: r_o = f.read() elif char_dev == "socket": session.cmd("echo test > /tmp/file") sock = socket.socket(socket.AF_UNIX) sock.connect(tmp_file) session.cmd("dd if=/tmp/file of=%s" % serial_file) r_o = sock.recv(1024) elif char_dev == "pty": session.cmd("echo test > /tmp/file") session.cmd("dd if=/tmp/file of=%s &" % serial_file) dev_file = "/dev/pts/%s" % id if not os.path.exists(dev_file): test.fail("%s doesn't exist." % dev_file) p = subprocess.Popen(["/usr/bin/cat", dev_file], universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) session.cmd("echo test >> /tmp/file &") while True: r_o = p.stdout.readline() if r_o or p.poll(): break time.sleep(0.2) p.kill() if not r_o.count("test"): err_info = "%s device file doesn't match 'test':%s" % (char_dev, r_o) test.fail(err_info) def unhotplug_serial_device(type, char_dev): if type == "qmp": del_dev_opt = "device_del %s" % char_dev del_char_opt = "chardev-remove %s" % char_dev result = virsh.qemu_monitor_command(vm_name, del_dev_opt, "--hmp") if result.exit_status: test.error('Failed to del device %s from %s.Result:\n%s' % (char_dev, vm_name, result)) result = virsh.qemu_monitor_command(vm_name, del_char_opt, "--hmp") elif type == "attach": xml_file = os.path.join(tmp_dir, "xml_%s" % char_dev) result = virsh.detach_device(vm_name, xml_file) def confirm_unhotplug_result(char_dev): serial_file = os.path.join("/dev/virtio-ports", char_dev) result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") uh_o = result.stdout.strip() if uh_o.count("chardev = \"%s\"" % char_dev): test.fail("Still can get serial device(%s) from: '%s'" % (char_dev, uh_o)) if os.path.exists(serial_file): test.fail("File '%s' still exists after unhotplug" % serial_file) # run test case try: if char_dev in ['file', 'socket']: # if char_dev is file or socket, it doesn't need pts index pts_id = 0 else: pts_id = str(utils_misc.aton(utils_misc.get_dev_pts_max_id()) + 1) if os.path.exists("/dev/pts/%s" % pts_id): test.error('invalid pts index(%s) provided.' % pts_id) if status_error: hotplug_device(hotplug_type, char_dev, pts_id) ret = dup_hotplug(hotplug_type, char_dev, pts_id, dup_charid, dup_devid, diff_devid) dup_o = ret.stdout.strip() if hotplug_type == "qmp": # although it has failed, ret.exit_status will be returned 0. err_o1 = "Duplicate ID" err_o2 = "Parsing chardev args failed" err_o3 = "Property 'virtserialport.chardev' can't" if (err_o1 not in dup_o) and (err_o2 not in dup_o) and (err_o3 not in dup_o): test.fail("Expect fail, but run successfully:\n%s" % ret) else: if "chardev already exists" not in dup_o: logging.info("Expect fail,but run successfully:\n%s" % ret) else: if char_dev != "all": #1.hotplug serial device hotplug_device(hotplug_type, char_dev, pts_id) #2.confirm hotplug result confirm_hotplug_result(char_dev, pts_id) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, char_dev) #4.confirm unhotplug result confirm_unhotplug_result(char_dev) else: #1.hotplug serial device hotplug_device(hotplug_type, "file") hotplug_device(hotplug_type, "socket") hotplug_device(hotplug_type, "pty", pts_id) #2.confirm hotplug result confirm_hotplug_result("file") confirm_hotplug_result("socket") confirm_hotplug_result("pty", pts_id) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, "file") unhotplug_serial_device(hotplug_type, "socket") unhotplug_serial_device(hotplug_type, "pty") #4.confirm unhotplug result confirm_unhotplug_result("file") confirm_unhotplug_result("socket") confirm_unhotplug_result("pty") finally: vm_xml_backup.sync() if os.path.exists(tmp_dir): shutil.rmtree(tmp_dir)
def run(test, params, env): """ Stress test for the hotplug feature of serial device """ vm_name = params.get("main_vm", "vm1") status_error = "yes" == params.get("status_error", "no") char_dev = params.get("char_dev", "file") hotplug_type = params.get("hotplug_type", "qmp") load_type = params.get("load_type", "") load_params = params.get("load_params", "") test_count = int(params.get("test_count", 5)) test_type = params.get("test_type", "multi") tmp_dir = os.path.join(test.tmpdir, "hotplug_serial_load") if not os.path.exists(tmp_dir): os.mkdir(tmp_dir) os.chmod(tmp_dir, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) load_vms = [] if load_type in ['cpu', 'memory', 'io']: params["stress_args"] = load_params load_vms.append(libvirt_vm.VM(vm_name, params, test.bindir, env.get("address_cache"))) vm = env.get_vm(vm_name) session = vm.wait_for_login() def prepare_channel_xml(to_file, char_type, index=1, id=0): params = {} mode = '' if char_type == "file": channel_type = char_type channel_path = ("%s/%s%s" % (tmp_dir, char_type, index)) elif char_type == "socket": channel_type = 'unix' channel_path = ("%s/%s%s" % (tmp_dir, char_type, index)) mode = 'bind' elif char_type == "pty": channel_type = char_type channel_path = ("/dev/pts/%s" % id) params = {'channel_type_name': channel_type, 'source_path': channel_path, 'source_mode': mode, 'target_type': 'virtio', 'target_name': char_type + str(index)} channel_xml = utlv.create_channel_xml(params, alias=True, address=True) shutil.copyfile(channel_xml.xml, to_file) def hotplug_device(hotplug_type, char_dev, index=1, id=0): if hotplug_type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": char_add_opt += ("file,path=%s/file%s,id=file%s" % (tmp_dir, index, index)) dev_add_opt += ("file%s,name=file%s,bus=virtio-serial0.0,id=file%s" % (index, index, index)) elif char_dev == "socket": char_add_opt += ("socket,path=%s/socket%s,server,nowait,id=socket%s" % (tmp_dir, index, index)) dev_add_opt += ("socket%s,name=socket%s,bus=virtio-serial0.0,id=socket%s" % (index, index, index)) elif char_dev == "pty": char_add_opt += "pty,path=/dev/pts/%s,id=pty%s" % (id, index) dev_add_opt += ("pty%s,name=pty%s,bus=virtio-serial0.0,id=pty%s" % (index, index, index)) virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") elif hotplug_type == "attach": xml_file = "%s/xml_%s%s" % (tmp_dir, char_dev, index) if char_dev in ["file", "socket"]: prepare_channel_xml(xml_file, char_dev, index) elif char_dev == "pty": prepare_channel_xml(xml_file, char_dev, index, id) virsh.attach_device(vm_name, xml_file, flagstr="--live") def confirm_hotplug_result(char_dev, index=1, id=0): result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") h_o = result.stdout.strip() chardev_c = h_o.count("chardev = %s%s" % (char_dev, index)) name_c = h_o.count("name = \"%s%s\"" % (char_dev, index)) if chardev_c == 0 and name_c == 0: raise error.TestFail("Cannot get serial device info: '%s'" % h_o) tmp_file = "%s/%s%s" % (tmp_dir, char_dev, index) serial_file = "/dev/virtio-ports/%s%s" % (char_dev, index) if char_dev == "file": session.cmd("echo test > %s" % serial_file) f = open(tmp_file, "r") output = f.read() f.close() elif char_dev == "socket": session.cmd("echo test > /tmp/file") sock = socket.socket(socket.AF_UNIX) sock.connect(tmp_file) session.cmd("dd if=/tmp/file of=%s" % serial_file) output = sock.recv(1024) sock.close() elif char_dev == "pty": session.cmd("echo test > /tmp/file") session.cmd("dd if=/tmp/file of=%s &" % serial_file) dev_file = "/dev/pts/%s" % id if not os.path.exists(dev_file): raise error.TestFail("%s doesn't exist." % dev_file) p = subprocess.Popen(["/usr/bin/cat", dev_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE) while True: output = p.stdout.readline() if output or p.poll(): break time.sleep(0.2) p.kill() if not output.count("test"): err_info = "%s device file doesn't match 'test':%s" % (char_dev, output) raise error.TestFail(err_info) def unhotplug_serial_device(hotplug_type, char_dev, index=1): if hotplug_type == "qmp": del_dev_opt = "device_del %s%s" % (char_dev, index) del_char_opt = "chardev-remove %s%s" % (char_dev, index) virsh.qemu_monitor_command(vm_name, del_dev_opt, "--hmp") virsh.qemu_monitor_command(vm_name, del_char_opt, "--hmp") elif hotplug_type == "attach": xml_file = "%s/xml_%s%s" % (tmp_dir, char_dev, index) virsh.detach_device(vm_name, xml_file, flagstr="--live") def confirm_unhotplug_result(char_dev, index=1): serial_file = "/dev/virtio-ports/%s%s" % (char_dev, index) result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") uh_o = result.stdout.strip() if uh_o.count("chardev = %s%s" % (char_dev, index)): raise error.TestFail("Still can get serial device info: '%s'" % uh_o) if not session.cmd_status("test -e %s" % serial_file): raise error.TestFail("File '%s' still exists after unhotplug" % serial_file) # run test case try: # increase workload if load_type in ['cpu', 'memory']: utils_test.load_stress("stress_in_vms", load_vms, params) else: utils_test.load_stress("iozone_in_vms", load_vms, params) if test_type == "multi": for i in range(test_count): if char_dev == "pty": ptsid = utils_misc.aton(utils_misc.get_dev_pts_max_id()) + 1 else: ptsid = 0 hotplug_device(hotplug_type, char_dev, i + 1, id=ptsid) confirm_hotplug_result(char_dev, i + 1, id=ptsid) unhotplug_serial_device(hotplug_type, char_dev, i + 1) confirm_unhotplug_result(char_dev, i + 1) elif test_type == "circle": if char_dev != "all": for i in range(test_count): if char_dev == "pty": ptsid = utils_misc.aton(utils_misc.get_dev_pts_max_id()) + 1 else: ptsid = 0 #1.hotplug serial device hotplug_device(hotplug_type, char_dev, id=ptsid) #2.confirm hotplug result confirm_hotplug_result(char_dev, id=ptsid) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, char_dev) #4.confirm unhotplug result confirm_unhotplug_result(char_dev) else: for i in range(test_count): #1.hotplug serial device hotplug_device(hotplug_type, "file") hotplug_device(hotplug_type, "socket") ptsid = utils_misc.aton(utils_misc.get_dev_pts_max_id()) + 1 hotplug_device(hotplug_type, "pty", id=ptsid) #2.confirm hotplug result confirm_hotplug_result("file") confirm_hotplug_result("socket") confirm_hotplug_result("pty", id=ptsid) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, "file") unhotplug_serial_device(hotplug_type, "socket") unhotplug_serial_device(hotplug_type, "pty") #4.confirm unhotplug result confirm_unhotplug_result("file") confirm_unhotplug_result("socket") confirm_unhotplug_result("pty") finally: session.close() if os.path.exists(tmp_dir): shutil.rmtree(tmp_dir)
def run(test, params, env): """ Verify hotplug feature for char device """ vm_name = params.get("main_vm", "vm1") status_error = "yes" == params.get("status_error", "no") char_dev = params.get("char_dev", "file") hotplug_type = params.get("hotplug_type", "qmp") dup_charid = "yes" == params.get("dup_charid", "no") dup_devid = "yes" == params.get("dup_devid", "no") diff_devid = "yes" == params.get("diff_devid", "no") tmp_dir = os.path.join(test.tmpdir, "hotplug_serial") if not os.path.exists(tmp_dir): os.mkdir(tmp_dir) os.chmod(tmp_dir, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) vm_xml = VMXML.new_from_inactive_dumpxml(vm_name) vm_xml_backup = vm_xml.copy() # add controller for each char device devices = vm_xml.get_devices() controllers = vm_xml.get_devices(device_type="controller") for dev in controllers: if dev.type == "virtio-serial": devices.remove(dev) controller = Controller("controller") controller.type = "virtio-serial" controller.index = 0 devices.append(controller) vm_xml.set_devices(devices) vm_xml.sync() # start and login vm vm = env.get_vm(vm_name) vm.start() session = vm.wait_for_login() def prepare_channel_xml(to_file, char_type, id=0): params = {} mode = '' if char_type == "file": channel_type = char_type channel_path = os.path.join(tmp_dir, char_type) elif char_type == "socket": channel_type = 'unix' channel_path = os.path.join(tmp_dir, char_type) mode = 'bind' elif char_type == "pty": channel_type = char_type channel_path = ("/dev/pts/%s" % id) params = {'channel_type_name': channel_type, 'source_path': channel_path, 'source_mode': mode, 'target_type': 'virtio', 'target_name': char_type} channel_xml = utlv.create_channel_xml(params, alias=True, address=True) shutil.copyfile(channel_xml.xml, to_file) def hotplug_device(type, char_dev, id=0): tmp_file = os.path.join(tmp_dir, char_dev) if type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": char_add_opt += "file,path=%s,id=file" % tmp_file dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file" elif char_dev == "socket": char_add_opt += "socket,path=%s,server,nowait,id=socket" % tmp_file dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket" elif char_dev == "pty": char_add_opt += ("pty,path=/dev/pts/%s,id=pty" % id) dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty" result = virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") if result.exit_status: raise error.TestError('Failed to add chardev %s to %s. Result:\n %s' % (char_dev, vm_name, result)) result = virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") if result.exit_status: raise error.TestError('Failed to add device %s to %s. Result:\n %s' % (char_dev, vm_name, result)) elif type == "attach": xml_file = os.path.join(tmp_dir, "xml_%s" % char_dev) if char_dev in ["file", "socket"]: prepare_channel_xml(xml_file, char_dev) elif char_dev == "pty": prepare_channel_xml(xml_file, char_dev, id) result = virsh.attach_device(vm_name, xml_file) # serial device was introduced by the following commit, # http://libvirt.org/git/? # p=libvirt.git;a=commit;h=b63ea467617e3cbee4282ab2e5e780b4119cef3d if "unknown device type" in result.stderr: raise error.TestNAError('Failed to attach %s to %s. Result:\n %s' % (char_dev, vm_name, result)) return result def dup_hotplug(type, char_dev, id, dup_charid=False, dup_devid=False, diff_devid=False): tmp_file = os.path.join(tmp_dir, char_dev) if type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": if dup_charid: char_add_opt += "file,path=%s,id=file" % tmp_file if dup_devid: dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file" if diff_devid: dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file1" elif char_dev == "socket": if dup_charid: char_add_opt += "socket,path=%s,server,nowait,id=socket" % tmp_file if dup_devid: dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket" if diff_devid: dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket1" elif char_dev == "pty": if dup_charid: char_add_opt += "pty,path=/dev/pts/%s,id=pty" % id if dup_devid: dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty" if diff_devid: dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty1" if dup_charid: result = virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") if dup_devid or diff_devid: result = virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") elif type == "attach": if dup_devid: result = hotplug_device(type, char_dev, id) return result def confirm_hotplug_result(char_dev, id=0): tmp_file = os.path.join(tmp_dir, char_dev) serial_file = os.path.join("/dev/virtio-ports", char_dev) result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") h_o = result.stdout.strip() if not h_o.count("name = \"%s\"" % char_dev): raise error.TestFail("Cann't find device(%s) from:\n%s" % (char_dev, h_o)) if char_dev == "file": session.cmd("echo test > %s" % serial_file) f = open(tmp_file, "r") r_o = f.read() f.close() elif char_dev == "socket": session.cmd("echo test > /tmp/file") sock = socket.socket(socket.AF_UNIX) sock.connect(tmp_file) session.cmd("dd if=/tmp/file of=%s" % serial_file) r_o = sock.recv(1024) elif char_dev == "pty": session.cmd("echo test > /tmp/file") session.cmd("dd if=/tmp/file of=%s &" % serial_file) dev_file = "/dev/pts/%s" % id if not os.path.exists(dev_file): raise error.TestFail("%s doesn't exist." % dev_file) p = subprocess.Popen(["/usr/bin/cat", dev_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE) session.cmd("echo test >> /tmp/file &") while True: r_o = p.stdout.readline() if r_o or p.poll(): break time.sleep(0.2) p.kill() if not r_o.count("test"): err_info = "%s device file doesn't match 'test':%s" % (char_dev, r_o) raise error.TestFail(err_info) def unhotplug_serial_device(type, char_dev): if type == "qmp": del_dev_opt = "device_del %s" % char_dev del_char_opt = "chardev-remove %s" % char_dev result = virsh.qemu_monitor_command(vm_name, del_dev_opt, "--hmp") if result.exit_status: raise error.TestError('Failed to del device %s from %s.Result:\n%s' % (char_dev, vm_name, result)) result = virsh.qemu_monitor_command(vm_name, del_char_opt, "--hmp") elif type == "attach": xml_file = os.path.join(tmp_dir, "xml_%s" % char_dev) result = virsh.detach_device(vm_name, xml_file) def confirm_unhotplug_result(char_dev): serial_file = os.path.join("/dev/virtio-ports", char_dev) result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") uh_o = result.stdout.strip() if uh_o.count("chardev = \"%s\"" % char_dev): raise error.TestFail("Still can get serial device(%s) from: '%s'" % (char_dev, uh_o)) if os.path.exists(serial_file): raise error.TestFail("File '%s' still exists after unhotplug" % serial_file) # run test case try: if char_dev in ['file', 'socket']: # if char_dev is file or socket, it doesn't need pts index pts_id = 0 else: pts_id = str(utils_misc.aton(utils_misc.get_dev_pts_max_id()) + 1) if os.path.exists("/dev/pts/%s" % pts_id): raise error.TestError('invalid pts index(%s) provided.' % pts_id) if status_error: hotplug_device(hotplug_type, char_dev, pts_id) ret = dup_hotplug(hotplug_type, char_dev, pts_id, dup_charid, dup_devid, diff_devid) dup_o = ret.stdout.strip() if hotplug_type == "qmp": # although it has failed, ret.exit_status will be returned 0. err_o1 = "Duplicate ID" err_o2 = "Parsing chardev args failed" err_o3 = "Property 'virtserialport.chardev' can't" if (err_o1 not in dup_o) and (err_o2 not in dup_o) and (err_o3 not in dup_o): raise error.TestFail("Expect fail, but run successfully:\n%s" % ret) else: if "chardev already exists" not in dup_o: logging.info("Expect fail,but run successfully:\n%s" % ret) else: if char_dev != "all": #1.hotplug serial device hotplug_device(hotplug_type, char_dev, pts_id) #2.confirm hotplug result confirm_hotplug_result(char_dev, pts_id) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, char_dev) #4.confirm unhotplug result confirm_unhotplug_result(char_dev) else: #1.hotplug serial device hotplug_device(hotplug_type, "file") hotplug_device(hotplug_type, "socket") hotplug_device(hotplug_type, "pty", pts_id) #2.confirm hotplug result confirm_hotplug_result("file") confirm_hotplug_result("socket") confirm_hotplug_result("pty", pts_id) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, "file") unhotplug_serial_device(hotplug_type, "socket") unhotplug_serial_device(hotplug_type, "pty") #4.confirm unhotplug result confirm_unhotplug_result("file") confirm_unhotplug_result("socket") confirm_unhotplug_result("pty") finally: vm_xml_backup.sync() if os.path.exists(tmp_dir): shutil.rmtree(tmp_dir)
def result_sum(topdir, params, guest_ver, resultsdir, test): case_type = params.get("test") unit_std = params.get("unit_std", "M") no_table_list = params.get("no_table_list", "").split() ignore_cases = params.get("ignore_cases", "").split() repeatn = "" if "repeat" in test.outputdir: repeatn = re.findall("repeat\d+", test.outputdir)[0] category_key = re.split("/", test.outputdir)[-1] category_key = re.split(case_type, category_key)[0] category_key = re.sub("\.repeat\d+", "", category_key) kvm_ver = utils.system_output(params.get('ver_cmd', "rpm -q qemu-kvm")) host_ver = os.uname()[2] test.write_test_keyval({'kvm-userspace-ver': kvm_ver}) test.write_test_keyval({'host-kernel-ver': host_ver}) test.write_test_keyval({'guest-kernel-ver': guest_ver}) # Find the results files results_files = {} file_list = ['guest_result', 'guest_monitor_result.*sum', 'host_monitor_result.*sum'] if params.get("file_list"): file_list = params.get("file_list").split() for files in os.walk(topdir): if files[2]: for file in files[2]: jump_flag = False for ignore_case in ignore_cases: if ignore_case in files[0]: jump_flag = True if jump_flag: continue file_dir_norpt = re.sub("\.repeat\d+", "", files[0]) if (repeatn in files[0] and category_key in file_dir_norpt and case_type in files[0]): for i, pattern in enumerate(file_list): if re.findall(pattern, file): prefix = re.findall("%s\.[\d\w_\.]+" % case_type, file_dir_norpt)[0] prefix = re.sub("\.|_", "--", prefix) if prefix not in results_files.keys(): results_files[prefix] = [] tmp = [] for j in range(len(file_list)): tmp.append(None) results_files[prefix] = tmp tmp_file = utils_misc.get_path(files[0], file) results_files[prefix][i] = tmp_file # Start to read results from results file and monitor file results_matrix = {} no_table_results = {} thread_tag = params.get("thread_tag", "thread") order_list = [] for prefix in results_files: marks = params.get("marks", "").split() case_infos = prefix.split("--") case_type = case_infos[0] threads = "" refresh_order_list = True prefix_perf = prefix if case_type == "ffsb": category = "-".join(case_infos[:-1]) threads = case_infos[-1] elif case_type == "qcow2perf": refresh_order_list = False if len(case_infos) > 2: category = "-".join(case_infos[:-2]) thread_tag = case_infos[-2] threads = " " marks[0] = re.sub("TIME", case_infos[-1], marks[0]) else: category = case_infos[-1] marks[0] = re.sub("TIME", case_infos[-1], marks[0]) prefix_perf = "--".join(case_infos[:-1]) else: category = "-".join(case_infos) if refresh_order_list: order_list = [] if (category not in results_matrix.keys() and category not in no_table_list): results_matrix[category] = {} if threads: if threads not in results_matrix[category].keys(): results_matrix[category][threads] = {} results_matrix["thread_tag"] = thread_tag tmp_dic = results_matrix[category][threads] elif category not in no_table_list: tmp_dic = results_matrix[category] result_context_file = open(results_files[prefix][0], 'r') result_context = result_context_file.read() result_context_file.close() for mark in marks: mark_tag, mark_key = mark.split(":") datas = re.findall(mark_key, result_context) if isinstance(datas[0], tuple): data = time_ana(datas[0]) else: tmp_data = 0.0 for data in datas: if re.findall("[bmkg]", data, re.I): data = utils_misc.normalize_data_size(data, unit_std) tmp_data += float(data) data = str(tmp_data) if data: if mark_tag in no_table_list: no_table_results[mark_tag] = utils_misc.aton(data) perf_value = no_table_results[mark_tag] else: tmp_dic[mark_tag] = utils_misc.aton(data) perf_value = tmp_dic[mark_tag] else: raise error.TestError("Can not get the right data from result." "Please check the debug file.") if mark_tag not in no_table_list and mark_tag not in order_list: order_list.append(mark_tag) test.write_perf_keyval({'%s-%s' % (prefix_perf, mark_tag): perf_value}) # start analyze the mpstat results if params.get('mpstat') == "yes": guest_cpu_infos = mpstat_ana(results_files[prefix][1]) for vcpu in guest_cpu_infos: if vcpu != "all": tmp_dic[vcpu] = float(guest_cpu_infos[vcpu]) order_list.append(vcpu) host_cpu_infos = mpstat_ana(results_files[prefix][2]) tmp_dic["Hostcpu"] = float(host_cpu_infos["all"]) order_list.append("Hostcpu") # Add some special key for cases if case_type == "ffsb": tmp_dic["MBps_per_Hostcpu"] = (tmp_dic["Thro-MBps"] / tmp_dic["Hostcpu"]) order_list.append("MBps_per_Hostcpu") elif case_type == "iozone": sum_kbps = 0 for mark in marks: mark_tag, _ = mark.split(":") sum_kbps += tmp_dic[mark_tag] tmp_dic["SUMKbps_per_Hostcpu"] = sum_kbps / tmp_dic["Hostcpu"] order_list.append("SUMKbps_per_Hostcpu") sum_marks = params.get("sum_marks", "").split() sum_matrix = {} order_line = "" if results_matrix.get("thread_tag"): headline = "%20s|" % results_matrix["thread_tag"] results_matrix.pop("thread_tag") else: headline = "" for index, tag in enumerate(order_list): headline += "%s|" % format_result(tag) order_line += "DATA%d|" % index headline = headline.rstrip("|") order_line = order_line.rstrip("|") result_path = utils_misc.get_path(resultsdir, "%s-result.RHS" % case_type) if os.path.isfile(result_path): result_file = open(result_path, "r+") else: result_file = open(result_path, "w") result_file.write("### kvm-userspace-version : %s\n" % kvm_ver) result_file.write("### kvm-version : %s\n" % host_ver) result_file.write("### guest-kernel-version :%s\n" % guest_ver) test.write_test_keyval({'category': headline}) result_file.write("Category:ALL\n") matrix_order = params.get("matrix_order", "").split() if not matrix_order: matrix_order = results_matrix.keys() matrix_order.sort() for category in matrix_order: out_loop_line = order_line result_file.write("%s\n" % category) line = "" write_out_loop = True result_file.write("%s\n" % headline) for item in results_matrix[category]: if isinstance(results_matrix[category][item], dict): tmp_dic = results_matrix[category][item] line = "%s|" % format_result(item) for tag in order_list: line += "%s|" % format_result(tmp_dic[tag]) if tag in sum_marks: sum_matrix = get_sum_result(sum_matrix, tmp_dic[tag], tag) result_file.write("%s\n" % line.rstrip("|")) write_out_loop = False else: #line += "%s|" % format_result(results_matrix[category][item]) re_data = "DATA%s" % order_list.index(item) out_loop_line = re.sub(re_data, format_result( results_matrix[category][item]), out_loop_line) if tag in sum_marks: sum_matrix = get_sum_result(sum_matrix, tmp_dic[tag], tag) if write_out_loop: result_file.write("%s\n" % out_loop_line) if sum_matrix: if case_type == "ffsb": sum_matrix["MBps_per_Hostcpu"] = (sum_matrix["Thro-MBps"] / sum_matrix["Hostcpu"]) sum_marks.append("MBps_per_Hostcpu") result_file.write("Category:SUM\n") headline = "" line = "" if len(sum_matrix) < 4: for i in range(4 - len(sum_matrix)): headline += "%20s|" % "None" line += "%20d|" % 0 for tag in sum_marks: headline += "%20s|" % tag line += "%s|" % format_result(sum_matrix[tag]) result_file.write("%s\n" % headline.rstrip("|")) result_file.write("%s\n" % line.rstrip("|")) if no_table_results: no_table_order = params.get("no_table_order", "").split() if not no_table_order: no_table_order = no_table_results.keys() no_table_order.sort() for item in no_table_order: result_file.write("%s: %s\n" % (item, no_table_results[item])) result_file.close()
sharing_page_2 = re.findall(query_regex, sharing_page_2)[0] # clean up work in guest error.context("Clean up env in guest", logging.info) session.cmd_output("die()", 20) session.cmd_status_output("swapon -a") session.cmd_output("echo 3 > /proc/sys/vm/drop_caches") sharing_page = [sharing_page_0, sharing_page_1, sharing_page_2] for i in sharing_page: if re.findall("[A-Za-z]", i): data = i[0:-1] unit = i[-1] index = sharing_page.index(i) if unit == "g": sharing_page[index] = utils_misc.aton(data) * 1024 else: sharing_page[index] = utils_misc.aton(data) fail_type = 0 if test_type == "disable": if int(sharing_page[0]) != 0 and int(sharing_page[1]) != 0: fail_type += 1 else: if int(sharing_page[0]) >= int(sharing_page[1]): fail_type += 2 if int(sharing_page[1]) <= int(sharing_page[2]): fail_type += 4 fail = ["Sharing page increased abnormally", "Sharing page didn't increase", "Sharing page didn't split"]
def run(test, params, env): """ Verify hotplug feature for char device """ vm_name = params.get("main_vm", "vm1") status_error = "yes" == params.get("status_error", "no") char_dev = params.get("char_dev", "file") hotplug_type = params.get("hotplug_type", "qmp") dup_charid = "yes" == params.get("dup_charid", "no") dup_devid = "yes" == params.get("dup_devid", "no") diff_devid = "yes" == params.get("diff_devid", "no") xml_file = params.get("xml_file", "/tmp/xml_file") vm_xml = VMXML.new_from_inactive_dumpxml(vm_name) vm_xml_backup = vm_xml.copy() # add controller for each char device devices = vm_xml.get_devices() controllers = vm_xml.get_devices(device_type="controller") for dev in controllers: if dev.type == "virtio-serial": devices.remove(dev) controller = Controller("controller") controller.type = "virtio-serial" controller.index = 0 devices.append(controller) vm_xml.set_devices(devices) vm_xml.sync() # start and login vm vm = env.get_vm(vm_name) vm.start() session = vm.wait_for_login() def create_channel_xml(vm_name, char_type, id=0): """ Create a XML contains channel information. """ channel_type = char_type if char_type == "file": channel_path = ("/tmp/%s" % char_type) channel_source = {'path': channel_path} channel_target = {'type': 'virtio', 'name': 'file'} if char_type == "socket": channel_type = 'unix' channel_path = ("/tmp/%s" % char_type) channel_source = {'mode': 'bind', 'path': channel_path} channel_target = {'type': 'virtio', 'name': 'socket'} if char_type == "pty": channel_path = ("/dev/pts/%s" % id) channel_source = {'path': channel_path} channel_target = {'type': 'virtio', 'name': 'pty'} channel_alias = {'name': char_type} channel_address = {'type': 'virtio-serial', 'controller': '0', 'bus': '0'} channel_params = {'type_name': channel_type, 'source': channel_source, 'target': channel_target, 'alias': channel_alias, 'address': channel_address} channelxml = channel.Channel.new_from_dict(channel_params) logging.debug("Channel XML:\n%s", channelxml) xmlf = open(channelxml.xml) try: xml_lines = xmlf.read() finally: xmlf.close() return xml_lines def hotplug_device(type, char_dev, id=0): tmp_file = "/tmp/%s" % char_dev if type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": char_add_opt += "file,path=/tmp/file,id=file" dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file" elif char_dev == "socket": char_add_opt += "socket,path=/tmp/socket,server,nowait,id=socket" dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket" elif char_dev == "pty": char_add_opt += ("pty,path=/dev/pts/%s,id=pty" % id) dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty" result = virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") if result.exit_status: raise error.TestError('Failed to add chardev %s to %s. Result:\n %s' % (char_dev, vm_name, result)) result = virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") if result.exit_status: raise error.TestError('Failed to add device %s to %s. Result:\n %s' % (char_dev, vm_name, result)) elif type == "attach": if char_dev in ["file", "socket"]: xml_info = create_channel_xml(vm_name, char_dev) elif char_dev == "pty": xml_info = create_channel_xml(vm_name, char_dev, id) f = open(xml_file, "w") f.write(xml_info) f.close() if os.path.exists(tmp_file): os.chmod(tmp_file, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) result = virsh.attach_device(vm_name, xml_file) return result def dup_hotplug(type, char_dev, id, dup_charid=False, dup_devid=False, diff_devid=False): if type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": if dup_charid: char_add_opt += "file,path=/tmp/file,id=file" if dup_devid: dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file" if diff_devid: dev_add_opt += "file,name=file,bus=virtio-serial0.0,id=file1" elif char_dev == "socket": if dup_charid: char_add_opt += "socket,path=/tmp/socket,server,nowait,id=socket" if dup_devid: dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket" if diff_devid: dev_add_opt += "socket,name=socket,bus=virtio-serial0.0,id=socket1" elif char_dev == "pty": if dup_charid: char_add_opt += "pty,path=/dev/pts/%s,id=pty" % id if dup_devid: dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty" if diff_devid: dev_add_opt += "pty,name=pty,bus=virtio-serial0.0,id=pty1" if dup_charid: result = virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") if dup_devid or diff_devid: result = virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") elif type == "attach": if dup_devid: result = hotplug_device(type, char_dev, id) return result def confirm_hotplug_result(char_dev, id=0): tmp_file = "/tmp/%s" % char_dev serial_file = "/dev/virtio-ports/%s" % char_dev result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") h_o = result.stdout.strip() if not h_o.count("name = \"%s\"" % char_dev): raise error.TestFail("Cann't find device(%s) from:\n%s" % (char_dev, h_o)) if char_dev == "file": session.cmd("echo test > %s" % serial_file) f = open(tmp_file, "r") r_o = f.read() f.close() elif char_dev == "socket": session.cmd("echo test > /tmp/file") sock = socket.socket(socket.AF_UNIX) sock.connect(tmp_file) session.cmd("dd if=/tmp/file of=%s" % serial_file) r_o = sock.recv(1024) elif char_dev == "pty": session.cmd("echo test > /tmp/file") session.cmd("dd if=/tmp/file of=%s &" % serial_file) dev_file = "/dev/pts/%s" % id if not os.path.exists(dev_file): raise error.TestFail("%s doesn't exist." % dev_file) p = subprocess.Popen(["/usr/bin/cat", dev_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE) session.cmd("echo test >> /tmp/file &") while True: r_o = p.stdout.readline() if r_o or p.poll(): break time.sleep(0.2) p.kill() if not r_o.count("test"): err_info = "%s device file doesn't match 'test':%s" % (char_dev, r_o) raise error.TestFail(err_info) def unhotplug_serial_device(type, char_dev): if type == "qmp": del_dev_opt = "device_del %s" % char_dev del_char_opt = "chardev-remove %s" % char_dev result = virsh.qemu_monitor_command(vm_name, del_dev_opt, "--hmp") if result.exit_status: raise error.TestError('Failed to del device %s from %s.Result:\n%s' % (char_dev, vm_name, result)) result = virsh.qemu_monitor_command(vm_name, del_char_opt, "--hmp") elif type == "attach": result = virsh.detach_device(vm_name, xml_file) def confirm_unhotplug_result(char_dev): serial_file = "/dev/virtio-ports/%s" % char_dev result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") uh_o = result.stdout.strip() if uh_o.count("chardev = \"%s\"" % char_dev): raise error.TestFail("Still can get serial device(%s) from: '%s'" % (char_dev, uh_o)) if os.path.exists(serial_file): raise error.TestFail("File '%s' still exists after unhotplug" % serial_file) # run test case try: if char_dev in ['file', 'socket']: # if char_dev is file or socket, it doesn't need pts index pts_id = 0 else: pts_id = str(utils_misc.aton(utils_misc.get_dev_pts_max_id()) + 1) if os.path.exists("/dev/pts/%s" % pts_id): raise error.TestError('invalid pts index(%s) provided.' % pts_id) if status_error: hotplug_device(hotplug_type, char_dev, pts_id) ret = dup_hotplug(hotplug_type, char_dev, pts_id, dup_charid, dup_devid, diff_devid) dup_o = ret.stdout.strip() if hotplug_type == "qmp": # although it has failed, ret.exit_status will be returned 0. err_o1 = "Duplicate ID" err_o2 = "Parsing chardev args failed" err_o3 = "Property 'virtserialport.chardev' can't" if (err_o1 not in dup_o) and (err_o2 not in dup_o) and (err_o3 not in dup_o): raise error.TestFail("Expect fail, but run successfully:\n%s" % ret) else: if "chardev already exists" not in dup_o: logging.info("Expect fail,but run successfully:\n%s" % ret) else: if char_dev != "all": #1.hotplug serial device hotplug_device(hotplug_type, char_dev, pts_id) #2.confirm hotplug result confirm_hotplug_result(char_dev, pts_id) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, char_dev) #4.confirm unhotplug result confirm_unhotplug_result(char_dev) else: #1.hotplug serial device hotplug_device(hotplug_type, "file") hotplug_device(hotplug_type, "socket") hotplug_device(hotplug_type, "pty", pts_id) #2.confirm hotplug result confirm_hotplug_result("file") confirm_hotplug_result("socket") confirm_hotplug_result("pty", pts_id) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, "file") unhotplug_serial_device(hotplug_type, "socket") unhotplug_serial_device(hotplug_type, "pty") #4.confirm unhotplug result confirm_unhotplug_result("file") confirm_unhotplug_result("socket") confirm_unhotplug_result("pty") finally: vm_xml_backup.sync() if os.path.exists(xml_file): os.remove(xml_file)
def run(test, params, env): """ Stress test for the hotplug feature of serial device """ vm_name = params.get("main_vm", "vm1") char_dev = params.get("char_dev", "file") hotplug_type = params.get("hotplug_type", "qmp") load_type = params.get("load_type", "") load_params = params.get("load_params", "") test_count = int(params.get("test_count", 5)) test_type = params.get("test_type", "multi") tmp_dir = os.path.join(data_dir.get_tmp_dir(), "hotplug_serial_load") if not os.path.exists(tmp_dir): os.mkdir(tmp_dir) os.chmod(tmp_dir, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) load_vms = [] if load_type in ['cpu', 'memory', 'io']: params["stress_args"] = load_params load_vms.append( libvirt_vm.VM(vm_name, params, test.bindir, env.get("address_cache"))) vm = env.get_vm(vm_name) session = vm.wait_for_login() def prepare_channel_xml(to_file, char_type, index=1, id=0): params = {} mode = '' if char_type == "file": channel_type = char_type channel_path = ("%s/%s%s" % (tmp_dir, char_type, index)) elif char_type == "socket": channel_type = 'unix' channel_path = ("%s/%s%s" % (tmp_dir, char_type, index)) mode = 'bind' elif char_type == "pty": channel_type = char_type channel_path = ("/dev/pts/%s" % id) params = { 'channel_type_name': channel_type, 'source_path': channel_path, 'source_mode': mode, 'target_type': 'virtio', 'target_name': char_type + str(index) } channel_xml = utlv.create_channel_xml(params, alias=True, address=True) shutil.copyfile(channel_xml.xml, to_file) def hotplug_device(hotplug_type, char_dev, index=1, id=0): if hotplug_type == "qmp": char_add_opt = "chardev-add " dev_add_opt = "device_add virtserialport,chardev=" if char_dev == "file": char_add_opt += ("file,path=%s/file%s,id=file%s" % (tmp_dir, index, index)) dev_add_opt += ( "file%s,name=file%s,bus=virtio-serial0.0,id=file%s" % (index, index, index)) elif char_dev == "socket": char_add_opt += ( "socket,path=%s/socket%s,server,nowait,id=socket%s" % (tmp_dir, index, index)) dev_add_opt += ( "socket%s,name=socket%s,bus=virtio-serial0.0,id=socket%s" % (index, index, index)) elif char_dev == "pty": char_add_opt += "pty,path=/dev/pts/%s,id=pty%s" % (id, index) dev_add_opt += ( "pty%s,name=pty%s,bus=virtio-serial0.0,id=pty%s" % (index, index, index)) virsh.qemu_monitor_command(vm_name, char_add_opt, "--hmp") virsh.qemu_monitor_command(vm_name, dev_add_opt, "--hmp") elif hotplug_type == "attach": xml_file = "%s/xml_%s%s" % (tmp_dir, char_dev, index) if char_dev in ["file", "socket"]: prepare_channel_xml(xml_file, char_dev, index) elif char_dev == "pty": prepare_channel_xml(xml_file, char_dev, index, id) virsh.attach_device(vm_name, xml_file, flagstr="--live") def confirm_hotplug_result(char_dev, index=1, id=0): result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") h_o = result.stdout.strip() chardev_c = h_o.count("chardev = %s%s" % (char_dev, index)) name_c = h_o.count("name = \"%s%s\"" % (char_dev, index)) if chardev_c == 0 and name_c == 0: test.fail("Cannot get serial device info: '%s'" % h_o) tmp_file = "%s/%s%s" % (tmp_dir, char_dev, index) serial_file = "/dev/virtio-ports/%s%s" % (char_dev, index) if char_dev == "file": session.cmd("echo test > %s" % serial_file) with open(tmp_file, "r") as f: output = f.read() elif char_dev == "socket": session.cmd("echo test > /tmp/file") sock = socket.socket(socket.AF_UNIX) sock.connect(tmp_file) session.cmd("dd if=/tmp/file of=%s" % serial_file) output = sock.recv(1024) sock.close() elif char_dev == "pty": session.cmd("echo test > /tmp/file") session.cmd("dd if=/tmp/file of=%s &" % serial_file) dev_file = "/dev/pts/%s" % id if not os.path.exists(dev_file): test.fail("%s doesn't exist." % dev_file) p = subprocess.Popen(["/usr/bin/cat", dev_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) while True: output = p.stdout.readline() if output or p.poll(): break time.sleep(0.2) p.kill() if not output.count("test"): err_info = "%s device file doesn't match 'test':%s" % (char_dev, output) test.fail(err_info) def unhotplug_serial_device(hotplug_type, char_dev, index=1): if hotplug_type == "qmp": del_dev_opt = "device_del %s%s" % (char_dev, index) del_char_opt = "chardev-remove %s%s" % (char_dev, index) virsh.qemu_monitor_command(vm_name, del_dev_opt, "--hmp") virsh.qemu_monitor_command(vm_name, del_char_opt, "--hmp") elif hotplug_type == "attach": xml_file = "%s/xml_%s%s" % (tmp_dir, char_dev, index) virsh.detach_device(vm_name, xml_file, flagstr="--live") def confirm_unhotplug_result(char_dev, index=1): serial_file = "/dev/virtio-ports/%s%s" % (char_dev, index) result = virsh.qemu_monitor_command(vm_name, "info qtree", "--hmp") uh_o = result.stdout.strip() if uh_o.count("chardev = %s%s" % (char_dev, index)): test.fail("Still can get serial device info: '%s'" % uh_o) if not session.cmd_status("test -e %s" % serial_file): test.fail("File '%s' still exists after unhotplug" % serial_file) # run test case try: # increase workload if load_type in ['cpu', 'memory']: utils_test.load_stress("stress_in_vms", load_vms, params) else: utils_test.load_stress("iozone_in_vms", load_vms, params) if test_type == "multi": for i in range(test_count): if char_dev == "pty": ptsid = utils_misc.aton( utils_misc.get_dev_pts_max_id()) + 1 else: ptsid = 0 hotplug_device(hotplug_type, char_dev, i + 1, id=ptsid) confirm_hotplug_result(char_dev, i + 1, id=ptsid) unhotplug_serial_device(hotplug_type, char_dev, i + 1) confirm_unhotplug_result(char_dev, i + 1) elif test_type == "circle": if char_dev != "all": for i in range(test_count): if char_dev == "pty": ptsid = utils_misc.aton( utils_misc.get_dev_pts_max_id()) + 1 else: ptsid = 0 #1.hotplug serial device hotplug_device(hotplug_type, char_dev, id=ptsid) #2.confirm hotplug result confirm_hotplug_result(char_dev, id=ptsid) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, char_dev) #4.confirm unhotplug result confirm_unhotplug_result(char_dev) else: for i in range(test_count): #1.hotplug serial device hotplug_device(hotplug_type, "file") hotplug_device(hotplug_type, "socket") ptsid = utils_misc.aton( utils_misc.get_dev_pts_max_id()) + 1 hotplug_device(hotplug_type, "pty", id=ptsid) #2.confirm hotplug result confirm_hotplug_result("file") confirm_hotplug_result("socket") confirm_hotplug_result("pty", id=ptsid) #3.unhotplug serial device unhotplug_serial_device(hotplug_type, "file") unhotplug_serial_device(hotplug_type, "socket") unhotplug_serial_device(hotplug_type, "pty") #4.confirm unhotplug result confirm_unhotplug_result("file") confirm_unhotplug_result("socket") confirm_unhotplug_result("pty") finally: session.close() if os.path.exists(tmp_dir): shutil.rmtree(tmp_dir)
def run(test, params, env): """ Test how KSM (Kernel Shared Memory) act when more than physical memory is used. In second part we also test how KVM handles a situation when the host runs out of memory (it is expected to pause the guest system, wait until some process returns memory and bring the guest back to life) :param test: QEMU test object. :param params: Dictionary with test parameters. :param env: Dictionary with the test environment. """ def _start_allocator(vm, session, timeout): """ Execute guest script and wait until it is initialized. :param vm: VM object. :param session: Remote session to a VM object. :param timeout: Timeout that will be used to verify if guest script started properly. """ logging.debug("Starting guest script on guest %s", vm.name) session.sendline("python /tmp/ksm_overcommit_guest.py") try: _ = session.read_until_last_line_matches(["PASS:"******"FAIL:"], timeout) except aexpect.ExpectProcessTerminatedError as exc: test.fail("Command guest script on vm '%s' failed: %s" % (vm.name, str(exc))) def _execute_allocator(command, vm, session, timeout): """ Execute a given command on guest script main loop, indicating the vm the command was executed on. :param command: Command that will be executed. :param vm: VM object. :param session: Remote session to VM object. :param timeout: Timeout used to verify expected output. :return: Tuple (match index, data) """ logging.debug( "Executing '%s' on guest script loop, vm: %s, timeout: " "%s", command, vm.name, timeout) session.sendline(command) try: (match, data) = session.read_until_last_line_matches(["PASS:"******"FAIL:"], timeout) except aexpect.ExpectProcessTerminatedError as exc: e_str = ("Failed to execute command '%s' on guest script, " "vm '%s': %s" % (command, vm.name, str(exc))) test.fail(e_str) return (match, data) timeout = float(params.get("login_timeout", 240)) guest_script_overhead = int(params.get("guest_script_overhead", 5)) vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_login(timeout=timeout) # Prepare work in guest error_context.context("Turn off swap in guest", logging.info) session.cmd_status_output("swapoff -a") script_file_path = os.path.join(data_dir.get_root_dir(), "shared/scripts/ksm_overcommit_guest.py") vm.copy_files_to(script_file_path, "/tmp") test_type = params.get("test_type") shared_mem = int(params["shared_mem"]) get_free_mem_cmd = params.get("get_free_mem_cmd", "grep MemFree /proc/meminfo") free_mem = vm.get_memory_size(get_free_mem_cmd) max_mem = int(free_mem / (1 + TMPFS_OVERHEAD) - guest_script_overhead) # Keep test from OOM killer if max_mem < shared_mem: shared_mem = max_mem fill_timeout = int(shared_mem) / 10 query_cmd = params.get("query_cmd") query_regex = params.get("query_regex") random_bits = params.get("random_bits") seed = random.randint(0, 255) query_cmd = re.sub("QEMU_PID", str(vm.process.get_pid()), query_cmd) sharing_page_0 = process.system_output(query_cmd, verbose=False, ignore_status=True, shell=True) if query_regex: sharing_page_0 = re.findall(query_regex, sharing_page_0)[0] error_context.context("Start to allocate pages inside guest", logging.info) _start_allocator(vm, session, 60) error_context.context("Start to fill memory in guest", logging.info) mem_fill = "mem = MemFill(%s, 0, %s)" % (shared_mem, seed) _execute_allocator(mem_fill, vm, session, fill_timeout) cmd = "mem.value_fill()" _execute_allocator(cmd, vm, session, fill_timeout) time.sleep(120) sharing_page_1 = process.system_output(query_cmd, verbose=False, ignore_status=True, shell=True) if query_regex: sharing_page_1 = re.findall(query_regex, sharing_page_1)[0] error_context.context("Start to fill memory with random value in guest", logging.info) split = params.get("split") if split == "yes": if test_type == "negative": cmd = "mem.static_random_fill(%s)" % random_bits else: cmd = "mem.static_random_fill()" _execute_allocator(cmd, vm, session, fill_timeout) time.sleep(120) sharing_page_2 = process.system_output(query_cmd, verbose=False, ignore_status=True, shell=True) if query_regex: sharing_page_2 = re.findall(query_regex, sharing_page_2)[0] # clean up work in guest error_context.context("Clean up env in guest", logging.info) session.cmd_output("die()", 20) session.cmd_status_output("swapon -a") session.cmd_output("echo 3 > /proc/sys/vm/drop_caches") sharing_page = [sharing_page_0, sharing_page_1, sharing_page_2] for i in sharing_page: if re.findall("[A-Za-z]", i): data = i[0:-1] unit = i[-1] index = sharing_page.index(i) if unit == "g": sharing_page[index] = utils_misc.aton(data) * 1024 else: sharing_page[index] = utils_misc.aton(data) fail_type = 0 if test_type == "disable": if int(sharing_page[0]) != 0 and int(sharing_page[1]) != 0: fail_type += 1 else: if int(sharing_page[0]) >= int(sharing_page[1]): fail_type += 2 if int(sharing_page[1]) <= int(sharing_page[2]): fail_type += 4 fail = [ "Sharing page increased abnormally", "Sharing page didn't increase", "Sharing page didn't split" ] if fail_type != 0: turns = 0 while (fail_type > 0): if fail_type % 2 == 1: logging.error(fail[turns]) fail_type = fail_type / 2 turns += 1 test.fail("KSM test failed: %s %s %s" % (sharing_page_0, sharing_page_1, sharing_page_2)) session.close()
sharing_page_2 = re.findall(query_regex, sharing_page_2)[0] # clean up work in guest error.context("Clean up env in guest", logging.info) session.cmd_output("die()", 20) session.cmd_status_output("swapon -a") session.cmd_output("echo 3 > /proc/sys/vm/drop_caches") sharing_page = [sharing_page_0, sharing_page_1, sharing_page_2] for i in sharing_page: if re.findall("[A-Za-z]", i): data = i[0:-1] unit = i[-1] index = sharing_page.index(i) if unit == "g": sharing_page[index] = utils_misc.aton(data) * 1024 else: sharing_page[index] = utils_misc.aton(data) fail_type = 0 if test_type == "disable": if int(sharing_page[0]) != 0 and int(sharing_page[1]) != 0: fail_type += 1 else: if int(sharing_page[0]) >= int(sharing_page[1]): fail_type += 2 if int(sharing_page[1]) <= int(sharing_page[2]): fail_type += 4 fail = [ "Sharing page increased abnormally", "Sharing page didn't increase",