diff options
-rw-r--r-- | config/config.yaml | 5 | ||||
-rw-r--r-- | utils/__init__.py | 2 | ||||
-rw-r--r-- | utils/dashboard/process_data.py | 4 | ||||
-rwxr-xr-x | utils/dashboard/rubbos_collector.py | 22 | ||||
-rwxr-xr-x | utils/dashboard/uploader.py | 4 | ||||
-rw-r--r-- | utils/env_prepare/__init__.py | 8 | ||||
-rw-r--r-- | utils/env_prepare/stack_prepare.py | 79 | ||||
-rw-r--r-- | utils/infra_setup/__init__.py | 2 | ||||
-rwxr-xr-x | utils/infra_setup/fetch_os_creds.sh | 169 | ||||
-rwxr-xr-x | utils/infra_setup/heat/common.py | 3 | ||||
-rwxr-xr-x | utils/infra_setup/heat/consts/parameters.py | 1 | ||||
-rw-r--r-- | utils/infra_setup/heat/manager.py | 7 | ||||
-rwxr-xr-x | utils/infra_setup/heat/template.py | 4 | ||||
-rwxr-xr-x | utils/infra_setup/heat/tests/generate_template_test.py | 4 | ||||
-rw-r--r-- | utils/logger.py | 18 | ||||
-rw-r--r-- | utils/parser.py | 59 | ||||
-rwxr-xr-x | utils/tools/bottlenecks_image_modify | 172 | ||||
-rwxr-xr-x | utils/tools/ubuntu-server-clouding-modify.sh | 43 |
18 files changed, 387 insertions, 219 deletions
diff --git a/config/config.yaml b/config/config.yaml index cf380e27..702a0c8c 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -1,2 +1,5 @@ common_config: - log_dir: '/tmp/bottlenecks_POSCA.log'
\ No newline at end of file + log_dir: '/tmp/' + rc_dir: '/tmp/admin_rc.sh' + releng_dir: '/home/opnfv/releng' + fetch_os_file: 'utils/fetch_os_creds.sh'
\ No newline at end of file diff --git a/utils/__init__.py b/utils/__init__.py index 38727287..b124dfa9 100644 --- a/utils/__init__.py +++ b/utils/__init__.py @@ -5,4 +5,4 @@ # are made available under the terms of the Apache License, Version 2.0 # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 -##############################################################################
\ No newline at end of file +############################################################################## diff --git a/utils/dashboard/process_data.py b/utils/dashboard/process_data.py index e71a1e82..4be09178 100644 --- a/utils/dashboard/process_data.py +++ b/utils/dashboard/process_data.py @@ -8,14 +8,14 @@ ############################################################################## -import subprocess as subp import sys from rubbos_collector import RubbosCollector from uploader import Uploader def printUsage(): - print "Usage: python process_data.py required_params(**) optional_params([])" + print ("Usage: python process_data.py required_params(**)" + " optional_params([])") print " ** -i|--input input_data_dir" print " ** -s|--suite suite_name" print " ** -c|--conf conf_file" diff --git a/utils/dashboard/rubbos_collector.py b/utils/dashboard/rubbos_collector.py index d9f86032..140700e3 100755 --- a/utils/dashboard/rubbos_collector.py +++ b/utils/dashboard/rubbos_collector.py @@ -17,19 +17,27 @@ def exec_shell(cmd): def get_onetime_data(dir_name): - cmd = "grep -in 'remote client nodes' %s/index.html|awk '{print $5}'|awk -F '<' '{print $1}'" % dir_name + cmd = ("grep -in 'remote client nodes' %s/index.html|awk " + "'{print $5}'|awk -F '<' '{print $1}'" % dir_name) client_node_num = int(exec_shell(cmd)) - cmd = "grep -n 'Number of clients' %s/index.html|awk '{print $5}'|awk -F '<' '{print $1}'" % dir_name + cmd = ("grep -n 'Number of clients' %s/index.html|awk " + "'{print $5}'|awk -F '<' '{print $1}'" % dir_name) each_client_num = int(exec_shell(cmd)) total_client = (client_node_num + 1) * each_client_num - cmd = 'grep -n "throughput" %s/stat_client*.html |awk -F "<B>" \'{if (FNR%%2==0 && FNR%%4!=0) {printf "%%s\\n", $3}}\'|awk \'BEGIN{sum=0;}{sum=sum+$1;}END{print sum}\'' % dir_name + cmd = ('grep -n "throughput" %s/stat_client*.html |awk -F "<B>"' + ' \'{if (FNR%%2==0 && FNR%%4!=0) {printf "%%s\\n", $3}}\'|awk \'' + 'BEGIN{sum=0;}{sum=sum+$1;}END{print sum}\'' % dir_name) throughput = int(exec_shell(cmd)) - cmd = 'grep -n "Total" %s/stat_client*.html |awk -F "<B>" \'{if (FNR==4) {printf "%%s\\n", $4}}\'|awk -F "</B>" \'BEGIN{sum=0;}{sum=sum+$1;}END{print sum}\'' % dir_name + cmd = ('grep -n "Total" %s/stat_client*.html |awk -F "<B>"' + ' \'{if (FNR==4) {printf "%%s\\n", $4}}\'|awk -F "</B>"' + ' \'BEGIN{sum=0;}{sum=sum+$1;}END{print sum}\'' % dir_name) request = int(exec_shell(cmd)) - cmd = 'grep -n "Total" %s/stat_client*.html |awk -F "<B>" \'{if (FNR==4) {printf "%%s\\n", $5}}\'|awk -F "</B>" \'BEGIN{sum=0;}{sum=sum+$1;}END{print sum}\'' % dir_name + cmd = ('grep -n "Total" %s/stat_client*.html |awk -F "<B>"' + ' \'{if (FNR==4) {printf "%%s\\n", $5}}\'|awk -F "</B>"' + ' \'BEGIN{sum=0;}{sum=sum+$1;}END{print sum}\'' % dir_name) error_request = int(exec_shell(cmd)) return total_client, throughput, request, error_request @@ -44,8 +52,8 @@ class RubbosCollector(object): cmd = 'ls -l %s |grep ^d|awk \'{print $9}\'' % data_home result = [] for subdir in exec_shell(cmd).split('\n'): - total_client, throughput, request, error_request = get_onetime_data( - data_home + '/' + subdir) + total_client, throughput, request, error_request = \ + get_onetime_data(data_home + '/' + subdir) result.append({'client': total_client, 'throughput': throughput, 'request': request, diff --git a/utils/dashboard/uploader.py b/utils/dashboard/uploader.py index a4686560..97ffd38c 100755 --- a/utils/dashboard/uploader.py +++ b/utils/dashboard/uploader.py @@ -51,7 +51,8 @@ class Uploader(object): def _test(): - #data = '{"details": [{"client": 200, "throughput": 20}, {"client": 300, "throughput": 20}], "case_name": "rubbos"}' + # data = '{"details": [{"client": 200, "throughput": 20}, + # {"client": 300, "throughput": 20}], "case_name": "rubbos"}' if len(sys.argv) < 2: print ("no argumens input!!") exit(1) @@ -60,5 +61,6 @@ def _test(): data = json.load(stream) Uploader().upload_result(data) + if __name__ == "__main__": _test() diff --git a/utils/env_prepare/__init__.py b/utils/env_prepare/__init__.py new file mode 100644 index 00000000..b124dfa9 --- /dev/null +++ b/utils/env_prepare/__init__.py @@ -0,0 +1,8 @@ +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## diff --git a/utils/env_prepare/stack_prepare.py b/utils/env_prepare/stack_prepare.py new file mode 100644 index 00000000..37b523d1 --- /dev/null +++ b/utils/env_prepare/stack_prepare.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +import os +import subprocess +import errno +from utils.logger import Logger +from utils.parser import Parser as config +import utils.infra_setup.heat.manager as utils + +LOG = Logger(__name__).getLogger() + + +def _prepare_env_daemon(): + + installer_ip = os.environ.get('INSTALLER_IP', 'undefined') + installer_type = os.environ.get('INSTALLER_TYPE', 'undefined') + + rc_file = config.bottlenecks_config["rc_dir"] + + _get_remote_rc_file(rc_file, installer_ip, installer_type) + + _source_file(rc_file) + + _append_external_network(rc_file) + + # update the external_network + _source_file(rc_file) + + +def _get_remote_rc_file(rc_file, installer_ip, installer_type): + + RELENG_DIR = config.bottlenecks_config["releng_dir"] + OS_FETCH_SCRIPT = config.bottlenecks_config["fetch_os"] + os_fetch_script = os.path.join(RELENG_DIR, OS_FETCH_SCRIPT) + + try: + cmd = [os_fetch_script, '-d', rc_file, '-i', installer_type, + '-a', installer_ip] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE) + p.communicate()[0] + + if p.returncode != 0: + LOG.debug('Failed to fetch credentials from installer') + except OSError as e: + if e.errno != errno.EEXIST: + raise + + +def _source_file(rc_file): + p = subprocess.Popen(". %s; env" % rc_file, stdout=subprocess.PIPE, + shell=True) + output = p.communicate()[0] + env = dict((line.split('=', 1) for line in output.splitlines())) + os.environ.update(env) + return env + + +def _append_external_network(rc_file): + neutron_client = utils._get_neutron_client() + networks = neutron_client.list_networks()['networks'] + try: + ext_network = next(n['name'] for n in networks if n['router:external']) + except StopIteration: + LOG.warning("Can't find external network") + else: + cmd = 'export EXTERNAL_NETWORK=%s' % ext_network + try: + with open(rc_file, 'a') as f: + f.write(cmd + '\n') + except OSError as e: + if e.errno != errno.EEXIST: + raise diff --git a/utils/infra_setup/__init__.py b/utils/infra_setup/__init__.py index 38727287..b124dfa9 100644 --- a/utils/infra_setup/__init__.py +++ b/utils/infra_setup/__init__.py @@ -5,4 +5,4 @@ # are made available under the terms of the Apache License, Version 2.0 # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 -##############################################################################
\ No newline at end of file +############################################################################## diff --git a/utils/infra_setup/fetch_os_creds.sh b/utils/infra_setup/fetch_os_creds.sh deleted file mode 100755 index 4ac7162e..00000000 --- a/utils/infra_setup/fetch_os_creds.sh +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/bash -############################################################################## -# Copyright (c) 2015 Ericsson AB and others. -# jose.lausuch@ericsson.com matthew.lijun@huawei.com -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - - -usage() { - echo "usage: $0 -d <destination> -i <installer_type> -a <installer_ip>" >&2 -} - -info () { - logger -s -t "fetch_os_creds.info" "$*" -} - - -error () { - logger -s -t "fetch_os_creds.error" "$*" - exit 1 -} - - -verify_connectivity() { - local ip=$1 - info "Verifying connectivity to $ip..." - for i in $(seq 0 10); do - if ping -c 1 -W 1 $ip > /dev/null; then - info "$ip is reachable!" - return 0 - fi - sleep 1 - done - error "Can not talk to $ip." -} - - - -#Get options -while getopts ":d:i:a:h:" optchar; do - case "${optchar}" in - d) dest_path=${OPTARG} ;; - i) installer_type=${OPTARG} ;; - a) installer_ip=${OPTARG} ;; - *) echo "Non-option argument: '-${OPTARG}'" >&2 - usage - exit 2 - ;; - esac -done - -# set vars from env if not provided by user as options -dest_path=${dest_path:-$HOME/opnfv-openrc.sh} -installer_type=${installer_type:-$INSTALLER_TYPE} -installer_ip=${installer_ip:-$INSTALLER_IP} - -if [ -z $dest_path ] || [ -z $installer_type ] || [ -z $installer_ip ]; then - usage - exit 2 -fi - -# Checking if destination path is valid -if [ -d $dest_path ]; then - error "Please provide the full destination path for the credentials file including the filename" -else - # Check if we can create the file (e.g. path is correct) - touch $dest_path || error "Cannot create the file specified. Check that the path is correct and run the script again." -fi - - -ssh_options="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" - -# Start fetching the files -if [ "$installer_type" == "fuel" ]; then - #ip_fuel="10.20.0.2" - verify_connectivity $installer_ip - - # Check if controller is alive (online='True') - controller_ip=$(sshpass -p r00tme ssh 2>/dev/null $ssh_options root@${installer_ip} \ - 'fuel node | grep controller | grep True | awk "{print \$10}" | tail -1') &> /dev/null - - if [ -z $controller_ip ]; then - error "The controller $controller_ip is not up. Please check that the POD is correctly deployed." - fi - - info "Fetching rc file from controller $controller_ip..." - sshpass -p r00tme ssh 2>/dev/null $ssh_options root@${installer_ip} \ - "scp $ssh_options ${controller_ip}:/root/openrc ." &> /dev/null - sshpass -p r00tme scp 2>/dev/null $ssh_options root@${installer_ip}:~/openrc $dest_path &> /dev/null - - #This file contains the mgmt keystone API, we need the public one for our rc file - admin_ip=$(cat $dest_path | grep "OS_AUTH_URL" | sed 's/^.*\=//' | sed "s/^\([\"']\)\(.*\)\1\$/\2/g" | sed s'/\/$//') - public_ip=$(sshpass -p r00tme ssh $ssh_options root@${installer_ip} \ - "ssh ${controller_ip} 'source openrc; keystone endpoint-list'" \ - | grep $admin_ip | sed 's/ /\n/g' | grep ^http | head -1) &> /dev/null - #| grep http | head -1 | cut -d '|' -f 4 | sed 's/v1\/.*/v1\//' | sed 's/ //g') &> /dev/null - #NOTE: this is super ugly sed 's/v1\/.*/v1\//'OS_AUTH_URL - # but sometimes the output of endpoint-list is like this: http://172.30.9.70:8004/v1/%(tenant_id)s - - -elif [ "$installer_type" == "foreman" ]; then - #ip_foreman="172.30.10.73" - controller="oscontroller1.opnfv.com" - verify_connectivity $installer_ip - - # Check if controller is alive (here is more difficult to get the ip from a command like "fuel node") - sshpass -p vagrant ssh $ssh_options root@${installer_ip} \ - "sshpass -p Op3nStack ssh $ssh_options root@${controller} 'ls'" &> /dev/null - if [ $? -ne 0 ]; then - error "The controller ${controller} is not up. Please check that the POD is correctly deployed." - fi - - info "Fetching openrc from a Foreman Controller '${controller}'..." - sshpass -p vagrant ssh $ssh_options root@${installer_ip} \ - "sshpass -p Op3nStack scp $ssh_options root@${controller}:~/keystonerc_admin ." &> /dev/null - sshpass -p vagrant scp $ssh_options root@${installer_ip}:~/keystonerc_admin $dest_path &> /dev/null - - #This file contains the mgmt keystone API, we need the public one for our rc file - admin_ip=$(cat $dest_path | grep "OS_AUTH_URL" | sed 's/^.*\=//' | sed "s/^\([\"']\)\(.*\)\1\$/\2/g" | sed s'/\/$//') - public_ip=$(sshpass -p vagrant ssh $ssh_options root@${installer_ip} \ - "sshpass -p Op3nStack ssh $ssh_options root@${controller} \ - 'source keystonerc_admin;keystone endpoint-list'" \ - | grep $admin_ip | sed 's/ /\n/g' | grep ^http | head -1) &> /dev/null - -elif [ "$installer_type" == "compass" ]; then - verify_connectivity $installer_ip - controller_ip=$(sshpass -p'root' ssh 2>/dev/null $ssh_options root@${installer_ip} \ - 'mysql -ucompass -pcompass -Dcompass -e"select * from cluster;"' \ - | awk -F"," '{for(i=1;i<NF;i++)if($i~/\"host1\"/) {print $(i+1);break;}}' \ - | grep -oP "\d+.\d+.\d+.\d+") - - if [ -z $controller_ip ]; then - error "The controller $controller_ip is not up. Please check that the POD is correctly deployed." - fi - - info "Fetching rc file from controller $controller_ip..." - sshpass -p root ssh 2>/dev/null $ssh_options root@${installer_ip} \ - "scp $ssh_options ${controller_ip}:/opt/admin-openrc.sh ." &> /dev/null - sshpass -p root scp 2>/dev/null $ssh_options root@${installer_ip}:~/admin-openrc.sh $dest_path &> /dev/null - echo 'export OS_REGION_NAME=regionOne' >> $dest_path - - info "This file contains the mgmt keystone API, we need the public one for our rc file" - admin_ip=$(cat $dest_path | grep "OS_AUTH_URL" | sed 's/^.*\=//' | sed "s/^\([\"']\)\(.*\)\1\$/\2/g" | sed s'/\/$//') - info "admin_ip: $admin_ip" - public_ip=$(sshpass -p root ssh $ssh_options root@${installer_ip} \ - "ssh ${controller_ip} 'source /opt/admin-openrc.sh; keystone endpoint-list'" \ - | grep $admin_ip | sed 's/ /\n/g' | grep ^http | head -1) - info "public_ip: $public_ip" - -else - error "Installer $installer is not supported by this script" -fi - - - -if [ "$public_ip" == "" ]; then - error "Cannot retrieve the public IP from keystone" -fi - -info "Keystone public IP is $public_ip" -sed -i "/OS_AUTH_URL/c\export OS_AUTH_URL=\'$public_ip'" $dest_path - -echo "-------- Credentials: --------" -cat $dest_path - -exit 0 diff --git a/utils/infra_setup/heat/common.py b/utils/infra_setup/heat/common.py index 28257ac7..ab0dadf5 100755 --- a/utils/infra_setup/heat/common.py +++ b/utils/infra_setup/heat/common.py @@ -97,6 +97,7 @@ def get_heat_api_version(): return api_version return DEFAULT_HEAT_API_VERSION + def get_nova_api_version(): api_version = os.getenv('OS_COMPUTE_API_VERSION') if api_version is not None: @@ -110,4 +111,4 @@ def get_glance_api_version(): if api_version is not None: log.info("GLANCE_API_VERSION is set in env as '%s'", api_version) return api_version - return DEFAULT_GLANCE_API_VERSION
\ No newline at end of file + return DEFAULT_GLANCE_API_VERSION diff --git a/utils/infra_setup/heat/consts/parameters.py b/utils/infra_setup/heat/consts/parameters.py index f275c25b..15aa5b5d 100755 --- a/utils/infra_setup/heat/consts/parameters.py +++ b/utils/infra_setup/heat/consts/parameters.py @@ -7,7 +7,6 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -import files # ------------------------------------------------------ # Directories and file locations diff --git a/utils/infra_setup/heat/manager.py b/utils/infra_setup/heat/manager.py index 3a270ac1..5c181ae6 100644 --- a/utils/infra_setup/heat/manager.py +++ b/utils/infra_setup/heat/manager.py @@ -11,6 +11,7 @@ import time import common as op_utils from glanceclient.client import Client as GlanceClient from novaclient.client import Client as NovaClient +from neutronclient.v2_0.client import Client as NeutronClient def _get_glance_client(): @@ -28,6 +29,12 @@ def _get_nova_client(): session=sess) +def _get_neutron_client(): + sess = op_utils.get_session() + neutron_client = NeutronClient(session=sess) + return neutron_client + + def stack_create_images( imagefile=None, image_name="bottlenecks_image"): diff --git a/utils/infra_setup/heat/template.py b/utils/infra_setup/heat/template.py index 28c20b72..cc652fb4 100755 --- a/utils/infra_setup/heat/template.py +++ b/utils/infra_setup/heat/template.py @@ -114,9 +114,9 @@ class HeatStack(HeatObject): i += 1 if self.uuid is not None: - sys.exit("delete stack failed!!!") + sys.exit("delete stack failed!!!") else: - HeatStack.stacks.remove(self) + HeatStack.stacks.remove(self) @staticmethod def delete_all(): diff --git a/utils/infra_setup/heat/tests/generate_template_test.py b/utils/infra_setup/heat/tests/generate_template_test.py index 83c905ad..374ca30e 100755 --- a/utils/infra_setup/heat/tests/generate_template_test.py +++ b/utils/infra_setup/heat/tests/generate_template_test.py @@ -7,14 +7,14 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## +import template +import common import os import unittest import mock import sys sys.path.append("..") -import template -import common def reset_common(): diff --git a/utils/logger.py b/utils/logger.py index 0f93bca7..80392f59 100644 --- a/utils/logger.py +++ b/utils/logger.py @@ -19,14 +19,14 @@ import logging import os -# from bottlenecks_cfg import Bottlenecks_cfg as bn_cfg +from utils.parser import Parser as conf class Logger: def __init__(self, logger_name): - #if user set --debug as a cli parameter - #we will set this variable “Debug” to output debug info. + # if user set --debug as a cli parameter + # we will set this variable "Debug" to output debug info. DEBUG = os.getenv('DEBUG') self.logger = logging.getLogger(logger_name) @@ -47,13 +47,15 @@ class Logger: ch.setLevel(logging.INFO) self.logger.addHandler(ch) -# result_path = bn_cfg.['log_dir'] -# if not os.path.exists(result_path): -# os.makedirs(result_path) - hdlr = logging.FileHandler('/tmp/bottlenecks.log') + result_path = conf.bottlenecks_config["log_dir"] + if not os.path.exists(result_path): + os.makedirs(result_path) + result_file = os.path.join(result_path, 'bottlenecks.log') + hdlr = logging.FileHandler(result_file) + hdlr.setFormatter(formatter) hdlr.setLevel(logging.DEBUG) self.logger.addHandler(hdlr) def getLogger(self): - return self.logger
\ No newline at end of file + return self.logger diff --git a/utils/parser.py b/utils/parser.py index 7ddf02a2..ce5096a3 100644 --- a/utils/parser.py +++ b/utils/parser.py @@ -7,50 +7,63 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -from logger import Logger import os import yaml class Parser(): - def __init__(self): - self.code_dir = os.path.dirname(os.path.abspath(__file__)) - self.root_dir = os.path.dirname(self.code_dir) - self.test_dir = os.path.join(self.root_dir, 'testsuites') + + bottlenecks_config = {} + + @classmethod + def config_init(cls): + cls.code_dir = os.path.dirname(os.path.abspath(__file__)) + cls.root_dir = os.path.dirname(cls.code_dir) + cls.test_dir = os.path.join(cls.root_dir, 'testsuites') config_dir = os.path.join( - self.root_dir, + cls.root_dir, 'config', 'config.yaml') + with open(config_dir) as file: - log_info = yaml.load(file) - self.logdir = log_info['common_config'] - self.LOG = Logger(__name__).getLogger() - - def config_read(self, testcase, story_name): - self.LOG.info("begin to parser config file!") - testcase_parser = {} - self.story_dir = os.path.join( - self.test_dir, + config_info = yaml.load(file) + common_config = config_info['common_config'] + cls.bottlenecks_config["releng_dir"] = common_config["releng_dir"] + cls.bottlenecks_config["fetch_os"] = common_config["fetch_os_file"] + cls.bottlenecks_config["log_dir"] = common_config['log_dir'] + cls.bottlenecks_config["rc_dir"] = common_config['rc_dir'] + cls.config_dir_check(cls.bottlenecks_config["log_dir"]) + + @classmethod + def config_read(cls, testcase, story_name): + story_dir = os.path.join( + cls.test_dir, testcase, 'testsuite_story', story_name) - with open(self.story_dir) as file: - self.LOG.info('testsuite:' + testcase + 'story:' + story_name) + with open(story_dir) as file: story_parser = yaml.load(file) for case_name in story_parser['testcase']: testcase_dir = os.path.join( - self.test_dir, + cls.test_dir, testcase, 'testcase_cfg', case_name) with open(testcase_dir) as f: - self.LOG.info('story: %s, testcase: %s' % (story_name, case_name)) - testcase_parser[case_name] = yaml.load(f) + cls.bottlenecks_config[case_name] = yaml.load(f) + + return cls.bottlenecks_config - return testcase_parser + @classmethod + def config_dir_check(cls, dirname): + if dirname is None: + dirname = '/tmp/' + if not os.path.exists(dirname): + os.makedirs(dirname) - def config_parser(self, testcase_cfg, parameters): + @staticmethod + def config_parser(testcase_cfg, parameters): test_cfg = testcase_cfg['test_config'] stack_cfg = testcase_cfg['stack_config'] # TO-DO add cli parameters to stack_config. - return test_cfg, stack_cfg
\ No newline at end of file + return test_cfg, stack_cfg diff --git a/utils/tools/bottlenecks_image_modify b/utils/tools/bottlenecks_image_modify new file mode 100755 index 00000000..f232fe73 --- /dev/null +++ b/utils/tools/bottlenecks_image_modify @@ -0,0 +1,172 @@ +#!/bin/bash + +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +# bottlenecks: this file is copied from yardstick and slightly modified +############################################################################## + +# bottlenecks-img-modify - download and modify a Ubuntu cloud image +# +# The actual customization is done by a script passed with an absolute path as +# the only single argument. The command needs to be invoked as sudo +# +# Example invocation: +# bottlenecks-img-modify /home/opnfv/bottlenecks/utils/tools/ubuntu-server-cloudimg-modify.sh +# +# Warning: the script will create files by default in: +# /tmp/workspace/bottlenecks +# the files will be owned by root! +# +# TODO: image resize is needed if the base image is too small +# + +set -ex + +die() { + echo "error: $1" >&2 + exit 1 +} + +test $# -eq 1 -o $# -eq 2 || die "no image specific script as argument" +test $(id -u) -eq 0 || die "should invoke using sudo" + +cmd=$1 +RELEASE=$2 +test -x $cmd +mountdir="/mnt/bottlenecks" +workspace=${WORKSPACE:-"/tmp/workspace/bottlenecks"} +host=${HOST:-"cloud-images.ubuntu.com"} +release=${RELEASE:-"xenial"} +image_path="${release}/current/${release}-server-cloudimg-amd64-disk1.img" +image_url=${IMAGE_URL:-"https://${host}/${image_path}"} +md5sums_path="${release}/current/MD5SUMS" +md5sums_url=${MD5SUMS_URL:-"https://${host}/${md5sums_path}"} + +imgfile="${workspace}/bottlenecks-image.img" +raw_imgfile="${workspace}/bottlenecks-${release}-server.raw" +filename=$(basename $image_url) + +# download and checksum base image, conditionally if local copy is outdated +download() { + test -d $workspace || mkdir -p $workspace + cd $workspace + rm -f MD5SUMS # always download the checksum file to a detect stale image + wget $md5sums_url + test -e $filename || wget -nc --progress=dot:giga $image_url + grep $filename MD5SUMS | md5sum -c || + if [ $? -ne 0 ]; then + rm $filename + wget -nc --progress=dot:giga $image_url + grep $filename MD5SUMS | md5sum -c + fi + + for i in $(seq 0 9); do + [ -a /dev/loop$i ] || mknod -m 660 /dev/loop$i b 7 $i + done + + qemu-img convert $filename $raw_imgfile + cd - +} + +# mount image +setup() { + # qemu-img resize $raw_imgfile +5GB + mkdir -p $mountdir + + loopdevice=$(kpartx -l $raw_imgfile | head -1 | cut -f1 -d ' ') + + kpartx -av $raw_imgfile + # for trouble shooting + sleep 2 + dmsetup ls + fdisk -l /dev/${loopdevice:0:5} || true + mount /dev/mapper/$loopdevice $mountdir + mount -t proc none $mountdir/proc + + cp $cmd $mountdir/$(basename $cmd) +} + +# modify image running a script using in a chrooted environment +modify() { + # resolv.conf does not exist in base image, pass nameserver value from host + nameserver_ip=$(grep -m 1 '^nameserver' \ + /etc/resolv.conf | awk '{ print $2 '}) + + # prevent init scripts from running during install + echo $'#!/bin/sh\nexit 101' >$mountdir/usr/sbin/policy-rc.d + chmod a+x $mountdir/usr/sbin/policy-rc.d + + chroot $mountdir /$(basename $cmd) $nameserver_ip + + rm -rf $mountdir/usr/sbin/policy-rc.d + + umount -f $mountdir/proc + umount $mountdir + + qemu-img convert -c -o compat=0.10 -O qcow2 $raw_imgfile $imgfile + + if dmsetup table | grep $loopdevice; then + dmsetup clear $loopdevice || true + fi +} + +# cleanup (umount) the image +cleanup() { + # designed to be idempotent + mount | grep $mountdir/proc && umount $mountdir/proc + mount | grep $mountdir && umount $mountdir + mount | grep "/mnt/vivid" && umount "/mnt/vivid" + + if [ -f $raw_imgfile ]; then + #kpartx -dv $raw_imgfile sometimes failed, we should checked it agein. + #if [ -z "$(kpartx -l $raw_imgfile | grep 'loop deleted')" ]; then + # kpartx -dv $raw_imgfile + #fi + kpartx -dv $raw_imgfile || true + fi + + rm -f $raw_imgfile + rm -rf $mountdir +} + +exitcode="" +error_trap() +{ + local rc=$? + + set +e + + if [ -z "$exitcode" ]; then + exitcode=$rc + fi + + dmesg -T | tail -50 + + cleanup + + echo "Image build failed with $exitcode" + + exit $exitcode +} + +main() { + cleanup + + trap "error_trap" EXIT SIGTERM + + download + setup + modify + + trap - EXIT SIGTERM + cleanup + + echo "the modified image is found here: $imgfile" +} + +main diff --git a/utils/tools/ubuntu-server-clouding-modify.sh b/utils/tools/ubuntu-server-clouding-modify.sh new file mode 100755 index 00000000..505825a1 --- /dev/null +++ b/utils/tools/ubuntu-server-clouding-modify.sh @@ -0,0 +1,43 @@ +#!/bin/bash +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +# bottlenecks: this file is copied from yardstick and slightly modified +############################################################################## + +# installs required packages +# must be run from inside the image (either chrooted or running) + +set -ex + +if [ $# -eq 1 ]; then + nameserver_ip=$1 + + # /etc/resolv.conf is a symbolic link to /run, restore at end + rm /etc/resolv.conf + echo "nameserver $nameserver_ip" > /etc/resolv.conf + echo "nameserver 8.8.8.8" >> /etc/resolv.conf + echo "nameserver 8.8.4.4" >> /etc/resolv.conf +fi + +# Add hostname to /etc/hosts. +# Allow console access via pwd +cat <<EOF >/etc/cloud/cloud.cfg.d/10_etc_hosts.cfg +manage_etc_hosts: True +password: RANDOM +chpasswd: { expire: False } +ssh_pwauth: True +EOF + +#install some software +apt-get update +apt-get install -y \ + netperf \ + sysstat + +# restore symlink +ln -sf /run/resolvconf/resolv.conf /etc/resolv.conf |