From 33ffeda0ebd938087fb43c137e7ed8873754c03e Mon Sep 17 00:00:00 2001 From: xudan Date: Tue, 23 Oct 2018 06:28:38 -0400 Subject: Update class in container.py Change-Id: I4fb24f86c6d15aea5a62baaca20531b2891437ff Signed-off-by: xudan --- dovetail/container.py | 181 ++++++++++++++++++++++-------------------------- dovetail/test_runner.py | 27 ++++---- 2 files changed, 98 insertions(+), 110 deletions(-) diff --git a/dovetail/container.py b/dovetail/container.py index be92a671..580d6c3e 100644 --- a/dovetail/container.py +++ b/dovetail/container.py @@ -18,12 +18,12 @@ from utils.dovetail_config import DovetailConfig as dt_cfg class Container(object): - container_list = {} - logger = None - def __init__(self): - pass + def __init__(self, testcase): + self.container_id = None + self.testcase = testcase + self.valid_type = self.testcase.validate_type() def __str__(self): pass @@ -32,46 +32,39 @@ class Container(object): def create_log(cls): cls.logger = dt_logger.Logger(__name__ + '.Container').getLogger() - @classmethod - def get(cls, type): - return cls.container_list[type] - - @classmethod - def _get_config(cls, field, project_cfg, testcase_cfg): + def _get_config(self, field, project_cfg, testcase_cfg): value = dt_utils.get_value_from_dict(field, testcase_cfg) if not value: value = dt_utils.get_value_from_dict(field, project_cfg) if not value: - cls.logger.error("Couldn't find key {}.".format(field)) + self.logger.error("Couldn't find key {}.".format(field)) return None return value - @classmethod - def get_docker_image(cls, testcase): - project_cfg = dt_cfg.dovetail_config[testcase.validate_type()] - testcase_cfg = testcase.testcase['validate'] + def get_docker_image(self): + project_cfg = dt_cfg.dovetail_config[self.valid_type] + testcase_cfg = self.testcase.testcase['validate'] - name = cls._get_config('image_name', project_cfg, testcase_cfg) - tag = cls._get_config('docker_tag', project_cfg, testcase_cfg) + name = self._get_config('image_name', project_cfg, testcase_cfg) + tag = self._get_config('docker_tag', project_cfg, testcase_cfg) return "{}:{}".format(name, tag) if name and tag else None # get the openrc_volume for creating the container - @classmethod - def openrc_volume(cls, type): + def openrc_volume(self): dovetail_config = dt_cfg.dovetail_config dovetail_config['openrc'] = os.path.join(dovetail_config['config_dir'], dovetail_config['env_file']) if os.path.isfile(dovetail_config['openrc']): - openrc = ' -v %s:%s ' % (dovetail_config['openrc'], - dovetail_config[type]['openrc']) + openrc = " -v {}:{} " \ + .format(dovetail_config['openrc'], + dovetail_config[self.valid_type]['openrc']) return openrc else: - cls.logger.error( + self.logger.error( "File {} doesn't exist.".format(dovetail_config['openrc'])) return None - @classmethod - def set_vnftest_config(cls): + def set_vnftest_config(self): dovetail_config = dt_cfg.dovetail_config log_vol = '-v %s:%s ' % (dovetail_config['result_dir'], @@ -81,19 +74,18 @@ class Container(object): dovetail_config['pri_key']) key_container_path = dovetail_config["vnftest"]['result']['key_path'] if not os.path.isfile(key_file): - cls.logger.debug("Key file {} is not found".format(key_file)) + self.logger.debug("Key file {} is not found".format(key_file)) key_vol = '' else: key_vol = '-v %s:%s ' % (key_file, key_container_path) return "%s %s" % (log_vol, key_vol) - @classmethod - def create(cls, valid_type, testcase_name, docker_image): + def create(self, docker_image): dovetail_config = dt_cfg.dovetail_config - project_cfg = dovetail_config[valid_type] + project_cfg = dovetail_config[self.valid_type] # credentials file openrc.sh is neccessary - openrc = cls.openrc_volume(valid_type) + openrc = self.openrc_volume() if not openrc: return None @@ -112,9 +104,9 @@ class Container(object): else: envs = envs + ' -e CI_DEBUG=false' envs = envs + ' -e BUILD_TAG=%s-%s' % (dovetail_config['build_tag'], - testcase_name) + self.testcase.name()) - hosts_config = dt_utils.get_hosts_info(cls.logger) + hosts_config = dt_utils.get_hosts_info(self.logger) # This part will be totally removed after remove the 4 functions # set_functest_config has been removed @@ -122,8 +114,8 @@ class Container(object): # set_bottlenecks_config has been removed # set_vnftest_config config = " " - if valid_type.lower() == "vnftest": - config = cls.set_vnftest_config() + if self.valid_type.lower() == "vnftest": + config = self.set_vnftest_config() if not config: return None @@ -133,20 +125,20 @@ class Container(object): project_cfg['config']['dir']) cacert_volume = "" - https_enabled = dt_utils.check_https_enabled(cls.logger) + https_enabled = dt_utils.check_https_enabled(self.logger) cacert = os.getenv('OS_CACERT') insecure = os.getenv('OS_INSECURE') if cacert is not None: - if dt_utils.check_cacert_file(cacert, cls.logger): + if dt_utils.check_cacert_file(cacert, self.logger): cacert_volume = ' -v %s:%s ' % (cacert, cacert) else: return None elif https_enabled: if insecure and insecure.lower() == 'true': - cls.logger.debug("Use the insecure mode...") + self.logger.debug("Use the insecure mode...") else: - cls.logger.error("https enabled, please set OS_CACERT or " - "insecure mode...") + self.logger.error("https enabled, please set OS_CACERT or " + "insecure mode...") return None images_volume = '' @@ -161,20 +153,18 @@ class Container(object): '{hosts_config} {openrc} {cacert_volume} {config_volume} ' \ '{result_volume} {images_volume} {docker_image} /bin/bash' \ .format(**locals()) - ret, container_id = dt_utils.exec_cmd(cmd, cls.logger) + ret, container_id = dt_utils.exec_cmd(cmd, self.logger) if ret != 0: return None - cls.container_list[valid_type] = container_id - - if valid_type.lower() == 'vnftest': - cls.set_vnftest_conf_file(container_id) + if self.valid_type.lower() == 'vnftest': + self.set_vnftest_conf_file(container_id) + self.container_id = container_id return container_id - @classmethod - def get_image_id(cls, image_name): + def get_image_id(self, image_name): cmd = 'sudo docker images -q %s' % (image_name) - ret, image_id = dt_utils.exec_cmd(cmd, cls.logger) + ret, image_id = dt_utils.exec_cmd(cmd, self.logger) if ret == 0: return image_id else: @@ -182,109 +172,104 @@ class Container(object): # remove the image according to the image_id # if there exists containers using this image, then skip - @classmethod - def remove_image(cls, image_id): + def remove_image(self, image_id): cmd = "sudo docker ps -aq -f 'ancestor=%s'" % (image_id) - ret, msg = dt_utils.exec_cmd(cmd, cls.logger) + ret, msg = dt_utils.exec_cmd(cmd, self.logger) if msg and ret == 0: - cls.logger.debug('Image {} has containers, skip.'.format(image_id)) + self.logger.debug('Image {} has containers, skip.' + .format(image_id)) return True cmd = 'sudo docker rmi %s' % (image_id) - cls.logger.debug('Remove image {}.'.format(image_id)) - ret, msg = dt_utils.exec_cmd(cmd, cls.logger) + self.logger.debug('Remove image {}.'.format(image_id)) + ret, msg = dt_utils.exec_cmd(cmd, self.logger) if ret == 0: - cls.logger.debug('Remove image {} successfully.'.format(image_id)) + self.logger.debug('Remove image {} successfully.'.format(image_id)) return True - cls.logger.error('Failed to remove image {}.'.format(image_id)) + self.logger.error('Failed to remove image {}.'.format(image_id)) return False - @classmethod - def pull_image_only(cls, image_name): + def pull_image_only(self, image_name): cmd = 'sudo docker pull %s' % (image_name) - ret, msg = dt_utils.exec_cmd(cmd, cls.logger) + ret, msg = dt_utils.exec_cmd(cmd, self.logger) if ret != 0: - cls.logger.error( + self.logger.error( 'Failed to pull docker image {}!'.format(image_name)) return False - cls.logger.debug('Success to pull docker image {}!'.format(image_name)) + self.logger.debug('Success to pull docker image {}!' + .format(image_name)) return True - @classmethod - def pull_image(cls, docker_image): + def pull_image(self, docker_image): if not docker_image: return None - old_image_id = cls.get_image_id(docker_image) - if not cls.pull_image_only(docker_image): + old_image_id = self.get_image_id(docker_image) + if not self.pull_image_only(docker_image): return None - new_image_id = cls.get_image_id(docker_image) + new_image_id = self.get_image_id(docker_image) if not new_image_id: - cls.logger.error( + self.logger.error( "Failed to get the id of image {}.".format(docker_image)) return None if not old_image_id: return docker_image if new_image_id == old_image_id: - cls.logger.debug('Image {} has no changes, no need to remove.' - .format(docker_image)) + self.logger.debug('Image {} has no changes, no need to remove.' + .format(docker_image)) else: - cls.remove_image(old_image_id) + self.remove_image(old_image_id) return docker_image - @classmethod - def check_container_exist(cls, container_name): + def check_container_exist(self, container_name): cmd = ('sudo docker ps -aq -f name={}'.format(container_name)) - ret, msg = dt_utils.exec_cmd(cmd, cls.logger) + ret, msg = dt_utils.exec_cmd(cmd, self.logger) if ret == 0 and msg: return True return False - @classmethod - def clean(cls, container_id, valid_type): - cmd = ('sudo docker rm -f {}'.format(container_id)) - dt_utils.exec_cmd(cmd, cls.logger) - if valid_type.lower() == 'bottlenecks': - containers = dt_cfg.dovetail_config[valid_type]['extra_container'] + def clean(self): + cmd = ('sudo docker rm -f {}'.format(self.container_id)) + dt_utils.exec_cmd(cmd, self.logger) + if self.valid_type.lower() == 'bottlenecks': + containers = dt_utils.get_value_from_dict( + 'extra_container', dt_cfg.dovetail_config[self.valid_type]) for container in containers: - if cls.check_container_exist(container): + if self.check_container_exist(container): cmd = ('sudo docker rm -f {}'.format(container)) - dt_utils.exec_cmd(cmd, cls.logger) + dt_utils.exec_cmd(cmd, self.logger) - @classmethod - def exec_cmd(cls, container_id, sub_cmd, exit_on_error=False): + def exec_cmd(self, sub_cmd, exit_on_error=False): if sub_cmd == "": return (1, 'sub_cmd is empty') - cmd = 'sudo docker exec %s /bin/bash -c "%s"' % (container_id, sub_cmd) - return dt_utils.exec_cmd(cmd, cls.logger, exit_on_error) + cmd = 'sudo docker exec {} /bin/bash -c "{}"'.format(self.container_id, + sub_cmd) + return dt_utils.exec_cmd(cmd, self.logger, exit_on_error) - @classmethod - def copy_file(cls, container_id, src_path, dest_path, - exit_on_error=False): + def copy_file(self, src_path, dest_path, exit_on_error=False): if not src_path or not dest_path: return (1, 'src_path or dest_path is empty') cmd = 'cp %s %s' % (src_path, dest_path) - return cls.exec_cmd(container_id, cmd, exit_on_error) + return self.exec_cmd(cmd, exit_on_error) - @classmethod - def docker_copy(cls, container_id, src_path, dest_path): + def docker_copy(self, src_path, dest_path): if not src_path or not dest_path: return (1, 'src_path or dest_path is empty') - cmd = 'docker cp %s %s:%s' % (src_path, container_id, dest_path) - return dt_utils.exec_cmd(cmd, cls.logger) + cmd = 'docker cp {} {}:{}'.format(src_path, + self.container_id, + dest_path) + return dt_utils.exec_cmd(cmd, self.logger) - @classmethod - def copy_files_in_container(cls, valid_type, container_id): - project_config = dt_cfg.dovetail_config[valid_type] + def copy_files_in_container(self): + project_config = dt_cfg.dovetail_config[self.valid_type] if 'copy_file_in_container' not in project_config.keys(): return if not project_config['copy_file_in_container']: return for item in project_config['copy_file_in_container']: - cls.copy_file(container_id, item['src_file'], item['dest_file']) + self.copy_file(item['src_file'], item['dest_file']) - @classmethod - def set_vnftest_conf_file(cls, container_id): + def set_vnftest_conf_file(self): valid_type = 'vnftest' for conf_file in dt_cfg.dovetail_config[valid_type]['vnftest_conf']: src = conf_file['src_file'] dest = conf_file['dest_file'] - cls.docker_copy(container_id, src, dest) + self.docker_copy(src, dest) diff --git a/dovetail/test_runner.py b/dovetail/test_runner.py index 9b5114f8..a2bc774c 100644 --- a/dovetail/test_runner.py +++ b/dovetail/test_runner.py @@ -33,8 +33,11 @@ class DockerRunner(object): def create_log(cls): cls.logger = dt_logger.Logger(__name__ + '.DockerRunner').getLogger() - def pre_copy(self, container_id=None, dest_path=None, + def pre_copy(self, container=None, dest_path=None, src_file=None, exist_file=None): + if not container: + self.logger.error("Container instance is None.") + return None if not dest_path: self.logger.error("There has no dest_path in {} config file." .format(self.testcase.name())) @@ -47,24 +50,24 @@ class DockerRunner(object): file_path = dt_cfg.dovetail_config[self.type]['config']['dir'] src_path = os.path.join(file_path, 'pre_config', exist_file) - Container.copy_file(container_id, src_path, dest_path) + container.copy_file(src_path, dest_path) return dest_path def run(self): - docker_image = Container.get_docker_image(self.testcase) + container = Container(self.testcase) + docker_image = container.get_docker_image() if dt_cfg.dovetail_config['offline']: - exist = Container.get_image_id(docker_image) + exist = container.get_image_id(docker_image) if not exist: self.logger.error("{} image doesn't exist, can't run offline." .format(self.testcase.validate_type())) return else: - if not Container.pull_image(docker_image): + if not container.pull_image(docker_image): self.logger.error("Failed to pull the image.") return - container_id = Container.create(self.testcase.validate_type(), - self.testcase.name(), docker_image) + container_id = container.create(docker_image) if not container_id: self.logger.error('Failed to create container.') return @@ -76,14 +79,14 @@ class DockerRunner(object): exist_file_name = self.testcase.pre_copy_path("exist_src_file") if src_file_name or exist_file_name: - if not self.pre_copy(container_id, dest_path, src_file_name, + if not self.pre_copy(container, dest_path, src_file_name, exist_file_name): return cmds = self.testcase.pre_condition() if cmds: for cmd in cmds: - ret, msg = Container.exec_cmd(container_id, cmd) + ret, msg = container.exec_cmd(cmd) if ret != 0: self.logger.error("Failed to exec all pre_condition cmds.") break @@ -93,7 +96,7 @@ class DockerRunner(object): 'Failed to prepare test case: {}'.format(self.testcase.name())) else: for cmd in self.testcase.cmds: - ret, msg = Container.exec_cmd(container_id, cmd) + ret, msg = container.exec_cmd(cmd) if ret != 0: self.logger.error('Failed to exec {}, ret: {}, msg: {}' .format(cmd, ret, msg)) @@ -102,11 +105,11 @@ class DockerRunner(object): cmds = self.testcase.post_condition() if cmds: for cmd in cmds: - ret, msg = Container.exec_cmd(container_id, cmd) + ret, msg = container.exec_cmd(cmd) self.testcase.cleaned(True) if not dt_cfg.dovetail_config['noclean']: - Container.clean(container_id, self.type) + container.clean() def archive_logs(self): result_path = os.path.join(os.environ["DOVETAIL_HOME"], 'results') -- cgit 1.2.3-korg