On Wed, Jun 22, 2011 at 1:22 AM, Yiqiao Pu <[email protected]> wrote: > 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 > > Changes from v2: > * Walk through the thp config directory. And test khugepaged > with the default value in system. > * Add 5s sleep time in khugepaged test
Hi Yiqiao, excellent changes to the test setup! I found and cleaned up some minor details, and made some comments, which I have fixed on a v4, that I'm sending to the list shortly. > Signed-off-by: Yiqiao Pu <[email protected]> > Signed-off-by: Lucas Meneghel Rodrigues <[email protected]> > --- > client/virt/virt_test_setup.py | 187 > +++++++++++++++++++++++++++++++++++++++- > 1 files changed, 186 insertions(+), 1 deletions(-) > > diff --git a/client/virt/virt_test_setup.py b/client/virt/virt_test_setup.py > index 3e1f5b5..70cf3c2 100644 > --- a/client/virt/virt_test_setup.py > +++ b/client/virt/virt_test_setup.py > @@ -1,11 +1,196 @@ > """ > Library to perform pre/post test setup for KVM autotest. > """ > -import os, logging > +import os, logging, time, re, sre, random > 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. > + """ > + def file_writeable(file_name): > + """ > + Check if the file is writeable > + """ > + o = utils.system_output("ls -l %s" % file_name) > + if re.findall("w", o[0:10]): > + return True > + return False ^ This can be replaced with os.access (file_name, os.W_OK) > + 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") > + > + tmp_list = [] > + test_cfg = {} > + 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] > + # Save host current config, so we can restore it during cleanup > + # We will only save the writeable part of the config files > + original_config = {} > + file_list_str = [] > + file_list_num = [] > + for f in os.walk(self.thp_path): > + base_dir = f[0] > + if f[2]: > + for name in f[2]: > + f_dir = os.path.join(base_dir, name) > + parameter = file(f_dir, 'r').read() > + if file_writeable(f_dir): ^ See comment above. > + if re.findall("\[(.*)\]", parameter): > + original_config[f_dir] = re.findall("\[(.*)\]", > + parameter)[0] > + file_list_str.append(f_dir) > + else: > + original_config[f_dir] = int(parameter) > + file_list_num.append(f_dir) > + > + self.test_config = test_cfg > + self.original_config = original_config > + self.file_list_str = file_list_str > + self.file_list_num = file_list_num ^ Same here, I verified and this intermediary assignment is not necessary. > + 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 value_listed(self, value): > + """ > + Get a parameters list from a string > + """ > + value_list = [] > + for i in re.split("\[|\]|\n+|\s+", value): > + if i: > + value_list.append(i) > + return value_list > + > + def khugepaged_test(self): > + """ > + Start, stop and frequency change test for khugepaged. > + """ > + def check_status_with_value(action_list, file_name): > + """ > + Check the status of khugepaged when set value to specify file > + """ > + for (a, r) in action_list: > + open(file_name, "w").write(a) > + time.sleep(5) > + try: > + utils.run('pgrep khugepaged') > + if r !=0: > + raise THPKhugepagedError("Khugepaged still alive > when" > + "transparent huge page is " > + "disabled") > + except error.CmdError: > + if r == 0: > + raise THPKhugepagedError("khugepaged can not set to" > + "status %s" % a) > + > + file_list_str = self.file_list_str > + file_list_num = self.file_list_num ^ I verified and see no reason to do this assignment, just use self.file_list_str and such... > + for file_path in file_list_str: > + action_list = [] > + if re.findall("enabled", file_path): > + # Start and stop test for khugepaged > + value_list = self.value_listed(open(file_path,"r").read()) > + for i in value_list: > + if re.match("n", i, re.I): > + action_stop = (i, 256) > + for i in value_list: > + if re.match("[^n]", i, re.I): > + action = (i, 0) > + action_list += [action_stop, action, action_stop] > + action_list += [action] > + > + check_status_with_value(action_list, file_path) > + else: > + value_list = self.value_listed(open(file_path,"r").read()) > + for i in value_list: > + action = (i, 0) > + action_list.append(action) > + check_status_with_value(action_list, file_path) > + > + for file_path in file_list_num: > + action_list = [] > + value = int(open(file_path, "r").read()) > + if value != 0 and value != 1: > + new_value = random.random() > + action_list.append((str(int(value * new_value)),0)) > + action_list.append((str(int(value * ( new_value + 1))),0)) > + else: > + action_list.append(("0", 0)) > + action_list.append(("1", 0)) > + > + check_status_with_value(action_list, file_path) > + > + > + 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(str(self.original_config[path])) > + p_file.close() > + > class HugePageConfig(object): > def __init__(self, params): > """ > -- > 1.7.1 > > _______________________________________________ > Autotest mailing list > [email protected] > http://test.kernel.org/cgi-bin/mailman/listinfo/autotest > -- Lucas _______________________________________________ Autotest mailing list [email protected] http://test.kernel.org/cgi-bin/mailman/listinfo/autotest
