In preparation of running the tests outside of a container, add two flags to ftests.py: --container and --no-container. As the names imply, these flags are used to specify whether the tests should be containerized or not.
Note1: Some tests (cgrulesengd) will only work in a non-containerized environment. Note2: Running the tests in a non-containerized environment could be destructive to a system as cgroup changes could be made that adversely affect the entire system. Signed-off-by: Tom Hromatka <tom.hroma...@oracle.com> --- ftests/cgroup.py | 49 +++++++++++++++++------------------ ftests/config.py | 20 ++++++++------- ftests/ftests.py | 65 +++++++++++++++++++++++++++++------------------ ftests/process.py | 17 ++++++------- 4 files changed, 82 insertions(+), 69 deletions(-) diff --git a/ftests/cgroup.py b/ftests/cgroup.py index a2f978dd01ca..5906a199dd48 100644 --- a/ftests/cgroup.py +++ b/ftests/cgroup.py @@ -1,7 +1,7 @@ # # Cgroup class for the libcgroup functional tests # -# Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019-2021 Oracle and/or its affiliates. # Author: Tom Hromatka <tom.hroma...@oracle.com> # @@ -79,21 +79,18 @@ class Cgroup(object): return True @staticmethod - def build_cmd_path(in_container, cmd): - if in_container: - return os.path.join(consts.LIBCG_MOUNT_POINT, - 'src/tools/{}'.format(cmd)) - else: - return cmd + def build_cmd_path(cmd): + return os.path.join(consts.LIBCG_MOUNT_POINT, + 'src/tools/{}'.format(cmd)) # TODO - add support for all of the cgcreate options @staticmethod - def create(config, controller_list, cgname, in_container=True): + def create(config, controller_list, cgname): if isinstance(controller_list, str): controller_list = [controller_list] cmd = list() - cmd.append(Cgroup.build_cmd_path(in_container, 'cgcreate')) + cmd.append(Cgroup.build_cmd_path('cgcreate')) controllers_and_path = '{}:{}'.format( ','.join(controller_list), cgname) @@ -101,18 +98,18 @@ class Cgroup(object): cmd.append('-g') cmd.append(controllers_and_path) - if in_container: + if config.args.container: config.container.run(cmd) else: Run.run(cmd) @staticmethod - def delete(config, controller_list, cgname, in_container=True, recursive=False): + def delete(config, controller_list, cgname, recursive=False): if isinstance(controller_list, str): controller_list = [controller_list] cmd = list() - cmd.append(Cgroup.build_cmd_path(in_container, 'cgdelete')) + cmd.append(Cgroup.build_cmd_path('cgdelete')) if recursive: cmd.append('-r') @@ -123,15 +120,15 @@ class Cgroup(object): cmd.append('-g') cmd.append(controllers_and_path) - if in_container: + if config.args.container: config.container.run(cmd) else: Run.run(cmd) @staticmethod - def set(config, cgname, setting, value, in_container=True): + def set(config, cgname, setting, value): cmd = list() - cmd.append(Cgroup.build_cmd_path(in_container, 'cgset')) + cmd.append(Cgroup.build_cmd_path('cgset')) if isinstance(setting, str) and isinstance(value, str): cmd.append('-r') @@ -146,7 +143,7 @@ class Cgroup(object): cmd.append(cgname) - if in_container: + if config.args.container: config.container.run(cmd) else: Run.run(cmd) @@ -169,10 +166,10 @@ class Cgroup(object): # Read all of the settings from a cgroup at a specific path # cgget -g memory:tomcgroup/tomcgroup def get(config, controller=None, cgname=None, setting=None, - in_container=True, print_headers=True, values_only=False, + print_headers=True, values_only=False, all_controllers=False): cmd = list() - cmd.append(Cgroup.build_cmd_path(in_container, 'cgget')) + cmd.append(Cgroup.build_cmd_path('cgget')) if not print_headers: cmd.append('-n') @@ -218,7 +215,7 @@ class Cgroup(object): for cg in cgname: cmd.append(cg) - if in_container: + if config.args.container: ret = config.container.run(cmd) else: ret = Run.run(cmd) @@ -227,9 +224,9 @@ class Cgroup(object): @staticmethod def classify(config, controller, cgname, pid_list, sticky=False, - cancel_sticky=False, in_container=True): + cancel_sticky=False): cmd = list() - cmd.append(Cgroup.build_cmd_path(in_container, 'cgclassify')) + cmd.append(Cgroup.build_cmd_path('cgclassify')) cmd.append('-g') cmd.append('{}:{}'.format(controller, cgname)) @@ -241,7 +238,7 @@ class Cgroup(object): for pid in pid_list: cmd.append(pid) - if in_container: + if config.args.container: config.container.run(cmd) else: Run.run(cmd) @@ -321,19 +318,19 @@ class Cgroup(object): return cgdict @staticmethod - def snapshot(config, controller=None, in_container=True): + def snapshot(config, controller=None): cmd = list() - cmd.append(Cgroup.build_cmd_path(in_container, 'cgsnapshot')) + cmd.append(Cgroup.build_cmd_path('cgsnapshot')) if controller is not None: cmd.append(controller) - if in_container: + if config.args.container: # if we're running in a container, it's unlikely that libcgroup # was installed and thus /etc/cgsnapshot_blacklist.conf likely # doesn't exist. Let's make it config.container.run(['sudo', 'touch', '/etc/cgsnapshot_blacklist.conf']) - if in_container: + if config.args.container: res = config.container.run(cmd) else: res = Run.run(cmd) diff --git a/ftests/config.py b/ftests/config.py index 5cdc21d36eb8..10664609113f 100644 --- a/ftests/config.py +++ b/ftests/config.py @@ -1,7 +1,7 @@ # # Config class for the libcgroup functional tests # -# Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019-2021 Oracle and/or its affiliates. # Author: Tom Hromatka <tom.hroma...@oracle.com> # @@ -27,13 +27,14 @@ class Config(object): def __init__(self, args, container=None): self.args = args - if container: - self.container = container - else: - # Use the default container settings - self.container = Container(name=consts.DEFAULT_CONTAINER_NAME, - stop_timeout=args.timeout, arch=None, - distro=args.distro, release=args.release) + if self.args.container: + if container: + self.container = container + else: + # Use the default container settings + self.container = Container(name=consts.DEFAULT_CONTAINER_NAME, + stop_timeout=args.timeout, arch=None, + distro=args.distro, release=args.release) self.ftest_dir = os.path.dirname(os.path.abspath(__file__)) self.libcg_dir = os.path.dirname(self.ftest_dir) @@ -44,7 +45,8 @@ class Config(object): def __str__(self): out_str = "Configuration" - out_str += "\n\tcontainer = {}".format(self.container) + if self.args.container: + out_str += "\n\tcontainer = {}".format(self.container) return out_str diff --git a/ftests/ftests.py b/ftests/ftests.py index 5971789097c0..6b3c96f897fb 100755 --- a/ftests/ftests.py +++ b/ftests/ftests.py @@ -2,7 +2,7 @@ # # Main entry point for the libcgroup functional tests # -# Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019-2021 Oracle and/or its affiliates. # Author: Tom Hromatka <tom.hroma...@oracle.com> # @@ -68,6 +68,18 @@ def parse_args(): parser.add_argument('-s', '--suite', help='Test suite to run, e.g. cpuset', required=False, default=consts.TESTS_RUN_ALL_SUITES, type=str) + + container_parser = parser.add_mutually_exclusive_group(required=False) + container_parser.add_argument('--container', action='store_true', + help='Run the tests in a container. ' + 'Note that some tests cannot be run in a container.', + dest='container') + container_parser.add_argument('--no-container', action='store_false', + help='Do not run the tests in a container. ' + 'Note that some tests are destructive and will modify your cgroup hierarchy.', + dest='container') + parser.set_defaults(container=True) + parser.add_argument('-v', '--verbose', help='Print all information about this test run', default=True, required=False, action="store_false") @@ -139,23 +151,25 @@ def setup(config, do_teardown=True, record_time=False): # log but ignore all exceptions Log.log_debug(e) - # this command initializes the lxd storage, networking, etc. - Run.run(['sudo', 'lxd', 'init', '--auto']) - update_host_subuid() - update_host_subgid() + if config.args.container: + # this command initializes the lxd storage, networking, etc. + Run.run(['sudo', 'lxd', 'init', '--auto']) + update_host_subuid() + update_host_subgid() - config.container.create() - config.container.config() - config.container.start() + config.container.create() + config.container.config() + config.container.start() - # LXC on Ubuntu 20.04 put sed in a different spot. Add a symlink - config.container.run(['ln', '-s', '/bin/sed', '/usr/bin/sed']) + # LXC on Ubuntu 20.04 put sed in a different spot. Add a symlink + config.container.run(['ln', '-s', '/bin/sed', '/usr/bin/sed']) + + # add the libcgroup library to the container's ld + echo_cmd = ['bash', '-c', 'echo {} >> /etc/ld.so.conf.d/libcgroup.conf'.format( + os.path.join(consts.LIBCG_MOUNT_POINT, 'src/.libs'))] + config.container.run(echo_cmd) + config.container.run('ldconfig') - # add the libcgroup library to the container's ld - echo_cmd = ['bash', '-c', 'echo {} >> /etc/ld.so.conf.d/libcgroup.conf'.format( - os.path.join(consts.LIBCG_MOUNT_POINT, 'src/.libs'))] - config.container.run(echo_cmd) - config.container.run('ldconfig') if record_time: setup_time = time.time() - start_time @@ -277,16 +291,17 @@ def teardown(config, record_time=False): Process.join_children() - try: - config.container.stop() - except Exception as e: - # log but ignore all exceptions - Log.log_debug(e) - try: - config.container.delete() - except Exception as e: - # log but ignore all exceptions - Log.log_debug(e) + if config.args.container: + try: + config.container.stop() + except Exception as e: + # log but ignore all exceptions + Log.log_debug(e) + try: + config.container.delete() + except Exception as e: + # log but ignore all exceptions + Log.log_debug(e) if record_time: teardown_time = time.time() - start_time diff --git a/ftests/process.py b/ftests/process.py index 82a40d2c8013..8996ce32382c 100644 --- a/ftests/process.py +++ b/ftests/process.py @@ -1,7 +1,7 @@ # # Cgroup class for the libcgroup functional tests # -# Copyright (c) 2020 Oracle and/or its affiliates. +# Copyright (c) 2020-2021 Oracle and/or its affiliates. # Author: Tom Hromatka <tom.hroma...@oracle.com> # @@ -28,16 +28,16 @@ children = list() class Process(object): @staticmethod - def __infinite_loop(config, sleep_time=1, in_container=True): + def __infinite_loop(config, sleep_time=1): cmd = ['nohup', 'perl', '-e', '\'while(1){{sleep({})}};\''.format(sleep_time), '&'] - if in_container: + if config.args.container: config.container.run(cmd, shell_bool=True) else: Run.run(cmd, shell_bool=True) @staticmethod - def create_process(config, in_container=True): + def create_process(config): # To allow for multiple processes to be created, each new process # sleeps for a different amount of time. This lets us uniquely find # each process later in this function @@ -53,7 +53,7 @@ class Process(object): # get the PID of the newly spawned infinite loop cmd = 'ps x | grep perl | grep "sleep({})" | awk \'{{print $1}}\''.format(sleep_time) - if in_container: + if config.args.container: pid = config.container.run(cmd, shell_bool=True) else: pid = Run.run(cmd, shell_bool=True) @@ -66,10 +66,9 @@ class Process(object): # Create a simple process in the requested cgroup @staticmethod - def create_process_in_cgroup(config, controller, cgname, in_container=True): - child_pid = Process.create_process(config, in_container=in_container) - Cgroup.classify(config, controller, cgname, child_pid, - in_container=in_container) + def create_process_in_cgroup(config, controller, cgname): + child_pid = Process.create_process(config) + Cgroup.classify(config, controller, cgname, child_pid) # The caller will block until all children are stopped. @staticmethod -- 2.26.2 _______________________________________________ Libcg-devel mailing list Libcg-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libcg-devel