summaryrefslogtreecommitdiffstats
path: root/dovetail/container.py
diff options
context:
space:
mode:
Diffstat (limited to 'dovetail/container.py')
-rw-r--r--dovetail/container.py191
1 files changed, 148 insertions, 43 deletions
diff --git a/dovetail/container.py b/dovetail/container.py
index ae7c8e2e..14045165 100644
--- a/dovetail/container.py
+++ b/dovetail/container.py
@@ -8,6 +8,7 @@
#
import os
+import yaml
import utils.dovetail_logger as dt_logger
import utils.dovetail_utils as dt_utils
@@ -17,7 +18,8 @@ from utils.dovetail_config import DovetailConfig as dt_cfg
class Container(object):
container_list = {}
- has_pull_latest_image = {'yardstick': False, 'functest': False}
+ has_pull_latest_image = {'yardstick': False, 'functest': False,
+ 'bottlenecks': False}
logger = None
@@ -41,20 +43,23 @@ class Container(object):
return '%s:%s' % (dt_cfg.dovetail_config[type]['image_name'],
dt_cfg.dovetail_config[type]['docker_tag'])
except KeyError as e:
- cls.logger.error('There is no %s in %s config file.', e, type)
+ cls.logger.exception(
+ 'There is no key {} in {} config file.'.format(e, type))
return None
# get the openrc_volume for creating the container
@classmethod
def openrc_volume(cls, type):
dovetail_config = dt_cfg.dovetail_config
- dovetail_config['openrc'] = os.path.abspath(dovetail_config['openrc'])
+ 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'])
return openrc
else:
- cls.logger.error("File %s is not exist", dovetail_config['openrc'])
+ cls.logger.error(
+ "File {} doesn't exist.".format(dovetail_config['openrc']))
return None
# set functest envs and TEST_DB_URL for creating functest container
@@ -72,8 +77,7 @@ class Container(object):
if 'sdnvpn' in testcase_name:
ins_type = "-e INSTALLER_TYPE=netvirt"
scenario = " -e DEPLOY_SCENARIO=bgpvpn"
- node = " -e NODE_NAME=master"
- envs = "%s %s %s" % (ins_type, scenario, node)
+ envs = "%s %s" % (ins_type, scenario)
dovetail_config = dt_cfg.dovetail_config
if dovetail_config['report_dest'].startswith("http"):
@@ -99,18 +103,40 @@ class Container(object):
cls.logger.error("Can't find any external network.")
return None
- if dovetail_config['report_dest'].startswith("http"):
- cls.logger.info("Yardstick can't push results to DB.")
- cls.logger.info("Results will be stored with files.")
-
log_vol = '-v %s:%s ' % (dovetail_config['result_dir'],
dovetail_config["yardstick"]['result']['log'])
- key_path = os.path.join(dovetail_config['userconfig_dir'], 'id_rsa')
- key_con_path = dovetail_config["yardstick"]['result']['key_path']
- key_vol = '-v %s:%s ' % (key_path, key_con_path)
+
+ # for yardstick, support pod.yaml configuration
+ pod_file = os.path.join(dovetail_config['config_dir'],
+ dovetail_config['pod_file'])
+ if not os.path.isfile(pod_file):
+ cls.logger.error("File {} doesn't exist.".format(pod_file))
+ return None
+ key_file = os.path.join(dovetail_config['config_dir'],
+ dovetail_config['pri_key'])
+ key_container_path = dovetail_config["yardstick"]['result']['key_path']
+ if not os.path.isfile(key_file):
+ cls.logger.debug("Key file {} is not found, must use password in "
+ "{} to do HA test.".format(key_file, pod_file))
+ key_vol = ''
+ else:
+ key_vol = '-v %s:%s ' % (key_file, key_container_path)
return "%s %s %s" % (envs, log_vol, key_vol)
@classmethod
+ def set_bottlenecks_config(cls, testcase_name):
+ dovetail_config = dt_cfg.dovetail_config
+ yard_tag = dovetail_config['yardstick']['docker_tag']
+ docker_vol = '-v /var/run/docker.sock:/var/run/docker.sock'
+ env = ('-e Yardstick_TAG={} -e OUTPUT_FILE={}.out'
+ .format(yard_tag, testcase_name))
+ report = ""
+ if dovetail_config['report_dest'].startswith("http"):
+ report = ("-e BOTTLENECKS_DB_TARGET={}"
+ .format(dovetail_config['report_dest']))
+ return "{} {} {}".format(docker_vol, env, report)
+
+ @classmethod
def create(cls, type, testcase_name):
dovetail_config = dt_cfg.dovetail_config
docker_image = cls.get_docker_image(type)
@@ -123,42 +149,91 @@ class Container(object):
# CI_DEBUG is used for showing the debug logs of the upstream projects
# BUILD_TAG is the unique id for this test
- envs = ' -e CI_DEBUG=true'
+ envs = ' -e CI_DEBUG=true -e NODE_NAME=master'
envs = envs + ' -e BUILD_TAG=%s-%s' % (dovetail_config['build_tag'],
testcase_name)
+ hosts_config = ""
+ hosts_config_file = os.path.join(dovetail_config['config_dir'],
+ 'hosts.yaml')
+ try:
+ with open(hosts_config_file) as f:
+ hosts_info = yaml.safe_load(f)
+ if hosts_info['hosts_info']:
+ for host in hosts_info['hosts_info']:
+ dt_utils.add_hosts_info(host)
+ hosts_config += " --add-host "
+ hosts_config += str(host)
+ cls.logger.debug('Get hosts info {}.'.format(host))
+ except Exception:
+ cls.logger.warn('Failed to get hosts info in {}, '
+ 'maybe some issues with domain name resolution.'
+ .format(hosts_config_file))
+
config = ""
if type.lower() == "functest":
config = cls.set_functest_config(testcase_name)
if type.lower() == "yardstick":
config = cls.set_yardstick_config()
+ if type.lower() == "bottlenecks":
+ config = cls.set_bottlenecks_config(testcase_name)
if not config:
return None
# for refstack, support user self_defined configuration
- # for yardstick, support pod.yaml configuration
- pod_file = os.path.join(dovetail_config['userconfig_dir'], 'pod.yaml')
- if type.lower() == "yardstick" and not os.path.exists(pod_file):
- cls.logger.error("File %s doesn't exist.", pod_file)
- return None
- key_file = os.path.join(dovetail_config['userconfig_dir'], 'id_rsa')
- if type.lower() == "yardstick" and not os.path.exists(key_file):
- cls.logger.debug("File %s doesn't exist.", key_file)
- cls.logger.debug("Can just use password in %s.", pod_file)
config_volume = \
- ' -v %s:%s ' % (dovetail_config['userconfig_dir'],
- dovetail_config["functest"]['config']['dir'])
+ ' -v %s:%s ' % (os.getenv("DOVETAIL_HOME"),
+ dovetail_config[type]['config']['dir'])
+
+ cacert_volume = ""
+ https_enabled = dt_utils.check_https_enabled(cls.logger)
+ cacert = os.getenv('OS_CACERT',)
+ if https_enabled:
+ cls.logger.info("https enabled...")
+ if cacert is not None:
+ if not os.path.isfile(cacert):
+ cls.logger.error("Env variable 'OS_CACERT' is set to {} "
+ "but the file does not exist."
+ .format(cacert))
+ return None
+ elif not dovetail_config['config_dir'] in cacert:
+ cls.logger.error("Credential file has to be put in {}, "
+ "which can be mount into container."
+ .format(dovetail_config['config_dir']))
+ return None
+ cacert_volume = ' -v %s:%s ' % (cacert, cacert)
+ else:
+ cls.logger.warn("https enabled, OS_CACERT not set, insecure "
+ "connection used or OS_CACERT missed")
result_volume = ' -v %s:%s ' % (dovetail_config['result_dir'],
dovetail_config[type]['result']['dir'])
- cmd = 'sudo docker run %s %s %s %s %s %s %s /bin/bash' % \
- (opts, envs, config, openrc, config_volume,
- result_volume, docker_image)
+ cmd = 'sudo docker run %s %s %s %s %s %s %s %s %s /bin/bash' % \
+ (opts, envs, config, hosts_config, openrc, cacert_volume,
+ config_volume, result_volume, docker_image)
dt_utils.exec_cmd(cmd, cls.logger)
ret, container_id = \
dt_utils.exec_cmd("sudo docker ps | grep " + docker_image +
" | awk '{print $1}' | head -1", cls.logger)
cls.container_list[type] = container_id
+
+ if 'sdnvpn' in str(testcase_name):
+ prefix_path = dt_cfg.dovetail_config[type]['config']['dir']
+ file_name = dt_cfg.dovetail_config['sdnvpn_image']
+ src_path = os.path.join(prefix_path, 'pre_config', file_name)
+ dest_path = '/home/opnfv/functest/images'
+ Container.pre_copy(container_id, src_path, dest_path)
+
+ if type.lower() == 'functest':
+ prefix_path = dt_cfg.dovetail_config[type]['config']['dir']
+ file_name = dt_cfg.dovetail_config['cirros_image']
+ src_path = os.path.join(prefix_path, 'pre_config', file_name)
+ dest_path = '/home/opnfv/functest/images'
+ Container.pre_copy(container_id, src_path, dest_path)
+
+ if type.lower() == 'yardstick':
+ cls.set_yardstick_conf_file(container_id)
+
return container_id
@classmethod
@@ -177,15 +252,15 @@ class Container(object):
cmd = "sudo docker ps -aq -f 'ancestor=%s'" % (image_id)
ret, msg = dt_utils.exec_cmd(cmd, cls.logger)
if msg and ret == 0:
- cls.logger.debug('image %s has containers, skip.', image_id)
+ cls.logger.debug('Image {} has containers, skip.'.format(image_id))
return True
cmd = 'sudo docker rmi %s' % (image_id)
- cls.logger.debug('remove image %s', image_id)
+ cls.logger.debug('Remove image {}.'.format(image_id))
ret, msg = dt_utils.exec_cmd(cmd, cls.logger)
if ret == 0:
- cls.logger.debug('remove image %s successfully', image_id)
+ cls.logger.debug('Remove image {} successfully.'.format(image_id))
return True
- cls.logger.error('fail to remove image %s.', image_id)
+ cls.logger.error('Failed to remove image {}.'.format(image_id))
return False
@classmethod
@@ -193,9 +268,10 @@ class Container(object):
cmd = 'sudo docker pull %s' % (image_name)
ret, msg = dt_utils.exec_cmd(cmd, cls.logger)
if ret != 0:
- cls.logger.error('fail to pull docker image %s!', image_name)
+ cls.logger.error(
+ 'Failed to pull docker image {}!'.format(image_name))
return False
- cls.logger.debug('success to pull docker image %s!', image_name)
+ cls.logger.debug('Success to pull docker image {}!'.format(image_name))
return True
@classmethod
@@ -204,7 +280,8 @@ class Container(object):
if not docker_image:
return None
if cls.has_pull_latest_image[validate_type] is True:
- cls.logger.debug('%s is already the newest version.', docker_image)
+ cls.logger.debug(
+ '{} is already the newest version.'.format(docker_image))
return docker_image
old_image_id = cls.get_image_id(docker_image)
if not cls.pull_image_only(docker_image):
@@ -212,13 +289,14 @@ class Container(object):
cls.has_pull_latest_image[validate_type] = True
new_image_id = cls.get_image_id(docker_image)
if not new_image_id:
- cls.logger.error("fail to get the new image's id %s", docker_image)
+ cls.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 %s has no changes, no need to remove.',
- docker_image)
+ cls.logger.debug('Image {} has no changes, no need to remove.'
+ .format(docker_image))
else:
cls.remove_image(old_image_id)
return docker_image
@@ -230,11 +308,23 @@ class Container(object):
return image_id
@classmethod
- def clean(cls, container_id):
- cmd1 = 'sudo docker stop %s' % (container_id)
- dt_utils.exec_cmd(cmd1, cls.logger)
- cmd2 = 'sudo docker rm %s' % (container_id)
- dt_utils.exec_cmd(cmd2, cls.logger)
+ def check_container_exist(cls, container_name):
+ cmd = ('sudo docker ps -aq -f name={}'.format(container_name))
+ ret, msg = dt_utils.exec_cmd(cmd, cls.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']
+ for container in containers:
+ if cls.check_container_exist(container):
+ cmd = ('sudo docker rm -f {}'.format(container))
+ dt_utils.exec_cmd(cmd, cls.logger)
@classmethod
def exec_cmd(cls, container_id, sub_cmd, exit_on_error=False):
@@ -250,3 +340,18 @@ class Container(object):
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)
+
+ @classmethod
+ def set_yardstick_conf_file(cls, container_id):
+ valid_type = 'yardstick'
+ src = dt_cfg.dovetail_config[valid_type]['yard_conf']['src_file']
+ dest = dt_cfg.dovetail_config[valid_type]['yard_conf']['dest_file']
+ cls.pre_copy(container_id, src, dest)
+ url = dt_cfg.dovetail_config['report_dest']
+ if url.startswith("http"):
+ cmd = ("sed -i '16s#http://127.0.0.1:8000/results#{}#g' {}"
+ .format(url, dest))
+ cls.exec_cmd(container_id, cmd)
+ if url.lower() == 'file':
+ cmd = ("sed -i '12s/http/file/g' {}".format(dest))
+ cls.exec_cmd(container_id, cmd)