diff --git a/test.py b/test.py index 648fc8f264cc7c0abfb26afa48cfba5861f95218..8e7de7a867e41186e569c4b3e6a76e902cbb9428 100644 --- a/test.py +++ b/test.py @@ -1,267 +1,547 @@ # Copyright (c) 2021-2023 Alibaba Cloud Computing Ltd. # SPDX-License-Identifier: MulanPSL-2.0 import os +import json +import unittest +import tornado +from tornado.httpserver import HTTPRequest +from tornado.httpclient import AsyncHTTPClient + from agent.common.config import Config +from agent.controller.backup import BackupHandler +from agent.controller.configure import ConfigureHandler +from agent.controller.method import MethodHandler +from agent.controller.rollback import RollbackHandler +from agent.controller.status import StatusHandler, AvaliableDomainHandler from agent.common.system import sysCommand +from agent.controller import load_handler_class + + +class DomainTest(unittest.TestCase): + def _test(self, param_list, domain): + try: + _domain = domain() + except Exception as e: + print("[-] load domain {} failed: {}".format(domain, e)) + else: + res = _domain.backup(param_list) + print("[+] backup result:{}".format(res)) + # res = _domain.BackupAll() + # print("[+] backup all result:{}".format(res)) + res = _domain.set_values(param_list) + print("[+] set result:{}".format(res)) + res = _domain.get_values(param_list) + print("[+] get result:{}".format(res)) + res = _domain.rollback() + print("[+] rollback result:{}".format(res)) + # res = _domain.Rollback(all_param = True) + # print("[+] rollback all result:{}".format(res)) + + def _create_file(self, script_path, dest_path): + if not os.path.exists(dest_path): + os.makedirs(dest_path) + sysCommand("cp {} {}".format(script_path, dest_path)) + if not os.path.exists("/etc/keentune/bench"): + os.makedirs("/etc/keentune/bench") + if not os.path.exists("/var/keentune/bench/scripts"): + os.makedirs("/var/keentune/bench/scripts") + + def test_audio(self): + from agent.domain.audio import Audio + param_list = { + "timeout":{"value": 10} + } + self._test(param_list, Audio) + + def test_cpu(self): + from agent.domain.cpu import Cpu + param_list = { + "governor":{"value":"performance"}, + "energy_perf_bias":{"value":"performance"}, + "energy_perf_bias":{"value":"invalid"}, + "min_perf_pct":{"value":100}, + "max_perf_pct":{"value":100000}, + "force_latency":{"value":"cstate.id:1"}, + } + self._test(param_list, Cpu) + + param_list = { + "force_latency":{"value":99}, + "governor":{"value":"conservative|powersave"}, + "energy_perf_bias":{"value":"normal"}, + } + self._test(param_list, Cpu) + + param_list = { + "force_latency":{"value":"cstate.id_no_zero:1|3"}, + "governor":{"value":"ondemand|powersave"}, + "energy_perf_bias":{"value":"powersave|power"}, + } + self._test(param_list, Cpu) + + def test_env(self): + from agent.domain.env import Env + param_list = { + "cpu-partitioning": {"value": "start"}, + "realtime": {"value": "start"} + } + self._test(param_list, Env) + + def test_file(self): + from agent.domain.file import File + param_list = { + "/proc/sys/vm/dirty_expire_centisecs": {"value": "700"} + } + self._test(param_list, File) + + def test_fio(self): + from agent.domain.fio import Fio + param_list = { + "iodepth": {"value": "1"}, + "bs": {"value": "512B"}, + "numjobs": {"value": 4} + } + script_path = "/etc/keentune/keentuned/benchmark/fio/fio_IOPS_base.py" + dest_path = os.path.join(Config.BENCKMARK_FIlE, "benchmark/fio") + self._create_file(script_path, dest_path) + self._test(param_list, Fio) + + def test_grub(self): + from agent.domain.grub import Grub + try: + _domian = Grub() + _domian.backup({"spectre_bhb": {'value': 'on'}}) + _domian.set_value("spectre_bhb", "on") + _domian.rollback() + except: + pass + + def test_iperf(self): + from agent.domain.iperf import Iperf + param_list = { + "Parallel": {"value": 1}, + "window_size": {"value": 10240}, + "length_buffers": {"value": 10240} + } + script_path = "/etc/keentune/keentuned/benchmark/iperf/iperf.py" + dest_path = os.path.join(Config.BENCKMARK_FIlE, "benchmark/iperf") + self._create_file(script_path, dest_path) + self._test(param_list, Iperf) + + def test_jemalloc(self): + from agent.domain.jemalloc import Jemalloc + _domain = Jemalloc() + param_name = "opt.percpu_arena" + param_value = 1 + if _domain.vaild_param(param_name): + _domain.pre_setting() + _domain.set_value(param_name, param_value) + _domain.post_setting() + _domain.get_value(param_name) + _domain.pre_setting() + + def test_limits(self): + from agent.domain.limits import Limits + param_list = { + "hard_nofile": {"value": 1048576}, + "soft_nofile": {"value": 1048576}, + "ulimit": {"value": 1048576}, + "file-max": {"value": 1048576} + } + self._test(param_list, Limits) + + def test_my_cnf(self): + from agent.domain.mysql import MySQL + param_list = { + "max_connections": {"value": 10000}, + "key_buffer_size": {"value": 21474836}, + "skip_ssl": {"value": "SET_TRUE"}, + "innodb_table_locks": {"value": "ON"} + } + self._test(param_list, MySQL) + + def test_nginx_conf(self): + from agent.domain.nginx import Nginx + param_list = { + "worker_processes": {"value": "auto"}, + "worker_connections":{"value":1024}, + "multi_accept":{"value":"on"}, + "open_file_cache":{"value":"max=10240 inactive=10s"}, + "ssl_buffer_size":{"value":"4k"}, + } + self._test(param_list, Nginx) + + def test_scheduler(self): + """ + accelerator-performance.conf + sched_min_granularity_ns = 10000000 + + mysql.conf + sched_latency_ns=60000000 + sched_migration_cost_ns=500000 + sched_min_granularity_ns=15000000 + sched_wakeup_granularity_ns=2000000 + + postgresql.conf + sched_min_granularity_ns = 10000000 + """ + from agent.domain.scheduler import Scheduler + param_list = { + "sched_min_granularity_ns":{"value":10000000}, + "sched_latency_ns":{"value":60000000}, + "sched_migration_cost_ns":{"value":500000}, + "sched_wakeup_granularity_ns":{"value":2000000}, + } + self._test(param_list, Scheduler) + + def test_sysbench(self): + from agent.domain.sysbench import Sysbench + param_list = { + "tables": {"value": 3}, + "threads": {"value": 3}, + "table-size": {"value": 100000}, + "thread-stack-size": {"value": 32768} + } + script_path = "/etc/keentune/keentuned/benchmark/sysbench/sysbench_mysql_read_write.py" + dest_path = os.path.join(Config.BENCKMARK_FIlE, "benchmark/sysbench") + self._create_file(script_path, dest_path) + self._test(param_list, Sysbench) + + def test_sysctl(self): + from agent.domain.sysctl import Sysctl + param_list = { + "fs.aio-max-nr": {"value": 102400}, + "fs.file-max": {"value": 102400}, + "kernel.dmesg_restrict": {"value": "0"}, + "kernel.sched_migration_cost_ns": {"value": 5000} + } + self._test(param_list, Sysctl) + + def test_sysfs(self): + from agent.domain.sysfs import Sysfs + param_list = { + "/sys/bus/workqueue/devices/writeback/cpumask": {"value": "000000df"}, + "/sys/devices/system/machinecheck/machinecheck*/ignore_ce": {"value": 1}, + "/sys/devices/virtual/workqueue/*/cpumask": {"value": "000000df"}, + "/sys/devices/virtual/workqueue/cpumask": {"value": "000000df"} + } + self._test(param_list, Sysfs) + + def test_vm(self): + from agent.domain.vm import Vm + param_list = { + "transparent_hugepages": {"value": "never"} + } + self._test(param_list, Vm) + + def test_wrk(self): + from agent.domain.wrk import Wrk + param_list = { + "threads": {"value": 2}, + "connections": {"value": 10} + } + script_path = "/etc/keentune/keentuned/benchmark/wrk/wrk_parameter_tuning.py" + dest_path = os.path.join(Config.BENCKMARK_FIlE, "benchmark/wrk") + self._create_file(script_path, dest_path) + self._test(param_list, Wrk) + + +class FeatureTest(unittest.TestCase): + def _test_feature(self, value, domain): + try: + _domain = domain() + except Exception as e: + print("[-] load domain {} failed: {}".format(domain, e)) + else: + res = _domain.backup() + print("[+] backup result:{}".format(res)) + res = _domain.set_value(value) + print("[+] set result:{}".format(res)) + res = _domain.get_value() + print("[+] get result:{}".format(res)) + res = _domain.rollback() + print("[+] rollback result:{}".format(res)) + + def test_net_affinity(self): + from agent.feature.affinity import SmpAffinity + self._test_feature("0-3", SmpAffinity) + self._test_feature("numa0", SmpAffinity) + self._test_feature("numa1", SmpAffinity) + self._test_feature("balance", SmpAffinity) + self._test_feature("dedicated", SmpAffinity) + self._test_feature("disperse", SmpAffinity) + self._test_feature("different", SmpAffinity) + self._test_feature("eighth", SmpAffinity) + self._test_feature("off", SmpAffinity) + + def test_scsi_host_alpm(self): + from agent.feature.alpm import Alpm + self._test_feature("medium_power", Alpm) + + def test_kernel_mem(self): + from agent.feature.code_hugepage import CodeHugepage + self._test_feature(1, CodeHugepage) + + def test_systemd(self): + from agent.feature.cpu_affinity import Affinity + self._test_feature("0,1,2,3,4,6,7", Affinity) + + def test_disk_elevator(self): + from agent.feature.elevator import Elevator + try: + self._test_feature("mq-deadline", Elevator) + except: + pass + + def test_net_erdma(self): + from agent.feature.erdma import ERDMA + self._test_feature("on", ERDMA) + + def test_cpu_governor(self): + from agent.feature.governor import Governor + self._test_feature("performance", Governor) + self._test_feature("conservative|powersave", Governor) + + def test_net_hashsize(self): + from agent.feature.hashsize import Hashsize + self._test_feature("1048576", Hashsize) + + def test_ifconfig(self): + from agent.feature.ifconfig import ifconfig + self._test_feature("8000", ifconfig) + + def test_irqbalance(self): + from agent.feature.irqbalance import Irqbalance + self._test_feature(5, Irqbalance) + + def test_disk_readahead(self): + from agent.feature.readahead import Readahead + self._test_feature(">4096", Readahead) + + def test_net_rfs(self): + from agent.feature.rfs import RFS + self._test_feature("on", RFS) + + def test_net_rps(self): + from agent.feature.rps import RPS + self._test_feature("auto", RPS) + self._test_feature("off", RPS) + self._test_feature("all", RPS) + self._test_feature("disperse", RPS) + self._test_feature("different", RPS) + + def test_sched_feature(self): + from agent.feature.sched_features import SchedFeature + try: + self._test_feature("GENTLE_FAIR_SLEEPERS NO_WAKEUP_PREEMPTION", SchedFeature) + except: + pass + + def test_net_xps(self): + from agent.feature.xps import XPS + try: + self._test_feature("different", XPS) + except: + pass + + def test_net_zlib(self): + from agent.feature.zlib import Zlib + try: + self._test_feature("on", Zlib) + except: + pass + + +class InterfaceTest(unittest.TestCase): + def setUp(self) -> None: + load_handler_class() + self.app = tornado.web.Application(handlers=[ + (r"/backup", BackupHandler), + (r"/rollback", RollbackHandler), + (r"/configure", ConfigureHandler), + (r"/method", MethodHandler), + (r"/status", StatusHandler), + (r"/avaliable", AvaliableDomainHandler), + ]) + + self.app.listen(Config.TARGET_PORT) + tornado.ioloop.IOLoop.current().run_sync(self.test_request) + tornado.ioloop.IOLoop.current().start() + + async def _test_status(self): + url = "http://{}:{}/{}".format("localhost", "9873", "status") + http_client = AsyncHTTPClient() + response = await http_client.fetch(url, method="GET") + print(response.body) + + async def _test_avaliable(self): + url = "http://{}:{}/{}".format("localhost", "9873", "avaliable") + http_client = AsyncHTTPClient() + response = await http_client.fetch(url, method="GET") + print(response.body) + + async def _test_backup(self): + url = "http://{}:{}/{}".format("localhost", "9873", "backup") + data = { + "sysctl": { + "fs.aio-max-nr": {"dtype": "string", "value": ""}, + "fs.file-max": {"dtype": "string", "value": ""} + }, + "net": { + "XPS": {"dtype": "string", "value": ""}, + "smp_affinity": {"dtype": "string", "value": ""} + } + } + http_client = AsyncHTTPClient() + response = await http_client.fetch(url, method="POST", body=json.dumps(data)) + print(response.body) + + async def _test_configure(self): + url = "http://{}:{}/{}".format("localhost", "9873", "configure") + data = { + "data": { + "sysctl": { + "fs.aio-max-nr": {"dtype": "string", "value": "102400"}, + "fs.file-max": {"dtype": "string", "value": ""} + }, + "net": { + "XPS": {"dtype": "string", "value": "different"}, + "smp_affinity": {"dtype": "string", "value": "dedicated"} + } + }, + "resp_ip": "localhost", + "resp_port": "9871", + "target_id": 1, + "readonly": True + } + http_client = AsyncHTTPClient() + response = await http_client.fetch(url, method="POST", body=json.dumps(data)) + print(response.body) + + data = { + "data": { + "sysctl": { + "fs.aio-max-nr": {"dtype": "string", "value": "102400"}, + "fs.file-max": {"dtype": "string", "value": ""} + }, + "net": { + "XPS": {"dtype": "string", "value": "different"}, + "smp_affinity": {"dtype": "string", "value": "dedicated"} + } + }, + "resp_ip": "localhost", + "resp_port": "9871", + "target_id": 1, + "readonly": False + } + http_client = AsyncHTTPClient() + response = await http_client.fetch(url, method="POST", body=json.dumps(data)) + print(response.body) + + async def _test_rollback(self): + url = "http://{}:{}/{}".format("localhost", "9873", "rollback") + data = {"domains": ["sysctl", "net"]} + http_client = AsyncHTTPClient() + response = await http_client.fetch(url, method="POST", body=json.dumps(data)) + print(response.body) + + async def _test_method(self): + url = "http://{}:{}/{}".format("localhost", "9873", "method") + data = [ + { + "method_name": "check_net_queue_count", + "method_args": [""] + }, + { + "method_name": "cpulist_invert", + "method_args": ["0", "2", "3"] + }, + { + "method_name": "cpulist_online", + "method_args": ["0x01", "2", "3", "5", "8"] + }, + { + "method_name": "cpulist_unpack", + "method_args": ["1-3", "4-6"] + }, + { + "method_name": "cpulist2hex_invert", + "method_args": ["0", "2", "3"] + }, + { + "method_name": "cpulist2hex", + "method_args": ["0", "2", "3"] + }, + { + "method_name": "regex_search_ternary", + "method_args": ["abc", "ab", 1, 3] + }, + { + "method_name": "strip", + "method_args": ["a", "b", "c"] + }, + { + "method_name": "cpu_core", + "method_args": [] + }, + { + "method_name": "mem_total", + "method_args": [] + }, + { + "method_name": "mem_free", + "method_args": [] + }, + { + "method_name": "uname_arch", + "method_args": [] + }, + { + "method_name": "thunderx_cpu_info", + "method_args": [] + }, + { + "method_name": "amd_cpu_model", + "method_args": [] + }, + { + "method_name": "os_release", + "method_args": [] + }, + { + "method_name": "virt", + "method_args": [] + }, + { + "method_name": "system", + "method_args": [] + } + ] + http_client = AsyncHTTPClient() + response = await http_client.fetch(url, method="POST", body=json.dumps(data)) + print(response.body) + + async def test_request(self): + await self._test_status() + await self._test_backup() + await self._test_configure() + await self._test_rollback() + await self._test_avaliable() + await self._test_method() + + tornado.ioloop.IOLoop.current().stop() + +if __name__ == '__main__': + print("--------------- start to run test cases ---------------") + domain_suite = unittest.TestSuite() + domain_suite.addTests(unittest.TestLoader().loadTestsFromTestCase(DomainTest)) + feature_suite = unittest.TestSuite() + feature_suite.addTests(unittest.TestLoader().loadTestsFromTestCase(FeatureTest)) + inter_suite = unittest.TestSuite() + inter_suite.addTests(unittest.TestLoader().loadTestsFromTestCase(InterfaceTest)) -def _test(param_list, domain): - try: - _domain = domain() - except Exception as e: - print("[-] load domain {} failed: {}".format(domain, e)) - else: - res = _domain.Backup(param_list) - print("[+] backup result:{}".format(res)) - res = _domain.BackupAll() - print("[+] backup all result:{}".format(res)) - res = _domain.SetParam(param_list) - print("[+] set result:{}".format(res)) - res = _domain.GetParam(param_list) - print("[+] get result:{}".format(res)) - res = _domain.Rollback(all_param = False) - print("[+] rollback result:{}".format(res)) - res = _domain.Rollback(all_param = True) - print("[+] rollback all result:{}".format(res)) - -def _create_file(script_path, dest_path): - if not os.path.exists(dest_path): - os.makedirs(dest_path) - sysCommand("cp {} {}".format(script_path, dest_path)) - -def test_audio(): - from agent.domain.audio import Audio - param_list = { - "timeout":{"value": 10} - } - _test(param_list, Audio) - -def test_cpu(): - from agent.domain.cpu import Cpu - param_list = { - "governor":{"value":"performance"}, - "energy_perf_bias":{"value":"performance"}, - "min_perf_pct":{"value":100}, - "force_latency":{"value":"cstate.id:1"}, - } - _test(param_list, Cpu) - - param_list = { - "force_latency":{"value":99}, - "governor":{"value":"conservative|powersave"}, - "energy_perf_bias":{"value":"normal"}, - } - _test(param_list, Cpu) - - param_list = { - "force_latency":{"value":"cstate.id_no_zero:1|3"}, - "governor":{"value":"ondemand|powersave"}, - "energy_perf_bias":{"value":"powersave|power"}, - } - _test(param_list, Cpu) - -def test_disk(): - from agent.domain.disk import Disk - param_list = { - "readahead":{"value": "4096"}, - "apm":{"value":128}, - "spindown":{"value":6}, - } - _test(param_list, Disk) - -def test_env(): - from agent.domain.env import Env - param_list = { - "cpu-partitioning": {"value": "start"}, - "realtime": {"value": "start"} - } - _test(param_list, Env) - -def test_fio(): - from agent.domain.fio import Fio - param_list = { - "iodepth": {"value": "1"}, - "bs": {"value": "512B"}, - "numjobs": {"value": 4} - } - script_path = "/etc/keentune/keentuned/benchmark/fio/fio_IOPS_base.py" - dest_path = os.path.join(Config.BENCKMARK_FIlE, "benchmark/fio") - _create_file(script_path, dest_path) - _test(param_list, Fio) - -def test_iperf(): - from agent.domain.iperf import Iperf - param_list = { - "Parallel": {"value": 1}, - "window_size": {"value": 10240}, - "length_buffers": {"value": 10240} - } - script_path = "/etc/keentune/keentuned/benchmark/iperf/iperf.py" - dest_path = os.path.join(Config.BENCKMARK_FIlE, "benchmark/iperf") - _create_file(script_path, dest_path) - _test(param_list, Iperf) - -def test_irqbalance(): - from agent.domain.irqbalance import Irqbalance - param_list = { - "banned_cpus": {"value": 5} - } - _test(param_list, Irqbalance) - -def test_kernel_mem(): - from agent.domain.kernel_mem import KernelMem - param_list = { - "code_hugepage": {"value": 1} - } - _test(param_list, KernelMem) - -def test_limits(): - from agent.domain.limits import Limits - param_list = { - "hard_nofile": {"value": 1048576}, - "soft_nofile": {"value": 1048576}, - "ulimit": {"value": 1048576}, - "file-max": {"value": 1048576} - } - _test(param_list, Limits) - -def test_my_cnf(): - from agent.domain.my_cnf import MyCnf - param_list = { - "max_connections": {"value": 10000}, - "key_buffer_size": {"value": 21474836}, - "skip_ssl": {"value": "SET_TRUE"}, - "innodb_table_locks": {"value": "ON"} - } - _test(param_list, MyCnf) - -def test_net(): - from agent.domain.net import Net - param_list = { - "XPS":{"value":"different"}, - "RPS":{"value":"different"}, - "smp_affinity":{"value":"dedicated"}, - "nf_conntrack_hashsize":{"value":"1048576"}, - } - _test(param_list, Net) - -def test_nginx_conf(): - from agent.domain.nginx_conf import NginxConf - param_list = { - "worker_connections":{"value":10240}, - "multi_accept":{"value":"on"}, - "open_file_cache":{"value":"max=10240 inactive=10s"}, - "ssl_buffer_size":{"value":"256k"}, - } - _test(param_list, NginxConf) - -def test_scheduler(): - """ - accelerator-performance.conf - sched_min_granularity_ns = 10000000 - - mysql.conf - sched_latency_ns=60000000 - sched_migration_cost_ns=500000 - sched_min_granularity_ns=15000000 - sched_wakeup_granularity_ns=2000000 - - postgresql.conf - sched_min_granularity_ns = 10000000 - """ - from agent.domain.scheduler import Scheduler - param_list = { - "sched_min_granularity_ns":{"value":10000000}, - "sched_latency_ns":{"value":60000000}, - "sched_migration_cost_ns":{"value":500000}, - "sched_wakeup_granularity_ns":{"value":2000000}, - } - _test(param_list, Scheduler) - -def test_scsi_host(): - from agent.domain.scsi_host import ScsiHost - param_list = { - "alpm":{"value":"medium_power"} - } - _test(param_list, ScsiHost) - -def test_sysbench(): - from agent.domain.sysbench import Sysbench - param_list = { - "tables": {"value": 3}, - "threads": {"value": 3}, - "table-size": {"value": 100000}, - "thread-stack-size": {"value": 32768} - } - script_path = "/etc/keentune/keentuned/benchmark/sysbench/sysbench_mysql_read_write.py" - dest_path = os.path.join(Config.BENCKMARK_FIlE, "benchmark/sysbench") - _create_file(script_path, dest_path) - _test(param_list, Sysbench) - -def test_sysctl(): - from agent.domain.sysctl import Sysctl - param_list = { - "fs.aio-max-nr": {"value": 102400}, - "fs.file-max": {"value": 102400}, - "kernel.dmesg_restrict": {"value": "0"}, - "kernel.sched_migration_cost_ns": {"value": 5000} - } - _test(param_list, Sysctl) - -def test_sysfs(): - from agent.domain.sysfs import Sysfs - param_list = { - "/sys/bus/workqueue/devices/writeback/cpumask": {"value": "000000df"}, - "/sys/devices/system/machinecheck/machinecheck*/ignore_ce": {"value": 1}, - "/sys/devices/virtual/workqueue/*/cpumask": {"value": "000000df"}, - "/sys/devices/virtual/workqueue/cpumask": {"value": "000000df"} - } - _test(param_list, Sysfs) - -def test_systemd(): - from agent.domain.systemd import Systemd - param_list = { - "cpu_affinity": {"value": "0,1,2,3,4,6,7"} - } - _test(param_list, Systemd) - -def test_vm(): - from agent.domain.vm import Vm - param_list = { - "transparent_hugepages": {"value": "never"} - } - _test(param_list, Vm) - -def test_wrk(): - from agent.domain.wrk import Wrk - param_list = { - "threads": {"value": 2}, - "connections": {"value": 10} - } - script_path = "/etc/keentune/keentuned/benchmark/wrk/wrk_parameter_tuning.py" - dest_path = os.path.join(Config.BENCKMARK_FIlE, "benchmark/wrk") - _create_file(script_path, dest_path) - _test(param_list, Wrk) - - -if __name__ == "__main__": - #test_audio() - test_cpu() - test_disk() - test_env() - test_fio() - test_iperf() - test_irqbalance() - test_kernel_mem() - test_limits() - test_my_cnf() - test_net() - test_nginx_conf() - test_scheduler() - #test_scsi_host() - test_sysbench() - test_sysctl() - test_sysfs() - test_systemd() - test_vm() - test_wrk() \ No newline at end of file + suite = unittest.TestSuite([domain_suite, feature_suite, inter_suite]) + runner = unittest.TextTestRunner(verbosity=2) + runner.run(suite) + print("--------------- run test cases end ---------------")