Update class in container.py 99/63899/7
authorxudan <xudan16@huawei.com>
Tue, 23 Oct 2018 10:28:38 +0000 (06:28 -0400)
committerDan Xu <xudan16@huawei.com>
Wed, 31 Oct 2018 06:21:33 +0000 (06:21 +0000)
Change-Id: I4fb24f86c6d15aea5a62baaca20531b2891437ff
Signed-off-by: xudan <xudan16@huawei.com>
dovetail/container.py
dovetail/test_runner.py

index be92a67..580d6c3 100644 (file)
@@ -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)
index 9b5114f..a2bc774 100644 (file)
@@ -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')