diff options
26 files changed, 3538 insertions, 265 deletions
diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 00000000..fe258c6c --- /dev/null +++ b/.coveragerc @@ -0,0 +1,3 @@ +[report] +exclude_lines = + if __name__ == .__main__.: diff --git a/docker/Dockerfile b/docker/Dockerfile index 674122cb..d7fb550e 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -31,7 +31,6 @@ LABEL version="0.1" description="OPNFV Functest Docker container" # Environment variables ARG BRANCH=master ARG TEMPEST_TAG=12.2.0 -ARG RALLY_TAG=0.7.0 ARG ODL_TAG=release/beryllium-sr4 ARG OPENSTACK_TAG=stable/mitaka ARG KINGBIRD_TAG=0.2.2 @@ -107,7 +106,7 @@ RUN git clone --depth 1 https://gerrit.opnfv.org/gerrit/releng ${REPOS_DIR}/rele # OpenStack repositories RUN git clone --depth 1 -b $OPENSTACK_TAG https://github.com/openstack/networking-bgpvpn ${REPOS_DIR}/bgpvpn #RUN git clone --depth 1 -b $KINGBIRD_TAG https://github.com/openstack/kingbird.git ${REPOS_DIR}/kingbird -RUN git clone --depth 1 -b $RALLY_TAG https://github.com/openstack/rally.git ${REPOS_DIR}/rally +RUN git clone https://github.com/openstack/rally.git ${REPOS_DIR}/rally RUN git clone --depth 1 -b $TEMPEST_TAG https://github.com/openstack/tempest.git ${REPOS_DIR}/tempest # other repositories diff --git a/functest/ci/check_os.sh b/functest/ci/check_os.sh index 053796d9..e2471026 100755 --- a/functest/ci/check_os.sh +++ b/functest/ci/check_os.sh @@ -24,7 +24,7 @@ fi echo "Checking OpenStack endpoints:" -publicURL=$OS_AUTH_URL +publicURL=$(openstack catalog show identity |awk '/public/ {print $4}') publicIP=$(echo $publicURL|sed 's/^.*http\:\/\///'|sed 's/.[^:]*$//') publicPort=$(echo $publicURL|sed 's/^.*://'|sed 's/\/.*$//') echo ">>Verifying connectivity to the public endpoint $publicIP:$publicPort..." diff --git a/functest/ci/config_functest.yaml b/functest/ci/config_functest.yaml index aa66b0dd..25be1724 100755 --- a/functest/ci/config_functest.yaml +++ b/functest/ci/config_functest.yaml @@ -88,6 +88,7 @@ onos_sfc: image_file_name: firewall_block_image.img tempest: + deployment_name: opnfv-tempest identity: tenant_name: tempest tenant_description: Tenant for Tempest test suite diff --git a/functest/ci/prepare_env.py b/functest/ci/prepare_env.py index 3df3a0e0..74c751af 100755 --- a/functest/ci/prepare_env.py +++ b/functest/ci/prepare_env.py @@ -29,12 +29,6 @@ import functest.utils.openstack_utils as os_utils from functest.utils.constants import CONST actions = ['start', 'check'] -parser = argparse.ArgumentParser() -parser.add_argument("action", help="Possible actions are: " - "'{d[0]}|{d[1]}' ".format(d=actions)) -parser.add_argument("-d", "--debug", help="Debug mode", action="store_true") -args = parser.parse_args() - """ logging configuration """ logger = ft_logger.Logger("prepare_env").getLogger() @@ -48,6 +42,19 @@ with open(CONFIG_PATCH_PATH) as f: functest_patch_yaml = yaml.safe_load(f) +class PrepareEnvParser(): + + def __init__(self): + self.parser = argparse.ArgumentParser() + self.parser.add_argument("action", help="Possible actions are: " + "'{d[0]}|{d[1]}' ".format(d=actions)) + self.parser.add_argument("-d", "--debug", help="Debug mode", + action="store_true") + + def parse_args(self, argv=[]): + return vars(self.parser.parse_args(argv)) + + def print_separator(): logger.info("==============================================") @@ -227,32 +234,36 @@ def install_rally(): rally_conf = os_utils.get_credentials_for_rally() with open('rally_conf.json', 'w') as fp: json.dump(rally_conf, fp) - cmd = "rally deployment create --file=rally_conf.json --name=" - cmd += CONST.rally_deployment_name - ft_utils.execute_command(cmd, - error_msg="Problem creating Rally deployment") - - logger.info("Installing tempest from existing repo...") - cmd = ("rally verify install --source " + - CONST.dir_repo_tempest + - " --system-wide") + cmd = ("rally deployment create " + "--file=rally_conf.json --name={}" + .format(CONST.rally_deployment_name)) ft_utils.execute_command(cmd, - error_msg="Problem installing Tempest.") + error_msg=("Problem while creating " + "Rally deployment")) cmd = "rally deployment check" ft_utils.execute_command(cmd, error_msg=("OpenStack not responding or " "faulty Rally deployment.")) - cmd = "rally show images" + cmd = "rally deployment list" ft_utils.execute_command(cmd, error_msg=("Problem while listing " - "OpenStack images.")) + "Rally deployment.")) - cmd = "rally show flavors" + cmd = "rally plugin list | head -5" ft_utils.execute_command(cmd, error_msg=("Problem while showing " - "OpenStack flavors.")) + "Rally plugins.")) + + +def install_tempest(): + logger.info("Installing tempest from existing repo...") + cmd = ("rally verify create-verifier --source {0} " + "--name {1} --type tempest" + .format(CONST.dir_repo_tempest, CONST.tempest_deployment_name)) + ft_utils.execute_command(cmd, + error_msg="Problem while installing Tempest.") def check_environment(): @@ -267,15 +278,15 @@ def check_environment(): logger.error(msg_not_active) sys.exit(1) - logger.info("Functest environment installed.") + logger.info("Functest environment is installed.") -def main(): - if not (args.action in actions): +def main(**kwargs): + if not (kwargs['action'] in actions): logger.error('Argument not valid.') sys.exit() - if args.action == "start": + if kwargs['action'] == "start": logger.info("######### Preparing Functest environment #########\n") check_env_variables() create_directories() @@ -283,17 +294,20 @@ def main(): patch_config_file() verify_deployment() install_rally() + install_tempest() with open(CONST.env_active, "w") as env_file: env_file.write("1") check_environment() - if args.action == "check": + if kwargs['action'] == "check": check_environment() exit(0) if __name__ == '__main__': - main() + parser = PrepareEnvParser() + args = parser.parse_args(sys.argv[1:]) + main(**args) diff --git a/functest/ci/run_tests.py b/functest/ci/run_tests.py index 7aac9d2c..10f1ac9a 100755 --- a/functest/ci/run_tests.py +++ b/functest/ci/run_tests.py @@ -26,17 +26,6 @@ import functest.utils.openstack_snapshot as os_snapshot import functest.utils.openstack_utils as os_utils from functest.utils.constants import CONST -parser = argparse.ArgumentParser() -parser.add_argument("-t", "--test", dest="test", action='store', - help="Test case or tier (group of tests) to be executed. " - "It will run all the test if not specified.") -parser.add_argument("-n", "--noclean", help="Do not clean OpenStack resources" - " after running each test (default=false).", - action="store_true") -parser.add_argument("-r", "--report", help="Push results to database " - "(default=false).", action="store_true") -args = parser.parse_args() - """ logging configuration """ logger = ft_logger.Logger("run_tests").getLogger() @@ -49,6 +38,26 @@ EXEC_SCRIPT = ("%s/functest/ci/exec_test.sh" % CONST.dir_repo_functest) # this variable will change to -1 +class RunTestsParser(): + + def __init__(self): + self.parser = argparse.ArgumentParser() + self.parser.add_argument("-t", "--test", dest="test", action='store', + help="Test case or tier (group of tests) " + "to be executed. It will run all the test " + "if not specified.") + self.parser.add_argument("-n", "--noclean", help="Do not clean " + "OpenStack resources after running each " + "test (default=false).", + action="store_true") + self.parser.add_argument("-r", "--report", help="Push results to " + "database (default=false).", + action="store_true") + + def parse_args(self, argv=[]): + return vars(self.parser.parse_args(argv)) + + class GlobalVariables: EXECUTED_TEST_CASES = [] OVERALL_RESULT = 0 @@ -118,7 +127,7 @@ def get_run_dict_if_defined(testname): return None -def run_test(test, tier_name): +def run_test(test, tier_name, testcases=None): result_str = "PASS" start = datetime.datetime.now() test_name = test.get_name() @@ -170,18 +179,19 @@ def run_test(test, tier_name): if result != 0: logger.error("The test case '%s' failed. " % test_name) - OVERALL_RESULT = -1 + GlobalVariables.OVERALL_RESULT = -1 result_str = "FAIL" if test.is_blocking(): - if not args.test or args.test == "all": + if not testcases or testcases == "all": logger.info("This test case is blocking. Aborting overall " "execution.") # if it is a single test we don't print the whole results table update_test_info(test_name, result_str, duration_str) generate_report.main(GlobalVariables.EXECUTED_TEST_CASES) - logger.info("Execution exit value: %s" % OVERALL_RESULT) - sys.exit(OVERALL_RESULT) + logger.info("Execution exit value: %s" % + GlobalVariables.OVERALL_RESULT) + sys.exit(GlobalVariables.OVERALL_RESULT) update_test_info(test_name, result_str, duration_str) @@ -222,7 +232,7 @@ def run_all(tiers): generate_report.main(GlobalVariables.EXECUTED_TEST_CASES) -def main(): +def main(**kwargs): CI_INSTALLER_TYPE = CONST.INSTALLER_TYPE CI_SCENARIO = CONST.DEPLOY_SCENARIO @@ -230,27 +240,29 @@ def main(): file = CONST.functest_testcases_yaml _tiers = tb.TierBuilder(CI_INSTALLER_TYPE, CI_SCENARIO, file) - if args.noclean: + if kwargs['noclean']: GlobalVariables.CLEAN_FLAG = False - if args.report: + if kwargs['report']: GlobalVariables.REPORT_FLAG = True - if args.test: + if kwargs['test']: source_rc_file() - if _tiers.get_tier(args.test): - run_tier(_tiers.get_tier(args.test)) + if _tiers.get_tier(kwargs['test']): + run_tier(_tiers.get_tier(kwargs['test'])) - elif _tiers.get_test(args.test): - run_test(_tiers.get_test(args.test), _tiers.get_tier(args.test)) + elif _tiers.get_test(kwargs['test']): + run_test(_tiers.get_test(kwargs['test']), + _tiers.get_tier(kwargs['test']), + kwargs['test']) - elif args.test == "all": + elif kwargs['test'] == "all": run_all(_tiers) else: logger.error("Unknown test case or tier '%s', or not supported by " "the given scenario '%s'." - % (args.test, CI_SCENARIO)) + % (kwargs['test'], CI_SCENARIO)) logger.debug("Available tiers are:\n\n%s" % _tiers) else: @@ -261,4 +273,6 @@ def main(): if __name__ == '__main__': - main() + parser = RunTestsParser() + args = parser.parse_args(sys.argv[1:]) + main(**args) diff --git a/functest/ci/testcases.yaml b/functest/ci/testcases.yaml index 4096bb79..ede08285 100755 --- a/functest/ci/testcases.yaml +++ b/functest/ci/testcases.yaml @@ -65,7 +65,7 @@ tiers: Tempest automatically and depends on the parameters of the OpenStack deplopyment. dependencies: - installer: '' + installer: '^((?!netvirt).)*$' scenario: '' run: module: 'functest.opnfv_tests.openstack.tempest.tempest' @@ -121,7 +121,7 @@ tiers: the cloud's private network. dependencies: - installer: '' + installer: '^((?!netvirt).)*$' scenario: '' run: module: 'functest.opnfv_tests.openstack.snaps.connection_check' @@ -139,7 +139,7 @@ tiers: the cloud's private network. dependencies: - installer: '' + installer: '^((?!netvirt).)*$' scenario: '' run: module: 'functest.opnfv_tests.openstack.snaps.api_check' @@ -159,7 +159,7 @@ tiers: the cloud's private network. dependencies: - installer: '' + installer: '^((?!netvirt).)*$' scenario: '' run: module: 'functest.opnfv_tests.openstack.snaps.smoke' @@ -200,7 +200,7 @@ tiers: description: >- Test suite from SDNVPN project. dependencies: - installer: '(fuel)|(apex)' + installer: '(fuel)|(apex)|(netvirt)' scenario: 'bgpvpn' run: module: 'functest.opnfv_tests.features.sdnvpn' @@ -309,7 +309,7 @@ tiers: Tempest automatically and depends on the parameters of the OpenStack deplopyment. dependencies: - installer: '' + installer: '^((?!netvirt).)*$' scenario: '' run: module: 'functest.opnfv_tests.openstack.tempest.tempest' @@ -323,7 +323,7 @@ tiers: This test case runs the full suite of scenarios of the OpenStack Rally suite using several threads and iterations. dependencies: - installer: '' + installer: '^((?!netvirt).)*$' scenario: '' - diff --git a/functest/opnfv_tests/features/copper.py b/functest/opnfv_tests/features/copper.py index 8d5393c9..204fa337 100755 --- a/functest/opnfv_tests/features/copper.py +++ b/functest/opnfv_tests/features/copper.py @@ -22,4 +22,4 @@ class Copper(base.FeatureBase): super(Copper, self).__init__(project='copper', case='copper-notification', repo='dir_repo_copper') - self.cmd = "%s/tests/run.sh %s/tests" % (self.repo, self.repo) + self.cmd = 'cd %s/tests && ./run.sh' % self.repo diff --git a/functest/opnfv_tests/openstack/healthcheck/healthcheck.sh b/functest/opnfv_tests/openstack/healthcheck/healthcheck.sh index e27cf4b4..57aa0c70 100755 --- a/functest/opnfv_tests/openstack/healthcheck/healthcheck.sh +++ b/functest/opnfv_tests/openstack/healthcheck/healthcheck.sh @@ -228,10 +228,11 @@ sleep ${wait_time} # Check if flavor exists -if [[ -z $(nova flavor-list|grep $flavor) ]]; then +if [[ -z $(openstack flavor list -f value -c Name | fgrep -x $flavor) ]]; then # if given flavor doesn't exist, we create one debug "Flavor $flavor doesn't exist. Creating a new flavor." - nova flavor-create --is-public false ${flavor} auto 512 1 1 --is-public True + openstack flavor create ${flavor} --id auto --ram 512 --disk 1 --vcpus 1 + openstack flavor set ${flavor} --property hw:mem_page_size=any fi debug "Using flavor $flavor to boot the instances." diff --git a/functest/opnfv_tests/openstack/rally/run_rally-cert.py b/functest/opnfv_tests/openstack/rally/run_rally-cert.py index ec22b52d..b02fd427 100755 --- a/functest/opnfv_tests/openstack/rally/run_rally-cert.py +++ b/functest/opnfv_tests/openstack/rally/run_rally-cert.py @@ -1,19 +1,12 @@ -#!/usr/bin/env python +#!/usr/bin/python # -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com -# morgan.richomme@orange.com -# All rights reserved. This program and the accompanying materials +# Copyright (c) 2015 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 # -# 0.1 (05/2015) initial commit -# 0.2 (28/09/2015) extract Tempest, format json result, add ceilometer suite -# 0.3 (19/10/2015) remove Tempest from run_rally -# and push result into test DB +# http://www.apache.org/licenses/LICENSE-2.0 # -""" tests configuration """ import argparse import json @@ -391,10 +384,11 @@ def run_task(test_name): logger.info('No tests for scenario "{}"'.format(test_name)) return - cmd_line = ("rally task start --abort-on-sla-failure " + - "--task {} ".format(task_file) + - "--task-args \"{}\" ".format(build_task_args(test_name))) - logger.debug('running command line : {}'.format(cmd_line)) + cmd_line = ("rally task start --abort-on-sla-failure " + "--task {0} " + "--task-args \"{1}\"" + .format(task_file, build_task_args(test_name))) + logger.debug('running command line: {}'.format(cmd_line)) p = subprocess.Popen(cmd_line, stdout=subprocess.PIPE, stderr=RALLY_STDERR, shell=True) @@ -404,10 +398,11 @@ def run_task(test_name): if task_id is None: logger.error('Failed to retrieve task_id, validating task...') - cmd_line = ("rally task validate " + - "--task {} ".format(task_file) + - "--task-args \"{}\" ".format(build_task_args(test_name))) - logger.debug('running command line : {}'.format(cmd_line)) + cmd_line = ("rally task validate " + "--task {0} " + "--task-args \"{1}\"" + .format(task_file, build_task_args(test_name))) + logger.debug('running command line: {}'.format(cmd_line)) p = subprocess.Popen(cmd_line, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) output = get_cmd_output(p) @@ -425,12 +420,12 @@ def run_task(test_name): cmd_line = "rally task report {} --out {}".format(task_id, report_html_dir) - logger.debug('running command line : {}'.format(cmd_line)) + logger.debug('running command line: {}'.format(cmd_line)) os.popen(cmd_line) # get and save rally operation JSON result cmd_line = "rally task results %s" % task_id - logger.debug('running command line : {}'.format(cmd_line)) + logger.debug('running command line: {}'.format(cmd_line)) cmd = os.popen(cmd_line) json_results = cmd.read() report_json_name = 'opnfv-{}.json'.format(test_name) diff --git a/functest/opnfv_tests/openstack/tempest/conf_utils.py b/functest/opnfv_tests/openstack/tempest/conf_utils.py index 5295ff37..67b52796 100644 --- a/functest/opnfv_tests/openstack/tempest/conf_utils.py +++ b/functest/opnfv_tests/openstack/tempest/conf_utils.py @@ -14,8 +14,10 @@ import shutil import opnfv.utils.constants as releng_constants -import functest.utils.functest_utils as ft_utils from functest.utils.constants import CONST +import functest.utils.functest_utils as ft_utils +import functest.utils.openstack_utils as os_utils + IMAGE_ID_ALT = None FLAVOR_ID_ALT = None @@ -42,16 +44,17 @@ def configure_tempest(logger, deployment_dir, IMAGE_ID=None, FLAVOR_ID=None): """ Add/update needed parameters into tempest.conf file generated by Rally """ - tempest_conf_file = deployment_dir + "/tempest.conf" + tempest_conf_file = os.path.join(deployment_dir, "tempest.conf") if os.path.isfile(tempest_conf_file): - logger.debug("Deleting old tempest.conf file...") - os.remove(tempest_conf_file) - - logger.debug("Generating new tempest.conf file...") - cmd = "rally verify genconfig" + logger.debug("Verifier is already configured.") + logger.debug("Reconfiguring the current verifier...") + cmd = "rally verify configure-verifier --reconfigure" + else: + logger.info("Configuring the verifier...") + cmd = "rally verify configure-verifier" ft_utils.execute_command(cmd) - logger.debug("Finding tempest.conf file...") + logger.debug("Looking for tempest.conf file...") if not os.path.isfile(tempest_conf_file): logger.error("Tempest configuration file %s NOT found." % tempest_conf_file) @@ -99,8 +102,8 @@ def configure_tempest(logger, deployment_dir, IMAGE_ID=None, FLAVOR_ID=None): config.write(config_file) # Copy tempest.conf to /home/opnfv/functest/results/tempest/ - shutil.copyfile( - tempest_conf_file, TEMPEST_RESULTS_DIR + '/tempest.conf') + shutil.copyfile(tempest_conf_file, + os.path.join(TEMPEST_RESULTS_DIR, 'tempest.conf')) return releng_constants.EXIT_OK @@ -113,7 +116,7 @@ def configure_tempest_multisite(logger, deployment_dir): configure_tempest(logger, deployment_dir) logger.debug("Finding tempest.conf file...") - tempest_conf_old = os.path.join(deployment_dir, '/tempest.conf') + tempest_conf_old = os.path.join(deployment_dir, 'tempest.conf') if not os.path.isfile(tempest_conf_old): logger.error("Tempest configuration file %s NOT found." % tempest_conf_old) @@ -121,7 +124,7 @@ def configure_tempest_multisite(logger, deployment_dir): # Copy tempest.conf to /home/opnfv/functest/results/tempest/ cur_path = os.path.split(os.path.realpath(__file__))[0] - tempest_conf_file = os.path.join(cur_path, '/tempest_multisite.conf') + tempest_conf_file = os.path.join(cur_path, 'tempest_multisite.conf') shutil.copyfile(tempest_conf_old, tempest_conf_file) logger.debug("Updating selected tempest.conf parameters...") @@ -129,9 +132,11 @@ def configure_tempest_multisite(logger, deployment_dir): config.read(tempest_conf_file) config.set('service_available', 'kingbird', 'true') - cmd = ("openstack endpoint show kingbird | grep publicurl |" - "awk '{print $4}' | awk -F '/' '{print $4}'") - kingbird_api_version = os.popen(cmd).read() + # cmd = ("openstack endpoint show kingbird | grep publicurl |" + # "awk '{print $4}' | awk -F '/' '{print $4}'") + # kingbird_api_version = os.popen(cmd).read() + kingbird_api_version = os_utils.get_endpoint(service_type='kingbird') + if CI_INSTALLER_TYPE == 'fuel': # For MOS based setup, the service is accessible # via bind host @@ -172,9 +177,10 @@ def configure_tempest_multisite(logger, deployment_dir): bind_details)[0] kingbird_endpoint_url = "http://%s:%s/" % (bind_host, bind_port) else: - cmd = "openstack endpoint show kingbird | grep publicurl |\ - awk '{print $4}' | awk -F '/' '{print $3}'" - kingbird_endpoint_url = os.popen(cmd).read() + # cmd = "openstack endpoint show kingbird | grep publicurl |\ + # awk '{print $4}' | awk -F '/' '{print $3}'" + # kingbird_endpoint_url = os.popen(cmd).read() + kingbird_endpoint_url = os_utils.get_endpoint(service_type='kingbird') try: config.add_section("kingbird") diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py index 20b1ebb4..0014b718 100644 --- a/functest/opnfv_tests/openstack/tempest/tempest.py +++ b/functest/opnfv_tests/openstack/tempest/tempest.py @@ -16,8 +16,8 @@ import time import yaml -import conf_utils -import functest.core.testcase_base as testcase_base +from functest.core import testcase_base +from functest.opnfv_tests.openstack.tempest import conf_utils from functest.utils.constants import CONST import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils @@ -35,12 +35,33 @@ class TempestCommon(testcase_base.TestcaseBase): self.OPTION = "" self.FLAVOR_ID = None self.IMAGE_ID = None - self.DEPLOYMENT_DIR = self.get_deployment_dir() + self.VERIFIER_ID = self.get_verifier_id() + self.VERIFIER_REPO_DIR = self.get_verifier_repo_dir() + self.DEPLOYMENT_ID = self.get_verifier_deployment_id() + self.DEPLOYMENT_DIR = self.get_verifier_deployment_dir() + self.VERIFICATION_ID = None @staticmethod - def get_deployment_dir(): + def get_verifier_id(): """ - Returns current Rally deployment directory + Returns verifer id for current Tempest + """ + cmd = ("rally verify list-verifiers | awk '/" + + CONST.tempest_deployment_name + + "/ {print $2}'") + p = subprocess.Popen(cmd, shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + deployment_uuid = p.stdout.readline().rstrip() + if deployment_uuid == "": + logger.error("Tempest verifier not found.") + raise Exception('Error with command:%s' % cmd) + return deployment_uuid + + @staticmethod + def get_verifier_deployment_id(): + """ + Returns deployment id for active Rally deployment """ cmd = ("rally deployment list | awk '/" + CONST.rally_deployment_name + @@ -51,9 +72,35 @@ class TempestCommon(testcase_base.TestcaseBase): deployment_uuid = p.stdout.readline().rstrip() if deployment_uuid == "": logger.error("Rally deployment not found.") - exit(-1) + raise Exception('Error with command:%s' % cmd) + return deployment_uuid + + def get_verifier_repo_dir(self): + """ + Returns installed verfier repo directory for Tempest + """ + if not self.VERIFIER_ID: + self.VERIFIER_ID = self.get_verifier_id() + + return os.path.join(CONST.dir_rally_inst, + 'verification', + 'verifier-{}'.format(self.VERIFIER_ID), + 'repo') + + def get_verifier_deployment_dir(self): + """ + Returns Rally deployment directory for current verifier + """ + if not self.VERIFIER_ID: + self.VERIFIER_ID = self.get_verifier_id() + + if not self.DEPLOYMENT_ID: + self.DEPLOYMENT_ID = self.get_verifier_deployment_id() + return os.path.join(CONST.dir_rally_inst, - "tempest/for-deployment-" + deployment_uuid) + 'verification', + 'verifier-{}'.format(self.VERIFIER_ID), + 'for-deployment-{}'.format(self.DEPLOYMENT_ID)) @staticmethod def read_file(filename): @@ -81,12 +128,11 @@ class TempestCommon(testcase_base.TestcaseBase): CONST.tempest_identity_user_name) logger.debug("Creating private network for Tempest suite") - network_dic = \ - os_utils.create_shared_network_full( - CONST.tempest_private_net_name, - CONST.tempest_private_subnet_name, - CONST.tempest_router_name, - CONST.tempest_private_subnet_cidr) + network_dic = os_utils.create_shared_network_full( + CONST.tempest_private_net_name, + CONST.tempest_private_subnet_name, + CONST.tempest_router_name, + CONST.tempest_private_subnet_cidr) if not network_dic: return testcase_base.TestcaseBase.EX_RUN_ERROR @@ -112,7 +158,7 @@ class TempestCommon(testcase_base.TestcaseBase): return testcase_base.TestcaseBase.EX_OK - def generate_test_list(self, DEPLOYMENT_DIR): + def generate_test_list(self, verifier_repo_dir): logger.debug("Generating test case list...") if self.MODE == 'defcore': shutil.copyfile( @@ -134,8 +180,11 @@ class TempestCommon(testcase_base.TestcaseBase): testr_mode = "" else: testr_mode = 'tempest.api.' + self.MODE - cmd = ("cd " + DEPLOYMENT_DIR + ";" + "testr list-tests " + - testr_mode + ">" + conf_utils.TEMPEST_RAW_LIST + ";cd") + cmd = ("cd {0};" + "testr list-tests {1} > {2};" + "cd -;".format(verifier_repo_dir, + testr_mode, + conf_utils.TEMPEST_RAW_LIST)) ft_utils.execute_command(cmd) return testcase_base.TestcaseBase.EX_OK @@ -163,7 +212,7 @@ class TempestCommon(testcase_base.TestcaseBase): for test in tests: black_tests.append(test) break - except: + except Exception: black_tests = [] logger.debug("Tempest blacklist file does not exist.") @@ -176,36 +225,15 @@ class TempestCommon(testcase_base.TestcaseBase): result_file.close() return testcase_base.TestcaseBase.EX_OK - def run(self): - - self.start_time = time.time() - - if not os.path.exists(conf_utils.TEMPEST_RESULTS_DIR): - os.makedirs(conf_utils.TEMPEST_RESULTS_DIR) - - # Pre-configuration - res = self.create_tempest_resources() - if res != testcase_base.TestcaseBase.EX_OK: - return res - - res = conf_utils.configure_tempest(logger, - self.DEPLOYMENT_DIR, - self.IMAGE_ID, - self.FLAVOR_ID) - if res != testcase_base.TestcaseBase.EX_OK: - return res - - res = self.generate_test_list(self.DEPLOYMENT_DIR) - if res != testcase_base.TestcaseBase.EX_OK: - return res - - res = self.apply_tempest_blacklist() - if res != testcase_base.TestcaseBase.EX_OK: - return res + def _parse_verification_id(line): + first_pos = line.index("UUID=") + len("UUID=") + last_pos = line.index(") for deployment") + return line[first_pos:last_pos] - self.OPTION += (" --tests-file %s " % conf_utils.TEMPEST_LIST) + def run_verifier_tests(self): + self.OPTION += (" --load-list {}".format(conf_utils.TEMPEST_LIST)) - cmd_line = "rally verify start " + self.OPTION + " --system-wide" + cmd_line = "rally verify start " + self.OPTION logger.info("Starting Tempest test suite: '%s'." % cmd_line) header = ("Tempest environment:\n" @@ -215,14 +243,15 @@ class TempestCommon(testcase_base.TestcaseBase): CONST.NODE_NAME, time.strftime("%a %b %d %H:%M:%S %Z %Y"))) - f_stdout = open(conf_utils.TEMPEST_RESULTS_DIR + "/tempest.log", 'w+') + f_stdout = open( + os.path.join(conf_utils.TEMPEST_RESULTS_DIR, "tempest.log"), 'w+') f_stderr = open( - conf_utils.TEMPEST_RESULTS_DIR + "/tempest-error.log", 'w+') - f_env = open(conf_utils.TEMPEST_RESULTS_DIR + "/environment.log", 'w+') + os.path.join(conf_utils.TEMPEST_RESULTS_DIR, + "tempest-error.log"), 'w+') + f_env = open(os.path.join(conf_utils.TEMPEST_RESULTS_DIR, + "environment.log"), 'w+') f_env.write(header) - # subprocess.call(cmd_line, shell=True, - # stdout=f_stdout, stderr=f_stderr) p = subprocess.Popen( cmd_line, shell=True, stdout=subprocess.PIPE, @@ -233,6 +262,12 @@ class TempestCommon(testcase_base.TestcaseBase): for line in iter(p.stdout.readline, b''): if re.search("\} tempest\.", line): logger.info(line.replace('\n', '')) + elif re.search('Starting verification', line): + logger.info(line.replace('\n', '')) + first_pos = line.index("UUID=") + len("UUID=") + last_pos = line.index(") for deployment") + self.VERIFICATION_ID = line[first_pos:last_pos] + logger.debug('Verication UUID: %s' % self.VERIFICATION_ID) f_stdout.write(line) p.wait() @@ -240,37 +275,33 @@ class TempestCommon(testcase_base.TestcaseBase): f_stderr.close() f_env.close() - cmd_line = "rally verify show" - output = "" + def parse_verifier_result(self): + if not self.VERIFICATION_ID: + raise Exception('Verification UUID not found') + + cmd_line = "rally verify show --uuid {}".format(self.VERIFICATION_ID) + logger.info("Showing result for a verification: '%s'." % cmd_line) p = subprocess.Popen(cmd_line, shell=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + stderr=subprocess.STDOUT) for line in p.stdout: - if re.search("Tests\:", line): + new_line = line.replace(' ', '').split('|') + if 'Tests' in new_line: break - output += line - logger.info(output) - - cmd_line = "rally verify list" - cmd = os.popen(cmd_line) - output = (((cmd.read()).splitlines()[-2]).replace(" ", "")).split("|") - # Format: - # | UUID | Deployment UUID | smoke | tests | failures | Created at | - # Duration | Status | - num_tests = output[4] - num_failures = output[5] - duration = output[7] - # Compute duration (lets assume it does not take more than 60 min) - dur_min = int(duration.split(':')[1]) - dur_sec_float = float(duration.split(':')[2]) - dur_sec_int = int(round(dur_sec_float, 0)) - dur_sec_int = dur_sec_int + 60 * dur_min + + logger.info(line) + if 'Testscount' in new_line: + num_tests = new_line[2] + elif 'Success' in new_line: + num_success = new_line[2] + elif 'Skipped' in new_line: + num_skipped = new_line[2] try: - diff = (int(num_tests) - int(num_failures)) - success_rate = 100 * diff / int(num_tests) - except: + num_executed = int(num_tests) - int(num_skipped) + success_rate = 100 * int(num_success) / int(num_executed) + except Exception: success_rate = 0 self.criteria = ft_utils.check_success_rate( @@ -278,6 +309,36 @@ class TempestCommon(testcase_base.TestcaseBase): logger.info("Tempest %s success_rate is %s%%, is marked as %s" % (self.case_name, success_rate, self.criteria)) + def run(self): + + self.start_time = time.time() + + if not os.path.exists(conf_utils.TEMPEST_RESULTS_DIR): + os.makedirs(conf_utils.TEMPEST_RESULTS_DIR) + + # Pre-configuration + res = self.create_tempest_resources() + if res != testcase_base.TestcaseBase.EX_OK: + return res + + res = conf_utils.configure_tempest(logger, + self.DEPLOYMENT_DIR, + self.IMAGE_ID, + self.FLAVOR_ID) + if res != testcase_base.TestcaseBase.EX_OK: + return res + + res = self.generate_test_list(self.VERIFIER_REPO_DIR) + if res != testcase_base.TestcaseBase.EX_OK: + return res + + res = self.apply_tempest_blacklist() + if res != testcase_base.TestcaseBase.EX_OK: + return res + + self.run_verifier_tests() + self.parse_verifier_result() + self.stop_time = time.time() if self.criteria == "PASS": @@ -292,7 +353,7 @@ class TempestSmokeSerial(TempestCommon): TempestCommon.__init__(self) self.case_name = "tempest_smoke_serial" self.MODE = "smoke" - self.OPTION = "--concur 1" + self.OPTION = "--concurrency 1" class TempestSmokeParallel(TempestCommon): @@ -318,7 +379,7 @@ class TempestMultisite(TempestCommon): TempestCommon.__init__(self) self.case_name = "multisite" self.MODE = "feature_multisite" - self.OPTION = "--concur 1" + self.OPTION = "--concurrency 1" conf_utils.configure_tempest_multisite(logger, self.DEPLOYMENT_DIR) diff --git a/functest/opnfv_tests/sdn/odl/odl.py b/functest/opnfv_tests/sdn/odl/odl.py index 0905e55c..606d59a1 100755 --- a/functest/opnfv_tests/sdn/odl/odl.py +++ b/functest/opnfv_tests/sdn/odl/odl.py @@ -15,7 +15,7 @@ import re import sys import urlparse -from robot.api import ExecutionResult, ResultVisitor +import robot.api from robot.errors import RobotError import robot.run from robot.utils.robottime import timestamp_to_secs @@ -25,7 +25,7 @@ import functest.utils.functest_logger as ft_logger import functest.utils.openstack_utils as op_utils -class ODLResultVisitor(ResultVisitor): +class ODLResultVisitor(robot.api.ResultVisitor): def __init__(self): self._data = [] @@ -79,7 +79,7 @@ class ODLTests(testcase_base.TestcaseBase): def parse_results(self): xml_file = os.path.join(self.res_dir, 'output.xml') - result = ExecutionResult(xml_file) + result = robot.api.ExecutionResult(xml_file) visitor = ODLResultVisitor() result.visit(visitor) self.criteria = result.suite.status @@ -161,7 +161,7 @@ class ODLTests(testcase_base.TestcaseBase): kwargs['odlwebport'] = '8282' elif installer_type == 'apex': kwargs['odlip'] = os.environ['SDN_CONTROLLER_IP'] - kwargs['odlwebport'] = '8181' + kwargs['odlwebport'] = '8081' elif installer_type == 'joid': kwargs['odlip'] = os.environ['SDN_CONTROLLER'] elif installer_type == 'compass': @@ -180,44 +180,52 @@ class ODLTests(testcase_base.TestcaseBase): return self.main(**kwargs) +class ODLParser(): + + def __init__(self): + self.parser = argparse.ArgumentParser() + self.parser.add_argument( + '-k', '--keystoneip', help='Keystone IP', + default='127.0.0.1') + self.parser.add_argument( + '-n', '--neutronip', help='Neutron IP', + default='127.0.0.1') + self.parser.add_argument( + '-a', '--osusername', help='Username for OpenStack', + default='admin') + self.parser.add_argument( + '-b', '--ostenantname', help='Tenantname for OpenStack', + default='admin') + self.parser.add_argument( + '-c', '--ospassword', help='Password for OpenStack', + default='admin') + self.parser.add_argument( + '-o', '--odlip', help='OpenDaylight IP', + default='127.0.0.1') + self.parser.add_argument( + '-w', '--odlwebport', help='OpenDaylight Web Portal Port', + default='8080') + self.parser.add_argument( + '-r', '--odlrestconfport', help='OpenDaylight RESTConf Port', + default='8181') + self.parser.add_argument( + '-d', '--odlusername', help='Username for ODL', + default='admin') + self.parser.add_argument( + '-e', '--odlpassword', help='Password for ODL', + default='admin') + self.parser.add_argument( + '-p', '--pushtodb', help='Push results to DB', + action='store_true') + + def parse_args(self, argv=[]): + return vars(self.parser.parse_args(argv)) + + if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('-k', '--keystoneip', - help='Keystone IP', - default='127.0.0.1') - parser.add_argument('-n', '--neutronip', - help='Neutron IP', - default='127.0.0.1') - parser.add_argument('-a', '--osusername', - help='Username for OpenStack', - default='admin') - parser.add_argument('-b', '--ostenantname', - help='Tenantname for OpenStack', - default='admin') - parser.add_argument('-c', '--ospassword', - help='Password for OpenStack', - default='admin') - parser.add_argument('-o', '--odlip', - help='OpenDaylight IP', - default='127.0.0.1') - parser.add_argument('-w', '--odlwebport', - help='OpenDaylight Web Portal Port', - default='8080') - parser.add_argument('-r', '--odlrestconfport', - help='OpenDaylight RESTConf Port', - default='8181') - parser.add_argument('-d', '--odlusername', - help='Username for ODL', - default='admin') - parser.add_argument('-e', '--odlpassword', - help='Password for ODL', - default='admin') - parser.add_argument('-p', '--pushtodb', - help='Push results to DB', - action='store_true') - - args = vars(parser.parse_args()) odl = ODLTests() + parser = ODLParser() + args = parser.parse_args(sys.argv[1:]) try: result = odl.main(**args) if result != testcase_base.TestcaseBase.EX_OK: diff --git a/functest/opnfv_tests/sdn/onos/teston/onos.py b/functest/opnfv_tests/sdn/onos/teston/onos.py index 300f56d1..213bdb7d 100755 --- a/functest/opnfv_tests/sdn/onos/teston/onos.py +++ b/functest/opnfv_tests/sdn/onos/teston/onos.py @@ -18,14 +18,15 @@ import datetime import os import re import time +import urlparse import argparse from neutronclient.v2_0 import client as neutronclient +import functest.utils.functest_constants as ft_constants import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils import functest.utils.openstack_utils as openstack_utils -import functest.utils.functest_constants as ft_constants parser = argparse.ArgumentParser() @@ -135,9 +136,9 @@ def GetResult(): def SetOnosIp(): - cmd = "openstack catalog show network | grep publicURL" - cmd_output = os.popen(cmd).read() - OC1 = re.search(r"\d+\.\d+\.\d+\.\d+", cmd_output).group() + # cmd = "openstack catalog show network | grep publicURL" + neutron_url = openstack_utils.get_endpoint(service_type='network') + OC1 = urlparse.urlparse(neutron_url).hostname os.environ['OC1'] = OC1 time.sleep(2) logger.debug("ONOS IP is " + OC1) @@ -180,10 +181,9 @@ def SfcTest(): def GetIp(type): - cmd = "openstack catalog show " + type + " | grep publicURL" - cmd_output = os.popen(cmd).read() - ip = re.search(r"\d+\.\d+\.\d+\.\d+", cmd_output).group() - return ip + # cmd = "openstack catalog show " + type + " | grep publicURL" + url = openstack_utils.get_endpoint(service_type=type) + return urlparse.urlparse(url).hostname def Replace(before, after): diff --git a/functest/tests/unit/cli/commands/test_cli_env.py b/functest/tests/unit/cli/commands/test_cli_env.py index 4b6ea57a..f70761dc 100644 --- a/functest/tests/unit/cli/commands/test_cli_env.py +++ b/functest/tests/unit/cli/commands/test_cli_env.py @@ -11,6 +11,7 @@ import unittest from git.exc import NoSuchPathError import mock +mock.patch('logging.FileHandler').start() # noqa from functest.cli.commands import cli_env from functest.utils.constants import CONST from functest.tests.unit import test_utils diff --git a/functest/tests/unit/cli/commands/test_cli_os.py b/functest/tests/unit/cli/commands/test_cli_os.py index 9e704806..f0e58c67 100644 --- a/functest/tests/unit/cli/commands/test_cli_os.py +++ b/functest/tests/unit/cli/commands/test_cli_os.py @@ -231,7 +231,7 @@ class CliOpenStackTesting(unittest.TestCase): value = 'OS_VALUE' with mock.patch.dict(os.environ, {key: value}): self.cli_os.show_credentials() - mock_click_echo.assert_called_once_with("{}={}".format(key, value)) + mock_click_echo.assert_any_call("{}={}".format(key, value)) if __name__ == "__main__": diff --git a/functest/tests/unit/core/test_testcase_base.py b/functest/tests/unit/core/test_testcase_base.py index b7c81d87..b6efa40d 100644 --- a/functest/tests/unit/core/test_testcase_base.py +++ b/functest/tests/unit/core/test_testcase_base.py @@ -11,6 +11,7 @@ import logging import mock import unittest +mock.patch('logging.FileHandler').start() # noqa from functest.core import testcase_base diff --git a/functest/tests/unit/odl/test_odl.py b/functest/tests/unit/odl/test_odl.py index d8c7f84e..8a52a9f6 100644 --- a/functest/tests/unit/odl/test_odl.py +++ b/functest/tests/unit/odl/test_odl.py @@ -11,12 +11,15 @@ import errno import logging import mock import os +import StringIO import unittest from keystoneauth1.exceptions import auth_plugins -from robot.errors import RobotError +from robot.errors import DataError, RobotError from robot.result import testcase +from robot.utils.robottime import timestamp_to_secs +mock.patch('logging.FileHandler').start() # noqa from functest.core import testcase_base from functest.opnfv_tests.sdn.odl import odl @@ -44,6 +47,17 @@ class ODLTesting(unittest.TestCase): os.environ["OS_PASSWORD"] = self._os_password os.environ["OS_TENANT_NAME"] = self._os_tenantname self.test = odl.ODLTests() + self.defaultargs = {'odlusername': self._odl_username, + 'odlpassword': self._odl_password, + 'keystoneip': self._keystone_ip, + 'neutronip': self._keystone_ip, + 'osusername': self._os_username, + 'ostenantname': self._os_tenantname, + 'ospassword': self._os_password, + 'odlip': self._keystone_ip, + 'odlwebport': self._odl_webport, + 'odlrestconfport': self._odl_restconfport, + 'pushtodb': False} def test_empty_visitor(self): visitor = odl.ODLResultVisitor() @@ -72,14 +86,65 @@ class ODLTesting(unittest.TestCase): visitor.visit_test(test) self.assertEqual(visitor.get_data(), [data]) + @mock.patch('robot.api.ExecutionResult', side_effect=DataError) + def test_parse_results_raises_exceptions(self, *args): + with self.assertRaises(DataError): + self.test.parse_results() + + def test_parse_results(self, *args): + config = {'name': 'dummy', 'starttime': '20161216 16:00:00.000', + 'endtime': '20161216 16:00:01.000', 'status': 'PASS'} + suite = mock.Mock() + suite.configure_mock(**config) + with mock.patch('robot.api.ExecutionResult', + return_value=mock.Mock(suite=suite)): + self.test.parse_results() + self.assertEqual(self.test.criteria, config['status']) + self.assertEqual(self.test.start_time, + timestamp_to_secs(config['starttime'])) + self.assertEqual(self.test.stop_time, + timestamp_to_secs(config['endtime'])) + self.assertEqual(self.test.details, + {'description': config['name'], 'tests': []}) + @mock.patch('fileinput.input', side_effect=Exception()) def test_set_robotframework_vars_failed(self, *args): self.assertFalse(self.test.set_robotframework_vars()) @mock.patch('fileinput.input', return_value=[]) - def test_set_robotframework_vars(self, args): + def test_set_robotframework_vars_empty(self, args): self.assertTrue(self.test.set_robotframework_vars()) + @mock.patch('sys.stdout', new_callable=StringIO.StringIO) + def _test_set_robotframework_vars(self, msg1, msg2, *args): + line = mock.MagicMock() + line.__iter__.return_value = [msg1] + with mock.patch('fileinput.input', return_value=line) as mock_method: + self.assertTrue(self.test.set_robotframework_vars()) + mock_method.assert_called_once_with( + os.path.join(odl.ODLTests.odl_test_repo, + 'csit/variables/Variables.py'), inplace=True) + self.assertEqual(args[0].getvalue(), "{}\n".format(msg2)) + + def test_set_robotframework_vars_auth_default(self): + self._test_set_robotframework_vars("AUTH = []", + "AUTH = [u'admin', u'admin']") + + def test_set_robotframework_vars_auth1(self): + self._test_set_robotframework_vars("AUTH1 = []", "AUTH1 = []") + + @mock.patch('sys.stdout', new_callable=StringIO.StringIO) + def test_set_robotframework_vars_auth_foo(self, *args): + line = mock.MagicMock() + line.__iter__.return_value = ["AUTH = []"] + with mock.patch('fileinput.input', return_value=line) as mock_method: + self.assertTrue(self.test.set_robotframework_vars('foo', 'bar')) + mock_method.assert_called_once_with( + os.path.join(odl.ODLTests.odl_test_repo, + 'csit/variables/Variables.py'), inplace=True) + self.assertEqual(args[0].getvalue(), + "AUTH = [u'{}', u'{}']\n".format('foo', 'bar')) + @classmethod def _fake_url_for(cls, service_type='identity', **kwargs): if service_type == 'identity': @@ -194,6 +259,8 @@ class ODLTesting(unittest.TestCase): def test_main_robot_run_failed(self, *args): with mock.patch.object(self.test, 'set_robotframework_vars', return_value=True), \ + mock.patch.object(odl, 'open', mock.mock_open(), + create=True), \ self.assertRaises(RobotError): self._test_main(testcase_base.TestcaseBase.EX_RUN_ERROR, *args) @@ -202,6 +269,8 @@ class ODLTesting(unittest.TestCase): def test_main_parse_results_failed(self, *args): with mock.patch.object(self.test, 'set_robotframework_vars', return_value=True), \ + mock.patch.object(odl, 'open', mock.mock_open(), + create=True), \ mock.patch.object(self.test, 'parse_results', side_effect=RobotError): self._test_main(testcase_base.TestcaseBase.EX_RUN_ERROR, *args) @@ -222,6 +291,8 @@ class ODLTesting(unittest.TestCase): def test_main(self, *args): with mock.patch.object(self.test, 'set_robotframework_vars', return_value=True), \ + mock.patch.object(odl, 'open', mock.mock_open(), + create=True), \ mock.patch.object(self.test, 'parse_results'): self._test_main(testcase_base.TestcaseBase.EX_OK, *args) @@ -231,6 +302,8 @@ class ODLTesting(unittest.TestCase): def test_main_makedirs_oserror17(self, *args): with mock.patch.object(self.test, 'set_robotframework_vars', return_value=True), \ + mock.patch.object(odl, 'open', mock.mock_open(), + create=True), \ mock.patch.object(self.test, 'parse_results'): self._test_main(testcase_base.TestcaseBase.EX_OK, *args) @@ -240,6 +313,8 @@ class ODLTesting(unittest.TestCase): def test_main_testcases_in_failure(self, *args): with mock.patch.object(self.test, 'set_robotframework_vars', return_value=True), \ + mock.patch.object(odl, 'open', mock.mock_open(), + create=True), \ mock.patch.object(self.test, 'parse_results'): self._test_main(testcase_base.TestcaseBase.EX_OK, *args) @@ -249,6 +324,8 @@ class ODLTesting(unittest.TestCase): def test_main_remove_oserror(self, *args): with mock.patch.object(self.test, 'set_robotframework_vars', return_value=True), \ + mock.patch.object(odl, 'open', mock.mock_open(), + create=True), \ mock.patch.object(self.test, 'parse_results'): self._test_main(testcase_base.TestcaseBase.EX_OK, *args) @@ -333,7 +410,7 @@ class ODLTesting(unittest.TestCase): os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip os.environ["INSTALLER_TYPE"] = "apex" self._test_run(testcase_base.TestcaseBase.EX_OK, - odlip=self._sdn_controller_ip, odlwebport='8181') + odlip=self._sdn_controller_ip, odlwebport='8081') def test_run_joid_missing_sdn_controller(self): with mock.patch('functest.utils.openstack_utils.get_endpoint', @@ -353,6 +430,77 @@ class ODLTesting(unittest.TestCase): self._test_run(testcase_base.TestcaseBase.EX_OK, odlip=self._neutron_ip, odlwebport='8181') + def test_argparser_default(self): + parser = odl.ODLParser() + self.assertEqual(parser.parse_args(), self.defaultargs) + + def test_argparser_basic(self): + self.defaultargs['neutronip'] = self._neutron_ip + self.defaultargs['odlip'] = self._sdn_controller_ip + parser = odl.ODLParser() + self.assertEqual(parser.parse_args( + ["--neutronip={}".format(self._neutron_ip), + "--odlip={}".format(self._sdn_controller_ip) + ]), self.defaultargs) + + @mock.patch('sys.stderr', new_callable=StringIO.StringIO) + def test_argparser_fail(self, *args): + self.defaultargs['foo'] = 'bar' + parser = odl.ODLParser() + with self.assertRaises(SystemExit): + parser.parse_args(["--foo=bar"]) + + def _test_argparser(self, arg, value): + self.defaultargs[arg] = value + parser = odl.ODLParser() + self.assertEqual(parser.parse_args(["--{}={}".format(arg, value)]), + self.defaultargs) + + def test_argparser_odlusername(self): + self._test_argparser('odlusername', 'foo') + + def test_argparser_odlpassword(self): + self._test_argparser('odlpassword', 'foo') + + def test_argparser_keystoneip(self): + self._test_argparser('keystoneip', '127.0.0.4') + + def test_argparser_neutronip(self): + self._test_argparser('neutronip', '127.0.0.4') + + def test_argparser_osusername(self): + self._test_argparser('osusername', 'foo') + + def test_argparser_ostenantname(self): + self._test_argparser('ostenantname', 'foo') + + def test_argparser_ospassword(self): + self._test_argparser('ospassword', 'foo') + + def test_argparser_odlip(self): + self._test_argparser('odlip', '127.0.0.4') + + def test_argparser_odlwebport(self): + self._test_argparser('odlwebport', '80') + + def test_argparser_odlrestconfport(self): + self._test_argparser('odlrestconfport', '80') + + def test_argparser_pushtodb(self): + self.defaultargs['pushtodb'] = True + parser = odl.ODLParser() + self.assertEqual(parser.parse_args(["--{}".format('pushtodb')]), + self.defaultargs) + + def test_argparser_multiple_args(self): + self.defaultargs['neutronip'] = self._neutron_ip + self.defaultargs['odlip'] = self._sdn_controller_ip + parser = odl.ODLParser() + self.assertEqual(parser.parse_args( + ["--neutronip={}".format(self._neutron_ip), + "--odlip={}".format(self._sdn_controller_ip) + ]), self.defaultargs) + if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/functest/tests/unit/utils/test_functest_utils.py b/functest/tests/unit/utils/test_functest_utils.py index ce9086a7..c4b56660 100644 --- a/functest/tests/unit/utils/test_functest_utils.py +++ b/functest/tests/unit/utils/test_functest_utils.py @@ -18,6 +18,7 @@ import mock import requests from functest.tests.unit import test_utils +mock.patch('logging.FileHandler').start() # noqa from functest.utils import functest_utils diff --git a/functest/tests/unit/utils/test_openstack_clean.py b/functest/tests/unit/utils/test_openstack_clean.py new file mode 100644 index 00000000..28eab4f8 --- /dev/null +++ b/functest/tests/unit/utils/test_openstack_clean.py @@ -0,0 +1,671 @@ +#!/usr/bin/env python + +# 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 logging +import mock +import unittest + +from functest.utils import openstack_clean +from functest.tests.unit import test_utils + + +class OSCleanTesting(unittest.TestCase): + + logging.disable(logging.CRITICAL) + + def _get_instance(self, key): + mock_obj = mock.Mock() + attrs = {'id': 'id' + str(key), 'name': 'name' + str(key), + 'ip': 'ip' + str(key)} + mock_obj.configure_mock(**attrs) + return mock_obj + + def setUp(self): + self.client = mock.Mock() + self.test_list = [self._get_instance(1), self._get_instance(2)] + self.update_list = {'id1': 'name1', 'id2': 'name2'} + self.remove_list = {'id3': 'name3', 'id4': 'name4'} + self.test_dict_list = [{'id': 'id1', 'name': 'name1', 'ip': 'ip1', + 'router:external': False, + 'external_gateway_info': None}, + {'id': 'id2', 'name': 'name2', 'ip': 'ip2', + 'router:external': False, + 'external_gateway_info': None}] + self.routers = [mock.Mock()] + self.ports = [mock.Mock()] + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_separator(self, mock_logger_debug): + openstack_clean.separator() + mock_logger_debug.assert_called_once_with("-----------------" + "-----------------" + "---------") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_instances(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_instances', return_value=self.test_list): + openstack_clean.remove_instances(self.client, self.update_list) + mock_logger_debug.assert_any_call("Removing Nova instances...") + mock_logger_debug.assert_any_call(" > this is a default " + "instance and will " + "NOT be deleted.") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_instances_missing_instances(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_instances', return_value=[]): + openstack_clean.remove_instances(self.client, self.update_list) + mock_logger_debug.assert_any_call("Removing Nova instances...") + mock_logger_debug.assert_any_call("No instances found.") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_instances_delete_success(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_instances', return_value=self.test_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_instance', return_value=True): + openstack_clean.remove_instances(self.client, self.remove_list) + mock_logger_debug.assert_any_call("Removing Nova instances...") + mock_logger_debug.assert_any_call(" > Request sent.") + mock_logger_debug.assert_any_call(test_utils.RegexMatch("Removing" + " instance" + " '\s*\S+'" + " ...")) + + @mock.patch('functest.utils.openstack_clean.logger.error') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_instances_delete_failed(self, mock_logger_debug, + mock_logger_error): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_instances', return_value=self.test_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_instance', return_value=False): + openstack_clean.remove_instances(self.client, self.remove_list) + mock_logger_debug.assert_any_call("Removing Nova instances...") + mock_logger_error.assert_any_call(test_utils. + RegexMatch("There has been a " + "problem removing " + "the instance \s*\S+" + "...")) + mock_logger_debug.assert_any_call(test_utils.RegexMatch("Removing" + " instance" + " '\s*\S+'" + " ...")) + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_images(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_images', return_value=self.test_list): + openstack_clean.remove_images(self.client, self.update_list) + mock_logger_debug.assert_any_call("Removing Glance images...") + mock_logger_debug.assert_any_call(" > this is a default " + "image and will " + "NOT be deleted.") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_images_missing_images(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_images', return_value=[]): + openstack_clean.remove_images(self.client, self.update_list) + mock_logger_debug.assert_any_call("Removing Glance images...") + mock_logger_debug.assert_any_call("No images found.") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_images_delete_success(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_images', return_value=self.test_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_glance_image', return_value=True): + openstack_clean.remove_images(self.client, self.remove_list) + mock_logger_debug.assert_any_call("Removing Glance images...") + mock_logger_debug.assert_any_call(" > Done!") + mock_logger_debug.assert_any_call(test_utils. + RegexMatch("Removing image " + "\s*\S+," + " ID=\s*\S+ ...")) + + @mock.patch('functest.utils.openstack_clean.logger.error') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_images_delete_failed(self, mock_logger_debug, + mock_logger_error): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_images', return_value=self.test_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_glance_image', return_value=False): + openstack_clean.remove_images(self.client, self.remove_list) + mock_logger_debug.assert_any_call("Removing Glance images...") + mock_logger_error.assert_any_call(test_utils. + RegexMatch("There has been a " + "problem removing the" + "image \s*\S+...")) + mock_logger_debug.assert_any_call(test_utils. + RegexMatch("Removing image " + "\s*\S+," + " ID=\s*\S+ ...")) + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_volumes(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_volumes', return_value=self.test_list): + openstack_clean.remove_volumes(self.client, self.update_list) + mock_logger_debug.assert_any_call("Removing Cinder volumes...") + mock_logger_debug.assert_any_call(" > this is a default " + "volume and will " + "NOT be deleted.") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_volumes_missing_volumes(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_volumes', return_value=[]): + openstack_clean.remove_volumes(self.client, self.update_list) + mock_logger_debug.assert_any_call("Removing Cinder volumes...") + mock_logger_debug.assert_any_call("No volumes found.") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_volumes_delete_success(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_volumes', return_value=self.test_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_volume', return_value=True): + openstack_clean.remove_volumes(self.client, self.remove_list) + mock_logger_debug.assert_any_call("Removing Cinder volumes...") + mock_logger_debug.assert_any_call(" > Done!") + mock_logger_debug.assert_any_call(test_utils. + RegexMatch("Removing cinder " + "volume \s*\S+ ...")) + + @mock.patch('functest.utils.openstack_clean.logger.error') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_volumes_delete_failed(self, mock_logger_debug, + mock_logger_error): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_volumes', return_value=self.test_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_volume', return_value=False): + openstack_clean.remove_volumes(self.client, self.remove_list) + mock_logger_debug.assert_any_call("Removing Cinder volumes...") + mock_logger_error.assert_any_call(test_utils. + RegexMatch("There has been a " + "problem removing " + "the " + "volume \s*\S+...")) + mock_logger_debug.assert_any_call(test_utils. + RegexMatch("Removing cinder " + "volume \s*\S+ ...")) + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_floatingips(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_floating_ips', return_value=self.test_list): + openstack_clean.remove_floatingips(self.client, self.update_list) + mock_logger_debug.assert_any_call("Removing floating IPs...") + mock_logger_debug.assert_any_call(" > this is a default " + "floating IP and will " + "NOT be deleted.") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_floatingips_missing_floatingips(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_floating_ips', return_value=[]): + openstack_clean.remove_floatingips(self.client, self.update_list) + mock_logger_debug.assert_any_call("Removing floating IPs...") + mock_logger_debug.assert_any_call("No floating IPs found.") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_floatingips_delete_success(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_floating_ips', return_value=self.test_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_volume', return_value=True): + openstack_clean.remove_floatingips(self.client, self.remove_list) + mock_logger_debug.assert_any_call("Removing floating IPs...") + mock_logger_debug.assert_any_call(" > Done!") + mock_logger_debug.assert_any_call(test_utils. + RegexMatch("Removing floating " + "IP \s*\S+ ...")) + + @mock.patch('functest.utils.openstack_clean.logger.error') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_floatingips_delete_failed(self, mock_logger_debug, + mock_logger_error): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_floating_ips', return_value=self.test_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_floating_ip', return_value=False): + openstack_clean.remove_floatingips(self.client, self.remove_list) + mock_logger_debug.assert_any_call("Removing floating IPs...") + mock_logger_error.assert_any_call(test_utils. + RegexMatch("There has been a " + "problem removing " + "the floating IP " + "\s*\S+...")) + mock_logger_debug.assert_any_call(test_utils. + RegexMatch("Removing floating " + "IP \s*\S+ ...")) + + @mock.patch('functest.utils.openstack_clean.remove_routers') + @mock.patch('functest.utils.openstack_clean.remove_ports') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_networks(self, mock_logger_debug, + mock_remove_ports, + mock_remove_routers): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_network_list', + return_value=self.test_dict_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.get_port_list', return_value=self.ports), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.get_router_list', return_value=self.routers): + openstack_clean.remove_networks(self.client, self.update_list, + self.update_list) + mock_logger_debug.assert_any_call("Removing Neutron objects") + mock_logger_debug.assert_any_call(" > this is a default " + "network and will " + "NOT be deleted.") + mock_remove_ports.assert_called_once_with(self.client, self.ports, + []) + mock_remove_routers.assert_called_once_with(self.client, + self.routers, + self.update_list) + + @mock.patch('functest.utils.openstack_clean.remove_routers') + @mock.patch('functest.utils.openstack_clean.remove_ports') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_networks_missing_networks(self, mock_logger_debug, + mock_remove_ports, + mock_remove_routers): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_network_list', return_value=None), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.get_port_list', return_value=self.ports), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.get_router_list', return_value=self.routers): + openstack_clean.remove_networks(self.client, self.update_list, + self.update_list) + mock_logger_debug.assert_any_call("Removing Neutron objects") + mock_logger_debug.assert_any_call("There are no networks in the" + " deployment. ") + mock_remove_ports.assert_called_once_with(self.client, self.ports, + []) + mock_remove_routers.assert_called_once_with(self.client, + self.routers, + self.update_list) + + @mock.patch('functest.utils.openstack_clean.remove_routers') + @mock.patch('functest.utils.openstack_clean.remove_ports') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_networks_delete_success(self, mock_logger_debug, + mock_remove_ports, + mock_remove_routers): + + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_network_list', + return_value=self.test_dict_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_neutron_net', return_value=True), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.get_port_list', return_value=self.ports), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.get_router_list', return_value=self.routers): + openstack_clean.remove_networks(self.client, self.remove_list, + self.remove_list) + mock_logger_debug.assert_any_call("Removing Neutron objects") + mock_logger_debug.assert_any_call(" > this network will be " + "deleted.") + mock_logger_debug.assert_any_call(" > Done!") + mock_logger_debug.assert_any_call(test_utils. + RegexMatch("Removing network " + "\s*\S+ ...")) + mock_remove_ports.assert_called_once_with(self.client, self.ports, + ['id1', 'id2']) + mock_remove_routers.assert_called_once_with(self.client, + self.routers, + self.remove_list) + + @mock.patch('functest.utils.openstack_clean.remove_routers') + @mock.patch('functest.utils.openstack_clean.remove_ports') + @mock.patch('functest.utils.openstack_clean.logger.error') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_networks_delete_failed(self, mock_logger_debug, + mock_logger_error, + mock_remove_ports, + mock_remove_routers): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_network_list', + return_value=self.test_dict_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_neutron_net', return_value=False), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.get_port_list', return_value=self.ports), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.get_router_list', return_value=self.routers): + openstack_clean.remove_networks(self.client, self.remove_list, + self.remove_list) + mock_logger_debug.assert_any_call("Removing Neutron objects") + mock_logger_error.assert_any_call(test_utils. + RegexMatch("There has been a" + " problem removing" + " the network \s*\S+" + "...")) + mock_logger_debug.assert_any_call(test_utils. + RegexMatch("Removing network " + "\s*\S+ ...")) + mock_remove_ports.assert_called_once_with(self.client, self.ports, + ['id1', 'id2']) + mock_remove_routers.assert_called_once_with(self.client, + self.routers, + self.remove_list) + + # TODO: ports + @mock.patch('functest.utils.openstack_clean.os_utils.update_neutron_port') + @mock.patch('functest.utils.openstack_clean.logger.error') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_force_remove_port(self, mock_logger_debug, + mock_logger_error, + mock_update_neutron_port): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_neutron_port', + return_value=True): + openstack_clean.force_remove_port(self.client, 'id') + mock_logger_debug.assert_any_call(" > Done!") + mock_logger_debug.assert_any_call(test_utils. + RegexMatch("Clearing device_" + "owner for port " + "\s*\S+ ...")) + + @mock.patch('functest.utils.openstack_clean.os_utils.update_neutron_port') + @mock.patch('functest.utils.openstack_clean.logger.error') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_force_remove_port_failed(self, mock_logger_debug, + mock_logger_error, + mock_update_neutron_port): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_neutron_port', + return_value=False): + openstack_clean.force_remove_port(self.client, 'id') + mock_logger_error.assert_any_call("There has been a " + "problem removing " + "the port id...") + mock_logger_debug.assert_any_call(test_utils. + RegexMatch("Clearing device_" + "owner for port " + "\s*\S+ ...")) + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_routers_missing_routers(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_neutron_router', + return_value=True): + openstack_clean.remove_routers(self.client, self.test_dict_list, + self.remove_list) + mock_logger_debug.assert_any_call("Router is not connected" + " to anything." + "Ready to remove...") + mock_logger_debug.assert_any_call(" > Done!") + mock_logger_debug.assert_any_call(test_utils. + RegexMatch("Removing router " + "\s*\S+(\s*\S+) ...")) + + @mock.patch('functest.utils.openstack_clean.logger.error') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_routers_failed(self, mock_logger_debug, + mock_logger_error): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_neutron_router', + return_value=False): + openstack_clean.remove_routers(self.client, self.test_dict_list, + self.remove_list) + mock_logger_debug.assert_any_call("Router is not connected" + " to anything." + "Ready to remove...") + mock_logger_debug.assert_any_call(test_utils. + RegexMatch("Removing router " + "\s*\S+(\s*\S+) ...")) + mock_logger_error.assert_any_call(test_utils. + RegexMatch("There has been " + "a problem" + " removing the " + "router \s*\S+(" + "\s*\S+)...")) + + @mock.patch('functest.utils.openstack_clean.logger.error') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_missing_external_gateway(self, mock_logger_debug, + mock_logger_error): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_neutron_router', + return_value=False), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.remove_gateway_router', + return_value=False): + self.test_dict_list[0]['external_gateway_info'] = mock.Mock() + openstack_clean.remove_routers(self.client, self.test_dict_list, + self.remove_list) + mock_logger_debug.assert_any_call("Router has gateway to external" + " network.Removing link...") + mock_logger_error.assert_any_call("There has been a problem " + "removing the gateway...") + mock_logger_debug.assert_any_call(test_utils. + RegexMatch("Removing router " + "\s*\S+(\s*\S+) ...")) + mock_logger_error.assert_any_call(test_utils. + RegexMatch("There has been " + "a problem" + " removing the " + "router \s*\S+(" + "\s*\S+)...")) + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def remove_security_groups(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_security_groups', + return_value=self.test_dict_list): + openstack_clean.remove_security_groups(self.client, + self.update_list) + mock_logger_debug.assert_any_call("Removing Security groups...") + mock_logger_debug.assert_any_call(" > this is a default " + "security group and will NOT " + "be deleted.") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_security_groups_missing_sec_group(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_security_groups', return_value=[]): + openstack_clean.remove_security_groups(self.client, + self.update_list) + mock_logger_debug.assert_any_call("Removing Security groups...") + mock_logger_debug.assert_any_call("No security groups found.") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_security_groups_delete_success(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_security_groups', + return_value=self.test_dict_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_security_group', return_value=True): + openstack_clean.remove_security_groups(self.client, + self.remove_list) + mock_logger_debug.assert_any_call("Removing Security groups...") + mock_logger_debug.assert_any_call(" > Done!") + mock_logger_debug.assert_any_call(test_utils. + RegexMatch(" Removing \s*\S+" + "...")) + + @mock.patch('functest.utils.openstack_clean.logger.error') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_security_groups_delete_failed(self, mock_logger_debug, + mock_logger_error): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_security_groups', + return_value=self.test_dict_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_security_group', return_value=False): + openstack_clean.remove_security_groups(self.client, + self.remove_list) + mock_logger_debug.assert_any_call("Removing Security groups...") + mock_logger_error.assert_any_call(test_utils. + RegexMatch("There has been a " + "problem removing " + "the security group" + " \s*\S+...")) + mock_logger_debug.assert_any_call(test_utils. + RegexMatch(" Removing \s*\S+" + "...")) + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_users(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_users', return_value=self.test_list): + openstack_clean.remove_users(self.client, self.update_list) + mock_logger_debug.assert_any_call("Removing Users...") + mock_logger_debug.assert_any_call(" > this is a default " + "user and will " + "NOT be deleted.") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_users_missing_users(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_users', return_value=None): + openstack_clean.remove_users(self.client, self.update_list) + mock_logger_debug.assert_any_call("Removing Users...") + mock_logger_debug.assert_any_call("There are no users in" + " the deployment. ") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_users_delete_success(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_users', return_value=self.test_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_user', return_value=True): + openstack_clean.remove_users(self.client, self.remove_list) + mock_logger_debug.assert_any_call("Removing Users...") + mock_logger_debug.assert_any_call(" > Done!") + mock_logger_debug.assert_any_call(test_utils. + RegexMatch(" Removing " + "\s*\S+...")) + + @mock.patch('functest.utils.openstack_clean.logger.error') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_users_delete_failed(self, mock_logger_debug, + mock_logger_error): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_users', return_value=self.test_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_user', return_value=False): + openstack_clean.remove_users(self.client, self.remove_list) + mock_logger_debug.assert_any_call("Removing Users...") + mock_logger_error.assert_any_call(test_utils. + RegexMatch("There has been a " + "problem removing " + "the user \s*\S+" + "...")) + mock_logger_debug.assert_any_call(test_utils. + RegexMatch(" Removing " + "\s*\S+...")) + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_tenants(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_tenants', return_value=self.test_list): + openstack_clean.remove_tenants(self.client, self.update_list) + mock_logger_debug.assert_any_call("Removing Tenants...") + mock_logger_debug.assert_any_call(" > this is a default" + " tenant and will " + "NOT be deleted.") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_tenants_missing_tenants(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_tenants', return_value=None): + openstack_clean.remove_tenants(self.client, self.update_list) + mock_logger_debug.assert_any_call("Removing Tenants...") + mock_logger_debug.assert_any_call("There are no tenants in" + " the deployment. ") + + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_tenants_delete_success(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_tenants', return_value=self.test_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_tenant', return_value=True): + openstack_clean.remove_tenants(self.client, self.remove_list) + mock_logger_debug.assert_any_call("Removing Tenants...") + mock_logger_debug.assert_any_call(" > Done!") + mock_logger_debug.assert_any_call(test_utils. + RegexMatch(" Removing " + "\s*\S+...")) + + @mock.patch('functest.utils.openstack_clean.logger.error') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_remove_tenants_delete_failed(self, mock_logger_debug, + mock_logger_error): + with mock.patch('functest.utils.openstack_clean.os_utils' + '.get_tenants', return_value=self.test_list), \ + mock.patch('functest.utils.openstack_clean.os_utils' + '.delete_tenant', return_value=False): + openstack_clean.remove_tenants(self.client, self.remove_list) + mock_logger_debug.assert_any_call("Removing Tenants...") + mock_logger_error.assert_any_call(test_utils. + RegexMatch("There has been a " + "problem removing " + "the tenant \s*\S+" + "...")) + mock_logger_debug.assert_any_call(test_utils. + RegexMatch(" Removing " + "\s*\S+...")) + + @mock.patch('functest.utils.openstack_clean.os_utils.get_cinder_client') + @mock.patch('functest.utils.openstack_clean.os_utils' + '.get_keystone_client') + @mock.patch('functest.utils.openstack_clean.os_utils' + '.get_neutron_client') + @mock.patch('functest.utils.openstack_clean.os_utils.get_nova_client') + @mock.patch('functest.utils.openstack_clean.os_utils.check_credentials', + return_value=True) + @mock.patch('functest.utils.openstack_clean.logger.info') + @mock.patch('functest.utils.openstack_clean.logger.debug') + def test_main_default(self, mock_logger_debug, mock_logger_info, + mock_creds, mock_nova, mock_neutron, + mock_keystone, mock_cinder): + + with mock.patch('functest.utils.openstack_clean.remove_instances') \ + as mock_remove_instances, \ + mock.patch('functest.utils.openstack_clean.remove_images') \ + as mock_remove_images, \ + mock.patch('functest.utils.openstack_clean.remove_volumes') \ + as mock_remove_volumes, \ + mock.patch('functest.utils.openstack_clean.remove_floatingips') \ + as mock_remove_floatingips, \ + mock.patch('functest.utils.openstack_clean.remove_networks') \ + as mock_remove_networks, \ + mock.patch('functest.utils.openstack_clean.' + 'remove_security_groups') \ + as mock_remove_security_groups, \ + mock.patch('functest.utils.openstack_clean.remove_users') \ + as mock_remove_users, \ + mock.patch('functest.utils.openstack_clean.remove_tenants') \ + as mock_remove_tenants, \ + mock.patch('functest.utils.openstack_clean.yaml.safe_load', + return_value=mock.Mock()), \ + mock.patch('__builtin__.open', mock.mock_open()) as m: + openstack_clean.main() + self.assertTrue(mock_remove_instances) + self.assertTrue(mock_remove_images) + self.assertTrue(mock_remove_volumes) + self.assertTrue(mock_remove_floatingips) + self.assertTrue(mock_remove_networks) + self.assertTrue(mock_remove_security_groups) + self.assertTrue(mock_remove_users) + self.assertTrue(mock_remove_tenants) + m.assert_called_once_with(openstack_clean.OS_SNAPSHOT_FILE) + mock_logger_info.assert_called_once_with("Cleaning OpenStack " + "resources...") + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/functest/tests/unit/utils/test_openstack_snapshot.py b/functest/tests/unit/utils/test_openstack_snapshot.py new file mode 100644 index 00000000..52744db1 --- /dev/null +++ b/functest/tests/unit/utils/test_openstack_snapshot.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python + +# 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 logging +import mock +import unittest + +from functest.utils import openstack_snapshot + + +class OSTackerTesting(unittest.TestCase): + + logging.disable(logging.CRITICAL) + + def _get_instance(self, key): + mock_obj = mock.Mock() + attrs = {'id': 'id' + str(key), 'name': 'name' + str(key), + 'ip': 'ip' + str(key)} + mock_obj.configure_mock(**attrs) + return mock_obj + + def setUp(self): + self.client = mock.Mock() + self.test_list = [self._get_instance(1), self._get_instance(2)] + self.update_list = {'id1': 'name1', 'id2': 'name2'} + self.update_floatingips = {'id1': 'ip1', 'id2': 'ip2'} + self.test_dict_list = [{'id': 'id1', 'name': 'name1', 'ip': 'ip1'}, + {'id': 'id2', 'name': 'name2', 'ip': 'ip2'}] + + @mock.patch('functest.utils.openstack_snapshot.logger.info') + def test_separator(self, mock_logger_info): + openstack_snapshot.separator() + mock_logger_info.assert_called_once_with("-----------------" + "-----------------" + "---------") + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_instances(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_instances', return_value=self.test_list): + resp = openstack_snapshot.get_instances(self.client) + mock_logger_debug.assert_called_once_with("Getting instances...") + self.assertDictEqual(resp, {'instances': self.update_list}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_instances_missing_instances(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_instances', return_value=[]): + resp = openstack_snapshot.get_instances(self.client) + mock_logger_debug.assert_called_once_with("Getting instances...") + self.assertDictEqual(resp, {'instances': {}}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_images(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_images', return_value=self.test_list): + resp = openstack_snapshot.get_images(self.client) + mock_logger_debug.assert_called_once_with("Getting images...") + self.assertDictEqual(resp, {'images': self.update_list}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_images_missing_images(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_images', return_value=[]): + resp = openstack_snapshot.get_images(self.client) + mock_logger_debug.assert_called_once_with("Getting images...") + self.assertDictEqual(resp, {'images': {}}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_volumes(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_volumes', return_value=self.test_list): + resp = openstack_snapshot.get_volumes(self.client) + mock_logger_debug.assert_called_once_with("Getting volumes...") + self.assertDictEqual(resp, {'volumes': self.update_list}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_volumes_missing_volumes(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_volumes', return_value=[]): + resp = openstack_snapshot.get_volumes(self.client) + mock_logger_debug.assert_called_once_with("Getting volumes...") + self.assertDictEqual(resp, {'volumes': {}}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_networks(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_network_list', return_value=self.test_dict_list): + resp = openstack_snapshot.get_networks(self.client) + mock_logger_debug.assert_called_once_with("Getting networks") + self.assertDictEqual(resp, {'networks': self.update_list}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_networks_missing_networks(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_network_list', return_value=[]): + resp = openstack_snapshot.get_networks(self.client) + mock_logger_debug.assert_called_once_with("Getting networks") + self.assertDictEqual(resp, {'networks': {}}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_routers(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_router_list', return_value=self.test_dict_list): + resp = openstack_snapshot.get_routers(self.client) + mock_logger_debug.assert_called_once_with("Getting routers") + self.assertDictEqual(resp, {'routers': self.update_list}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_routers_missing_routers(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_router_list', return_value=[]): + resp = openstack_snapshot.get_routers(self.client) + mock_logger_debug.assert_called_once_with("Getting routers") + self.assertDictEqual(resp, {'routers': {}}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_secgroups(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_security_groups', + return_value=self.test_dict_list): + resp = openstack_snapshot.get_security_groups(self.client) + mock_logger_debug.assert_called_once_with("Getting Security " + "groups...") + self.assertDictEqual(resp, {'secgroups': self.update_list}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_secgroups_missing_secgroups(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_security_groups', return_value=[]): + resp = openstack_snapshot.get_security_groups(self.client) + mock_logger_debug.assert_called_once_with("Getting Security " + "groups...") + self.assertDictEqual(resp, {'secgroups': {}}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_floatingips(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_floating_ips', return_value=self.test_list): + resp = openstack_snapshot.get_floatinips(self.client) + mock_logger_debug.assert_called_once_with("Getting Floating " + "IPs...") + self.assertDictEqual(resp, {'floatingips': + self.update_floatingips}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_floatingips_missing_floatingips(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_floating_ips', return_value=[]): + resp = openstack_snapshot.get_floatinips(self.client) + mock_logger_debug.assert_called_once_with("Getting Floating " + "IPs...") + self.assertDictEqual(resp, {'floatingips': {}}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_users(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_users', return_value=self.test_list): + resp = openstack_snapshot.get_users(self.client) + mock_logger_debug.assert_called_once_with("Getting users...") + self.assertDictEqual(resp, {'users': self.update_list}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_users_missing_users(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_users', return_value=[]): + resp = openstack_snapshot.get_users(self.client) + mock_logger_debug.assert_called_once_with("Getting users...") + self.assertDictEqual(resp, {'users': {}}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_tenants(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_tenants', return_value=self.test_list): + resp = openstack_snapshot.get_tenants(self.client) + mock_logger_debug.assert_called_once_with("Getting tenants...") + self.assertDictEqual(resp, {'tenants': self.update_list}) + + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_get_tenants_missing_tenants(self, mock_logger_debug): + with mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_tenants', return_value=[]): + resp = openstack_snapshot.get_tenants(self.client) + mock_logger_debug.assert_called_once_with("Getting tenants...") + self.assertDictEqual(resp, {'tenants': {}}) + + @mock.patch('functest.utils.openstack_snapshot.os_utils.get_cinder_client') + @mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_keystone_client') + @mock.patch('functest.utils.openstack_snapshot.os_utils' + '.get_neutron_client') + @mock.patch('functest.utils.openstack_snapshot.os_utils.get_nova_client') + @mock.patch('functest.utils.openstack_snapshot.os_utils.check_credentials') + @mock.patch('functest.utils.openstack_snapshot.logger.info') + @mock.patch('functest.utils.openstack_snapshot.logger.debug') + def test_main_default(self, mock_logger_debug, mock_logger_info, + mock_creds, mock_nova, mock_neutron, + mock_keystone, mock_cinder): + with mock.patch('functest.utils.openstack_snapshot.get_instances', + return_value=self.update_list), \ + mock.patch('functest.utils.openstack_snapshot.get_images', + return_value=self.update_list), \ + mock.patch('functest.utils.openstack_snapshot.get_images', + return_value=self.update_list), \ + mock.patch('functest.utils.openstack_snapshot.get_volumes', + return_value=self.update_list), \ + mock.patch('functest.utils.openstack_snapshot.get_networks', + return_value=self.update_list), \ + mock.patch('functest.utils.openstack_snapshot.get_routers', + return_value=self.update_list), \ + mock.patch('functest.utils.openstack_snapshot.get_security_groups', + return_value=self.update_list), \ + mock.patch('functest.utils.openstack_snapshot.get_floatinips', + return_value=self.update_floatingips), \ + mock.patch('functest.utils.openstack_snapshot.get_users', + return_value=self.update_list), \ + mock.patch('functest.utils.openstack_snapshot.get_tenants', + return_value=self.update_list), \ + mock.patch('__builtin__.open', mock.mock_open()) as m: + openstack_snapshot.main() + mock_logger_info.assert_called_once_with("Generating OpenStack " + "snapshot...") + m.assert_called_once_with(openstack_snapshot.OS_SNAPSHOT_FILE, + 'w+') + mock_logger_debug.assert_any_call("NOTE: These objects will " + "NOT be deleted after " + + "running the test.") + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/functest/tests/unit/utils/test_openstack_tacker.py b/functest/tests/unit/utils/test_openstack_tacker.py new file mode 100644 index 00000000..a8330c0e --- /dev/null +++ b/functest/tests/unit/utils/test_openstack_tacker.py @@ -0,0 +1,455 @@ +#!/usr/bin/env python + +# 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 logging +import mock +import unittest + +from functest.utils import openstack_tacker +from functest.tests.unit import test_utils + + +class OSTackerTesting(unittest.TestCase): + + logging.disable(logging.CRITICAL) + + def setUp(self): + self.tacker_client = mock.Mock() + self.getresponse = {'vnfds': [{'id': 'test_id'}], + 'vnfs': [{'id': 'test_id'}], + 'sfcs': [{'id': 'test_id'}]} + self.vnfdlist = {'vnfds': [{'id': 'test_vnfd1'}, {'id': 'test_vnfd2'}]} + self.vnflist = {'vnfs': [{'id': 'test_vnf1'}, {'id': 'test_vnf2'}]} + self.sfclist = {'sfcs': [{'id': 'test_sfc1'}, {'id': 'test_sfc2'}]} + self.sfc_classifierlist = {'sfc_classifiers': [{'id': 'test_sfc_cl1'}, + {'id': 'test_sfc_cl2'}]} + + self.createvnfd = {"vnfd": {"attributes": {"vnfd": 'vnfd_body'}}} + self.createvnf = {"vnf": {"attributes": {"vnf": 'vnf_body'}}} + self.createsfc = {"sfc": {"attributes": {"sfc": 'sfc_body'}}} + self.createsfc_clf = {"sfc_classifier": {"attributes": + {"sfc_clf": 'sfc_clf_body'}}} + + self.resource_type = 'vnfd' + self.resource_name = 'resource_name' + self.tosca_file = 'test_tosca_file' + self.vnfd = 'test_vnfd' + self.vnf = 'test_vnf' + self.sfc = 'test_sfc' + self.sfc_clf = 'test_sfc_clf' + + def _get_creds(self): + cred_dict = { + 'OS_USERNAME': 'username', + 'OS_PASSWORD': 'password', + 'OS_AUTH_URL': 'auth_url', + 'OS_TENANT_NAME': 'tenant_name', + 'OS_USER_DOMAIN_NAME': 'user_domain_name', + 'OS_PROJECT_DOMAIN_NAME': 'project_domain_name', + 'OS_PROJECT_NAME': 'project_name', + 'OS_ENDPOINT_TYPE': 'endpoint_type', + 'OS_REGION_NAME': 'region_name' + } + return cred_dict + + def test_get_id_from_name(self): + with mock.patch.object(self.tacker_client, 'get', + return_value=self.getresponse): + resp = openstack_tacker.get_id_from_name(self.tacker_client, + self.resource_type, + self.resource_name) + self.assertEqual(resp, 'test_id') + + @mock.patch('functest.utils.openstack_tacker.logger.error') + def test_get_id_from_name_exception(self, mock_logger_error): + with mock.patch.object(self.tacker_client, 'get', + side_effect=Exception): + resp = openstack_tacker.get_id_from_name(self.tacker_client, + self.resource_type, + self.resource_name) + self.assertIsNone(resp) + mock_logger_error.assert_called_once_with(test_utils. + SubstrMatch("Error [get" + "_id_from_" + "name(tacker" + "_client" + ", resource_" + "type, " + "resource_" + "name)]:")) + + @mock.patch('functest.utils.openstack_tacker.get_id_from_name') + def test_get_vnfd_id(self, mock_get_id_from_name): + openstack_tacker.get_vnfd_id(self.tacker_client, self.resource_name) + mock_get_id_from_name.assert_called_once_with(self.tacker_client, + 'vnfd', + self.resource_name) + + @mock.patch('functest.utils.openstack_tacker.get_id_from_name') + def test_get_vnf_id(self, mock_get_id_from_name): + openstack_tacker.get_vnf_id(self.tacker_client, self.resource_name) + mock_get_id_from_name.assert_called_once_with(self.tacker_client, + 'vnf', + self.resource_name) + + @mock.patch('functest.utils.openstack_tacker.get_id_from_name') + def test_get_sfc_id(self, mock_get_id_from_name): + openstack_tacker.get_sfc_id(self.tacker_client, self.resource_name) + mock_get_id_from_name.assert_called_once_with(self.tacker_client, + 'sfc', + self.resource_name) + + @mock.patch('functest.utils.openstack_tacker.get_id_from_name') + def test_get_sfc_classifier_id(self, mock_get_id_from_name): + openstack_tacker.get_sfc_classifier_id(self.tacker_client, + self.resource_name) + mock_get_id_from_name.assert_called_once_with(self.tacker_client, + 'sfc-classifier', + self.resource_name) + + def test_list_vnfds(self): + with mock.patch.object(self.tacker_client, 'list_vnfds', + return_value=self.vnfdlist): + resp = openstack_tacker.list_vnfds(self.tacker_client, + verbose=False) + self.assertEqual(resp, ['test_vnfd1', 'test_vnfd2']) + + def test_list_vnfds_verbose(self): + with mock.patch.object(self.tacker_client, 'list_vnfds', + return_value=self.vnfdlist): + resp = openstack_tacker.list_vnfds(self.tacker_client, + verbose=True) + self.assertEqual(resp, self.vnfdlist) + + @mock.patch('functest.utils.openstack_tacker.logger.error') + def test_list_vnfds_exception(self, mock_logger_error): + with mock.patch.object(self.tacker_client, 'list_vnfds', + side_effect=Exception): + resp = openstack_tacker.list_vnfds(self.tacker_client, + verbose=False) + mock_logger_error.assert_called_once_with(test_utils. + SubstrMatch("Error" + " [list" + "_vnfds(" + "tacker_" + "client)]:")) + self.assertIsNone(resp) + + def test_create_vnfd_missing_file(self): + with mock.patch.object(self.tacker_client, 'create_vnfd', + return_value=self.createvnfd): + resp = openstack_tacker.create_vnfd(self.tacker_client, + tosca_file=None) + self.assertEqual(resp, self.createvnfd) + + @mock.patch('functest.utils.openstack_tacker.logger.error') + def test_create_vnfd_default(self, mock_logger_error): + with mock.patch.object(self.tacker_client, 'create_vnfd', + return_value=self.createvnfd), \ + mock.patch('__builtin__.open', mock.mock_open(read_data='1')) \ + as m: + resp = openstack_tacker.create_vnfd(self.tacker_client, + tosca_file=self.tosca_file) + m.assert_called_once_with(self.tosca_file) + mock_logger_error.assert_called_once_with('1') + self.assertEqual(resp, self.createvnfd) + + @mock.patch('functest.utils.openstack_tacker.logger.exception') + def test_create_vnfd_exception(self, mock_logger_excep): + with mock.patch.object(self.tacker_client, 'create_vnfd', + side_effect=Exception): + resp = openstack_tacker.create_vnfd(self.tacker_client, + tosca_file=self.tosca_file) + mock_logger_excep.assert_called_once_with(test_utils. + SubstrMatch("Error" + " [create" + "_vnfd(" + "tacker_" + "client, " + "'%s')]" + % self. + tosca_file)) + self.assertIsNone(resp) + + def test_delete_vnfd(self): + with mock.patch('functest.utils.openstack_tacker.get_vnfd_id', + return_value=self.vnfd), \ + mock.patch.object(self.tacker_client, 'delete_vnfd', + return_value=self.vnfd): + resp = openstack_tacker.delete_vnfd(self.tacker_client, + vnfd_id='vnfd_id', + vnfd_name=self.vnfd) + self.assertEqual(resp, self.vnfd) + + # TODO: Exception('You need to provide an VNFD' + # 'id or name') AssertionError + + @mock.patch('functest.utils.openstack_tacker.logger.error') + def test_delete_vnfd_exception(self, mock_logger_error): + with mock.patch('functest.utils.openstack_tacker.get_vnfd_id', + return_value=self.vnfd), \ + mock.patch.object(self.tacker_client, 'delete_vnfd', + side_effect=Exception): + resp = openstack_tacker.delete_vnfd(self.tacker_client, + vnfd_id=None, + vnfd_name=None) + self.assertIsNone(resp) + self.assertTrue(mock_logger_error.called) + + def test_list_vnfs(self): + with mock.patch.object(self.tacker_client, 'list_vnfs', + return_value=self.vnflist): + resp = openstack_tacker.list_vnfs(self.tacker_client, + verbose=False) + self.assertEqual(resp, ['test_vnf1', 'test_vnf2']) + + def test_list_vnfs_verbose(self): + with mock.patch.object(self.tacker_client, 'list_vnfs', + return_value=self.vnflist): + resp = openstack_tacker.list_vnfs(self.tacker_client, + verbose=True) + self.assertEqual(resp, self.vnflist) + + @mock.patch('functest.utils.openstack_tacker.logger.error') + def test_list_vnfs_exception(self, mock_logger_error): + with mock.patch.object(self.tacker_client, 'list_vnfs', + side_effect=Exception): + resp = openstack_tacker.list_vnfs(self.tacker_client, + verbose=False) + mock_logger_error.assert_called_once_with(test_utils. + SubstrMatch("Error" + " [list" + "_vnfs(" + "tacker_" + "client)]:")) + self.assertIsNone(resp) + + def test_create_vnf_default(self): + with mock.patch.object(self.tacker_client, 'create_vnf', + return_value=self.createvnf), \ + mock.patch('functest.utils.openstack_tacker.get_vnfd_id', + return_value=self.vnf): + resp = openstack_tacker.create_vnf(self.tacker_client, + vnf_name=self.vnf, + vnfd_id='vnfd_id', + vnfd_name=self.vnfd) + self.assertEqual(resp, self.createvnf) + + @mock.patch('functest.utils.openstack_tacker.logger.error') + def test_create_vnf_exception(self, mock_logger_error): + with mock.patch.object(self.tacker_client, 'create_vnf', + side_effect=Exception): + resp = openstack_tacker.create_vnf(self.tacker_client, + vnf_name=self.vnf, + vnfd_id='vnfd_id', + vnfd_name=self.vnfd) + mock_logger_error.assert_called_once_with(test_utils. + SubstrMatch("error" + " [create" + "_vnf(" + "tacker_" + "client")) + self.assertIsNone(resp) + + # TODO: wait_for_vnf + + def test_delete_vnf(self): + with mock.patch('functest.utils.openstack_tacker.get_vnf_id', + return_value=self.vnf), \ + mock.patch.object(self.tacker_client, 'delete_vnf', + return_value=self.vnf): + resp = openstack_tacker.delete_vnf(self.tacker_client, + vnf_id='vnf_id', + vnf_name=self.vnf) + self.assertEqual(resp, self.vnf) + + # TODO: Exception('You need to provide an VNF' + # 'classifier id or name') AssertionError + + @mock.patch('functest.utils.openstack_tacker.logger.error') + def test_delete_vnf_exception(self, mock_logger_error): + with mock.patch('functest.utils.openstack_tacker.get_vnf_id', + return_value=self.vnf), \ + mock.patch.object(self.tacker_client, 'delete_vnf', + side_effect=Exception): + resp = openstack_tacker.delete_vnf(self.tacker_client, + vnf_id=None, + vnf_name=None) + self.assertIsNone(resp) + self.assertTrue(mock_logger_error.called) + + def test_list_sfcs(self): + with mock.patch.object(self.tacker_client, 'list_sfcs', + return_value=self.sfclist): + resp = openstack_tacker.list_sfcs(self.tacker_client, + verbose=False) + self.assertEqual(resp, ['test_sfc1', 'test_sfc2']) + + def test_list_sfcs_verbose(self): + with mock.patch.object(self.tacker_client, 'list_sfcs', + return_value=self.sfclist): + resp = openstack_tacker.list_sfcs(self.tacker_client, + verbose=True) + self.assertEqual(resp, self.sfclist) + + @mock.patch('functest.utils.openstack_tacker.logger.error') + def test_list_sfcs_exception(self, mock_logger_error): + with mock.patch.object(self.tacker_client, 'list_sfcs', + side_effect=Exception): + resp = openstack_tacker.list_sfcs(self.tacker_client, + verbose=False) + mock_logger_error.assert_called_once_with(test_utils. + SubstrMatch("Error" + " [list" + "_sfcs(" + "tacker_" + "client)]:")) + self.assertIsNone(resp) + + def test_create_sfc_default(self): + with mock.patch.object(self.tacker_client, 'create_sfc', + return_value=self.createsfc), \ + mock.patch('functest.utils.openstack_tacker.get_vnf_id', + return_value=self.vnf): + resp = openstack_tacker.create_sfc(self.tacker_client, + sfc_name=self.sfc, + chain_vnf_ids=['chain_vnf_id'], + chain_vnf_names=[self.vnf]) + self.assertEqual(resp, self.createsfc) + + @mock.patch('functest.utils.openstack_tacker.logger.error') + def test_create_sfc_exception(self, mock_logger_error): + with mock.patch.object(self.tacker_client, 'create_sfc', + side_effect=Exception): + resp = openstack_tacker.create_sfc(self.tacker_client, + sfc_name=self.sfc, + chain_vnf_ids=['chain_vnf_id'], + chain_vnf_names=[self.vnf]) + mock_logger_error.assert_called_once_with(test_utils. + SubstrMatch("error" + " [create" + "_sfc(" + "tacker_" + "client")) + self.assertIsNone(resp) + + def test_delete_sfc(self): + with mock.patch('functest.utils.openstack_tacker.get_sfc_id', + return_value=self.sfc), \ + mock.patch.object(self.tacker_client, 'delete_sfc', + return_value=self.sfc): + resp = openstack_tacker.delete_sfc(self.tacker_client, + sfc_id='sfc_id', + sfc_name=self.sfc) + self.assertEqual(resp, self.sfc) + + # TODO: Exception('You need to provide an SFC' + # 'id or name') AssertionError + + @mock.patch('functest.utils.openstack_tacker.logger.error') + def test_delete_sfc_exception(self, mock_logger_error): + with mock.patch('functest.utils.openstack_tacker.get_sfc_id', + return_value=self.sfc), \ + mock.patch.object(self.tacker_client, 'delete_sfc', + side_effect=Exception): + resp = openstack_tacker.delete_sfc(self.tacker_client, + sfc_id=None, + sfc_name=None) + self.assertIsNone(resp) + self.assertTrue(mock_logger_error.called) + + def test_list_sfc_classifiers(self): + with mock.patch.object(self.tacker_client, 'list_sfc_classifiers', + return_value=self.sfc_classifierlist): + resp = openstack_tacker.list_sfc_classifiers(self.tacker_client, + verbose=False) + self.assertEqual(resp, ['test_sfc_cl1', 'test_sfc_cl2']) + + def test_list_sfc_classifiers_verbose(self): + with mock.patch.object(self.tacker_client, 'list_sfc_classifiers', + return_value=self.sfc_classifierlist): + resp = openstack_tacker.list_sfc_classifiers(self.tacker_client, + verbose=True) + self.assertEqual(resp, self.sfc_classifierlist) + + @mock.patch('functest.utils.openstack_tacker.logger.error') + def test_list_sfc_classifiers_exception(self, mock_logger_error): + with mock.patch.object(self.tacker_client, 'list_sfc_classifiers', + side_effect=Exception): + resp = openstack_tacker.list_sfc_classifiers(self.tacker_client, + verbose=False) + mock_logger_error.assert_called_once_with(test_utils. + SubstrMatch("Error" + " [list" + "_sfc_cl" + "assifiers(" + "tacker_" + "client)]:")) + self.assertIsNone(resp) + + def test_create_sfc_classifier_default(self): + with mock.patch.object(self.tacker_client, 'create_sfc_classifier', + return_value=self.createsfc_clf), \ + mock.patch('functest.utils.openstack_tacker.get_sfc_id', + return_value=self.sfc): + cl = self.sfc_clf + resp = openstack_tacker.create_sfc_classifier(self.tacker_client, + sfc_clf_name=cl, + sfc_id='sfc_id', + sfc_name=self.sfc) + self.assertEqual(resp, self.createsfc_clf) + + @mock.patch('functest.utils.openstack_tacker.logger.error') + def test_sfc_classifier_exception(self, mock_logger_error): + with mock.patch.object(self.tacker_client, 'create_sfc_classifier', + side_effect=Exception): + cl = self.sfc_clf + resp = openstack_tacker.create_sfc_classifier(self.tacker_client, + sfc_clf_name=cl, + sfc_id='sfc_id', + sfc_name=self.sfc) + mock_logger_error.assert_called_once_with(test_utils. + SubstrMatch("error" + " [create" + "_sfc_cl" + "assifier(" + "tacker_" + "client")) + self.assertIsNone(resp) + + def test_delete_sfc_classifier(self): + with mock.patch('functest.utils.openstack_tacker.get_sfc_' + 'classifier_id', + return_value=self.sfc_clf), \ + mock.patch.object(self.tacker_client, 'delete_sfc_classifier', + return_value=self.sfc_clf): + cl = self.sfc_clf + resp = openstack_tacker.delete_sfc_classifier(self.tacker_client, + sfc_clf_id='sfc_id', + sfc_clf_name=cl) + self.assertEqual(resp, cl) + + # TODO: Exception('You need to provide an SFC' + # 'classifier id or name') AssertionError + + @mock.patch('functest.utils.openstack_tacker.logger.error') + def test_delete_sfc_classifier_exception(self, mock_logger_error): + with mock.patch('functest.utils.openstack_tacker.get_sfc_' + 'classifier_id', + return_value=self.sfc_clf), \ + mock.patch.object(self.tacker_client, 'delete_sfc_classifier', + side_effect=Exception): + cl = self.sfc_clf + resp = openstack_tacker.delete_sfc_classifier(self.tacker_client, + sfc_clf_id='sfc_id', + sfc_clf_name=cl) + self.assertIsNone(resp) + self.assertTrue(mock_logger_error.called) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/functest/tests/unit/utils/test_openstack_utils.py b/functest/tests/unit/utils/test_openstack_utils.py new file mode 100644 index 00000000..0f510414 --- /dev/null +++ b/functest/tests/unit/utils/test_openstack_utils.py @@ -0,0 +1,1688 @@ +#!/usr/bin/env python + +# 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 copy +import logging +import unittest + +import mock + +from functest.utils import openstack_utils + + +class OSUtilsTesting(unittest.TestCase): + + logging.disable(logging.CRITICAL) + + def _get_env_cred_dict(self, os_prefix=''): + return {'OS_USERNAME': os_prefix + 'username', + 'OS_PASSWORD': os_prefix + 'password', + 'OS_AUTH_URL': os_prefix + 'auth_url', + 'OS_TENANT_NAME': os_prefix + 'tenant_name', + 'OS_USER_DOMAIN_NAME': os_prefix + 'user_domain_name', + 'OS_PROJECT_DOMAIN_NAME': os_prefix + 'project_domain_name', + 'OS_PROJECT_NAME': os_prefix + 'project_name', + 'OS_ENDPOINT_TYPE': os_prefix + 'endpoint_type', + 'OS_REGION_NAME': os_prefix + 'region_name'} + + def _get_os_env_vars(self): + return {'username': 'test_username', 'password': 'test_password', + 'auth_url': 'test_auth_url', 'tenant_name': 'test_tenant_name', + 'user_domain_name': 'test_user_domain_name', + 'project_domain_name': 'test_project_domain_name', + 'project_name': 'test_project_name', + 'endpoint_type': 'test_endpoint_type', + 'region_name': 'test_region_name'} + + def setUp(self): + self.env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD'] + self.tenant_name = 'test_tenant_name' + self.env_cred_dict = self._get_env_cred_dict() + self.os_environs = self._get_env_cred_dict(os_prefix='test_') + self.os_env_vars = self._get_os_env_vars() + + mock_obj = mock.Mock() + attrs = {'name': 'test_flavor', + 'id': 'flavor_id', + 'ram': 2} + mock_obj.configure_mock(**attrs) + self.flavor = mock_obj + + mock_obj = mock.Mock() + attrs = {'name': 'test_aggregate', + 'id': 'aggregate_id', + 'hosts': ['host_name']} + mock_obj.configure_mock(**attrs) + self.aggregate = mock_obj + + mock_obj = mock.Mock() + attrs = {'id': 'instance_id', + 'name': 'test_instance', + 'status': 'ok'} + mock_obj.configure_mock(**attrs) + self.instance = mock_obj + + mock_obj = mock.Mock() + attrs = {'id': 'azone_id', + 'zoneName': 'test_azone', + 'status': 'ok'} + mock_obj.configure_mock(**attrs) + self.availability_zone = mock_obj + + mock_obj = mock.Mock() + attrs = {'id': 'floating_id', + 'zoneName': 'test_floating_ip', + 'status': 'ok'} + mock_obj.configure_mock(**attrs) + self.floating_ip = mock_obj + + mock_obj = mock.Mock() + attrs = {'id': 'hypervisor_id', + 'hypervisor_hostname': 'test_hostname', + 'state': 'up'} + mock_obj.configure_mock(**attrs) + self.hypervisor = mock_obj + + mock_obj = mock.Mock() + attrs = {'id': 'image_id', + 'name': 'test_image'} + mock_obj.configure_mock(**attrs) + self.image = mock_obj + + mock_obj = mock.Mock() + self.mock_return = mock_obj + + self.nova_client = mock.Mock() + attrs = {'servers.list.return_value': [self.instance], + 'servers.get.return_value': self.instance, + 'servers.find.return_value': self.instance, + 'servers.create.return_value': self.instance, + 'flavors.list.return_value': [self.flavor], + 'flavors.find.return_value': self.flavor, + 'flavors.list.return_value': [self.flavor], + 'servers.add_floating_ip.return_value': mock.Mock(), + 'servers.force_delete.return_value': mock.Mock(), + 'aggregates.list.return_value': [self.aggregate], + 'aggregates.add_host.return_value': mock.Mock(), + 'aggregates.remove_host.return_value': mock.Mock(), + 'aggregates.get.return_value': self.aggregate, + 'aggregates.delete.return_value': mock.Mock(), + 'availability_zones.list.return_value': + [self.availability_zone], + 'floating_ips.list.return_value': [self.floating_ip], + 'floating_ips.delete.return_value': mock.Mock(), + 'hypervisors.list.return_value': [self.hypervisor], + 'create.return_value': mock.Mock(), + 'add_security_group.return_value': mock.Mock(), + 'images.list.return_value': [self.image], + 'images.delete.return_value': mock.Mock(), + } + self.nova_client.configure_mock(**attrs) + + self.glance_client = mock.Mock() + attrs = {'images.list.return_value': [self.image], + 'images.create.return_value': self.image, + 'images.upload.return_value': mock.Mock()} + self.glance_client.configure_mock(**attrs) + + mock_obj = mock.Mock() + attrs = {'id': 'volume_id', + 'name': 'test_volume'} + mock_obj.configure_mock(**attrs) + self.volume = mock_obj + + mock_obj = mock.Mock() + attrs = {'id': 'volume_type_id', + 'name': 'test_volume_type', + 'is_public': True} + mock_obj.configure_mock(**attrs) + self.volume_types = [mock_obj] + + mock_obj = mock.Mock() + attrs = {'id': 'volume_type_id', + 'name': 'test_volume_type', + 'is_public': False} + mock_obj.configure_mock(**attrs) + self.volume_types.append(mock_obj) + + self.cinder_client = mock.Mock() + attrs = {'volumes.list.return_value': [self.volume], + 'volume_types.list.return_value': self.volume_types, + 'volume_types.create.return_value': self.volume_types[0], + 'volume_types.delete.return_value': mock.Mock(), + 'quotas.update.return_value': mock.Mock(), + 'volumes.detach.return_value': mock.Mock(), + 'volumes.force_delete.return_value': mock.Mock(), + 'volumes.delete.return_value': mock.Mock() + } + self.cinder_client.configure_mock(**attrs) + + mock_obj = mock.Mock() + attrs = {'id': 'tenant_id', + 'name': 'test_tenant'} + mock_obj.configure_mock(**attrs) + self.tenant = mock_obj + + mock_obj = mock.Mock() + attrs = {'id': 'user_id', + 'name': 'test_user'} + mock_obj.configure_mock(**attrs) + self.user = mock_obj + + mock_obj = mock.Mock() + attrs = {'id': 'role_id', + 'name': 'test_role'} + mock_obj.configure_mock(**attrs) + self.role = mock_obj + + self.keystone_client = mock.Mock() + attrs = {'projects.list.return_value': [self.tenant], + 'tenants.list.return_value': [self.tenant], + 'users.list.return_value': [self.user], + 'roles.list.return_value': [self.role], + 'projects.create.return_value': self.tenant, + 'tenants.create.return_value': self.tenant, + 'users.create.return_value': self.user, + 'roles.grant.return_value': mock.Mock(), + 'roles.add_user_role.return_value': mock.Mock(), + 'projects.delete.return_value': mock.Mock(), + 'tenants.delete.return_value': mock.Mock(), + 'users.delete.return_value': mock.Mock(), + } + self.keystone_client.configure_mock(**attrs) + + self.router = {'id': 'router_id', + 'name': 'test_router'} + + self.subnet = {'id': 'subnet_id', + 'name': 'test_subnet'} + + self.networks = [{'id': 'network_id', + 'name': 'test_network', + 'router:external': False, + 'shared': True, + 'subnets': [self.subnet]}, + {'id': 'network_id1', + 'name': 'test_network1', + 'router:external': True, + 'shared': True, + 'subnets': [self.subnet]}] + + self.port = {'id': 'port_id', + 'name': 'test_port'} + + self.sec_group = {'id': 'sec_group_id', + 'name': 'test_sec_group'} + + self.neutron_floatingip = {'id': 'fip_id', + 'floating_ip_address': 'test_ip'} + self.neutron_client = mock.Mock() + attrs = {'list_networks.return_value': {'networks': self.networks}, + 'list_routers.return_value': {'routers': [self.router]}, + 'list_ports.return_value': {'ports': [self.port]}, + 'list_subnets.return_value': {'subnets': [self.subnet]}, + 'create_network.return_value': {'network': self.networks[0]}, + 'create_subnet.return_value': {'subnets': [self.subnet]}, + 'create_router.return_value': {'router': self.router}, + 'create_port.return_value': {'port': self.port}, + 'create_floatingip.return_value': {'floatingip': + self.neutron_floatingip}, + 'update_network.return_value': mock.Mock(), + 'update_port.return_value': {'port': self.port}, + 'add_interface_router.return_value': mock.Mock(), + 'add_gateway_router.return_value': mock.Mock(), + 'delete_network.return_value': mock.Mock(), + 'delete_subnet.return_value': mock.Mock(), + 'delete_router.return_value': mock.Mock(), + 'delete_port.return_value': mock.Mock(), + 'remove_interface_router.return_value': mock.Mock(), + 'remove_gateway_router.return_value': mock.Mock(), + 'create_bgpvpn.return_value': self.mock_return, + 'create_network_association.return_value': self.mock_return, + 'create_router_association.return_value': self.mock_return, + 'update_bgpvpn.return_value': self.mock_return, + 'delete_bgpvpn.return_value': self.mock_return, + 'show_bgpvpn.return_value': self.mock_return, + 'list_security_groups.return_value': {'security_groups': + [self.sec_group]}, + 'create_security_group_rule.return_value': mock.Mock(), + 'create_security_group.return_value': {'security_group': + self.sec_group}, + 'update_quota.return_value': mock.Mock(), + 'delete_security_group.return_value': mock.Mock() + } + self.neutron_client.configure_mock(**attrs) + + self.empty_client = mock.Mock() + attrs = {'list_networks.return_value': {'networks': []}, + 'list_routers.return_value': {'routers': []}, + 'list_ports.return_value': {'ports': []}, + 'list_subnets.return_value': {'subnets': []}} + self.empty_client.configure_mock(**attrs) + + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value=None) + def test_is_keystone_v3_missing_identity(self, mock_os_getenv): + self.assertEqual(openstack_utils.is_keystone_v3(), False) + + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value='3') + def test_is_keystone_v3_default(self, mock_os_getenv): + self.assertEqual(openstack_utils.is_keystone_v3(), True) + + @mock.patch('functest.utils.openstack_utils.is_keystone_v3', + return_value=False) + def test_get_rc_env_vars_missing_identity(self, mock_get_rc_env): + exp_resp = self.env_vars + exp_resp.extend(['OS_TENANT_NAME']) + self.assertEqual(openstack_utils.get_rc_env_vars(), exp_resp) + + @mock.patch('functest.utils.openstack_utils.is_keystone_v3', + return_value=True) + def test_get_rc_env_vars_default(self, mock_get_rc_env): + exp_resp = self.env_vars + exp_resp.extend(['OS_PROJECT_NAME', + 'OS_USER_DOMAIN_NAME', + 'OS_PROJECT_DOMAIN_NAME']) + self.assertEqual(openstack_utils.get_rc_env_vars(), exp_resp) + + @mock.patch('functest.utils.openstack_utils.get_rc_env_vars') + def test_check_credentials_missing_env(self, mock_get_rc_env): + exp_resp = self.env_vars + exp_resp.extend(['OS_TENANT_NAME']) + mock_get_rc_env.return_value = exp_resp + with mock.patch.dict('functest.utils.openstack_utils.os.environ', {}, + clear=True): + self.assertEqual(openstack_utils.check_credentials(), False) + + @mock.patch('functest.utils.openstack_utils.get_rc_env_vars') + def test_check_credentials_default(self, mock_get_rc_env): + exp_resp = ['OS_TENANT_NAME'] + mock_get_rc_env.return_value = exp_resp + with mock.patch.dict('functest.utils.openstack_utils.os.environ', + {'OS_TENANT_NAME': self.tenant_name}, + clear=True): + self.assertEqual(openstack_utils.check_credentials(), True) + + def test_get_env_cred_dict(self): + self.assertDictEqual(openstack_utils.get_env_cred_dict(), + self.env_cred_dict) + + @mock.patch('functest.utils.openstack_utils.get_rc_env_vars') + def test_get_credentials_default(self, mock_get_rc_env): + mock_get_rc_env.return_value = self.env_cred_dict.keys() + with mock.patch.dict('functest.utils.openstack_utils.os.environ', + self.os_environs, + clear=True): + self.assertDictEqual(openstack_utils.get_credentials(), + self.os_env_vars) + + def _get_credentials_missing_env(self, var): + dic = copy.deepcopy(self.os_environs) + dic.pop(var) + with mock.patch('functest.utils.openstack_utils.get_rc_env_vars', + return_value=self.env_cred_dict.keys()), \ + mock.patch.dict('functest.utils.openstack_utils.os.environ', + dic, + clear=True): + self.assertRaises(openstack_utils.MissingEnvVar, + lambda: openstack_utils.get_credentials()) + + def test_get_credentials_missing_username(self): + self._get_credentials_missing_env('OS_USERNAME') + + def test_get_credentials_missing_password(self): + self._get_credentials_missing_env('OS_PASSWORD') + + def test_get_credentials_missing_auth_url(self): + self._get_credentials_missing_env('OS_AUTH_URL') + + def test_get_credentials_missing_tenantname(self): + self._get_credentials_missing_env('OS_TENANT_NAME') + + def test_get_credentials_missing_domainname(self): + self._get_credentials_missing_env('OS_USER_DOMAIN_NAME') + + def test_get_credentials_missing_projectname(self): + self._get_credentials_missing_env('OS_PROJECT_NAME') + + def test_get_credentials_missing_endpoint_type(self): + self._get_credentials_missing_env('OS_ENDPOINT_TYPE') + + def test_source_credentials(self): + with mock.patch('functest.utils.openstack_utils.subprocess.Popen') \ + as mock_subproc_popen, \ + mock.patch('functest.utils.openstack_utils.os.environ'): + process_mock = mock.Mock() + attrs = {'communicate.return_value': ('OS_USER_NAME=test_name', + 'success')} + process_mock.configure_mock(**attrs) + mock_subproc_popen.return_value = process_mock + + self.assertDictEqual(openstack_utils.source_credentials('rc_file'), + {'OS_USER_NAME': 'test_name'}) + + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value=None) + def test_get_keystone_client_version_missing_env(self, mock_os_getenv): + self.assertEqual(openstack_utils.get_keystone_client_version(), + openstack_utils.DEFAULT_API_VERSION) + + @mock.patch('functest.utils.openstack_utils.logger.info') + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value='3') + def test_get_keystone_client_version_default(self, mock_os_getenv, + mock_logger_info): + self.assertEqual(openstack_utils.get_keystone_client_version(), + '3') + mock_logger_info.assert_called_once_with("OS_IDENTITY_API_VERSION is " + "set in env as '%s'", '3') + + def test_get_keystone_client(self): + mock_keystone_obj = mock.Mock() + mock_session_obj = mock.Mock() + with mock.patch('functest.utils.openstack_utils' + '.get_keystone_client_version', return_value='3'), \ + mock.patch('functest.utils.openstack_utils' + '.keystoneclient.Client', + return_value=mock_keystone_obj) \ + as mock_key_client, \ + mock.patch('functest.utils.openstack_utils.get_session', + return_value=mock_session_obj): + self.assertEqual(openstack_utils.get_keystone_client(), + mock_keystone_obj) + mock_key_client.assert_called_once_with('3', + session=mock_session_obj) + + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value=None) + def test_get_nova_client_version_missing_env(self, mock_os_getenv): + self.assertEqual(openstack_utils.get_nova_client_version(), + openstack_utils.DEFAULT_API_VERSION) + + @mock.patch('functest.utils.openstack_utils.logger.info') + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value='3') + def test_get_nova_client_version_default(self, mock_os_getenv, + mock_logger_info): + self.assertEqual(openstack_utils.get_nova_client_version(), + '3') + mock_logger_info.assert_called_once_with("OS_COMPUTE_API_VERSION is " + "set in env as '%s'", '3') + + def test_get_nova_client(self): + mock_nova_obj = mock.Mock() + mock_session_obj = mock.Mock() + with mock.patch('functest.utils.openstack_utils' + '.get_nova_client_version', return_value='3'), \ + mock.patch('functest.utils.openstack_utils' + '.novaclient.Client', + return_value=mock_nova_obj) \ + as mock_nova_client, \ + mock.patch('functest.utils.openstack_utils.get_session', + return_value=mock_session_obj): + self.assertEqual(openstack_utils.get_nova_client(), + mock_nova_obj) + mock_nova_client.assert_called_once_with('3', + session=mock_session_obj) + + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value=None) + def test_get_cinder_client_version_missing_env(self, mock_os_getenv): + self.assertEqual(openstack_utils.get_cinder_client_version(), + openstack_utils.DEFAULT_API_VERSION) + + @mock.patch('functest.utils.openstack_utils.logger.info') + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value='3') + def test_get_cinder_client_version_default(self, mock_os_getenv, + mock_logger_info): + self.assertEqual(openstack_utils.get_cinder_client_version(), + '3') + mock_logger_info.assert_called_once_with("OS_VOLUME_API_VERSION is " + "set in env as '%s'", '3') + + def test_get_cinder_client(self): + mock_cinder_obj = mock.Mock() + mock_session_obj = mock.Mock() + with mock.patch('functest.utils.openstack_utils' + '.get_cinder_client_version', return_value='3'), \ + mock.patch('functest.utils.openstack_utils' + '.cinderclient.Client', + return_value=mock_cinder_obj) \ + as mock_cind_client, \ + mock.patch('functest.utils.openstack_utils.get_session', + return_value=mock_session_obj): + self.assertEqual(openstack_utils.get_cinder_client(), + mock_cinder_obj) + mock_cind_client.assert_called_once_with('3', + session=mock_session_obj) + + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value=None) + def test_get_neutron_client_version_missing_env(self, mock_os_getenv): + self.assertEqual(openstack_utils.get_neutron_client_version(), + openstack_utils.DEFAULT_API_VERSION) + + @mock.patch('functest.utils.openstack_utils.logger.info') + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value='3') + def test_get_neutron_client_version_default(self, mock_os_getenv, + mock_logger_info): + self.assertEqual(openstack_utils.get_neutron_client_version(), + '3') + mock_logger_info.assert_called_once_with("OS_NETWORK_API_VERSION is " + "set in env as '%s'", '3') + + def test_get_neutron_client(self): + mock_neutron_obj = mock.Mock() + mock_session_obj = mock.Mock() + with mock.patch('functest.utils.openstack_utils' + '.get_neutron_client_version', return_value='3'), \ + mock.patch('functest.utils.openstack_utils' + '.neutronclient.Client', + return_value=mock_neutron_obj) \ + as mock_neut_client, \ + mock.patch('functest.utils.openstack_utils.get_session', + return_value=mock_session_obj): + self.assertEqual(openstack_utils.get_neutron_client(), + mock_neutron_obj) + mock_neut_client.assert_called_once_with('3', + session=mock_session_obj) + + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value=None) + def test_get_glance_client_version_missing_env(self, mock_os_getenv): + self.assertEqual(openstack_utils.get_glance_client_version(), + openstack_utils.DEFAULT_API_VERSION) + + @mock.patch('functest.utils.openstack_utils.logger.info') + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value='3') + def test_get_glance_client_version_default(self, mock_os_getenv, + mock_logger_info): + self.assertEqual(openstack_utils.get_glance_client_version(), + '3') + mock_logger_info.assert_called_once_with("OS_IMAGE_API_VERSION is " + "set in env as '%s'", '3') + + def test_get_glance_client(self): + mock_glance_obj = mock.Mock() + mock_session_obj = mock.Mock() + with mock.patch('functest.utils.openstack_utils' + '.get_glance_client_version', return_value='3'), \ + mock.patch('functest.utils.openstack_utils' + '.glanceclient.Client', + return_value=mock_glance_obj) \ + as mock_glan_client, \ + mock.patch('functest.utils.openstack_utils.get_session', + return_value=mock_session_obj): + self.assertEqual(openstack_utils.get_glance_client(), + mock_glance_obj) + mock_glan_client.assert_called_once_with('3', + session=mock_session_obj) + + def test_get_instances_default(self): + self.assertEqual(openstack_utils.get_instances(self.nova_client), + [self.instance]) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_instances_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_instances(Exception), + None) + self.assertTrue(mock_logger_error.called) + + def test_get_instance_status_default(self): + self.assertEqual(openstack_utils.get_instance_status(self.nova_client, + self.instance), + 'ok') + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_instance_status_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_instance_status(Exception, + self.instance), + None) + self.assertTrue(mock_logger_error.called) + + def test_get_instance_by_name_default(self): + self.assertEqual(openstack_utils. + get_instance_by_name(self.nova_client, + 'test_instance'), + self.instance) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_instance_by_name_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_instance_by_name(Exception, + 'test_instance'), + None) + self.assertTrue(mock_logger_error.called) + + def test_get_flavor_id_default(self): + self.assertEqual(openstack_utils. + get_flavor_id(self.nova_client, + 'test_flavor'), + self.flavor.id) + + def test_get_flavor_id_by_ram_range_default(self): + self.assertEqual(openstack_utils. + get_flavor_id_by_ram_range(self.nova_client, + 1, 3), + self.flavor.id) + + def test_get_aggregates_default(self): + self.assertEqual(openstack_utils. + get_aggregates(self.nova_client), + [self.aggregate]) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_aggregates_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_aggregates(Exception), + None) + self.assertTrue(mock_logger_error.called) + + def test_get_aggregate_id_default(self): + with mock.patch('functest.utils.openstack_utils.get_aggregates', + return_value=[self.aggregate]): + self.assertEqual(openstack_utils. + get_aggregate_id(self.nova_client, + 'test_aggregate'), + 'aggregate_id') + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_aggregate_id_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_aggregate_id(Exception, + 'test_aggregate'), + None) + self.assertTrue(mock_logger_error.called) + + def test_get_availability_zone_names_default(self): + with mock.patch('functest.utils.openstack_utils' + '.get_availability_zones', + return_value=[self.availability_zone]): + self.assertEqual(openstack_utils. + get_availability_zone_names(self.nova_client), + ['test_azone']) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_availability_zone_names_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_availability_zone_names(Exception), + None) + self.assertTrue(mock_logger_error.called) + + def test_get_availability_zones_default(self): + self.assertEqual(openstack_utils. + get_availability_zones(self.nova_client), + [self.availability_zone]) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_availability_zones_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_availability_zones(Exception), + None) + self.assertTrue(mock_logger_error.called) + + def test_get_floating_ips_default(self): + self.assertEqual(openstack_utils. + get_floating_ips(self.nova_client), + [self.floating_ip]) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_floating_ips_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_floating_ips(Exception), + None) + self.assertTrue(mock_logger_error.called) + + def test_get_hypervisors_default(self): + self.assertEqual(openstack_utils. + get_hypervisors(self.nova_client), + ['test_hostname']) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_hypervisors_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_hypervisors(Exception), + None) + self.assertTrue(mock_logger_error.called) + + def test_create_aggregate_default(self): + self.assertTrue(openstack_utils. + create_aggregate(self.nova_client, + 'test_aggregate', + 'azone')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_aggregate_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + create_aggregate(Exception, + 'test_aggregate', + 'azone'), + None) + self.assertTrue(mock_logger_error.called) + + def test_add_host_to_aggregate_default(self): + with mock.patch('functest.utils.openstack_utils.get_aggregate_id'): + self.assertTrue(openstack_utils. + add_host_to_aggregate(self.nova_client, + 'test_aggregate', + 'test_hostname')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_add_host_to_aggregate_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + add_host_to_aggregate(Exception, + 'test_aggregate', + 'test_hostname'), + None) + self.assertTrue(mock_logger_error.called) + + def test_create_aggregate_with_host_default(self): + with mock.patch('functest.utils.openstack_utils.create_aggregate'), \ + mock.patch('functest.utils.openstack_utils.' + 'add_host_to_aggregate'): + self.assertTrue(openstack_utils. + create_aggregate_with_host(self.nova_client, + 'test_aggregate', + 'test_azone', + 'test_hostname')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_aggregate_with_host_exception(self, mock_logger_error): + with mock.patch('functest.utils.openstack_utils.create_aggregate', + side_effect=Exception): + self.assertEqual(openstack_utils. + create_aggregate_with_host(Exception, + 'test_aggregate', + 'test_azone', + 'test_hostname'), + None) + self.assertTrue(mock_logger_error.called) + + def test_create_instance_default(self): + with mock.patch('functest.utils.openstack_utils.' + 'get_nova_client', + return_value=self.nova_client): + self.assertEqual(openstack_utils. + create_instance('test_flavor', + 'image_id', + 'network_id'), + self.instance) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_instance_exception(self, mock_logger_error): + with mock.patch('functest.utils.openstack_utils.' + 'get_nova_client', + return_value=self.nova_client): + self.nova_client.flavors.find.side_effect = Exception + self.assertEqual(openstack_utils. + create_instance('test_flavor', + 'image_id', + 'network_id'), + None) + self.assertTrue(mock_logger_error) + + def test_create_floating_ip_default(self): + with mock.patch('functest.utils.openstack_utils.' + 'get_external_net_id', + return_value='external_net_id'): + exp_resp = {'fip_addr': 'test_ip', 'fip_id': 'fip_id'} + self.assertEqual(openstack_utils. + create_floating_ip(self.neutron_client), + exp_resp) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_floating_ip_exception(self, mock_logger_error): + with mock.patch('functest.utils.openstack_utils.' + 'get_external_net_id', + return_value='external_net_id'): + self.assertEqual(openstack_utils. + create_floating_ip(Exception), + None) + self.assertTrue(mock_logger_error) + + def test_add_floating_ip_default(self): + with mock.patch('functest.utils.openstack_utils.get_aggregate_id'): + self.assertTrue(openstack_utils. + add_floating_ip(self.nova_client, + 'test_serverid', + 'test_floatingip_addr')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_add_floating_ip_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + add_floating_ip(Exception, + 'test_serverid', + 'test_floatingip_addr')) + self.assertTrue(mock_logger_error.called) + + def test_delete_instance_default(self): + self.assertTrue(openstack_utils. + delete_instance(self.nova_client, + 'instance_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_delete_instance_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + delete_instance(Exception, + 'instance_id')) + self.assertTrue(mock_logger_error.called) + + def test_delete_floating_ip_default(self): + self.assertTrue(openstack_utils. + delete_floating_ip(self.nova_client, + 'floating_ip_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_delete_floating_ip_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + delete_floating_ip(Exception, + 'floating_ip_id')) + self.assertTrue(mock_logger_error.called) + + def test_remove_host_from_aggregate_default(self): + with mock.patch('functest.utils.openstack_utils.' + 'get_aggregate_id'): + self.assertTrue(openstack_utils. + remove_host_from_aggregate(self.nova_client, + 'agg_name', + 'host_name')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_remove_host_from_aggregate_exception(self, mock_logger_error): + with mock.patch('functest.utils.openstack_utils.' + 'get_aggregate_id', side_effect=Exception): + self.assertFalse(openstack_utils. + remove_host_from_aggregate(self.nova_client, + 'agg_name', + 'host_name')) + self.assertTrue(mock_logger_error.called) + + def test_remove_hosts_from_aggregate_default(self): + with mock.patch('functest.utils.openstack_utils.' + 'get_aggregate_id'), \ + mock.patch('functest.utils.openstack_utils.' + 'remove_host_from_aggregate', + return_value=True) \ + as mock_method: + openstack_utils.remove_hosts_from_aggregate(self.nova_client, + 'test_aggregate') + mock_method.assert_any_call(self.nova_client, + 'test_aggregate', + 'host_name') + + def test_delete_aggregate_default(self): + with mock.patch('functest.utils.openstack_utils.' + 'remove_hosts_from_aggregate'): + self.assertTrue(openstack_utils. + delete_aggregate(self.nova_client, + 'agg_name')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_delete_aggregate_exception(self, mock_logger_error): + with mock.patch('functest.utils.openstack_utils.' + 'remove_hosts_from_aggregate', side_effect=Exception): + self.assertFalse(openstack_utils. + delete_aggregate(self.nova_client, + 'agg_name')) + self.assertTrue(mock_logger_error.called) + + def test_get_network_list_default(self): + self.assertEqual(openstack_utils. + get_network_list(self.neutron_client), + self.networks) + + def test_get_network_list_missing_network(self): + self.assertEqual(openstack_utils. + get_network_list(self.empty_client), + None) + + def test_get_router_list_default(self): + self.assertEqual(openstack_utils. + get_router_list(self.neutron_client), + [self.router]) + + def test_get_router_list_missing_router(self): + self.assertEqual(openstack_utils. + get_router_list(self.empty_client), + None) + + def test_get_port_list_default(self): + self.assertEqual(openstack_utils. + get_port_list(self.neutron_client), + [self.port]) + + def test_get_port_list_missing_port(self): + self.assertEqual(openstack_utils. + get_port_list(self.empty_client), + None) + + def test_get_network_id_default(self): + self.assertEqual(openstack_utils. + get_network_id(self.neutron_client, + 'test_network'), + 'network_id') + + def test_get_subnet_id_default(self): + self.assertEqual(openstack_utils. + get_subnet_id(self.neutron_client, + 'test_subnet'), + 'subnet_id') + + def test_get_router_id_default(self): + self.assertEqual(openstack_utils. + get_router_id(self.neutron_client, + 'test_router'), + 'router_id') + + def test_get_private_net_default(self): + self.assertEqual(openstack_utils. + get_private_net(self.neutron_client), + self.networks[0]) + + def test_get_private_net_missing_net(self): + self.assertEqual(openstack_utils. + get_private_net(self.empty_client), + None) + + def test_get_external_net_default(self): + self.assertEqual(openstack_utils. + get_external_net(self.neutron_client), + 'test_network1') + + def test_get_external_net_missing_net(self): + self.assertEqual(openstack_utils. + get_external_net(self.empty_client), + None) + + def test_get_external_net_id_default(self): + self.assertEqual(openstack_utils. + get_external_net_id(self.neutron_client), + 'network_id1') + + def test_get_external_net_id_missing_net(self): + self.assertEqual(openstack_utils. + get_external_net_id(self.empty_client), + None) + + def test_check_neutron_net_default(self): + self.assertTrue(openstack_utils. + check_neutron_net(self.neutron_client, + 'test_network')) + + def test_check_neutron_net_missing_net(self): + self.assertFalse(openstack_utils. + check_neutron_net(self.empty_client, + 'test_network')) + + def test_create_neutron_net_default(self): + self.assertEqual(openstack_utils. + create_neutron_net(self.neutron_client, + 'test_network'), + 'network_id') + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_neutron_net_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + create_neutron_net(Exception, + 'test_network'), + None) + self.assertTrue(mock_logger_error.called) + + def test_create_neutron_subnet_default(self): + self.assertEqual(openstack_utils. + create_neutron_subnet(self.neutron_client, + 'test_subnet', + 'test_cidr', + 'network_id'), + 'subnet_id') + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_neutron_subnet_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + create_neutron_subnet(Exception, + 'test_subnet', + 'test_cidr', + 'network_id'), + None) + self.assertTrue(mock_logger_error.called) + + def test_create_neutron_router_default(self): + self.assertEqual(openstack_utils. + create_neutron_router(self.neutron_client, + 'test_router'), + 'router_id') + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_neutron_router_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + create_neutron_router(Exception, + 'test_router'), + None) + self.assertTrue(mock_logger_error.called) + + def test_create_neutron_port_default(self): + self.assertEqual(openstack_utils. + create_neutron_port(self.neutron_client, + 'test_port', + 'network_id', + 'test_ip'), + 'port_id') + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_neutron_port_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + create_neutron_port(Exception, + 'test_port', + 'network_id', + 'test_ip'), + None) + self.assertTrue(mock_logger_error.called) + + def test_update_neutron_net_default(self): + self.assertTrue(openstack_utils. + update_neutron_net(self.neutron_client, + 'network_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_update_neutron_net_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + update_neutron_net(Exception, + 'network_id')) + self.assertTrue(mock_logger_error.called) + + def test_update_neutron_port_default(self): + self.assertEqual(openstack_utils. + update_neutron_port(self.neutron_client, + 'port_id', + 'test_owner'), + 'port_id') + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_update_neutron_port_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + update_neutron_port(Exception, + 'port_id', + 'test_owner'), + None) + self.assertTrue(mock_logger_error.called) + + def test_add_interface_router_default(self): + self.assertTrue(openstack_utils. + add_interface_router(self.neutron_client, + 'router_id', + 'subnet_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_add_interface_router_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + add_interface_router(Exception, + 'router_id', + 'subnet_id')) + self.assertTrue(mock_logger_error.called) + + def test_add_gateway_router_default(self): + with mock.patch('functest.utils.openstack_utils.' + 'get_external_net_id', + return_value='network_id'): + self.assertTrue(openstack_utils. + add_gateway_router(self.neutron_client, + 'router_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_add_gateway_router_exception(self, mock_logger_error): + with mock.patch('functest.utils.openstack_utils.' + 'get_external_net_id', + return_value='network_id'): + self.assertFalse(openstack_utils. + add_gateway_router(Exception, + 'router_id')) + self.assertTrue(mock_logger_error.called) + + def test_delete_neutron_net_default(self): + self.assertTrue(openstack_utils. + delete_neutron_net(self.neutron_client, + 'network_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_delete_neutron_net_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + delete_neutron_net(Exception, + 'network_id')) + self.assertTrue(mock_logger_error.called) + + def test_delete_neutron_subnet_default(self): + self.assertTrue(openstack_utils. + delete_neutron_subnet(self.neutron_client, + 'subnet_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_delete_neutron_subnet_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + delete_neutron_subnet(Exception, + 'subnet_id')) + self.assertTrue(mock_logger_error.called) + + def test_delete_neutron_router_default(self): + self.assertTrue(openstack_utils. + delete_neutron_router(self.neutron_client, + 'router_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_delete_neutron_router_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + delete_neutron_router(Exception, + 'router_id')) + self.assertTrue(mock_logger_error.called) + + def test_delete_neutron_port_default(self): + self.assertTrue(openstack_utils. + delete_neutron_port(self.neutron_client, + 'port_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_delete_neutron_port_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + delete_neutron_port(Exception, + 'port_id')) + self.assertTrue(mock_logger_error.called) + + def test_remove_interface_router_default(self): + self.assertTrue(openstack_utils. + remove_interface_router(self.neutron_client, + 'router_id', + 'subnet_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_remove_interface_router_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + remove_interface_router(Exception, + 'router_id', + 'subnet_id')) + self.assertTrue(mock_logger_error.called) + + def test_remove_gateway_router_default(self): + self.assertTrue(openstack_utils. + remove_gateway_router(self.neutron_client, + 'router_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_remove_gateway_router_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + remove_gateway_router(Exception, + 'router_id')) + self.assertTrue(mock_logger_error.called) + + def test_create_bgpvpn(self): + self.assertEqual(openstack_utils. + create_bgpvpn(self.neutron_client), + self.mock_return) + + def test_create_network_association(self): + self.assertEqual(openstack_utils. + create_network_association(self.neutron_client, + 'bgpvpn_id', + 'network_id'), + self.mock_return) + + def test_create_router_association(self): + self.assertEqual(openstack_utils. + create_router_association(self.neutron_client, + 'bgpvpn_id', + 'router_id'), + self.mock_return) + + def test_update_bgpvpn(self): + self.assertEqual(openstack_utils. + update_bgpvpn(self.neutron_client, + 'bgpvpn_id'), + self.mock_return) + + def test_delete_bgpvpn(self): + self.assertEqual(openstack_utils. + delete_bgpvpn(self.neutron_client, + 'bgpvpn_id'), + self.mock_return) + + def test_get_bgpvpn(self): + self.assertEqual(openstack_utils. + get_bgpvpn(self.neutron_client, + 'bgpvpn_id'), + self.mock_return) + + def test_get_bgpvpn_routers(self): + with mock.patch('functest.utils.openstack_utils.' + 'get_bgpvpn', + return_value={'bgpvpn': + {'routers': [self.router]}}): + self.assertEqual(openstack_utils. + get_bgpvpn_routers(self.neutron_client, + 'bgpvpn_id'), + [self.router]) + + def test_get_security_groups_default(self): + self.assertEqual(openstack_utils. + get_security_groups(self.neutron_client), + [self.sec_group]) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_security_groups_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_security_groups(Exception), + None) + self.assertTrue(mock_logger_error.called) + + def test_get_security_group_id_default(self): + with mock.patch('functest.utils.openstack_utils.' + 'get_security_groups', + return_value=[self.sec_group]): + self.assertEqual(openstack_utils. + get_security_group_id(self.neutron_client, + 'test_sec_group'), + 'sec_group_id') + + def test_create_security_group_default(self): + self.assertEqual(openstack_utils. + create_security_group(self.neutron_client, + 'test_sec_group', + 'sec_group_desc'), + self.sec_group) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_security_group_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + create_security_group(Exception, + 'test_sec_group', + 'sec_group_desc'), + None) + self.assertTrue(mock_logger_error.called) + + def test_create_secgroup_rule_default(self): + self.assertTrue(openstack_utils. + create_secgroup_rule(self.neutron_client, + 'sg_id', + 'direction', + 'protocol', + 80, + 80)) + self.assertTrue(openstack_utils. + create_secgroup_rule(self.neutron_client, + 'sg_id', + 'direction', + 'protocol')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_secgroup_rule_invalid_port_range(self, mock_logger_error): + self.assertFalse(openstack_utils. + create_secgroup_rule(self.neutron_client, + 'sg_id', + 'direction', + 'protocol', + 80)) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_secgroup_rule_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + create_secgroup_rule(Exception, + 'sg_id', + 'direction', + 'protocol')) + + @mock.patch('functest.utils.openstack_utils.logger.info') + def test_create_security_group_full_default(self, mock_logger_info): + with mock.patch('functest.utils.openstack_utils.' + 'get_security_group_id', + return_value='sg_id'): + self.assertEqual(openstack_utils. + create_security_group_full(self.neutron_client, + 'sg_name', + 'sg_desc'), + 'sg_id') + self.assertTrue(mock_logger_info) + + @mock.patch('functest.utils.openstack_utils.logger.info') + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_security_group_full_sec_group_fail(self, + mock_logger_error, + mock_logger_info): + with mock.patch('functest.utils.openstack_utils.' + 'get_security_group_id', + return_value=''), \ + mock.patch('functest.utils.openstack_utils.' + 'create_security_group', + return_value=False): + self.assertEqual(openstack_utils. + create_security_group_full(self.neutron_client, + 'sg_name', + 'sg_desc'), + None) + self.assertTrue(mock_logger_error) + self.assertTrue(mock_logger_info) + + @mock.patch('functest.utils.openstack_utils.logger.debug') + @mock.patch('functest.utils.openstack_utils.logger.info') + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_security_group_full_secgroup_rule_fail(self, + mock_logger_error, + mock_logger_info, + mock_logger_debug): + with mock.patch('functest.utils.openstack_utils.' + 'get_security_group_id', + return_value=''), \ + mock.patch('functest.utils.openstack_utils.' + 'create_security_group', + return_value={'id': 'sg_id', + 'name': 'sg_name'}), \ + mock.patch('functest.utils.openstack_utils.' + 'create_secgroup_rule', + return_value=False): + self.assertEqual(openstack_utils. + create_security_group_full(self.neutron_client, + 'sg_name', + 'sg_desc'), + None) + self.assertTrue(mock_logger_error) + self.assertTrue(mock_logger_info) + self.assertTrue(mock_logger_debug) + + def test_add_secgroup_to_instance_default(self): + self.assertTrue(openstack_utils. + add_secgroup_to_instance(self.nova_client, + 'instance_id', + 'sec_group_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_add_secgroup_to_instance_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + add_secgroup_to_instance(Exception, + 'instance_id', + 'sec_group_id')) + self.assertTrue(mock_logger_error.called) + + def test_update_sg_quota_default(self): + self.assertTrue(openstack_utils. + update_sg_quota(self.neutron_client, + 'tenant_id', + 'sg_quota', + 'sg_rule_quota')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_update_sg_quota_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + update_sg_quota(Exception, + 'tenant_id', + 'sg_quota', + 'sg_rule_quota')) + self.assertTrue(mock_logger_error.called) + + def test_delete_security_group_default(self): + self.assertTrue(openstack_utils. + delete_security_group(self.neutron_client, + 'sec_group_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_delete_security_group_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + delete_security_group(Exception, + 'sec_group_id')) + self.assertTrue(mock_logger_error.called) + + def test_get_images_default(self): + self.assertEqual(openstack_utils. + get_images(self.nova_client), + [self.image]) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_images_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_images(Exception), + None) + self.assertTrue(mock_logger_error.called) + + def test_get_image_id_default(self): + self.assertEqual(openstack_utils. + get_image_id(self.glance_client, + 'test_image'), + 'image_id') + + # create_glance_image, get_or_create_image + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_glance_image_file_present(self, mock_logger_error): + with mock.patch('functest.utils.openstack_utils.' + 'os.path.isfile', + return_value=False): + self.assertEqual(openstack_utils. + create_glance_image(self.glance_client, + 'test_image', + 'file_path'), + None) + self.assertTrue(mock_logger_error.called) + + @mock.patch('functest.utils.openstack_utils.logger.info') + def test_create_glance_image_already_exist(self, mock_logger_info): + with mock.patch('functest.utils.openstack_utils.' + 'os.path.isfile', + return_value=True), \ + mock.patch('functest.utils.openstack_utils.get_image_id', + return_value='image_id'): + self.assertEqual(openstack_utils. + create_glance_image(self.glance_client, + 'test_image', + 'file_path'), + 'image_id') + self.assertTrue(mock_logger_info.called) + + @mock.patch('functest.utils.openstack_utils.logger.info') + def test_create_glance_image_default(self, mock_logger_info): + with mock.patch('functest.utils.openstack_utils.' + 'os.path.isfile', + return_value=True), \ + mock.patch('functest.utils.openstack_utils.get_image_id', + return_value=''), \ + mock.patch('__builtin__.open', + mock.mock_open(read_data='1')) as m: + self.assertEqual(openstack_utils. + create_glance_image(self.glance_client, + 'test_image', + 'file_path'), + 'image_id') + m.assert_called_once_with('file_path') + self.assertTrue(mock_logger_info.called) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_glance_image_exception(self, mock_logger_error): + with mock.patch('functest.utils.openstack_utils.' + 'os.path.isfile', + return_value=True), \ + mock.patch('functest.utils.openstack_utils.get_image_id', + side_effect=Exception): + self.assertEqual(openstack_utils. + create_glance_image(self.glance_client, + 'test_image', + 'file_path'), + None) + self.assertTrue(mock_logger_error.called) + + def test_delete_glance_image_default(self): + self.assertTrue(openstack_utils. + delete_glance_image(self.nova_client, + 'image_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_delete_glance_image_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + delete_glance_image(Exception, + 'image_id')) + self.assertTrue(mock_logger_error.called) + + def test_get_volumes_default(self): + self.assertEqual(openstack_utils. + get_volumes(self.cinder_client), + [self.volume]) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_volumes_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_volumes(Exception), + None) + self.assertTrue(mock_logger_error.called) + + def test_list_volume_types_default_private(self): + self.assertEqual(openstack_utils. + list_volume_types(self.cinder_client, + public=False, + private=True), + [self.volume_types[1]]) + + def test_list_volume_types_default_public(self): + self.assertEqual(openstack_utils. + list_volume_types(self.cinder_client, + public=True, + private=False), + [self.volume_types[0]]) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_list_volume_types_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + list_volume_types(Exception), + None) + self.assertTrue(mock_logger_error.called) + + def test_create_volume_type_default(self): + self.assertEqual(openstack_utils. + create_volume_type(self.cinder_client, + 'test_volume_type'), + self.volume_types[0]) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_volume_type_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + create_volume_type(Exception, + 'test_volume_type'), + None) + self.assertTrue(mock_logger_error.called) + + def test_update_cinder_quota_default(self): + self.assertTrue(openstack_utils. + update_cinder_quota(self.cinder_client, + 'tenant_id', + 'vols_quota', + 'snap_quota', + 'giga_quota')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_update_cinder_quota_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + update_cinder_quota(Exception, + 'tenant_id', + 'vols_quota', + 'snap_quota', + 'giga_quota')) + self.assertTrue(mock_logger_error.called) + + def test_delete_volume_default(self): + self.assertTrue(openstack_utils. + delete_volume(self.cinder_client, + 'volume_id', + forced=False)) + + self.assertTrue(openstack_utils. + delete_volume(self.cinder_client, + 'volume_id', + forced=True)) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_delete_volume_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + delete_volume(Exception, + 'volume_id', + forced=True)) + self.assertTrue(mock_logger_error.called) + + def test_delete_volume_type_default(self): + self.assertTrue(openstack_utils. + delete_volume_type(self.cinder_client, + self.volume_types[0])) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_delete_volume_type_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + delete_volume_type(Exception, + self.volume_types[0])) + self.assertTrue(mock_logger_error.called) + + def test_get_tenants_default(self): + with mock.patch('functest.utils.openstack_utils.' + 'is_keystone_v3', return_value=True): + self.assertEqual(openstack_utils. + get_tenants(self.keystone_client), + [self.tenant]) + with mock.patch('functest.utils.openstack_utils.' + 'is_keystone_v3', return_value=False): + self.assertEqual(openstack_utils. + get_tenants(self.keystone_client), + [self.tenant]) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_tenants_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_tenants(Exception), + None) + self.assertTrue(mock_logger_error.called) + + def test_get_users_default(self): + self.assertEqual(openstack_utils. + get_users(self.keystone_client), + [self.user]) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_users_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_users(Exception), + None) + self.assertTrue(mock_logger_error.called) + + def test_get_tenant_id_default(self): + self.assertEqual(openstack_utils. + get_tenant_id(self.keystone_client, + 'test_tenant'), + 'tenant_id') + + def test_get_user_id_default(self): + self.assertEqual(openstack_utils. + get_user_id(self.keystone_client, + 'test_user'), + 'user_id') + + def test_get_role_id_default(self): + self.assertEqual(openstack_utils. + get_role_id(self.keystone_client, + 'test_role'), + 'role_id') + + def test_create_tenant_default(self): + with mock.patch('functest.utils.openstack_utils.' + 'is_keystone_v3', return_value=True): + self.assertEqual(openstack_utils. + create_tenant(self.keystone_client, + 'test_tenant', + 'tenant_desc'), + 'tenant_id') + with mock.patch('functest.utils.openstack_utils.' + 'is_keystone_v3', return_value=False): + self.assertEqual(openstack_utils. + create_tenant(self.keystone_client, + 'test_tenant', + 'tenant_desc'), + 'tenant_id') + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_tenant_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + create_tenant(Exception, + 'test_tenant', + 'tenant_desc'), + None) + self.assertTrue(mock_logger_error.called) + + def test_create_user_default(self): + with mock.patch('functest.utils.openstack_utils.' + 'is_keystone_v3', return_value=True): + self.assertEqual(openstack_utils. + create_user(self.keystone_client, + 'test_user', + 'password', + 'email', + 'tenant_id'), + 'user_id') + with mock.patch('functest.utils.openstack_utils.' + 'is_keystone_v3', return_value=False): + self.assertEqual(openstack_utils. + create_user(self.keystone_client, + 'test_user', + 'password', + 'email', + 'tenant_id'), + 'user_id') + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_create_user_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + create_user(Exception, + 'test_user', + 'password', + 'email', + 'tenant_id'), + None) + self.assertTrue(mock_logger_error.called) + + def test_add_role_user_default(self): + with mock.patch('functest.utils.openstack_utils.' + 'is_keystone_v3', return_value=True): + self.assertTrue(openstack_utils. + add_role_user(self.keystone_client, + 'user_id', + 'role_id', + 'tenant_id')) + + with mock.patch('functest.utils.openstack_utils.' + 'is_keystone_v3', return_value=False): + self.assertTrue(openstack_utils. + add_role_user(self.keystone_client, + 'user_id', + 'role_id', + 'tenant_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_add_role_user_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + add_role_user(Exception, + 'user_id', + 'role_id', + 'tenant_id')) + self.assertTrue(mock_logger_error.called) + + def test_delete_tenant_default(self): + with mock.patch('functest.utils.openstack_utils.' + 'is_keystone_v3', return_value=True): + self.assertTrue(openstack_utils. + delete_tenant(self.keystone_client, + 'tenant_id')) + + with mock.patch('functest.utils.openstack_utils.' + 'is_keystone_v3', return_value=False): + self.assertTrue(openstack_utils. + delete_tenant(self.keystone_client, + 'tenant_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_delete_tenant_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + delete_tenant(Exception, + 'tenant_id')) + self.assertTrue(mock_logger_error.called) + + def test_delete_user_default(self): + self.assertTrue(openstack_utils. + delete_user(self.keystone_client, + 'user_id')) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_delete_user_exception(self, mock_logger_error): + self.assertFalse(openstack_utils. + delete_user(Exception, + 'user_id')) + self.assertTrue(mock_logger_error.called) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/functest/utils/functest_logger.py b/functest/utils/functest_logger.py index b154f563..c0fba082 100644 --- a/functest/utils/functest_logger.py +++ b/functest/utils/functest_logger.py @@ -40,8 +40,10 @@ class Logger: ch.setFormatter(formatter) if CI_DEBUG is not None and CI_DEBUG.lower() == "true": ch.setLevel(logging.DEBUG) + self.logger.parent.level = logging.DEBUG else: ch.setLevel(logging.INFO) + self.logger.parent.level = logging.INFO self.logger.addHandler(ch) hdlr = logging.FileHandler('/home/opnfv/functest/results/functest.log') diff --git a/run_unit_tests.sh b/run_unit_tests.sh index e0e6195c..79d05d3d 100755 --- a/run_unit_tests.sh +++ b/run_unit_tests.sh @@ -2,32 +2,6 @@ set -o errexit set -o pipefail -function clean_results_dir { - if [ -d "/home/opnfv/functest/results" ] - then - sudo rm -rf /home/opnfv/functest/results - fi -} - -# ****************************** -# prepare the env for the tests -# ****************************** -# clean useless results dir -# should be done at the end -# but in case of crash during unit test -# clean it anyway -clean_results_dir - -# TODO clean that... -# Create log dir if needed -# log shall be disabled during unit tests -# fix to be done in Logger -echo "Create dummy log file...." -sudo mkdir -p /home/opnfv/functest/results/odl -sudo touch /home/opnfv/functest/results/functest.log -sudo touch /home/opnfv/functest/results/odl/stdout.txt -sudo chmod -Rf a+rw /home/opnfv - # Either Workspace is set (CI) if [ -z $WORKSPACE ] then @@ -69,10 +43,4 @@ rc=$? deactivate -# ******* -# clean -# ******* -# Clean useless logs -clean_results_dir - exit $rc diff --git a/test-requirements.txt b/test-requirements.txt index f724d5b1..2bf297ba 100755 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -16,6 +16,7 @@ python-congressclient==1.5.0 python-keystoneclient==3.5.0 python-neutronclient==6.0.0 python-openstackclient==2.3.0 +python-tackerclient==0.7.0 pyyaml==3.10 requests==2.8.0 robotframework==2.9.1 |