def host_stress_event(self, event): """ Host Stress events :param event: event name """ for itr in range(self.host_iterations): if "cpu_freq_governor" in event: cpu.set_cpufreq_governor() logging.debug("Current governor: %s", cpu.get_cpufreq_governor()) time.sleep(self.event_sleep_time) elif "cpu_idle" in event: idlestate = cpu.get_cpuidle_state() cpu.set_cpuidle_state() time.sleep(self.event_sleep_time) cpu.set_cpuidle_state(setstate=idlestate) time.sleep(self.event_sleep_time) elif "cpuoffline" in event: processor = self.host_cpu_list[random.randint( 0, cpu.online_cpus_count() - 1)] cpu.offline(processor) time.sleep(self.event_sleep_time) cpu.online(processor) else: raise NotImplementedError time.sleep(self.itr_sleep_time)
def run(test, params, env): """ Test commands: virsh.vcpupin, virsh.iothreadpin, virsh.emulatorpin. """ check_to_skip_case(params, test) vm_name = params.get("main_vm") vm = env.get_vm(vm_name) original_vm_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) vm_xml_copy = original_vm_xml.copy() host_cpus = cpu.online_cpus_count() cpu_max_index = int(host_cpus) - 1 test_case = params.get("test_case", "") run_test = eval("test_%s" % test_case) try: if vm.is_alive(): vm.destroy() run_test(test, original_vm_xml, cpu_max_index, vm, params) finally: vm_xml_copy.sync() if vm.is_alive(): vm.destroy()
def setUp(self): smm = SoftwareManager() self.minthreads = self.params.get( 'minthrd', default=(500 + cpu.online_cpus_count())) self.maxthreads = self.params.get('maxthrd', default=None) self.iothreads = self.params.get('iothrd', default=self.minthreads/2) self.maxmem = self.params.get('maxmem', default=int( memory.meminfo.MemFree.m / self.minthreads)) self.maxio = self.params.get('maxio', default=None) self.longthreads = self.params.get('longthrd', default=False) self.shrtthreads = self.params.get('shortthrd', default=False) self.time = self.params.get('time', default=100) self.iotime = self.params.get('iotime', default=50) if self.longthreads and self.shrtthreads: self.cancel('Please choose right inputs') dist = distro.detect() packages = ['gcc', 'patch'] if dist.name == 'Ubuntu': packages.extend(['g++']) elif dist.name in ['SuSE', 'fedora', 'rhel']: packages.extend(['gcc-c++']) for package in packages: if not smm.check_installed(package) and not smm.install(package): self.cancel('%s is needed for the test to be run' % package) for file_name in ['dwh.cpp', 'Makefile']: self.copyutil(file_name) os.chdir(self.teststmpdir) if dist.name in ['fedora', 'rhel']: process.system('patch -p0 < %s' % self.get_data('fofd.patch'), shell=True) build.make(self.teststmpdir)
def setUp(self): self.test_file = self.params.get('tmp_file', default='/tmp/dummy') self.duration = self.params.get('duration', default='30') self.threads = self.params.get( 'threads', default=cpu.online_cpus_count()) self.size = self.params.get( 'memory_to_test', default=int(0.9 * memory.meminfo.MemFree.m)) smm = SoftwareManager() for package in ['gcc', 'libtool', 'autoconf', 'automake', 'make']: if not smm.check_installed(package) and not smm.install(package): self.cancel("Failed to install %s, which is needed for" "the test to be run" % package) if not os.path.exists(self.test_file): try: os.mknod(self.test_file) except OSError: self.cancel("Skipping test since test file creation failed") loc = ["https://github.com/stressapptest/" "stressapptest/archive/master.zip"] tarball = self.fetch_asset("stressapp.zip", locations=loc, expire='7d') archive.extract(tarball, self.workdir) self.sourcedir = os.path.join(self.workdir, 'stressapptest-master') os.chdir(self.sourcedir) process.run('./configure', shell=True) build.make(self.sourcedir)
def setUp(self): self.test_file = self.params.get('tmp_file', default='/tmp/dummy') self.duration = self.params.get('duration', default='30') self.threads = self.params.get('threads', default=cpu.online_cpus_count()) self.size = self.params.get('memory_to_test', default=int(0.9 * memory.meminfo.MemFree.m)) smm = SoftwareManager() for package in ['gcc', 'libtool', 'autoconf', 'automake', 'make']: if not smm.check_installed(package) and not smm.install(package): self.cancel("Failed to install %s, which is needed for" "the test to be run" % package) if not os.path.exists(self.test_file): try: os.mknod(self.test_file) except OSError: self.cancel("Skipping test since test file creation failed") loc = [ "https://github.com/stressapptest/" "stressapptest/archive/master.zip" ] tarball = self.fetch_asset("stressapp.zip", locations=loc, expire='7d') archive.extract(tarball, self.workdir) self.sourcedir = os.path.join(self.workdir, 'stressapptest-master') os.chdir(self.sourcedir) process.run('./configure', shell=True) build.make(self.sourcedir)
def host(): logging.info("Setup monitor server on host") # Kill previous instances of the host load programs, if any _kill_host_programs(kill_stress_cmd, kill_monitor_cmd) # Cleanup previous log instances if os.path.isfile(monitor_log_file_server): os.remove(monitor_log_file_server) # Opening firewall ports on host process.run("iptables -F", ignore_status=True) # Run heartbeat on host process.run( server_setup_cmd % (monitor_dir, threshold, monitor_log_file_server, monitor_port), shell=True) if stress_setup_cmd is not None: logging.info("Build stress on host") # Uncompress and build stress on host process.run(stress_setup_cmd % stress_dir, shell=True) logging.info("Run stress on host") # stress_threads = 2 * n_cpus threads_host = 2 * cpu.online_cpus_count() # Run stress test on host process.run(stress_cmd % (stress_dir, threads_host), shell=True)
def host_stress_event(self, event): """ Host Stress events :param event: event name """ for itr in range(self.host_iterations): if "cpu_freq_governor" in event: cpu.set_cpufreq_governor() logging.debug("Current governor: %s", cpu.get_cpufreq_governor()) time.sleep(self.event_sleep_time) elif "cpu_idle" in event: idlestate = cpu.get_cpuidle_state() cpu.set_cpuidle_state() time.sleep(self.event_sleep_time) cpu.set_cpuidle_state(setstate=idlestate) time.sleep(self.event_sleep_time) elif "cpuoffline" in event: processor = self.host_cpu_list[random.randint(0, cpu.online_cpus_count()-1)] cpu.offline(processor) time.sleep(self.event_sleep_time) cpu.online(processor) else: raise NotImplementedError time.sleep(self.itr_sleep_time)
def setUp(self): smm = SoftwareManager() self.minthreads = self.params.get( 'minthrd', default=(500 + cpu.online_cpus_count())) self.maxthreads = self.params.get('maxthrd', default=None) self.iothreads = self.params.get('iothrd', default=self.minthreads/2) self.maxmem = self.params.get('maxmem', default=int( memory.meminfo.MemFree.m / self.minthreads)) self.maxio = self.params.get('maxio', default=None) self.longthreads = self.params.get('longthrd', default=False) self.shrtthreads = self.params.get('shortthrd', default=False) self.time = self.params.get('time', default=100) self.iotime = self.params.get('iotime', default=50) if self.longthreads and self.shrtthreads: self.cancel('Please choose right inputs') dist = distro.detect() packages = ['gcc'] if dist.name == 'Ubuntu': packages.extend(['g++']) elif dist.name in ['SuSE', 'fedora', 'rhel']: packages.extend(['gcc-c++']) for package in packages: if not smm.check_installed(package) and not smm.install(package): self.cancel('%s is needed for the test to be run' % package) for file_name in ['dwh.cpp', 'Makefile']: self.copyutil(file_name) os.chdir(self.teststmpdir) if dist.name in ['fedora', 'rhel']: process.system('patch -p0 < %s' % self.get_data('fofd.patch'), shell=True) build.make(self.teststmpdir)
def setUp(self): """ Setting up the env for the kernel building """ smg = SoftwareManager() detected_distro = distro.detect() deps = ['gcc', 'make', 'automake', 'autoconf', 'time', 'bison', 'flex'] if 'Ubuntu' in detected_distro.name: deps.extend(['libpopt0', 'libc6', 'libc6-dev', 'libpopt-dev', 'libcap-ng0', 'libcap-ng-dev', 'elfutils', 'libelf1', 'libnuma-dev', 'libfuse-dev', 'libssl-dev']) elif 'SuSE' in detected_distro.name: deps.extend(['libpopt0', 'glibc', 'glibc-devel', 'popt-devel', 'libcap2', 'libcap-devel', 'libcap-ng-devel', 'openssl-devel']) elif detected_distro.name in ['centos', 'fedora', 'rhel']: deps.extend(['popt', 'glibc', 'glibc-devel', 'libcap-ng', 'libcap', 'libcap-devel', 'elfutils-libelf', 'elfutils-libelf-devel', 'openssl-devel']) for package in deps: if not smg.check_installed(package) and not smg.install(package): self.cancel('%s is needed for the test to be run' % package) self.kernel_version = platform.uname()[2] self.iterations = self.params.get('runs', default=1) self.threads = self.params.get( 'cpus', default=2 * cpu.online_cpus_count()) self.location = self.params.get( 'url', default='https://github.com/torvalds/linux/archive' '/master.zip') self.config_path = os.path.join('/boot/config-', self.kernel_version) # Uncompress the kernel archive to the work directory tarball = self.fetch_asset("kernbench.zip", locations=[self.location], expire='1d') archive.extract(tarball, self.workdir)
def host(): logging.info("Setup monitor server on host") # Kill previous instances of the host load programs, if any _kill_host_programs(kill_stress_cmd, kill_monitor_cmd) # Cleanup previous log instances if os.path.isfile(monitor_log_file_server): os.remove(monitor_log_file_server) # Opening firewall ports on host process.run("iptables -F", ignore_status=True) # Run heartbeat on host process.run( server_setup_cmd % (monitor_dir, threshold, monitor_log_file_server, monitor_port), shell=True) if stress_setup_cmd is not None: logging.info("Build stress on host") # Uncompress and build stress on host process.run(stress_setup_cmd % stress_dir, shell=True) logging.info("Run stress on host") # stress_threads = 2 * n_cpus threads_host = 2 * cpu.online_cpus_count() # Run stress test on host process.run(stress_cmd % (stress_dir, threads_host), shell=True)
def core(self): """ Tests the core in ppc64_cpu command. """ op1 = process.system_output("ppc64_cpu --cores-present", shell=True).strip().split()[-1] op2 = cpu.online_cpus_count() / int(self.key) self.equality_check("Core", op1, op2)
def core(self): """ Tests the core in ppc64_cpu command. """ op1 = process.system_output( "ppc64_cpu --cores-present", shell=True).strip().split()[-1] op2 = cpu.online_cpus_count() / int(self.key) self.equality_check("Core", op1, op2)
def setUp(self): """ Verify : 1. It is Power system and platform is Power NV. 2. Cpupower tool is installed. """ if 'ppc' not in distro.detect().arch: self.cancel("Processor is not ppc64") if not os.path.exists('/sys/devices/system/cpu/cpu0/cpufreq'): self.cancel('CPUFREQ is supported only on Power NV') smm = SoftwareManager() detected_distro = distro.detect() if 'Ubuntu' in detected_distro.name: deps = [ 'linux-tools-common', 'linux-tools-%s' % platform.uname()[2] ] elif detected_distro.name == "SuSE": deps = ['cpupower'] else: deps = ['kernel-tools'] for package in deps: if not smm.check_installed(package) and not smm.install(package): self.cancel('%s is needed for the test to be run' % package) fre_min = 0 fre_max = 0 freq_info = process.system_output("cpupower frequency-info", shell=True).decode("utf-8") for line in str(freq_info).splitlines(): if re.search('hardware limits:', line, re.IGNORECASE): frq = line.split(":")[1] frq_init = frq.split('-')[0] frq_last = frq.split('-')[1] fre_min = float(frq_init.split('GHz')[0]) fre_max = float(frq_last.split('GHz')[0]) break threshold = (fre_max - fre_min) * (10**6) self.threshold = int(self.params.get("threshold", default=threshold)) self.cpus = cpu.online_cpus_count() self.cpu_num = 0 self.max_freq = 0 self.quad_dict = {} self.max_freq_dict = {} self.quad_to_cpu_mapping()
def run(test, params, env): """ Test virsh cpu-stats command. The command can display domain per-CPU and total statistics. 1. Call virsh cpu-stats [domain] 2. Call virsh cpu-stats [domain] with valid options 3. Call virsh cpu-stats [domain] with invalid options """ if not virsh.has_help_command('cpu-stats'): test.cancel("This version of libvirt does not support " "the cpu-stats test") vm_name = params.get("main_vm", "vm1") vm_ref = params.get("cpu_stats_vm_ref") status_error = params.get("status_error", "no") options = params.get("cpu_stats_options") error_msg = params.get("error_msg", "") logging.debug("options are %s", options) if vm_ref == "name": vm_ref = vm_name # get host cpus num cpus = cpu.online_cpus_count() logging.debug("host online cpu num is %s", cpus) # get options and put into a dict get_total = re.search('total', options) get_start = re.search('start', options) get_count = re.search('count', options) # command without options get_noopt = 0 if not get_total and not get_start and not get_count: get_noopt = 1 # command with only --total option get_totalonly = 0 if not get_start and not get_count and get_total: get_totalonly = 1 option_dict = {} if options.strip(): option_list = options.split('--') logging.debug("option_list is %s", option_list) for match in option_list[1:]: if get_start or get_count: option_dict[match.split(' ')[0]] = match.split(' ')[1] # check if cpu is enough,if not cancel the test if (status_error == "no"): cpu_start = int(option_dict.get("start", "0")) if cpu_start == 32: cpus = cpu.total_cpus_count() logging.debug("Host total cpu num: %s", cpus) if (cpu_start >= cpus): test.cancel("Host cpus are not enough") # Run virsh command cmd_result = virsh.cpu_stats(vm_ref, options, ignore_status=True, debug=True) output = cmd_result.stdout.strip() status = cmd_result.exit_status # check status_error if status_error == "yes": if status == 0: test.fail("Run successfully with wrong command! Output: {}".format( output)) else: # Check error message is expected if not re.search(error_msg, cmd_result.stderr.strip()): test.fail("Error message is not expected! " "Expected: {} Actual: {}".format( error_msg, cmd_result.stderr.strip())) elif status_error == "no": if status != 0: test.fail("Run failed with right command! Error: {}".format( cmd_result.stderr.strip())) else: # Get cgroup cpu_time if not get_totalonly: vm = env.get_vm(vm_ref) cgpath = utils_cgroup.resolve_task_cgroup_path( vm.get_pid(), "cpuacct") # When a VM has an 'emulator' child cgroup present, we must # strip off that suffix when detecting the cgroup for a machine if os.path.basename(cgpath) == "emulator": cgpath = os.path.dirname(cgpath) usage_file = os.path.join(cgpath, "cpuacct.usage_percpu") with open(usage_file, 'r') as f: cgtime = f.read().strip().split() logging.debug("cgtime get is %s", cgtime) # Cut CPUs from output and format to list output = re.sub(r'\.', '', output) if get_total: mt_start = re.search('Total', output).start() else: mt_start = len(output) output_cpus = " ".join(output[:mt_start].split()) cpus_list = re.compile(r'CPU\d+:').split(output_cpus) # conditions that list total time info if get_noopt or get_total: mt_end = re.search('Total', output).end() total_list = output[mt_end + 1:].split() total_time = int(total_list[1]) user_time = int(total_list[4]) system_time = int(total_list[7]) # check Total cpu_time >= User + System cpu_time if user_time + system_time >= total_time: test.fail("total cpu_time < user_time + " "system_time") logging.debug( "Check total cpu_time %d >= user + system " "cpu_time %d", total_time, user_time + system_time) start_num = 0 if get_start: start_num = int(option_dict["start"]) end_num = int(cpus) if get_count: count_num = int(option_dict["count"]) if end_num > start_num + count_num: end_num = start_num + count_num # for only give --total option it only shows "Total" cpu info if get_totalonly: end_num = -1 # find CPU[N] in output and sum the cpu_time and cgroup cpu_time sum_cputime = 0 sum_cgtime = 0 logging.debug("start_num %d, end_num %d", start_num, end_num) for i in range(start_num, end_num): if not re.search('CPU' + "%i" % i, output): test.fail("Fail to find CPU" + "%i" % i + "in " "result") logging.debug("Check CPU" + "%i" % i + " exist") sum_cputime += int(cpus_list[i - start_num + 1].split()[1]) sum_cgtime += int(cgtime[i]) # check cgroup cpu_time > sum of cpu_time if end_num >= 0: if sum_cputime > sum_cgtime: test.fail("Check sum of cgroup cpu_time < sum " "of output cpu_time") logging.debug("Check sum of cgroup cpu_time %d >= cpu_time %d", sum_cgtime, sum_cputime) # check Total cpu_time >= sum of cpu_time when no options if get_noopt: if total_time < sum_cputime: test.fail("total time < sum of output cpu_time") logging.debug( "Check total time %d >= sum of output cpu_time" " %d", total_time, sum_cputime)
def run(test, params, env): """ Test virsh cpu-stats command. The command can display domain per-CPU and total statistics. 1. Call virsh cpu-stats [domain] 2. Call virsh cpu-stats [domain] with valid options 3. Call virsh cpu-stats [domain] with invalid options """ def get_cpuacct_info(suffix): """ Get the CPU accounting info within the vm :param suffix: str, suffix of the CPU accounting.(stat/usage/usage_percpu) :return: list, the list of CPU accounting info """ if 'cg_obj' not in locals(): return # On cgroup v2 use cpu.stat as a substitute if cg_obj.is_cgroup_v2_enabled(): cg_path = cg_obj.get_cgroup_path("cpu") para = ('cpu.%s' % suffix) else: cg_path = cg_obj.get_cgroup_path("cpuacct") para = ('cpuacct.%s' % suffix) # We only need the info in file which "emulator" is not in path if os.path.basename(cg_path) == "emulator": cg_path = os.path.dirname(cg_path) usage_file = os.path.join(cg_path, para) with open(usage_file, 'r') as f: cpuacct_info = f.read().strip().split() logging.debug("cpuacct info %s", cpuacct_info) return cpuacct_info def check_user_and_system_time(total_list): user_time = float(total_list[4]) system_time = float(total_list[7]) # Check libvirt user and system time between pre and next cgroup time # Unit conversion (Unit: second) # Default time unit is microseconds on cgroup v2 while 1/100 second on v1 if cg_obj.is_cgroup_v2_enabled(): pre_user_time = float(cpuacct_res_pre[3]) / 1000000 pre_sys_time = float(cpuacct_res_pre[5]) / 1000000 next_user_time = float(cpuacct_res_next[3]) / 1000000 next_sys_time = float(cpuacct_res_next[5]) / 1000000 else: pre_user_time = float(cpuacct_res_pre[1]) / 100 pre_sys_time = float(cpuacct_res_pre[3]) / 100 next_user_time = float(cpuacct_res_next[1]) / 100 next_sys_time = float(cpuacct_res_next[3]) / 100 # check user_time if next_user_time >= user_time >= pre_user_time: logging.debug("Got the expected user_time: %s", user_time) else: test.fail("Got unexpected user_time: %s, " % user_time + "should between pre_user_time:%s " % pre_user_time + "and next_user_time:%s" % next_user_time) # check system_time if next_sys_time >= system_time >= pre_sys_time: logging.debug("Got the expected system_time: %s", system_time) else: test.fail("Got unexpected system_time: %s, " % system_time + "should between pre_sys_time:%s " % pre_sys_time + "and next_sys_time:%s" % next_sys_time) if not virsh.has_help_command('cpu-stats'): test.cancel("This version of libvirt does not support " "the cpu-stats test") vm_name = params.get("main_vm", "vm1") vm_ref = params.get("cpu_stats_vm_ref") status_error = params.get("status_error", "no") options = params.get("cpu_stats_options") error_msg = params.get("error_msg", "") logging.debug("options are %s", options) if vm_ref == "name": vm_ref = vm_name vm = env.get_vm(vm_ref) if vm and vm.get_pid(): cg_obj = libvirt_cgroup.CgroupTest(vm.get_pid()) # get host cpus num cpus = cpu.online_cpus_count() logging.debug("host online cpu num is %s", cpus) # get options and put into a dict get_total = re.search('total', options) get_start = re.search('start', options) get_count = re.search('count', options) # command without options get_noopt = 0 if not get_total and not get_start and not get_count: get_noopt = 1 # command with only --total option get_totalonly = 0 if not get_start and not get_count and get_total: get_totalonly = 1 option_dict = {} if options.strip(): option_list = options.split('--') logging.debug("option_list is %s", option_list) for match in option_list[1:]: if get_start or get_count: option_dict[match.split(' ')[0]] = match.split(' ')[1] # check if cpu is enough,if not cancel the test if (status_error == "no"): cpu_start = int(option_dict.get("start", "0")) if cpu_start == 32: cpus = cpu.total_cpus_count() logging.debug("Host total cpu num: %s", cpus) if (cpu_start >= cpus): test.cancel("Host cpus are not enough") # get CPU accounting info twice to compare with user_time and system_time cpuacct_res_pre = get_cpuacct_info('stat') # Run virsh command cmd_result = virsh.cpu_stats(vm_ref, options, ignore_status=True, debug=True) output = cmd_result.stdout.strip() status = cmd_result.exit_status cpuacct_res_next = get_cpuacct_info('stat') # check status_error if status_error == "yes": if status == 0: test.fail("Run successfully with wrong command! Output: {}".format( output)) else: # Check error message is expected if not re.search(error_msg, cmd_result.stderr.strip()): test.fail("Error message is not expected! " "Expected: {} Actual: {}".format( error_msg, cmd_result.stderr.strip())) elif status_error == "no": if status != 0: test.fail("Run failed with right command! Error: {}".format( cmd_result.stderr.strip())) else: # Get cgroup cpu_time if not get_totalonly: cgtime = get_cpuacct_info('usage_percpu') # Cut CPUs from output and format to list if get_total: mt_start = re.search('Total', output).start() else: mt_start = len(output) output_cpus = " ".join(output[:mt_start].split()) cpus_list = re.compile(r'CPU\d+:').split(output_cpus) # conditions that list total time info if get_noopt or get_total: mt_end = re.search('Total', output).end() total_list = output[mt_end + 1:].split() total_time = float(total_list[1]) check_user_and_system_time(total_list) start_num = 0 if get_start: start_num = int(option_dict["start"]) end_num = int(cpus) if get_count: count_num = int(option_dict["count"]) if end_num > start_num + count_num: end_num = start_num + count_num # for only give --total option it only shows "Total" cpu info if get_totalonly: end_num = -1 # find CPU[N] in output and sum the cpu_time and cgroup cpu_time sum_cputime = 0 sum_cgtime = 0 logging.debug("start_num %d, end_num %d", start_num, end_num) for i in range(start_num, end_num): logging.debug("Check CPU" + "%i" % i + " exist") sum_cputime += float(cpus_list[i - start_num + 1].split()[1]) sum_cgtime += float(cgtime[i]) if not re.search('CPU' + "%i" % i, output): test.fail("Fail to find CPU" + "%i" % i + "in " "result") # check cgroup cpu_time > sum of cpu_time if end_num >= 0: logging.debug("Check sum of cgroup cpu_time %d >= cpu_time %d", sum_cgtime, sum_cputime) if sum_cputime > sum_cgtime: test.fail("Check sum of cgroup cpu_time < sum " "of output cpu_time") # check Total cpu_time >= sum of cpu_time when no options if get_noopt: logging.debug( "Check total time %d >= sum of output cpu_time" " %d", total_time, sum_cputime) if total_time < sum_cputime: test.fail("total time < sum of output cpu_time")
def run(test, params, env): """ Qemu multiqueue test for virtio-scsi controller: 1) Boot up a guest with virtio-scsi device which support multi-queue and the vcpu and images number of guest should match the multi-queue number 2) Check the multi queue option from monitor 3) Check device init status in guest 4) Load I/O in all targets 5) Check the interrupt queues in guest :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def proc_interrupts_results(results, irqs_pattern): results_dict = {} cpu_count = 0 cpu_list = [] for line in results.splitlines(): line = line.strip() if re.match("CPU0", line): cpu_list = re.findall(r"CPU\d+", line) cpu_count = len(cpu_list) continue if cpu_count > 0: irq_key = re.split(":", line)[0] if re.findall(irqs_pattern, re.split(":", line)[-1]): results_dict[irq_key] = {} content = line[len(irq_key) + 1:].strip() if len(re.split(r"\s+", content)) < cpu_count: continue count = 0 irq_des = "" for irq_item in re.split(r"\s+", content): if count < cpu_count: if count == 0: results_dict[irq_key]["count"] = [] results_dict[irq_key]["count"].append(irq_item) else: irq_des += " %s" % irq_item count += 1 results_dict[irq_key]["irq_des"] = irq_des.strip() if not results_dict: test.error("Couldn't find virtio request interrupts from procfs") return results_dict, cpu_list timeout = float(params.get("login_timeout", 240)) host_cpu_num = utils_cpu.online_cpus_count() while host_cpu_num: num_queues = str(host_cpu_num) host_cpu_num &= host_cpu_num - 1 params['smp'] = num_queues params['num_queues'] = num_queues images_num = int(num_queues) extra_image_size = params.get("image_size_extra_images", "512M") system_image = params.get("images") system_image_drive_format = params.get("system_image_drive_format", "virtio") params["drive_format_%s" % system_image] = system_image_drive_format error_context.context("Boot up guest with block devcie with num_queues" " is %s and smp is %s" % (num_queues, params['smp']), logging.info) for vm in env.get_all_vms(): if vm.is_alive(): vm.destroy() for extra_image in range(images_num): image_tag = "stg%s" % extra_image params["images"] += " %s" % image_tag params["image_name_%s" % image_tag] = "images/%s" % image_tag params["image_size_%s" % image_tag] = extra_image_size params["force_create_image_%s" % image_tag] = "yes" image_params = params.object_params(image_tag) env_process.preprocess_image(test, image_params, image_tag) params["start_vm"] = "yes" vm = env.get_vm(params["main_vm"]) env_process.preprocess_vm(test, params, env, vm.name) session = vm.wait_for_login(timeout=timeout) if params.get("os_type") == "windows": driver_name = params["driver_name"] wmi_check_cmd = params["wmi_check_cmd"] pattern = params["pattern"] session = utils_test.qemu.windrv_check_running_verifier(session, vm, test, driver_name, timeout) wmi_check_cmd = utils_misc.set_winutils_letter(session, wmi_check_cmd) error_context.context("Run wmi check in guest.", logging.info) output = session.cmd_output(wmi_check_cmd) queue_num = re.findall(pattern, output, re.M) try: if not queue_num or queue_num[0] != num_queues: test.fail("The queue_num from guest is not match with expected.\n" "queue_num from guest is %s, expected is %s" % (queue_num, num_queues)) finally: session.close() return error_context.context("Check irqbalance service status", logging.info) output = session.cmd_output("systemctl status irqbalance") if not re.findall("Active: active", output): session.cmd("systemctl start irqbalance") output = session.cmd_output("systemctl status irqbalance") output = utils_misc.strip_console_codes(output) if not re.findall("Active: active", output): test.cancel("Can not start irqbalance inside guest. " "Skip this test.") error_context.context("Pin vcpus to host cpus", logging.info) host_numa_nodes = utils_misc.NumaInfo() vcpu_num = 0 for numa_node_id in host_numa_nodes.nodes: numa_node = host_numa_nodes.nodes[numa_node_id] for _ in range(len(numa_node.cpus)): if vcpu_num >= len(vm.vcpu_threads): break vcpu_tid = vm.vcpu_threads[vcpu_num] logging.debug("pin vcpu thread(%s) to cpu" "(%s)" % (vcpu_tid, numa_node.pin_cpu(vcpu_tid))) vcpu_num += 1 error_context.context("Verify num_queues from monitor", logging.info) qtree = qemu_qtree.QtreeContainer() try: qtree.parse_info_qtree(vm.monitor.info('qtree')) except AttributeError: test.cancel("Monitor deson't supoort qtree skip this test") error_msg = "Number of queues mismatch: expect %s" error_msg += " report from monitor: %s(%s)" scsi_bus_addr = "" qtree_num_queues_full = "" qtree_num_queues = "" for node in qtree.get_nodes(): if isinstance(node, qemu_qtree.QtreeDev) and ( node.qtree['type'] == "virtio-scsi-device"): qtree_num_queues_full = node.qtree["num_queues"] qtree_num_queues = re.search( "[0-9]+", qtree_num_queues_full).group() elif isinstance(node, qemu_qtree.QtreeDev) and node.qtree['type'] == "virtio-scsi-pci": scsi_bus_addr = node.qtree['addr'] if qtree_num_queues != num_queues: error_msg = error_msg % (num_queues, qtree_num_queues, qtree_num_queues_full) test.fail(error_msg) if not scsi_bus_addr: test.error("Didn't find addr from qtree. Please check the log.") error_context.context("Check device init status in guest", logging.info) irq_check_cmd = params.get("irq_check_cmd", "cat /proc/interrupts") output = session.cmd_output(irq_check_cmd) irq_name = params.get("irq_regex") prev_irq_results, _ = proc_interrupts_results(output, irq_name) logging.debug('The info of interrupters before testing:') for irq_watch in prev_irq_results.keys(): logging.debug('%s : %s %s' % (irq_watch, prev_irq_results[irq_watch]['count'], prev_irq_results[irq_watch]['irq_des'])) error_context.context("Pin the interrupters to vcpus", logging.info) cpu_select = 1 for irq_id in prev_irq_results.keys(): bind_cpu_cmd = "echo %s > /proc/irq/%s/smp_affinity" % \ (hex(cpu_select).replace('0x', ''), irq_id) cpu_select = cpu_select << 1 session.cmd(bind_cpu_cmd) error_context.context("Load I/O in all targets", logging.info) get_dev_cmd = params.get("get_dev_cmd", "ls /dev/[svh]d*") output = session.cmd_output(get_dev_cmd) system_dev = re.findall(r"/dev/[svh]d\w+(?=\d+)", output)[0] dd_timeout = int(re.findall(r"\d+", extra_image_size)[0]) fill_cmd = "" count = 0 for dev in re.split(r"\s+", output): if not dev: continue if not re.findall(system_dev, dev): fill_cmd += " dd of=%s if=/dev/urandom bs=1M " % dev fill_cmd += "count=%s oflag=direct &" % dd_timeout count += 1 if count != images_num: test.error("Disks are not all show up in system. Output " "from the check command: %s" % output) # As Bug 1177332 exists, mq is not supported completely. # So don't considering performance currently, dd_timeout is longer. dd_timeout = dd_timeout * images_num * 2 session.cmd(fill_cmd, timeout=dd_timeout) dd_thread_num = count while dd_thread_num: time.sleep(5) dd_thread_num = session.cmd_output("pgrep -x dd", timeout=dd_timeout) error_context.context("Check the interrupt queues in guest", logging.info) output = session.cmd_output(irq_check_cmd) next_irq_results, cpu_list = proc_interrupts_results(output, irq_name) logging.debug('The info of interrupters after testing :') for irq_watch in next_irq_results.keys(): logging.debug('%s : %s %s' % (irq_watch, next_irq_results[irq_watch]['count'], next_irq_results[irq_watch]['irq_des'])) irq_bit_map = 0 for irq_watch in next_irq_results.keys(): for index, count in enumerate(next_irq_results[irq_watch]["count"]): if (int(count) - int(prev_irq_results[irq_watch]["count"][index])) > 0: irq_bit_map |= 2 ** index error_msg = "" cpu_not_used = [] for index, cpu in enumerate(cpu_list): if 2 ** index & irq_bit_map != 2 ** index: cpu_not_used.append(cpu) if cpu_not_used: logging.debug("Interrupt info from procfs:\n%s" % output) error_msg = " ".join(cpu_not_used) if len(cpu_not_used) > 1: error_msg += " are" else: error_msg += " is" error_msg += " not used during test. Please check debug log for" error_msg += " more information." test.fail(error_msg)
def run(test, params, env): """ Test virsh cpu-stats command. The command can display domain per-CPU and total statistics. 1. Call virsh cpu-stats [domain] 2. Call virsh cpu-stats [domain] with valid options 3. Call virsh cpu-stats [domain] with invalide options """ if not virsh.has_help_command('cpu-stats'): test.cancel("This version of libvirt does not support " "the cpu-stats test") vm_name = params.get("main_vm", "vm1") vm_ref = params.get("cpu_stats_vm_ref") status_error = params.get("status_error", "no") options = params.get("cpu_stats_options") error_msg = params.get("error_msg", "") logging.debug("options are %s", options) if vm_ref == "name": vm_ref = vm_name # get host cpus num cpus = cpu.online_cpus_count() logging.debug("host online cpu num is %s", cpus) # get options and put into a dict get_total = re.search('total', options) get_start = re.search('start', options) get_count = re.search('count', options) # command without options get_noopt = 0 if not get_total and not get_start and not get_count: get_noopt = 1 # command with only --total option get_totalonly = 0 if not get_start and not get_count and get_total: get_totalonly = 1 option_dict = {} if options.strip(): option_list = options.split('--') logging.debug("option_list is %s", option_list) for match in option_list[1:]: if get_start or get_count: option_dict[match.split(' ')[0]] = match.split(' ')[1] # check if cpu is enough,if not cancel the test if (status_error == "no"): cpu_start = int(option_dict.get("start", "0")) if cpu_start == 32: cpus = cpu.total_cpus_count() logging.debug("Host total cpu num: %s", cpus) if (cpu_start >= cpus): test.cancel("Host cpus are not enough") # Run virsh command cmd_result = virsh.cpu_stats(vm_ref, options, ignore_status=True, debug=True) output = cmd_result.stdout.strip() status = cmd_result.exit_status # check status_error if status_error == "yes": if status == 0: test.fail("Run successfully with wrong command!") else: # Check error message is expected if not re.search(error_msg, cmd_result.stderr.strip()): test.fail("Error message is not expected!") elif status_error == "no": if status != 0: test.fail("Run failed with right command") else: # Get cgroup cpu_time if not get_totalonly: vm = env.get_vm(vm_ref) cgpath = utils_cgroup.resolve_task_cgroup_path( vm.get_pid(), "cpuacct") # When a VM has an 'emulator' child cgroup present, we must # strip off that suffix when detecting the cgroup for a machine if os.path.basename(cgpath) == "emulator": cgpath = os.path.dirname(cgpath) usage_file = os.path.join(cgpath, "cpuacct.usage_percpu") with open(usage_file, 'r') as f: cgtime = f.read().strip().split() logging.debug("cgtime get is %s", cgtime) # Cut CPUs from output and format to list output = re.sub(r'\.', '', output) if get_total: mt_start = re.search('Total', output).start() else: mt_start = len(output) output_cpus = " ".join(output[:mt_start].split()) cpus_list = re.compile(r'CPU\d+:').split(output_cpus) # conditions that list total time info if get_noopt or get_total: mt_end = re.search('Total', output).end() total_list = output[mt_end + 1:].split() total_time = int(total_list[1]) user_time = int(total_list[4]) system_time = int(total_list[7]) # check Total cpu_time >= User + System cpu_time if user_time + system_time >= total_time: test.fail("total cpu_time < user_time + " "system_time") logging.debug("Check total cpu_time %d >= user + system " "cpu_time %d", total_time, user_time + system_time) start_num = 0 if get_start: start_num = int(option_dict["start"]) end_num = int(cpus) if get_count: count_num = int(option_dict["count"]) if end_num > start_num + count_num: end_num = start_num + count_num # for only give --total option it only shows "Total" cpu info if get_totalonly: end_num = -1 # find CPU[N] in output and sum the cpu_time and cgroup cpu_time sum_cputime = 0 sum_cgtime = 0 logging.debug("start_num %d, end_num %d", start_num, end_num) for i in range(start_num, end_num): if not re.search('CPU' + "%i" % i, output): test.fail("Fail to find CPU" + "%i" % i + "in " "result") logging.debug("Check CPU" + "%i" % i + " exist") sum_cputime += int(cpus_list[i - start_num + 1].split()[1]) sum_cgtime += int(cgtime[i]) # check cgroup cpu_time > sum of cpu_time if end_num >= 0: if sum_cputime > sum_cgtime: test.fail("Check sum of cgroup cpu_time < sum " "of output cpu_time") logging.debug("Check sum of cgroup cpu_time %d >= cpu_time %d", sum_cgtime, sum_cputime) # check Total cpu_time >= sum of cpu_time when no options if get_noopt: if total_time < sum_cputime: test.fail("total time < sum of output cpu_time") logging.debug("Check total time %d >= sum of output cpu_time" " %d", total_time, sum_cputime)
def run(test, params, env): """ Run kernbench for performance testing. 1) Set up testing environment. 2) Get a kernel code. 3) Make the kernel with kernbench -M or time make -j 2*smp :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def download_if_not_exists(): if not os.path.exists(file_name): cmd = "wget -t 10 -c -P %s %s" % (tmp_dir, file_link) process.system(cmd) def cmd_status_output(cmd, timeout=360): s = 0 o = "" if "guest" in test_type: (s, o) = session.cmd_status_output(cmd, timeout=timeout) else: cmd_result = process.run(cmd, ignore_status=True, shell=True) (s, o) = cmd_result.exit_status, cmd_result.stdout return (s, o) def check_ept(): output = process.system_output("grep 'flags' /proc/cpuinfo") flags = output.splitlines()[0].split(':')[1].split() need_ept = params.get("need_ept", "no") if 'ept' not in flags and "yes" in need_ept: test.cancel("This test requires a host that supports EPT") elif 'ept' in flags and "no" in need_ept: cmd = "modprobe -r kvm_intel && modprobe kvm_intel ept=0" process.system(cmd, timeout=100, shell=True) elif 'ept' in flags and "yes" in need_ept: cmd = "modprobe -r kvm_intel && modprobe kvm_intel ept=1" process.system(cmd, timeout=100, shell=True) def install_gcc(): logging.info("Update gcc to request version....") cmd = "rpm -q gcc" cpp_link = params.get("cpp_link") gcc_link = params.get("gcc_link") libgomp_link = params.get("libgomp_link") libgcc_link = params.get("libgcc_link") (s, o) = cmd_status_output(cmd) if s: cmd = "rpm -ivh %s --nodeps; rpm -ivh %s --nodeps; rpm -ivh %s"\ " --nodeps; rpm -ivh %s --nodeps" % (libgomp_link, libgcc_link, cpp_link, gcc_link) else: gcc = o.splitlines()[0].strip() if gcc in gcc_link: cmd = "rpm -e %s && rpm -ivh %s" % (gcc, gcc_link) else: cmd = "rpm -ivh %s --nodeps; rpm -ivh %s --nodeps; rpm -ivh"\ " %s --nodeps; rpm -ivh %s --nodeps" % (libgomp_link, libgcc_link, cpp_link, gcc_link) (s, o) = cmd_status_output(cmd) if s: logging.debug("Fail to install gcc.output:%s" % o) def record_result(result): re_result = params.get("re_result") (m_value, s_value) = re.findall(re_result, result)[0] s_value = float(m_value) * 60 + float(s_value) shortname = params.get("shortname") result_str = "%s: %ss\n" % (shortname, s_value) result_file = params.get("result_file") f1 = open(result_file, "a+") result = f1.read() result += result_str f1.write(result_str) f1.close() open(os.path.basename(result_file), 'w').write(result) logging.info("Test result got from %s:\n%s" % (result_file, result)) test_type = params.get("test_type") guest_thp_cmd = params.get("guest_thp_cmd") cmd_timeout = int(params.get("cmd_timeout", 1200)) tmp_dir = params.get("tmp_dir", "/tmp/kernbench/") check_ept() vm_name = params.get("main_vm", "vm1") cpu_multiplier = int(params.get("cpu_multiplier", 2)) session = None if "guest" in test_type: env_process.preprocess_vm(test, params, env, vm_name) vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_login( timeout=int(params.get("login_timeout", 360))) # Create tmp folder and download files if need. if not os.path.exists(tmp_dir): process.system("mkdir %s" % tmp_dir) files = params.get("files_need").split() for file in files: file_link = params.get("%s_link" % file) file_name = os.path.join(tmp_dir, os.path.basename(file_link)) download_if_not_exists() if "guest" in test_type: logging.info("test in guest") vm.copy_files_to(tmp_dir, os.path.dirname(tmp_dir)) if guest_thp_cmd is not None: session.cmd_output(guest_thp_cmd) try: if params.get("update_gcc") and params.get("update_gcc") == "yes": install_gcc() pre_cmd = params.get("pre_cmd") (s, o) = cmd_status_output(pre_cmd, timeout=cmd_timeout) if s: test.error("Fail command:%s\nOutput: %s" % (pre_cmd, o)) if "guest" in test_type: cpu_num = params.get("smp") else: cpu_num = cpu.online_cpus_count() test_cmd = params.get("test_cmd") % (int(cpu_num) * cpu_multiplier) logging.info("Start making the kernel ....") (s, o) = cmd_status_output(test_cmd, timeout=cmd_timeout) if s: test.error("Fail command:%s\n Output:%s" % (test_cmd, o)) else: logging.info("Output for command %s is:\n %s" % (test_cmd, o)) record_result(o) finally: if params.get("post_cmd"): cmd_status_output(params.get("post_cmd"), timeout=cmd_timeout) if session: session.close()
def run(test, params, env): """ NIC option check test. :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def test_netperf(): """ Netperf stress test for nic option. """ netperf_client_link = os.path.join(data_dir.get_deps_dir("netperf"), params.get("netperf_client_link")) client_path = params.get("client_path") n_client = utils_netperf.NetperfClient( vm.get_address(), client_path, netperf_source=netperf_client_link, client=params.get("shell_client"), port=params.get("shell_port"), username=params.get("username"), password=params.get("password"), prompt=params.get("shell_prompt"), linesep=params.get("shell_linesep", "\n").encode().decode('unicode_escape'), status_test_command=params.get("status_test_command", "")) n_server = utils_netperf.NetperfServer( utils_net.get_host_ip_address(params), params.get("server_path", "/var/tmp"), netperf_source=os.path.join(data_dir.get_deps_dir("netperf"), params.get("netperf_server_link")), password=params.get("hostpassword")) try: n_server.start() # Run netperf with message size defined in range. netperf_test_duration = int( params.get("netperf_test_duration", 180)) netperf_para_sess = params.get("netperf_para_sessions", "1") test_protocols = params.get("test_protocols", "TCP_STREAM") netperf_cmd_prefix = params.get("netperf_cmd_prefix", "") netperf_output_unit = params.get("netperf_output_unit") netperf_package_sizes = params.get("netperf_sizes") test_option = params.get("test_option", "") test_option += " -l %s" % netperf_test_duration if params.get("netperf_remote_cpu") == "yes": test_option += " -C" if params.get("netperf_local_cpu") == "yes": test_option += " -c" if netperf_output_unit in "GMKgmk": test_option += " -f %s" % netperf_output_unit start_time = time.time() stop_time = start_time + netperf_test_duration num = 0 for protocol in test_protocols.split(): error_context.context("Testing %s protocol" % protocol, logging.info) t_option = "%s -t %s" % (test_option, protocol) n_client.bg_start(utils_net.get_host_ip_address(params), t_option, netperf_para_sess, netperf_cmd_prefix, package_sizes=netperf_package_sizes) if utils_misc.wait_for(n_client.is_netperf_running, 10, 0, 1, "Wait netperf test start"): logging.info("Netperf test start successfully.") else: test.error("Can not start netperf client.") num += 1 # here when set a run flag, when other case call this case as a # subprocess backgroundly,can set this run flag to False to stop # the stress test. env["netperf_run"] = True netperf_test_duration = stop_time - time.time() utils_misc.wait_for( lambda: not n_client.is_netperf_running(), netperf_test_duration, 0, 5, "Wait netperf test finish %ss" % netperf_test_duration) time.sleep(5) finally: n_server.stop() n_server.package.env_cleanup(True) n_client.package.env_cleanup(True) def test_ping(): """ Ping test for nic option. """ package_sizes = params.objects("ping_sizes") if params["os_type"] == "windows": ifname = utils_net.get_windows_nic_attribute( session=session, key="netenabled", value=True, target="netconnectionID") else: ifname = utils_net.get_linux_ifname(session, vm.get_mac_address()) dest = utils_net.get_host_ip_address(params) for size in package_sizes: error_context.context( "Test ping from '%s' to host '%s' on guest '%s'" " with package size %s. " % (ifname, dest, vm.name, size), logging.info) status, output = utils_net.ping(dest=dest, count=10, packetsize=size, session=session, timeout=30) if status: test.fail("%s ping %s unexpected, output %s" % (vm.name, dest, output)) if params["os_type"] == "windows": # windows guest get loss=0 when ping failed sometime, # need further check loss = utils_test.get_loss_ratio(output) if loss or "TTL" in output: pass else: test.fail("Guest ping test hit unexpected loss, " "error_info: %s" % output) check_type = params.get("check_type") smp_value = params.get_numeric("smp") or params.get_numeric("vcpu_maxcpus") if cpu.online_cpus_count() < 2 * smp_value: test.cancel("The number of smp counts in this host is not big enough") vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_serial_login() try: if params["os_type"] == "windows": error_context.context("Verify if netkvm.sys is enabled in guest", logging.info) session = utils_test.qemu.windrv_check_running_verifier( session, vm, test, "netkvm") func_name = {"ping": test_ping, "netperf": test_netperf} func_name[check_type]() finally: session.close()
def run(test, params, env): """ Test commands: virsh.vcpupin, virsh.iothreadpin, virsh.emulatorpin. Steps: - Configure the test VM - Check default values are correct - Perform virsh vcpupin, check iothreadpin and emulatorpin are not impacted - Perform virsh emulatorpin, check vcpupin and iothreadpin are not impacted - Perform virsh iotheadpin, check vcpupin and emulatorpin are not impacted - Recover test environment """ start_vm = params.get("start_vm", "yes") == "yes" change_vcpupin = params.get("change_vcpupin", "no") == 'yes' change_emulatorpin = params.get("change_emulatorpin", "no") == 'yes' change_iothreadpin = params.get("change_iothreadpin", "no") == 'yes' vm_name = params.get("main_vm") vm = env.get_vm(vm_name) check_to_skip_case(params, test) if vm.is_alive(): vm.destroy() original_vm_xml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) vm_xml_copy = original_vm_xml.copy() prepare_vm(original_vm_xml, params) host_cpus = cpu.online_cpus_count() cpu_max_index = int(host_cpus) - 1 try: if start_vm: vm.start() logging.debug("After vm starts, vm xml is:" "%s\n", vm_xml.VMXML.new_from_dumpxml(vm_name)) logging.debug("Get default vcpupin/emulatorpin/iothreadpin values of the vm") vcpupin_result, emulatorpin_result, iothreadpin_result = get_current_values(vm_name) logging.debug("Check and compare default vcpupin/emulatorpin/iothreadpin values") compare_results(vcpupin_result, emulatorpin_result, iothreadpin_result, params.get("iothreadid", '1'), test) if change_vcpupin: # Change vcpupin, then check vcpupin, and emulatorpin/iothreadpin # should not be effected. logging.debug("Now change vcpupin value to the guest") cpu_list = "0-%s" % (cpu_max_index - 1) if cpu_max_index > 1 else "0" virsh.vcpupin(vm_name, "0", cpu_list, None, debug=True, ignore_status=False) changed_vcpupin = {'0': cpu_list} check_vcpupin(vcpupin_result, changed_vcpupin, vm_name, test) check_emulatorpin(emulatorpin_result, None, vm_name, test) check_iothreadpin(iothreadpin_result, None, vm_name, test) if change_emulatorpin: # Change emulatorpin, then check emulatorpin, and vcpupin/iothreadpin # should not be effected logging.debug("Now change emulatorpin value to the guest") vcpupin_result, emulatorpin_result, iothreadpin_result = get_current_values(vm_name) cpu_list = "0,%s" % (cpu_max_index - 1) if cpu_max_index > 1 else "0" virsh.emulatorpin(vm_name, cpu_list, ignore_status=False, debug=True) changed_emulatorpin = {'*': cpu_list} check_emulatorpin(emulatorpin_result, changed_emulatorpin, vm_name, test) check_vcpupin(vcpupin_result, None, vm_name, test) check_iothreadpin(iothreadpin_result, None, vm_name, test) if change_iothreadpin: # Change iothreadpin, then check iothreadpin, and vcpupin/emulatorpin # should not be effected logging.debug("Now change iothreadpin value to the guest") vcpupin_result, emulatorpin_result, iothreadpin_result = get_current_values(vm_name) cpu_list = "%s" % (cpu_max_index - 1) if cpu_max_index > 1 else "0" iothread_id = params.get("iothread_id", "1") virsh.iothreadpin(vm_name, iothread_id, cpu_list, ignore_status=False, debug=True) changed_iothreadpin = {iothread_id: cpu_list} check_iothreadpin(iothreadpin_result, changed_iothreadpin, vm_name, test) check_vcpupin(vcpupin_result, None, vm_name, test) check_emulatorpin(emulatorpin_result, None, vm_name, test) finally: vm_xml_copy.sync() if vm.is_alive(): vm.destroy()
def run(test, params, env): """ Check the TSC(time stamp counter) frequency of guest and host whether match or not 1) Test the vcpus' TSC of host by C the program 2) Copy the C code to the guest, complie and run it to get the vcpus' TSC of guest 3) Sleep sometimes and get the TSC of host and guest again 4) Compute the TSC frequency of host and guest 5) Compare the frequency deviation between host and guest with standard :param test: QEMU test object :param params: Dictionary with the test parameters. :param env: Dictionary with test environment. """ drift_threshold = float(params.get("drift_threshold")) interval = float(params.get("interval")) cpu_chk_cmd = params.get("cpu_chk_cmd") tsc_cmd_guest = params.get("tsc_cmd_guest", "./a.out") tsc_cmd_host = params.get("tsc_cmd_host", "./a.out") tsc_freq_path = os.path.join(data_dir.get_deps_dir(), 'timedrift/get_tsc.c') host_freq = 0 def get_tsc(machine="host", i=0): tsc_cmd = tsc_cmd_guest if tsc_cmd == "host": tsc_cmd = tsc_cmd_host cmd = "taskset %s %s" % (1 << i, tsc_cmd) if machine == "host": s, o = commands.getstatusoutput(cmd) else: s, o = session.cmd_status_output(cmd) if s != 0: test.error("Fail to get tsc of host, ncpu: %d" % i) o = re.findall(r"(\d+)", o)[0] return float(o) vm = env.get_vm(params["main_vm"]) vm.verify_alive() session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360))) if not os.path.exists(tsc_cmd_guest): commands.getoutput("gcc %s" % tsc_freq_path) ncpu = cpu.online_cpus_count() logging.info("Interval is %s" % interval) logging.info("Determine the TSC frequency in the host") for i in range(ncpu): tsc1 = get_tsc("host", i) time.sleep(interval) tsc2 = get_tsc("host", i) delta = tsc2 - tsc1 logging.info("Host TSC delta for cpu %s is %s" % (i, delta)) if delta < 0: test.error("Host TSC for cpu %s warps %s" % (i, delta)) host_freq += delta / ncpu logging.info("Average frequency of host's cpus: %s" % host_freq) if session.cmd_status("test -x %s" % tsc_cmd_guest): vm.copy_files_to(tsc_freq_path, '/tmp/get_tsc.c') if session.cmd_status("gcc /tmp/get_tsc.c") != 0: test.error("Fail to compile program on guest") s, guest_ncpu = session.cmd_status_output(cpu_chk_cmd) if s != 0: test.error("Fail to get cpu number of guest") success = True for i in range(int(guest_ncpu)): tsc1 = get_tsc("guest", i) time.sleep(interval) tsc2 = get_tsc("guest", i) delta = tsc2 - tsc1 logging.info("Guest TSC delta for vcpu %s is %s" % (i, delta)) if delta < 0: logging.error("Guest TSC for vcpu %s warps %s" % (i, delta)) ratio = 100 * (delta - host_freq) / host_freq logging.info("TSC drift ratio for vcpu %s is %s" % (i, ratio)) if abs(ratio) > drift_threshold: logging.error("TSC drift found for vcpu %s ratio %s" % (i, ratio)) success = False if not success: test.fail("TSC drift found for the guest, please check the " "log for details") session.close()
def run(test, params, env): """ Test emulatorpin tuning 1) Positive testing 1.1) get the current emulatorpin parameters for a running/shutoff guest 1.2) set the current emulatorpin parameters for a running/shutoff guest 2) Negative testing 2.1) get emulatorpin parameters for a running/shutoff guest 2.2) set emulatorpin parameters running/shutoff guest """ # Run test case vm_name = params.get("main_vm") vm = env.get_vm(vm_name) cgconfig = params.get("cgconfig", "on") cpulist = params.get("emulatorpin_cpulist") status_error = params.get("status_error", "no") change_parameters = params.get("change_parameters", "no") # Backup original vm vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) vmxml_backup = vmxml.copy() emulatorpin_placement = params.get("emulatorpin_placement", "") if emulatorpin_placement: vm.destroy() vmxml.placement = emulatorpin_placement vmxml.sync() try: vm.start() except VMStartError as detail: # Recover the VM and failout early vmxml_backup.sync() logging.debug("Used VM XML:\n %s", vmxml) test.fail("VM Fails to start: %s" % detail) test_dicts = dict(params) test_dicts['vm'] = vm host_cpus = cpu.online_cpus_count() test_dicts['host_cpus'] = host_cpus cpu_max = int(host_cpus) - 1 cpu_list = None # Assemble cpu list for positive test if status_error == "no": if cpulist is None: pass elif cpulist == "x": cpu_online_map = list(map(str, cpu.cpu_online_list())) cpulist = random.choice(cpu_online_map) elif cpulist == "x-y": # By default, emulator is pined to all cpus, and element # 'cputune/emulatorpin' may not exist in VM's XML. # And libvirt will do nothing if pin emulator to the same # cpus, that means VM's XML still have that element. # So for testing, we should avoid that value(0-$cpu_max). if cpu_max < 2: cpulist = "0-0" else: cpulist = "0-%s" % (cpu_max - 1) elif cpulist == "x,y": cpu_online_map = list(map(str, cpu.cpu_online_list())) cpulist = ','.join(random.sample(cpu_online_map, 2)) elif cpulist == "x-y,^z": cpulist = "0-%s,^%s" % (cpu_max, cpu_max) elif cpulist == "-1": cpulist = "-1" elif cpulist == "out_of_max": cpulist = str(cpu_max + 1) else: test.cancel("CPU-list=%s is not recognized." % cpulist) test_dicts['emulatorpin_cpulist'] = cpulist if cpulist: cpu_list = cpus_parser(cpulist) test_dicts['cpu_list'] = cpu_list logging.debug("CPU list is %s", cpu_list) cg = utils_cgroup.CgconfigService() if cgconfig == "off": if cg.cgconfig_is_running(): cg.cgconfig_stop() # positive and negative testing ######### try: if status_error == "no": if change_parameters == "no": get_emulatorpin_parameter(test_dicts, test) else: set_emulatorpin_parameter(test_dicts, test) if status_error == "yes": if change_parameters == "no": get_emulatorpin_parameter(test_dicts, test) else: set_emulatorpin_parameter(test_dicts, test) finally: # Recover cgconfig and libvirtd service if not cg.cgconfig_is_running(): cg.cgconfig_start() utils_libvirtd.libvirtd_restart() # Recover vm. vmxml_backup.sync()
def run(test, params, env): """ Test emulatorpin tuning 1) Positive testing 1.1) get the current emulatorpin parameters for a running/shutoff guest 1.2) set the current emulatorpin parameters for a running/shutoff guest 2) Negative testing 2.1) get emulatorpin parameters for a running/shutoff guest 2.2) set emulatorpin parameters running/shutoff guest """ # Run test case vm_name = params.get("main_vm") vm = env.get_vm(vm_name) cgconfig = params.get("cgconfig", "on") cpulist = params.get("emulatorpin_cpulist") status_error = params.get("status_error", "no") change_parameters = params.get("change_parameters", "no") # Backup original vm vmxml = vm_xml.VMXML.new_from_inactive_dumpxml(vm_name) vmxml_backup = vmxml.copy() emulatorpin_placement = params.get("emulatorpin_placement", "") if emulatorpin_placement: vm.destroy() vmxml.placement = emulatorpin_placement vmxml.sync() try: vm.start() except VMStartError as detail: # Recover the VM and failout early vmxml_backup.sync() logging.debug("Used VM XML:\n %s", vmxml) test.fail("VM Fails to start: %s", detail) test_dicts = dict(params) test_dicts['vm'] = vm host_cpus = cpu.online_cpus_count() test_dicts['host_cpus'] = host_cpus cpu_max = int(host_cpus) - 1 cpu_list = None # Assemble cpu list for positive test if status_error == "no": if cpulist is None: pass elif cpulist == "x": cpu_online_map = list(map(str, cpu.cpu_online_list())) cpulist = random.choice(cpu_online_map) elif cpulist == "x-y": # By default, emulator is pined to all cpus, and element # 'cputune/emulatorpin' may not exist in VM's XML. # And libvirt will do nothing if pin emulator to the same # cpus, that means VM's XML still have that element. # So for testing, we should avoid that value(0-$cpu_max). if cpu_max < 2: cpulist = "0-0" else: cpulist = "0-%s" % (cpu_max - 1) elif cpulist == "x,y": cpu_online_map = list(map(str, cpu.cpu_online_list())) cpulist = ','.join(random.sample(cpu_online_map, 2)) elif cpulist == "x-y,^z": cpulist = "0-%s,^%s" % (cpu_max, cpu_max) elif cpulist == "-1": cpulist = "-1" elif cpulist == "out_of_max": cpulist = str(cpu_max + 1) else: test.cancel("CPU-list=%s is not recognized." % cpulist) test_dicts['emulatorpin_cpulist'] = cpulist if cpulist: cpu_list = cpus_parser(cpulist) test_dicts['cpu_list'] = cpu_list logging.debug("CPU list is %s", cpu_list) cg = utils_cgroup.CgconfigService() if cgconfig == "off": if cg.cgconfig_is_running(): cg.cgconfig_stop() # positive and negative testing ######### try: if status_error == "no": if change_parameters == "no": get_emulatorpin_parameter(test_dicts, test) else: set_emulatorpin_parameter(test_dicts, test) if status_error == "yes": if change_parameters == "no": get_emulatorpin_parameter(test_dicts, test) else: set_emulatorpin_parameter(test_dicts, test) finally: # Recover cgconfig and libvirtd service if not cg.cgconfig_is_running(): cg.cgconfig_start() utils_libvirtd.libvirtd_restart() # Recover vm. vmxml_backup.sync()
def run(test, params, env): """ Qemu multiqueue test for virtio-scsi controller: 1) Boot up a guest with virtio-scsi device which support multi-queue and the vcpu and images number of guest should match the multi-queue number. 2) Pin the vcpus to the host cpus. 3) Check the multi queue option from monitor. 4) Check device init status in guest 5) Pin the interrupts to the vcpus. 6) Load I/O in all targets. 7) Check the interrupt queues in guest. :param test: QEMU test object :param params: Dictionary with the test parameters :param env: Dictionary with test environment. """ def get_mapping_interrupts2vcpus(irqs, pattern): """ Get the mapping of between virtio interrupts and vcpus. """ regex = r'(\d+):(\s+(\d+\s+){%d})\s+.+\s%s\s' % (len( re.findall(r"\s+CPU\d+", irqs, re.M)), pattern) return { f[0]: { 'count': f[1].split() } for f in re.findall(regex, irqs, re.M) } def create_data_images(): """ Create date image objects. """ for extra_image in range(images_num): image_tag = "stg%s" % extra_image params["images"] += " %s" % image_tag params["image_name_%s" % image_tag] = "images/%s" % image_tag params["image_size_%s" % image_tag] = extra_image_size params["force_create_image_%s" % image_tag] = "yes" image_params = params.object_params(image_tag) env_process.preprocess_image(test, image_params, image_tag) def check_irqbalance_status(): """ Check the status of irqbalance service. """ error_context.context("Check irqbalance service status.", logging.info) return re.findall("Active: active", session.cmd_output(status_cmd)) def start_irqbalance_service(): """ Start the irqbalance service. """ error_context.context("Start the irqbalance service.", logging.info) session.cmd("systemctl start irqbalance") output = utils_misc.strip_console_codes(session.cmd_output(status_cmd)) if not re.findall("Active: active", output): test.cancel( "Can not start irqbalance inside guest.Skip this test.") def pin_vcpus2host_cpus(): """ Pint the vcpus to the host cpus. """ error_context.context("Pin vcpus to host cpus.", logging.info) host_numa_nodes = utils_misc.NumaInfo() vcpu_num = 0 for numa_node_id in host_numa_nodes.nodes: numa_node = host_numa_nodes.nodes[numa_node_id] for _ in range(len(numa_node.cpus)): if vcpu_num >= len(vm.vcpu_threads): break vcpu_tid = vm.vcpu_threads[vcpu_num] logging.debug("pin vcpu thread(%s) to cpu(%s)" % (vcpu_tid, numa_node.pin_cpu(vcpu_tid))) vcpu_num += 1 def verify_num_queues(): """ Verify the number of queues. """ error_context.context("Verify num_queues from monitor.", logging.info) qtree = qemu_qtree.QtreeContainer() try: qtree.parse_info_qtree(vm.monitor.info('qtree')) except AttributeError: test.cancel("Monitor deson't supoort qtree skip this test") error_msg = "Number of queues mismatch: expect %s report from monitor: %s(%s)" scsi_bus_addr = "" qtree_num_queues_full = "" qtree_num_queues = "" for node in qtree.get_nodes(): type = node.qtree['type'] if isinstance(node, qemu_qtree.QtreeDev) and (type == "virtio-scsi-device"): qtree_num_queues_full = node.qtree["num_queues"] qtree_num_queues = re.search("[0-9]+", qtree_num_queues_full).group() elif (isinstance(node, qemu_qtree.QtreeDev)) and (type == "virtio-scsi-pci"): scsi_bus_addr = node.qtree['addr'] if qtree_num_queues != num_queues: error_msg = error_msg % (num_queues, qtree_num_queues, qtree_num_queues_full) test.fail(error_msg) if not scsi_bus_addr: test.error("Didn't find addr from qtree. Please check the log.") def check_interrupts(): """ Check the interrupt queues in guest. """ error_context.context("Check the interrupt queues in guest.", logging.info) return session.cmd_output(irq_check_cmd) def check_interrupts2vcpus(irq_map): """ Check the status of interrupters to vcpus. """ error_context.context("Check the status of interrupters to vcpus.", logging.info) cpu_selects = {} cpu_select = 1 for _ in range(int(num_queues)): val = ','.join([ _[::-1] for _ in re.findall(r'\w{8}|\w+', format(cpu_select, 'x')[::-1]) ][::-1]) cpu_selects[val] = format(cpu_select, 'b').count('0') cpu_select = cpu_select << 1 irqs_id_reset = [] for irq_id in irq_map.keys(): cmd = 'cat /proc/irq/%s/smp_affinity' % irq_id cpu_selected = re.sub(r'(^[0+,?0+]+)|(,)', '', session.cmd_output(cmd)).strip() if cpu_selected not in cpu_selects: irqs_id_reset.append(irq_id) else: cpu_irq_map[irq_id] = cpu_selects[cpu_selected] del cpu_selects[cpu_selected] return irqs_id_reset, cpu_selects def pin_interrupts2vcpus(irqs_id_reset, cpu_selects): """ Pint the interrupts to vcpus. """ bind_cpu_cmd = [] for irq_id, cpu_select in zip(irqs_id_reset, cpu_selects): bind_cpu_cmd.append("echo %s > /proc/irq/%s/smp_affinity" % (cpu_select, irq_id)) cpu_irq_map[irq_id] = cpu_selects[cpu_select] if bind_cpu_cmd: error_context.context("Pin interrupters to vcpus", logging.info) session.cmd(' && '.join(bind_cpu_cmd)) return cpu_irq_map def _get_data_disks(session): """ Get the data disks. """ output = session.cmd_output( params.get("get_dev_cmd", "ls /dev/[svh]d*")) system_dev = re.search(r"/dev/([svh]d\w+)(?=\d+)", output, re.M).group(1) return (dev for dev in output.split() if system_dev not in dev) def check_io_status(timeout): """ Check the status of I/O. """ chk_session = vm.wait_for_login(timeout=360) while int(chk_session.cmd_output("pgrep -lx dd | wc -l", timeout)): time.sleep(5) chk_session.close() def load_io_data_disks(): """ Load I/O on data disks. """ error_context.context("Load I/O in all targets", logging.info) dd_session = vm.wait_for_login(timeout=360) dd_timeout = int(re.findall(r"\d+", extra_image_size)[0]) cmd = "dd of=%s if=/dev/urandom bs=1M count=%s oflag=direct &" cmds = [cmd % (dev, dd_timeout) for dev in _get_data_disks(dd_session)] if len(cmds) != images_num: test.error("Disks are not all show up in system, only %s disks." % len(cmds)) # As Bug 1177332 exists, mq is not supported completely. # So don't considering performance currently, dd_timeout is longer. dd_session.cmd(' '.join(cmds), dd_timeout * images_num * 2) check_io_status(dd_timeout) dd_session.close() def compare_interrupts(prev_irqs, cur_irqs): """ Compare the interrupts between after and before IO. """ cpu_not_used = [] diff_interrupts = {} for irq in prev_irqs.keys(): cpu = int(cpu_irq_map[irq]) diff_val = int(cur_irqs[irq]['count'][cpu]) - int( prev_irqs[irq]['count'][cpu]) if diff_val == 0: cpu_not_used.append('CPU%s' % cpu) else: diff_interrupts[cpu] = diff_val logging.debug('The changed number of interrupts:') for k, v in sorted(diff_interrupts.items()): logging.debug(' CPU%s: %d' % (k, v)) if cpu_not_used: cpus = " ".join(cpu_not_used) error_msg = ("%s are not used during test. " "Please check debug log for more information.") test.fail(error_msg % cpus) def wmi_facility_test(session): driver_name = params["driver_name"] wmi_check_cmd = params["wmi_check_cmd"] pattern = params["pattern"] session = utils_test.qemu.windrv_check_running_verifier( session, vm, test, driver_name, timeout) wmi_check_cmd = utils_misc.set_winutils_letter(session, wmi_check_cmd) error_context.context("Run wmi check in guest.", logging.info) output = session.cmd_output(wmi_check_cmd) queue_num = re.findall(pattern, output, re.M) try: if not queue_num or queue_num[0] != num_queues: test.fail( "The queue_num from guest is not match with expected.\n" "queue_num from guest is %s, expected is %s" % (queue_num, num_queues)) finally: session.close() cpu_irq_map = {} timeout = float(params.get("login_timeout", 240)) num_queues = str(utils_cpu.online_cpus_count()) params['smp'] = num_queues params['num_queues'] = num_queues images_num = int(num_queues) extra_image_size = params.get("image_size_extra_images", "512M") system_image = params.get("images") system_image_drive_format = params.get("system_image_drive_format", "virtio") params["drive_format_%s" % system_image] = system_image_drive_format irq_check_cmd = params.get("irq_check_cmd", "cat /proc/interrupts") irq_name = params.get("irq_regex") status_cmd = "systemctl status irqbalance" error_context.context( "Boot up guest with block devcie with num_queues" " is %s and smp is %s" % (num_queues, params['smp']), logging.info) for vm in env.get_all_vms(): if vm.is_alive(): vm.destroy() create_data_images() params["start_vm"] = "yes" vm = env.get_vm(params["main_vm"]) env_process.preprocess_vm(test, params, env, vm.name) session = vm.wait_for_login(timeout=timeout) if params["os_type"] == "windows": wmi_facility_test(session) return if not check_irqbalance_status(): start_irqbalance_service() pin_vcpus2host_cpus() verify_num_queues() prev_irqs = check_interrupts() prev_mapping = get_mapping_interrupts2vcpus(prev_irqs, irq_name) pin_interrupts2vcpus(*check_interrupts2vcpus(prev_mapping)) load_io_data_disks() cur_irqs = check_interrupts() cur_mapping = get_mapping_interrupts2vcpus(cur_irqs, irq_name) compare_interrupts(prev_mapping, cur_mapping)