This class configures khugepaged to active mode, with functions to restore original guest configuration. Changes from v1: * Rather than a pre/post script, config is now part of the framework * No need to store configuration in files anymore to restore host khugepaged original behavior Signed-off-by: Yiqiao Pu <ypu@xxxxxxxxxx Signed-off-by: Lucas Meneghel Rodrigues <lmr@xxxxxxxxxx> --- client/virt/virt_test_setup.py | 143 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 142 insertions(+), 1 deletions(-) diff --git a/client/virt/virt_test_setup.py b/client/virt/virt_test_setup.py index 3e1f5b5..792ffe6 100644 --- a/client/virt/virt_test_setup.py +++ b/client/virt/virt_test_setup.py @@ -1,11 +1,152 @@ """ Library to perform pre/post test setup for KVM autotest. """ -import os, logging +import os, logging, re, sre from autotest_lib.client.common_lib import error from autotest_lib.client.bin import utils +class THPError(Exception): + """ + Base exception for Transparent Hugepage setup. + """ + pass + + +class THPNotSupportedError(THPError): + """ + Thrown when host does not support tansparent hugepages. + """ + pass + + +class THPWriteConfigError(THPError): + """ + Thrown when host does not support tansparent hugepages. + """ + pass + + +class THPKhugepagedError(THPError): + """ + Thrown when khugepaged is not behaving as expected. + """ + pass + + +class TransparentHugePageConfig(object): + def __init__(self, test, params): + """ + Find paths for transparent hugepages and kugepaged configuration. Also, + back up original host configuration so it can be restored during + cleanup. + """ + self.params = params + + RH_THP_PATH = "/sys/kernel/mm/redhat_transparent_hugepage" + UPSTREAM_THP_PATH = "/sys/kernel/mm/transparent_hugepage" + if os.path.isdir(RH_THP_PATH): + self.thp_path = RH_THP_PATH + elif os.path.isdir(UPSTREAM_THP_PATH): + self.thp_path = UPSTREAM_THP_PATH + else: + raise THPNotSupportedError("System doesn't support transparent " + "hugepages") + + # test_cfg holds all the desired host config values we want to set + # before THP tests + test_cfg={"%s/defrag" % self.thp_path: "yes", + "%s/enabled" % self.thp_path: "always", + "%s/khugepaged/defrag" % self.thp_path: "yes", + "%s/khugepaged/scan_sleep_millisecs" % self.thp_path: "100", + "%s/khugepaged/pages_to_scan" % self.thp_path: "4096", + "%s/khugepaged/alloc_sleep_millisecs" % self.thp_path: "100", + "/sys/kernel/mm/ksm/run": "1", + "/proc/sys/vm/nr_hugepages":"0"} + if os.path.isfile("%s/khugepaged/enabled" % self.thp_path): + test_cfg["%s/khugepaged/enabled" % self.thp_path] = "always" + if os.path.isfile("%s/khugepaged/max_ptes_none" % self.thp_path): + test_cfg["%s/khugepaged/max_ptes_none" % self.thp_path] = "511" + test_cfg["%s/defrag" % self.thp_path] = "always" + + tmp_list = [] + test_config = self.params.get("test_config", None) + if test_config is not None: + tmp_list = re.split(';', test_config) + while len(tmp_list) > 0: + tmp_cfg = tmp_list.pop() + test_cfg[re.split(":", tmp_cfg)[0]] = sre.split(":", tmp_cfg)[1] + + self.original_config = {} + # Save host current config, so we can restore it during cleanup + for path in test_cfg: + param = open(path, 'r').read() + if ("enabled" in param) or ("defrag" in param): + param = re.split("\[|\]", param)[1] + '\n' + self.original_config[path] = param + + self.test_config = test_cfg + + + def set_env(self): + """ + Applies test configuration on the host. + """ + if self.test_config: + for path in self.test_config.keys(): + file(path, 'w').write(self.test_config[path]) + + + def set_params(self, path_dict={}, filename="", value=""): + """ + Sets the value of a config file for a given path. + + @param path_dict: Dict of files' paths {path : value} + @param filename: Name of file to setup + @param value: Value set to the configuration files + """ + for path in path_dict.keys(): + if path in filename: + try: + file(path, "w").write(value) + except IOError, e: + raise THPWriteConfigError("Can not set %s to %s: %s" % + (value, filename, e)) + + + def khugepaged_test(self): + """ + Start, stop and frequency change test for khugepaged. + """ + status_list = ["never", "always", "never"] + for status in status_list: + self.set_params(self.test_config, "enabled", status) + try: + utils.run('pgrep khugepaged') + except error.CmdError: + raise THPKhugepagedError("khugepaged can not be set to " + "status %s" % status) + + + def setup(self): + """ + Configure host for testing. Also, check that khugepaged is working as + expected. + """ + self.set_env() + self.khugepaged_test() + + + def cleanup(self): + """: + Restore the host's original configuration after test + """ + for path in self.original_config: + p_file = open(path, 'w') + p_file.write(self.original_config[path]) + p_file.close() + + class HugePageConfig(object): def __init__(self, params): """ -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html