diff options
70 files changed, 6679 insertions, 1553 deletions
diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 000000000..fe258c6c6 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,3 @@ +[report] +exclude_lines = + if __name__ == .__main__.: @@ -12,7 +12,7 @@ Repository: functest Committers: yaohelan@huawei.com -serena.feng.711@gmail.com +feng.xiaowei@zte.com.cn ollivier.cedric@gmail.com jose.lausuch@ericsson.com morgan.richomme@orange.com diff --git a/docker/Dockerfile b/docker/Dockerfile index 5105fbbd1..dce657e8e 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 @@ -44,6 +43,7 @@ ARG FUNCTEST_RESULTS_DIR=${FUNCTEST_BASE_DIR}/results ARG FUNCTEST_REPO_DIR=${REPOS_DIR}/functest ARG FUNCTEST_TEST_DIR=${FUNCTEST_REPO_DIR}/functest/opnfv_tests ARG RELENG_MODULE_DIR=${REPOS_DIR}/releng/modules +ARG REPOS_VNFS_DIR=${REPOS_DIR}/vnfs # Environment variables ENV HOME /home/opnfv @@ -82,6 +82,7 @@ wget \ RUN pip install --upgrade pip RUN mkdir -p ${REPOS_DIR} \ + && mkdir -p ${REPOS_VNFS_DIR} \ && mkdir -p ${FUNCTEST_BASE_DIR}/results \ && mkdir -p ${FUNCTEST_BASE_DIR}/conf \ && mkdir -p /root/.ssh \ @@ -106,12 +107,12 @@ 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 RUN git clone --depth 1 -b $ODL_TAG https://git.opendaylight.org/gerrit/p/integration/test.git ${REPOS_DIR}/odl_test -RUN git clone --depth 1 -b $VIMS_TAG https://github.com/boucherv-orange/clearwater-live-test ${REPOS_DIR}/vims-test +RUN git clone --depth 1 -b $VIMS_TAG https://github.com/boucherv-orange/clearwater-live-test ${REPOS_VNFS_DIR}/vims-test RUN git clone --depth 1 https://github.com/wuwenbin2/OnosSystemTest.git ${REPOS_DIR}/onos RUN cd ${FUNCTEST_REPO_DIR} \ @@ -154,16 +155,16 @@ RUN cd ${REPOS_DIR}/bgpvpn && pip install . RUN cd ${REPOS_DIR}/moon/moonclient/ && python setup.py install RUN /bin/bash -c ". /etc/profile.d/rvm.sh \ - && cd ${REPOS_DIR}/vims-test \ + && cd ${REPOS_VNFS_DIR}/vims-test \ && rvm autolibs enable" RUN /bin/bash -c ". /etc/profile.d/rvm.sh \ - && cd ${REPOS_DIR}/vims-test \ + && cd ${REPOS_VNFS_DIR}/vims-test \ && rvm install 1.9.3" RUN /bin/bash -c ". /etc/profile.d/rvm.sh \ - && cd ${REPOS_DIR}/vims-test \ + && cd ${REPOS_VNFS_DIR}/vims-test \ && rvm use 1.9.3" RUN /bin/bash -c ". /etc/profile.d/rvm.sh \ - && cd ${REPOS_DIR}/vims-test \ + && cd ${REPOS_VNFS_DIR}/vims-test \ && bundle install" RUN sh -c 'curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -' \ diff --git a/functest/ci/check_os.sh b/functest/ci/check_os.sh index 053796d98..e2471026c 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 11ff7fdb5..25be17240 100755 --- a/functest/ci/config_functest.yaml +++ b/functest/ci/config_functest.yaml @@ -1,39 +1,39 @@ general: - directories: + dir: # Relative to the path where the repo is cloned: - dir_vping: functest/opnfv_tests/openstack/vping + vping: functest/opnfv_tests/openstack/vping dir_odl: functest/opnfv_tests/sdn/odl - dir_rally: functest/opnfv_tests/openstack/rally - dir_tempest_cases: functest/opnfv_tests/openstack/tempest/custom_tests + rally: functest/opnfv_tests/openstack/rally + tempest_cases: functest/opnfv_tests/openstack/tempest/custom_tests dir_vIMS: functest/opnfv_tests/vnf/ims dir_onos: functest/opnfv_tests/sdn/onos/teston dir_onos_sfc: functest/opnfv_tests/sdn/onos/sfc # Absolute path - dir_home: /home/opnfv - dir_repos: /home/opnfv/repos - dir_repo_functest: /home/opnfv/repos/functest + home: /home/opnfv + repos: /home/opnfv/repos + repo_functest: /home/opnfv/repos/functest dir_repo_rally: /home/opnfv/repos/rally - dir_repo_tempest: /home/opnfv/repos/tempest + repo_tempest: /home/opnfv/repos/tempest dir_repo_releng: /home/opnfv/repos/releng - dir_repo_vims_test: /home/opnfv/repos/vims-test - dir_repo_sdnvpn: /home/opnfv/repos/sdnvpn - dir_repo_sfc: /home/opnfv/repos/sfc + repo_vims_test: /home/opnfv/repos/vnfs/vims-test + repo_sdnvpn: /home/opnfv/repos/sdnvpn + repo_sfc: /home/opnfv/repos/sfc dir_repo_onos: /home/opnfv/repos/onos dir_repo_promise: /home/opnfv/repos/promise dir_repo_doctor: /home/opnfv/repos/doctor - dir_repo_copper: /home/opnfv/repos/copper + repo_copper: /home/opnfv/repos/copper dir_repo_ovno: /home/opnfv/repos/ovno - dir_repo_parser: /home/opnfv/repos/parser - dir_repo_domino: /home/opnfv/repos/domino - dir_repo_snaps: /home/opnfv/repos/snaps - dir_functest: /home/opnfv/functest - dir_functest_test: /home/opnfv/repos/functest/functest/opnfv_tests - dir_results: /home/opnfv/functest/results - dir_functest_conf: /home/opnfv/functest/conf - dir_functest_data: /home/opnfv/functest/data + repo_parser: /home/opnfv/repos/parser + repo_domino: /home/opnfv/repos/domino + repo_snaps: /home/opnfv/repos/snaps + functest: /home/opnfv/functest + functest_test: /home/opnfv/repos/functest/functest/opnfv_tests + results: /home/opnfv/functest/results + functest_conf: /home/opnfv/functest/conf + functest_data: /home/opnfv/functest/data dir_vIMS_data: /home/opnfv/functest/data/vIMS/ - dir_rally_inst: /home/opnfv/.rally + rally_inst: /home/opnfv/.rally openstack: creds: /home/opnfv/functest/conf/openstack.creds @@ -75,12 +75,12 @@ vping: vm_name_1: opnfv-vping-1 vm_name_2: opnfv-vping-2 image_name: functest-vping - vping_private_net_name: vping-net - vping_private_subnet_name: vping-subnet - vping_private_subnet_cidr: 192.168.130.0/24 - vping_router_name: vping-router - vping_sg_name: vPing-sg - vping_sg_descr: Security group for vPing test case + private_net_name: vping-net + private_subnet_name: vping-subnet + private_subnet_cidr: 192.168.130.0/24 + router_name: vping-router + sg_name: vPing-sg + sg_desc: Security group for vPing test case onos_sfc: image_base_url: http://artifacts.opnfv.org/sfc/demo @@ -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 @@ -109,53 +110,64 @@ rally: subnet_cidr: 192.168.140.0/24 router_name: rally-router -vIMS: - general: - tenant_name: vIMS - tenant_description: vIMS Functionality Testing - images: - ubuntu: - image_url: http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img - image_name: ubuntu_14.04 - centos: - image_url: http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1510.qcow2 - image_name: centos_7 - cloudify: - blueprint: - url: https://github.com/boucherv-orange/cloudify-manager-blueprints.git - branch: "3.3.1-build" - requierments: - ram_min: 3000 - os_image: centos_7 - inputs: - keystone_username: "" - keystone_password: "" - keystone_tenant_name: "" - keystone_url: "" - manager_public_key_name: 'manager-kp' - agent_public_key_name: 'agent-kp' - image_id: "" - flavor_id: "3" - external_network_name: "" - ssh_user: centos - agents_user: ubuntu - clearwater: - blueprint: - file_name: 'openstack-blueprint.yaml' - name: "clearwater-opnfv" - destination_folder: "opnfv-cloudify-clearwater" - url: https://github.com/Orange-OpenSource/opnfv-cloudify-clearwater.git - branch: "stable" - deployment-name: 'clearwater-opnfv' - requierments: - ram_min: 1700 - os_image: ubuntu_14.04 - inputs: - image_id: '' - flavor_id: '' - agent_user: 'ubuntu' - external_network_name: '' - public_domain: clearwater.opnfv +vnf: + aaa: + tenant_name: aaa + tenant_description: Freeradius server + tenant_images: {} + juju_epc: + tenant_name: epc + tenant_description: OAI EPC deployed with Juju + tenant_images: {} + cloudify_ims: + tenant_name: cloudify_ims + tenant_description: vIMS + tenant_images: + ubuntu_14.04: http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img + centos_7: http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1510.qcow2 + cloudify: + blueprint: + url: https://github.com/boucherv-orange/cloudify-manager-blueprints.git + branch: "3.3.1-build" + requierments: + ram_min: 3000 + os_image: centos_7 + inputs: + keystone_username: "" + keystone_password: "" + keystone_tenant_name: "" + keystone_url: "" + manager_public_key_name: 'manager-kp' + agent_public_key_name: 'agent-kp' + image_id: "" + flavor_id: "3" + external_network_name: "" + ssh_user: centos + agents_user: ubuntu + clearwater: + blueprint: + file_name: 'openstack-blueprint.yaml' + name: "clearwater-opnfv" + destination_folder: "opnfv-cloudify-clearwater" + url: https://github.com/Orange-OpenSource/opnfv-cloudify-clearwater.git + branch: "stable" + deployment_name: 'clearwater-opnfv' + requirements: + ram_min: 1700 + os_image: ubuntu_14.04 + inputs: + image_id: '' + flavor_id: '' + agent_user: 'ubuntu' + external_network_name: '' + public_domain: clearwater.opnfv + orchestra_ims: + tenant_name: orchestra_ims + tenant_description: ims deployed with openbaton + opera_ims: + tenant_name: opera_ims + tenant_description: ims deployed with open-o + ONOS: general: onosbench_username: 'root' @@ -174,10 +186,10 @@ ONOS: installer_master_username: 'root' installer_master_password: 'r00tme' multisite: - fuel_environment: + fuel: installer_username: 'root' installer_password: 'r00tme' - compass_environment: + compass: installer_username: 'root' installer_password: 'root' multisite_controller_ip: '10.1.0.50' @@ -197,15 +209,15 @@ promise: router_name: promise-router example: - example_vm_name: example-vm - example_flavor: m1.small - example_image_name: functest-example-vm - example_private_net_name: example-net - example_private_subnet_name: example-subnet - example_private_subnet_cidr: 192.168.170.0/24 - example_router_name: example-router - example_sg_name: example-sg - example_sg_descr: Example Security group + vm_name: example-vm + flavor: m1.small + image_name: functest-example-vm + private_net_name: example-net + private_subnet_name: example-subnet + private_subnet_cidr: 192.168.170.0/24 + router_name: example-router + sg_name: example-sg + sg_desc: Example Security group results: test_db_url: http://testresults.opnfv.org/test/api/v1 diff --git a/functest/ci/exec_test.sh b/functest/ci/exec_test.sh index 2b4cd8b45..7c96d69c3 100755 --- a/functest/ci/exec_test.sh +++ b/functest/ci/exec_test.sh @@ -47,11 +47,13 @@ function odl_tests(){ neutron_ip=$(openstack catalog show network | grep publicURL | cut -f3 -d"/" | cut -f1 -d":") odl_ip=${neutron_ip} odl_port=8080 + odl_restport=8181 if [ "$INSTALLER_TYPE" == "fuel" ]; then odl_port=8282 elif [ "$INSTALLER_TYPE" == "apex" ]; then odl_ip=$SDN_CONTROLLER_IP - odl_port=8181 + odl_port=8081 + odl_restport=8081 elif [ "$INSTALLER_TYPE" == "joid" ]; then odl_ip=$SDN_CONTROLLER elif [ "$INSTALLER_TYPE" == "compass" ]; then @@ -78,10 +80,15 @@ function run_test(){ odl_tests [[ "$report" == "-r" ]] && args=-p ${FUNCTEST_TEST_DIR}/sdn/odl/odl.py \ - --keystoneip $keystone_ip --neutronip $neutron_ip \ - --osusername ${OS_USERNAME} --ostenantname ${OS_TENANT_NAME} \ + --keystoneip $keystone_ip \ + --neutronip $neutron_ip \ + --odlip $odl_ip \ + --odlrestconfport $odl_restport \ + --odlwebport $odl_port \ --ospassword ${OS_PASSWORD} \ - --odlip $odl_ip --odlwebport $odl_port ${args} + --ostenantname ${OS_TENANT_NAME} \ + --osusername ${OS_USERNAME} \ + ${args} ;; "vims") python ${FUNCTEST_TEST_DIR}/vnf/ims/vims.py $clean_flag $report @@ -114,7 +121,7 @@ function run_test(){ "security_scan") echo "Sourcing Credentials ${FUNCTEST_CONF_DIR}/stackrc for undercloud .." source ${FUNCTEST_CONF_DIR}/stackrc - python ${REPOS_DIR}/securityscanning/security_scan.py --config ${REPOS_DIR}/securityscanning/config.ini + python ${FUNCTEST_TEST_DIR}/security_scan/security_scan.py --config ${FUNCTEST_TEST_DIR}/security_scan/config.ini ;; "copper") python ${FUNCTEST_TEST_DIR}/features/copper.py $report diff --git a/functest/ci/generate_report.py b/functest/ci/generate_report.py index a90bc5553..89d8fc628 100755 --- a/functest/ci/generate_report.py +++ b/functest/ci/generate_report.py @@ -1,11 +1,17 @@ +#!/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 json import re import urllib2 import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils -import functest.utils.functest_constants as ft_constants - +from functest.utils.constants import CONST COL_1_LEN = 25 COL_2_LEN = 15 @@ -17,14 +23,6 @@ COL_5_LEN = 75 # and then we can print the url to the specific test result -class GlobalVariables: - IS_CI_RUN = ft_constants.IS_CI_RUN - BUILD_TAG = ft_constants.CI_BUILD_TAG - INSTALLER = ft_constants.CI_INSTALLER_TYPE - CI_LOOP = ft_constants.CI_LOOP - SCENARIO = ft_constants.CI_SCENARIO - - logger = ft_logger.Logger("generate_report").getLogger() @@ -42,7 +40,7 @@ def init(tiers_to_run): def get_results_from_db(): url = "%s/results?build_tag=%s" % (ft_utils.get_db_url(), - GlobalVariables.BUILD_TAG) + CONST.BUILD_TAG) logger.debug("Query to rest api: %s" % url) try: data = json.load(urllib2.urlopen(url)) @@ -69,7 +67,7 @@ def print_line(w1, w2='', w3='', w4='', w5=''): '| ' + w2.ljust(COL_2_LEN - 1) + '| ' + w3.ljust(COL_3_LEN - 1) + '| ' + w4.ljust(COL_4_LEN - 1)) - if GlobalVariables.IS_CI_RUN: + if CONST.IS_CI_RUN: str += ('| ' + w5.ljust(COL_5_LEN - 1)) str += '|\n' return str @@ -77,7 +75,7 @@ def print_line(w1, w2='', w3='', w4='', w5=''): def print_line_no_columns(str): TOTAL_LEN = COL_1_LEN + COL_2_LEN + COL_3_LEN + COL_4_LEN + 2 - if GlobalVariables.IS_CI_RUN: + if CONST.IS_CI_RUN: TOTAL_LEN += COL_5_LEN + 1 return ('| ' + str.ljust(TOTAL_LEN) + "|\n") @@ -87,7 +85,7 @@ def print_separator(char="=", delimiter="+"): delimiter + char * COL_2_LEN + delimiter + char * COL_3_LEN + delimiter + char * COL_4_LEN) - if GlobalVariables.IS_CI_RUN: + if CONST.IS_CI_RUN: str += (delimiter + char * COL_5_LEN) str += '+\n' return str @@ -96,7 +94,7 @@ def print_separator(char="=", delimiter="+"): def main(args): executed_test_cases = args - if GlobalVariables.IS_CI_RUN: + if CONST.IS_CI_RUN: results = get_results_from_db() if results is not None: for test in executed_test_cases: @@ -105,15 +103,15 @@ def main(args): "result": data['result']}) TOTAL_LEN = COL_1_LEN + COL_2_LEN + COL_3_LEN + COL_4_LEN - if GlobalVariables.IS_CI_RUN: + if CONST.IS_CI_RUN: TOTAL_LEN += COL_5_LEN MID = TOTAL_LEN / 2 - if GlobalVariables.BUILD_TAG is not None: - if re.search("daily", GlobalVariables.BUILD_TAG) is not None: - GlobalVariables.CI_LOOP = "daily" + if CONST.BUILD_TAG is not None: + if re.search("daily", CONST.BUILD_TAG) is not None: + CONST.CI_LOOP = "daily" else: - GlobalVariables.CI_LOOP = "weekly" + CONST.CI_LOOP = "weekly" str = '' str += print_separator('=', delimiter="=") @@ -122,19 +120,19 @@ def main(args): str += print_line_no_columns(' ') str += print_line_no_columns(" Deployment description:") str += print_line_no_columns(" INSTALLER: %s" - % GlobalVariables.INSTALLER) - if GlobalVariables.SCENARIO is not None: + % CONST.INSTALLER_TYPE) + if CONST.DEPLOY_SCENARIO is not None: str += print_line_no_columns(" SCENARIO: %s" - % GlobalVariables.SCENARIO) - if GlobalVariables.BUILD_TAG is not None: + % CONST.DEPLOY_SCENARIO) + if CONST.BUILD_TAG is not None: str += print_line_no_columns(" BUILD TAG: %s" - % GlobalVariables.BUILD_TAG) - if GlobalVariables.CI_LOOP is not None: + % CONST.BUILD_TAG) + if CONST.CI_LOOP is not None: str += print_line_no_columns(" CI LOOP: %s" - % GlobalVariables.CI_LOOP) + % CONST.CI_LOOP) str += print_line_no_columns(' ') str += print_separator('=') - if GlobalVariables.IS_CI_RUN: + if CONST.IS_CI_RUN: str += print_line('TEST CASE', 'TIER', 'DURATION', 'RESULT', 'URL') else: str += print_line('TEST CASE', 'TIER', 'DURATION', 'RESULT') diff --git a/functest/ci/prepare_env.py b/functest/ci/prepare_env.py index 41cbbe098..74c751af9 100755 --- a/functest/ci/prepare_env.py +++ b/functest/ci/prepare_env.py @@ -13,35 +13,28 @@ # +import argparse import json import os import re import subprocess import sys -import argparse import yaml +from opnfv.utils import constants as opnfv_constants import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils import functest.utils.openstack_utils as os_utils -import functest.utils.functest_constants as ft_constants - -from opnfv.utils import constants as opnfv_constants +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() -CONFIG_FUNCTEST_PATH = ft_constants.CONFIG_FUNCTEST_YAML +CONFIG_FUNCTEST_PATH = CONST.CONFIG_FUNCTEST_YAML CONFIG_PATCH_PATH = os.path.join(os.path.dirname( CONFIG_FUNCTEST_PATH), "config_patch.yaml") @@ -49,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("==============================================") @@ -57,97 +63,97 @@ def check_env_variables(): print_separator() logger.info("Checking environment variables...") - if ft_constants.CI_INSTALLER_TYPE is None: + if CONST.INSTALLER_TYPE is None: logger.warning("The env variable 'INSTALLER_TYPE' is not defined.") - ft_constants.CI_INSTALLER_TYPE = "undefined" + CONST.INSTALLER_TYPE = "undefined" else: - if ft_constants.CI_INSTALLER_TYPE not in ft_constants.INSTALLERS: + if CONST.INSTALLER_TYPE not in opnfv_constants.INSTALLERS: logger.warning("INSTALLER_TYPE=%s is not a valid OPNFV installer. " "Available OPNFV Installers are : %s. " "Setting INSTALLER_TYPE=undefined." - % (ft_constants.CI_INSTALLER_TYPE, - ft_constants.INSTALLERS)) - ft_constants.CI_INSTALLER_TYPE = "undefined" + % (CONST.INSTALLER_TYPE, + opnfv_constants.INSTALLERS)) + CONST.INSTALLER_TYPE = "undefined" else: logger.info(" INSTALLER_TYPE=%s" - % ft_constants.CI_INSTALLER_TYPE) + % CONST.INSTALLER_TYPE) - if ft_constants.CI_INSTALLER_IP is None: + if CONST.INSTALLER_IP is None: logger.warning("The env variable 'INSTALLER_IP' is not defined. " "It is needed to fetch the OpenStack credentials. " "If the credentials are not provided to the " "container as a volume, please add this env variable " "to the 'docker run' command.") else: - logger.info(" INSTALLER_IP=%s" % ft_constants.CI_INSTALLER_IP) + logger.info(" INSTALLER_IP=%s" % CONST.INSTALLER_IP) - if ft_constants.CI_SCENARIO is None: + if CONST.DEPLOY_SCENARIO is None: logger.warning("The env variable 'DEPLOY_SCENARIO' is not defined. " "Setting CI_SCENARIO=undefined.") - ft_constants.CI_SCENARIO = "undefined" + CONST.DEPLOY_SCENARIO = "undefined" else: - logger.info(" DEPLOY_SCENARIO=%s" % ft_constants.CI_SCENARIO) - if ft_constants.CI_DEBUG: - logger.info(" CI_DEBUG=%s" % ft_constants.CI_DEBUG) + logger.info(" DEPLOY_SCENARIO=%s" % CONST.DEPLOY_SCENARIO) + if CONST.CI_DEBUG: + logger.info(" CI_DEBUG=%s" % CONST.CI_DEBUG) - if ft_constants.CI_NODE: - logger.info(" NODE_NAME=%s" % ft_constants.CI_NODE) + if CONST.NODE_NAME: + logger.info(" NODE_NAME=%s" % CONST.NODE_NAME) - if ft_constants.CI_BUILD_TAG: - logger.info(" BUILD_TAG=%s" % ft_constants.CI_BUILD_TAG) + if CONST.BUILD_TAG: + logger.info(" BUILD_TAG=%s" % CONST.BUILD_TAG) - if ft_constants.IS_CI_RUN: - logger.info(" IS_CI_RUN=%s" % ft_constants.IS_CI_RUN) + if CONST.IS_CI_RUN: + logger.info(" IS_CI_RUN=%s" % CONST.IS_CI_RUN) def create_directories(): print_separator() logger.info("Creating needed directories...") - if not os.path.exists(ft_constants.FUNCTEST_CONF_DIR): - os.makedirs(ft_constants.FUNCTEST_CONF_DIR) - logger.info(" %s created." % ft_constants.FUNCTEST_CONF_DIR) + if not os.path.exists(CONST.dir_functest_conf): + os.makedirs(CONST.dir_functest_conf) + logger.info(" %s created." % CONST.dir_functest_conf) else: logger.debug(" %s already exists." - % ft_constants.FUNCTEST_CONF_DIR) + % CONST.dir_functest_conf) - if not os.path.exists(ft_constants.FUNCTEST_DATA_DIR): - os.makedirs(ft_constants.FUNCTEST_DATA_DIR) - logger.info(" %s created." % ft_constants.FUNCTEST_DATA_DIR) + if not os.path.exists(CONST.dir_functest_data): + os.makedirs(CONST.dir_functest_data) + logger.info(" %s created." % CONST.dir_functest_data) else: logger.debug(" %s already exists." - % ft_constants.FUNCTEST_DATA_DIR) + % CONST.dir_functest_data) def source_rc_file(): print_separator() logger.info("Fetching RC file...") - if ft_constants.OPENSTACK_CREDS is None: + if CONST.openstack_creds is None: logger.warning("The environment variable 'creds' must be set and" "pointing to the local RC file. Using default: " "/home/opnfv/functest/conf/openstack.creds ...") - os.path.join(ft_constants.FUNCTEST_CONF_DIR, 'openstack.creds') + os.path.join(CONST.dir_functest_conf, 'openstack.creds') - if not os.path.isfile(ft_constants.OPENSTACK_CREDS): + if not os.path.isfile(CONST.openstack_creds): logger.info("RC file not provided. " "Fetching it from the installer...") - if ft_constants.CI_INSTALLER_IP is None: + if CONST.INSTALLER_IP is None: logger.error("The env variable CI_INSTALLER_IP must be provided in" " order to fetch the credentials from the installer.") sys.exit("Missing CI_INSTALLER_IP.") - if ft_constants.CI_INSTALLER_TYPE not in ft_constants.INSTALLERS: + if CONST.INSTALLER_TYPE not in opnfv_constants.INSTALLERS: logger.error("Cannot fetch credentials. INSTALLER_TYPE=%s is " "not a valid OPNFV installer. Available " "installers are : %s." % - (ft_constants.CI_INSTALLER_TYPE, + (CONST.INSTALLER_TYPE, opnfv_constants.INSTALLERS)) sys.exit("Wrong INSTALLER_TYPE.") cmd = ("/home/opnfv/repos/releng/utils/fetch_os_creds.sh " "-d %s -i %s -a %s" - % (ft_constants.OPENSTACK_CREDS, - ft_constants.CI_INSTALLER_TYPE, - ft_constants.CI_INSTALLER_IP)) + % (CONST.openstack_creds, + CONST.INSTALLER_TYPE, + CONST.INSTALLER_IP)) logger.debug("Executing command: %s" % cmd) p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) output = p.communicate()[0] @@ -157,38 +163,38 @@ def source_rc_file(): sys.exit(1) else: logger.info("RC file provided in %s." - % ft_constants.OPENSTACK_CREDS) - if os.path.getsize(ft_constants.OPENSTACK_CREDS) == 0: + % CONST.openstack_creds) + if os.path.getsize(CONST.openstack_creds) == 0: logger.error("The file %s is empty." - % ft_constants.OPENSTACK_CREDS) + % CONST.openstack_creds) sys.exit(1) logger.info("Sourcing the OpenStack RC file...") creds = os_utils.source_credentials( - ft_constants.OPENSTACK_CREDS) + CONST.openstack_creds) str = "" for key, value in creds.iteritems(): if re.search("OS_", key): str += "\n\t\t\t\t\t\t " + key + "=" + value if key == 'OS_AUTH_URL': - ft_constants.OS_AUTH_URL = value + CONST.OS_AUTH_URL = value elif key == 'OS_USERNAME': - ft_constants.OS_USERNAME = value + CONST.OS_USERNAME = value elif key == 'OS_TENANT_NAME': - ft_constants.OS_TENANT_NAME = value + CONST.OS_TENANT_NAME = value elif key == 'OS_PASSWORD': - ft_constants.OS_PASSWORD = value + CONST.OS_PASSWORD = value logger.debug("Used credentials: %s" % str) - logger.debug("OS_AUTH_URL:%s" % ft_constants.OS_AUTH_URL) - logger.debug("OS_USERNAME:%s" % ft_constants.OS_USERNAME) - logger.debug("OS_TENANT_NAME:%s" % ft_constants.OS_TENANT_NAME) - logger.debug("OS_PASSWORD:%s" % ft_constants.OS_PASSWORD) + logger.debug("OS_AUTH_URL:%s" % CONST.OS_AUTH_URL) + logger.debug("OS_USERNAME:%s" % CONST.OS_USERNAME) + logger.debug("OS_TENANT_NAME:%s" % CONST.OS_TENANT_NAME) + logger.debug("OS_PASSWORD:%s" % CONST.OS_PASSWORD) def patch_config_file(): updated = False for key in functest_patch_yaml: - if key in ft_constants.CI_SCENARIO: + if key in CONST.DEPLOY_SCENARIO: new_functest_yaml = dict(ft_utils.merge_dicts( ft_utils.get_functest_yaml(), functest_patch_yaml[key])) updated = True @@ -203,7 +209,7 @@ def patch_config_file(): def verify_deployment(): print_separator() logger.info("Verifying OpenStack services...") - cmd = ("%s/functest/ci/check_os.sh" % ft_constants.FUNCTEST_REPO_DIR) + cmd = ("%s/functest/ci/check_os.sh" % CONST.dir_repo_functest) logger.debug("Executing command: %s" % cmd) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) @@ -223,60 +229,64 @@ def install_rally(): cmd = "rally deployment destroy opnfv-rally" ft_utils.execute_command(cmd, error_msg=( "Deployment %s does not exist." - % ft_constants.RALLY_DEPLOYMENT_NAME), + % CONST.rally_deployment_name), verbose=False) 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 += ft_constants.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 " + - ft_constants.TEMPEST_REPO_DIR + - " --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(): msg_not_active = "The Functest environment is not installed." - if not os.path.isfile(ft_constants.ENV_FILE): + if not os.path.isfile(CONST.env_active): logger.error(msg_not_active) sys.exit(1) - with open(ft_constants.ENV_FILE, "r") as env_file: + with open(CONST.env_active, "r") as env_file: s = env_file.read() if not re.search("1", s): 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() @@ -284,17 +294,20 @@ def main(): patch_config_file() verify_deployment() install_rally() + install_tempest() - with open(ft_constants.ENV_FILE, "w") as env_file: + 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 557ba08dd..a5f1ab9e8 100755 --- a/functest/ci/run_tests.py +++ b/functest/ci/run_tests.py @@ -8,35 +8,23 @@ # http://www.apache.org/licenses/LICENSE-2.0 # +import argparse import datetime import importlib import os import re import sys -import argparse - import functest.ci.generate_report as generate_report import functest.ci.tier_builder as tb import functest.core.testcase_base as testcase_base +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.functest_constants as ft_constants import functest.utils.openstack_clean as os_clean import functest.utils.openstack_snapshot as os_snapshot import functest.utils.openstack_utils as os_utils - - -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() +from functest.utils.constants import CONST """ logging configuration """ @@ -44,12 +32,32 @@ logger = ft_logger.Logger("run_tests").getLogger() """ global variables """ -EXEC_SCRIPT = ("%s/functest/ci/exec_test.sh" % ft_constants.FUNCTEST_REPO_DIR) +EXEC_SCRIPT = ("%s/functest/ci/exec_test.sh" % CONST.dir_repo_functest) # This will be the return code of this script. If any of the tests fails, # 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 @@ -65,7 +73,7 @@ def print_separator(str, count=45): def source_rc_file(): - rc_file = ft_constants.OPENSTACK_CREDS + rc_file = CONST.openstack_creds if not os.path.isfile(rc_file): logger.error("RC file %s does not exist..." % rc_file) sys.exit(1) @@ -75,16 +83,20 @@ def source_rc_file(): if re.search("OS_", key): if key == 'OS_AUTH_URL': ft_constants.OS_AUTH_URL = value + CONST.OS_AUTH_URL = value elif key == 'OS_USERNAME': ft_constants.OS_USERNAME = value + CONST.OS_USERNAME = value elif key == 'OS_TENANT_NAME': ft_constants.OS_TENANT_NAME = value + CONST.OS_TENANT_NAME = value elif key == 'OS_PASSWORD': ft_constants.OS_PASSWORD = value - logger.debug("OS_AUTH_URL:%s" % ft_constants.OS_AUTH_URL) - logger.debug("OS_USERNAME:%s" % ft_constants.OS_USERNAME) - logger.debug("OS_TENANT_NAME:%s" % ft_constants.OS_TENANT_NAME) - logger.debug("OS_PASSWORD:%s" % ft_constants.OS_PASSWORD) + CONST.OS_PASSWORD = value + logger.debug("OS_AUTH_URL:%s" % CONST.OS_AUTH_URL) + logger.debug("OS_USERNAME:%s" % CONST.OS_USERNAME) + logger.debug("OS_TENANT_NAME:%s" % CONST.OS_TENANT_NAME) + logger.debug("OS_PASSWORD:%s" % CONST.OS_PASSWORD) def generate_os_snapshot(): @@ -115,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() @@ -143,7 +155,7 @@ def run_test(test, tier_name): result = test_case.run() if result == testcase_base.TestcaseBase.EX_OK: if GlobalVariables.REPORT_FLAG: - test_case.push_to_db() + test_case.publish_report() result = test_case.check_criteria() except ImportError: logger.exception("Cannot import module {}".format( @@ -167,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) @@ -201,17 +214,11 @@ def run_tier(tier): def run_all(tiers): summary = "" - BUILD_TAG = ft_constants.CI_BUILD_TAG - if BUILD_TAG is not None and re.search("daily", BUILD_TAG) is not None: - CI_LOOP = "daily" - else: - CI_LOOP = "weekly" - tiers_to_run = [] for tier in tiers.get_tiers(): if (len(tier.get_tests()) != 0 and - re.search(CI_LOOP, tier.get_ci_loop()) is not None): + re.search(CONST.CI_LOOP, tier.get_ci_loop()) is not None): tiers_to_run.append(tier) summary += ("\n - %s:\n\t %s" % (tier.get_name(), @@ -225,35 +232,37 @@ def run_all(tiers): generate_report.main(GlobalVariables.EXECUTED_TEST_CASES) -def main(): +def main(**kwargs): - CI_INSTALLER_TYPE = ft_constants.CI_INSTALLER_TYPE - CI_SCENARIO = ft_constants.CI_SCENARIO + CI_INSTALLER_TYPE = CONST.INSTALLER_TYPE + CI_SCENARIO = CONST.DEPLOY_SCENARIO - file = ft_constants.FUNCTEST_TESTCASES_YAML + 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: @@ -264,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 6f57c7030..ede082856 100755 --- a/functest/ci/testcases.yaml +++ b/functest/ci/testcases.yaml @@ -65,11 +65,12 @@ 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' class: 'TempestSmokeSerial' + - name: rally_sanity criteria: 'success_rate == 100%' @@ -120,7 +121,7 @@ tiers: the cloud's private network. dependencies: - installer: '' + installer: '^((?!netvirt).)*$' scenario: '' run: module: 'functest.opnfv_tests.openstack.snaps.connection_check' @@ -138,7 +139,7 @@ tiers: the cloud's private network. dependencies: - installer: '' + installer: '^((?!netvirt).)*$' scenario: '' run: module: 'functest.opnfv_tests.openstack.snaps.api_check' @@ -158,7 +159,7 @@ tiers: the cloud's private network. dependencies: - installer: '' + installer: '^((?!netvirt).)*$' scenario: '' run: module: 'functest.opnfv_tests.openstack.snaps.smoke' @@ -199,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' @@ -214,7 +215,6 @@ tiers: dependencies: installer: 'apex' scenario: '^((?!fdio).)*$' - - name: copper criteria: 'status == "PASS"' @@ -227,7 +227,6 @@ tiers: run: module: 'functest.opnfv_tests.features.copper' class: 'Copper' - - name: moon criteria: 'status == "PASS"' @@ -282,6 +281,18 @@ tiers: run: module: 'functest.opnfv_tests.vnf.rnc.parser' class: 'Parser' + - + name: orchestra + criteria: 'ret == 0' + blocking: false + description: >- + Test OpenBaton (Orchestra) stack + dependencies: + installer: 'joid' + scenario: 'unknown' + run: + module: 'functest.opnfv_tests.features.orchestrator.orchestra' + class: 'OpenbatonOrchestrator' - name: components order: 3 @@ -298,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' @@ -312,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: '' - @@ -323,7 +334,7 @@ tiers: Collection of VNF test cases. testcases: - - name: vims + name: cloudify_ims criteria: 'status == "PASS"' blocking: false description: >- @@ -332,3 +343,57 @@ tiers: dependencies: installer: '' scenario: '(ocl)|(nosdn)|^(os-odl)((?!bgpvpn).)*$' + run: + module: 'functest.opnfv_tests.vnf.ims.cloudify_ims' + class: 'ImsVnf' + - + name: aaa + criteria: 'ret == 0' + blocking: false + description: >- + Test suite from Parser project. + dependencies: + installer: '' + scenario: '' + run: + module: 'functest.opnfv_tests.vnf.aaa.aaa' + class: 'AaaVnf' + + - + name: juju_epc + criteria: 'ret == 0' + blocking: false + description: >- + Test suite from OAI project, vEPC deployed with Juju. + dependencies: + installer: 'unknown' + scenario: 'unknown' + run: + module: 'functest.opnfv_tests.vnf.epc.epc' + class: 'EpcVnf' + + - + name: orchestra_ims + criteria: 'ret == 0' + blocking: false + description: >- + VNF deployment with OpenBaton (Orchestra) + dependencies: + installer: 'unknown' + scenario: 'unknown' + run: + module: 'functest.opnfv_tests.vnf.ims.orchestra_ims' + class: 'ImsVnf' + + - + name: opera_ims + criteria: 'ret == 0' + blocking: false + description: >- + Evolution of vIMS + dependencies: + installer: 'unknown' + scenario: 'unknown' + run: + module: 'functest.opnfv_tests.vnf.ims.opera_ims' + class: 'ImsVnf' diff --git a/functest/cli/cli_base.py b/functest/cli/cli_base.py index 3b14fa336..cc697ed7e 100644 --- a/functest/cli/cli_base.py +++ b/functest/cli/cli_base.py @@ -121,8 +121,11 @@ def testcase_show(testname): @click.option('-n', '--noclean', is_flag=True, default=False, help='The created openstack resources by the test' 'will not be cleaned after the execution.') -def testcase_run(testname, noclean): - _testcase.run(testname, noclean) +@click.option('-r', '--report', is_flag=True, default=False, + help='Push results to the results DataBase. Only CI Pods' + 'have rights to do that.') +def testcase_run(testname, noclean, report): + _testcase.run(testname, noclean, report) @tier.command('list', help="Lists the available tiers.") @@ -147,5 +150,8 @@ def tier_gettests(tiername): @click.option('-n', '--noclean', is_flag=True, default=False, help='The created openstack resources by the tests' 'will not be cleaned after the execution.') -def tier_run(tiername, noclean): - _tier.run(tiername, noclean) +@click.option('-r', '--report', is_flag=True, default=False, + help='Push results to the results DataBase. Only CI Pods' + 'have rights to do that.') +def tier_run(tiername, noclean, report): + _tier.run(tiername, noclean, report) diff --git a/functest/cli/commands/cli_env.py b/functest/cli/commands/cli_env.py index 9f793e71f..9423631bf 100644 --- a/functest/cli/commands/cli_env.py +++ b/functest/cli/commands/cli_env.py @@ -12,8 +12,8 @@ import os import click import git +from functest.utils.constants import CONST import functest.utils.functest_utils as ft_utils -import functest.utils.functest_constants as ft_constants class CliEnv: @@ -28,7 +28,7 @@ class CliEnv: "it again? [y|n]\n") while True: if answer.lower() in ["y", "yes"]: - os.remove(ft_constants.ENV_FILE) + os.remove(CONST.env_active) break elif answer.lower() in ["n", "no"]: return @@ -36,40 +36,32 @@ class CliEnv: answer = raw_input("Invalid answer. Please type [y|n]\n") cmd = ("python %s/functest/ci/prepare_env.py start" % - ft_constants.FUNCTEST_REPO_DIR) + CONST.dir_repo_functest) ft_utils.execute_command(cmd) def show(self): - CI_INSTALLER_TYPE = ft_constants.CI_INSTALLER_TYPE - if CI_INSTALLER_TYPE is None: - CI_INSTALLER_TYPE = "Unknown" - CI_INSTALLER_IP = ft_constants.CI_INSTALLER_IP - if CI_INSTALLER_IP is None: - CI_INSTALLER_IP = "Unknown" - CI_INSTALLER = ("%s, %s" % (CI_INSTALLER_TYPE, CI_INSTALLER_IP)) - - CI_SCENARIO = ft_constants.CI_SCENARIO - if CI_SCENARIO is None: - CI_SCENARIO = "Unknown" - - CI_NODE = ft_constants.CI_NODE - if CI_NODE is None: - CI_NODE = "Unknown" - - repo = git.Repo(ft_constants.FUNCTEST_REPO_DIR) - branch = repo.head.reference - GIT_BRANCH = branch.name - GIT_HASH = branch.commit.hexsha - - CI_BUILD_TAG = ft_constants.CI_BUILD_TAG - if CI_BUILD_TAG is not None: - CI_BUILD_TAG = CI_BUILD_TAG.lstrip( + def _get_value(attr, default='Unknown'): + return attr if attr else default + + install_type = _get_value(CONST.INSTALLER_TYPE) + installer_ip = _get_value(CONST.INSTALLER_IP) + installer_info = ("%s, %s" % (install_type, installer_ip)) + scenario = _get_value(CONST.DEPLOY_SCENARIO) + node = _get_value(CONST.NODE_NAME) + repo_h = git.Repo(CONST.dir_repo_functest).head + if repo_h.is_detached: + git_branch = 'detached from FETCH_HEAD' + git_hash = repo_h.commit.hexsha + else: + branch = repo_h.reference + git_branch = branch.name + git_hash = branch.commit.hexsha + is_debug = _get_value(CONST.CI_DEBUG, 'false') + build_tag = CONST.BUILD_TAG + if build_tag is not None: + build_tag = build_tag.lstrip( "jenkins-").lstrip("functest").lstrip("-") - CI_DEBUG = ft_constants.CI_DEBUG - if CI_DEBUG is None: - CI_DEBUG = "false" - STATUS = "not ready" if self.status(verbose=False) == 0: STATUS = "ready" @@ -77,14 +69,14 @@ class CliEnv: click.echo("+======================================================+") click.echo("| Functest Environment info |") click.echo("+======================================================+") - click.echo("| INSTALLER: %s|" % CI_INSTALLER.ljust(41)) - click.echo("| SCENARIO: %s|" % CI_SCENARIO.ljust(41)) - click.echo("| POD: %s|" % CI_NODE.ljust(41)) - click.echo("| GIT BRACNH: %s|" % GIT_BRANCH.ljust(41)) - click.echo("| GIT HASH: %s|" % GIT_HASH.ljust(41)) - if CI_BUILD_TAG: - click.echo("| BUILD TAG: %s|" % CI_BUILD_TAG.ljust(41)) - click.echo("| DEBUG FLAG: %s|" % CI_DEBUG.ljust(41)) + click.echo("| INSTALLER: %s|" % installer_info.ljust(41)) + click.echo("| SCENARIO: %s|" % scenario.ljust(41)) + click.echo("| POD: %s|" % node.ljust(41)) + click.echo("| GIT BRACNH: %s|" % git_branch.ljust(41)) + click.echo("| GIT HASH: %s|" % git_hash.ljust(41)) + if build_tag: + click.echo("| BUILD TAG: %s|" % build_tag.ljust(41)) + click.echo("| DEBUG FLAG: %s|" % is_debug.ljust(41)) click.echo("+------------------------------------------------------+") click.echo("| STATUS: %s|" % STATUS.ljust(41)) click.echo("+------------------------------------------------------+") @@ -92,7 +84,7 @@ class CliEnv: def status(self, verbose=True): ret_val = 0 - if not os.path.isfile(ft_constants.ENV_FILE): + if not os.path.isfile(CONST.env_active): if verbose: click.echo("Functest environment is not installed.\n") ret_val = 1 diff --git a/functest/cli/commands/cli_os.py b/functest/cli/commands/cli_os.py index bb8592195..aeb34974f 100644 --- a/functest/cli/commands/cli_os.py +++ b/functest/cli/commands/cli_os.py @@ -12,23 +12,21 @@ import os import click +from functest.utils.constants import CONST import functest.utils.functest_utils as ft_utils import functest.utils.openstack_clean as os_clean import functest.utils.openstack_snapshot as os_snapshot -import functest.utils.functest_constants as ft_constants - - -OPENSTACK_RC_FILE = ft_constants.OPENSTACK_CREDS -OPENSTACK_SNAPSHOT_FILE = ft_constants.OPENSTACK_SNAPSHOT_FILE class CliOpenStack: def __init__(self): - self.os_auth_url = ft_constants.OS_AUTH_URL + self.os_auth_url = CONST.OS_AUTH_URL self.endpoint_ip = None self.endpoint_port = None - if self.os_auth_url is not None: + self.openstack_creds = CONST.openstack_creds + self.snapshot_file = CONST.openstack_snapshot_file + if self.os_auth_url: self.endpoint_ip = self.os_auth_url.rsplit("/")[2].rsplit(":")[0] self.endpoint_port = self.os_auth_url.rsplit("/")[2].rsplit(":")[1] @@ -43,13 +41,14 @@ class CliOpenStack: click.echo("Cannot talk to the endpoint %s\n" % self.endpoint_ip) exit(0) - def show_credentials(self): + @staticmethod + def show_credentials(): for key, value in os.environ.items(): if key.startswith('OS_'): click.echo("{}={}".format(key, value)) def fetch_credentials(self): - if os.path.isfile(OPENSTACK_RC_FILE): + if os.path.isfile(self.openstack_creds): answer = raw_input("It seems the RC file is already present. " "Do you want to overwrite it? [y|n]\n") while True: @@ -60,31 +59,31 @@ class CliOpenStack: else: answer = raw_input("Invalid answer. Please type [y|n]\n") - CI_INSTALLER_TYPE = ft_constants.CI_INSTALLER_TYPE - if CI_INSTALLER_TYPE is None: + installer_type = CONST.INSTALLER_TYPE + if installer_type is None: click.echo("The environment variable 'INSTALLER_TYPE' is not" "defined. Please export it") - CI_INSTALLER_IP = ft_constants.CI_INSTALLER_IP - if CI_INSTALLER_IP is None: + installer_ip = CONST.INSTALLER_IP + if installer_ip is None: click.echo("The environment variable 'INSTALLER_IP' is not" "defined. Please export it") cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s" - % (ft_constants.REPOS_DIR, - OPENSTACK_RC_FILE, - CI_INSTALLER_TYPE, - CI_INSTALLER_IP)) + % (CONST.dir_repos, + self.openstack_creds, + installer_type, + installer_ip)) click.echo("Fetching credentials from installer node '%s' with IP=%s.." - % (CI_INSTALLER_TYPE, CI_INSTALLER_IP)) + % (installer_type, installer_ip)) ft_utils.execute_command(cmd, verbose=False) def check(self): self.ping_endpoint() - cmd = ft_constants.FUNCTEST_REPO_DIR + "/functest/ci/check_os.sh" + cmd = CONST.dir_repo_functest + "/functest/ci/check_os.sh" ft_utils.execute_command(cmd, verbose=False) def snapshot_create(self): self.ping_endpoint() - if os.path.isfile(OPENSTACK_SNAPSHOT_FILE): + if os.path.isfile(self.snapshot_file): answer = raw_input("It seems there is already an OpenStack " "snapshot. Do you want to overwrite it with " "the current OpenStack status? [y|n]\n") @@ -100,18 +99,18 @@ class CliOpenStack: os_snapshot.main() def snapshot_show(self): - if not os.path.isfile(OPENSTACK_SNAPSHOT_FILE): + if not os.path.isfile(self.snapshot_file): click.echo("There is no OpenStack snapshot created. To create " "one run the command " "'functest openstack snapshot-create'") return - with open(OPENSTACK_SNAPSHOT_FILE, 'r') as yaml_file: + with open(self.snapshot_file, 'r') as yaml_file: click.echo("\n%s" % yaml_file.read()) def clean(self): self.ping_endpoint() - if not os.path.isfile(OPENSTACK_SNAPSHOT_FILE): + if not os.path.isfile(self.snapshot_file): click.echo("Not possible to clean OpenStack without a snapshot. " "This could cause problems. " "Run first the command " diff --git a/functest/cli/commands/cli_testcase.py b/functest/cli/commands/cli_testcase.py index 70a77a142..b6566245a 100644 --- a/functest/cli/commands/cli_testcase.py +++ b/functest/cli/commands/cli_testcase.py @@ -14,19 +14,17 @@ import os import click import functest.ci.tier_builder as tb +from functest.utils.constants import CONST import functest.utils.functest_utils as ft_utils import functest.utils.functest_vacation as vacation -import functest.utils.functest_constants as ft_constants class CliTestcase: def __init__(self): - CI_INSTALLER_TYPE = ft_constants.CI_INSTALLER_TYPE - CI_SCENARIO = ft_constants.CI_SCENARIO - testcases = ft_constants.FUNCTEST_TESTCASES_YAML - - self.tiers = tb.TierBuilder(CI_INSTALLER_TYPE, CI_SCENARIO, testcases) + self.tiers = tb.TierBuilder(CONST.INSTALLER_TYPE, + CONST.DEPLOY_SCENARIO, + CONST.functest_testcases_yaml) def list(self): summary = "" @@ -43,19 +41,23 @@ class CliTestcase: click.echo(description) - def run(self, testname, noclean=False): + @staticmethod + def run(testname, noclean=False, report=False): + + flags = "" + if noclean: + flags += "-n " + if report: + flags += "-r " + if testname == 'vacation': vacation.main() - elif not os.path.isfile(ft_constants.ENV_FILE): + elif not os.path.isfile(CONST.env_active): click.echo("Functest environment is not ready. " "Run first 'functest env prepare'") else: tests = testname.split(",") for test in tests: - if noclean: - cmd = ("python %s/functest/ci/run_tests.py " - "-n -t %s" % (ft_constants.FUNCTEST_REPO_DIR, test)) - else: - cmd = ("python %s/functest/ci/run_tests.py " - "-t %s" % (ft_constants.FUNCTEST_REPO_DIR, test)) + cmd = ("python %s/functest/ci/run_tests.py " + "%s -t %s" % (CONST.dir_repo_functest, flags, test)) ft_utils.execute_command(cmd) diff --git a/functest/cli/commands/cli_tier.py b/functest/cli/commands/cli_tier.py index 9da51072a..b9d25b6d0 100644 --- a/functest/cli/commands/cli_tier.py +++ b/functest/cli/commands/cli_tier.py @@ -14,17 +14,16 @@ import os import click import functest.ci.tier_builder as tb +from functest.utils.constants import CONST import functest.utils.functest_utils as ft_utils -import functest.utils.functest_constants as ft_constants class CliTier: def __init__(self): - CI_INSTALLER_TYPE = ft_constants.CI_INSTALLER_TYPE - CI_SCENARIO = ft_constants.CI_SCENARIO - testcases = ft_constants.FUNCTEST_TESTCASES_YAML - self.tiers = tb.TierBuilder(CI_INSTALLER_TYPE, CI_SCENARIO, testcases) + self.tiers = tb.TierBuilder(CONST.INSTALLER_TYPE, + CONST.DEPLOY_SCENARIO, + CONST.functest_testcases_yaml) def list(self): summary = "" @@ -54,15 +53,19 @@ class CliTier: tests = tier.get_test_names() click.echo("Test cases in tier '%s':\n %s\n" % (tiername, tests)) - def run(self, tiername, noclean=False): - if not os.path.isfile(ft_constants.ENV_FILE): + @staticmethod + def run(tiername, noclean=False, report=False): + + flags = "" + if noclean: + flags += "-n " + if report: + flags += "-r " + + if not os.path.isfile(CONST.env_active): click.echo("Functest environment is not ready. " "Run first 'functest env prepare'") else: - if noclean: - cmd = ("python %s/functest/ci/run_tests.py " - "-n -t %s" % (ft_constants.FUNCTEST_REPO_DIR, tiername)) - else: - cmd = ("python %s/functest/ci/run_tests.py " - "-t %s" % (ft_constants.FUNCTEST_REPO_DIR, tiername)) + cmd = ("python %s/functest/ci/run_tests.py " + "%s -t %s" % (CONST.dir_repo_functest, flags, tiername)) ft_utils.execute_command(cmd) diff --git a/functest/core/feature_base.py b/functest/core/feature_base.py index 01a27f305..873e21dae 100644 --- a/functest/core/feature_base.py +++ b/functest/core/feature_base.py @@ -3,6 +3,7 @@ import time import testcase_base as base import functest.utils.functest_utils as ft_utils import functest.utils.functest_logger as ft_logger +from functest.utils.constants import CONST class FeatureBase(base.TestcaseBase): @@ -11,7 +12,7 @@ class FeatureBase(base.TestcaseBase): self.project_name = project self.case_name = case self.cmd = cmd - self.repo = self.get_conf('general.directories.{}'.format(repo)) + self.repo = CONST.__getattribute__(repo) self.result_file = self.get_result_file() self.logger = ft_logger.Logger(project).getLogger() @@ -44,15 +45,10 @@ class FeatureBase(base.TestcaseBase): return exit_code def get_result_file(self): - dir = self.get_conf('general.directories.dir_results') - return "{}/{}.log".format(dir, self.project_name) + return "{}/{}.log".format(CONST.dir_results, self.project_name) def log_results(self): ft_utils.logger_test_results(self.project_name, self.case_name, self.criteria, self.details) - - @staticmethod - def get_conf(parameter): - return ft_utils.get_functest_config(parameter) diff --git a/functest/core/testcase_base.py b/functest/core/testcase_base.py index 838b63983..ec46bc643 100644 --- a/functest/core/testcase_base.py +++ b/functest/core/testcase_base.py @@ -9,6 +9,7 @@ import os +from functest.utils.constants import CONST import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils @@ -17,7 +18,7 @@ class TestcaseBase(object): EX_OK = os.EX_OK EX_RUN_ERROR = os.EX_SOFTWARE - EX_PUSH_TO_DB_ERROR = os.EX_SOFTWARE - 1 + EX_PUBLISH_RESULT_FAILED = os.EX_SOFTWARE - 1 EX_TESTCASE_FAILED = os.EX_SOFTWARE - 2 logger = ft_logger.Logger(__name__).getLogger() @@ -43,21 +44,45 @@ class TestcaseBase(object): self.logger.error("Run must be implemented") return TestcaseBase.EX_RUN_ERROR - def push_to_db(self): + def publish_report(self): + if "RESULTS_STORE" in os.environ: + CONST.results_test_db_url = os.environ['RESULTS_STORE'] + try: assert self.project_name assert self.case_name assert self.criteria assert self.start_time assert self.stop_time - if ft_utils.push_results_to_db( - self.project_name, self.case_name, self.start_time, - self.stop_time, self.criteria, self.details): - self.logger.info("The results were successfully pushed to DB") - return TestcaseBase.EX_OK + if CONST.results_test_db_url.lower().startswith( + ("http://", "https://")): + self.push_to_db() + elif CONST.results_test_db_url.lower().startswith("file://"): + self.write_to_file() else: - self.logger.error("The results cannot be pushed to DB") - return TestcaseBase.EX_PUSH_TO_DB_ERROR + self.logger.error("Please check parameter test_db_url and " + "OS environ variable RESTULTS_STORE") + return TestcaseBase.EX_PUBLISH_RESULT_FAILED except Exception: - self.logger.exception("The results cannot be pushed to DB") - return TestcaseBase.EX_PUSH_TO_DB_ERROR + self.logger.exception("The results cannot be stored") + return TestcaseBase.EX_PUBLISH_RESULT_FAILED + + def write_to_file(self): + if ft_utils.write_results_to_file( + self.project_name, self.case_name, self.start_time, + self.stop_time, self.criteria, self.details): + self.logger.info("The results were successfully written to a file") + return TestcaseBase.EX_OK + else: + self.logger.error("write results to a file failed") + return TestcaseBase.EX_PUBLISH_RESULT_FAILED + + def push_to_db(self): + if ft_utils.push_results_to_db( + self.project_name, self.case_name, self.start_time, + self.stop_time, self.criteria, self.details): + self.logger.info("The results were successfully pushed to DB") + return TestcaseBase.EX_OK + else: + self.logger.error("The results cannot be pushed to DB") + return TestcaseBase.EX_PUBLISH_RESULT_FAILED diff --git a/functest/core/vnf_base.py b/functest/core/vnf_base.py new file mode 100644 index 000000000..4d019858a --- /dev/null +++ b/functest/core/vnf_base.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python + +# Copyright (c) 2016 Orange and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +import os +import time + +import inspect + + +import functest.utils.functest_logger as ft_logger +import functest.utils.openstack_utils as os_utils +import functest.utils.functest_utils as ft_utils +import testcase_base as base +from functest.utils.constants import CONST + + +class VnfOnBoardingBase(base.TestcaseBase): + + logger = ft_logger.Logger(__name__).getLogger() + + def __init__(self, project='functest', case='', repo='', cmd=''): + super(VnfOnBoardingBase, self).__init__() + self.repo = repo + self.project_name = project + self.case_name = case + self.cmd = cmd + self.details = {} + self.data_dir = CONST.dir_functest_data + self.details['orchestrator'] = {} + self.details['vnf'] = {} + self.details['test_vnf'] = {} + self.images = {} + try: + self.tenant_name = CONST.__getattribute__( + 'vnf_{}_tenant_name'.format(self.case_name)) + self.tenant_description = CONST.__getattribute__( + 'vnf_{}_tenant_description'.format(self.case_name)) + except: + raise Exception("Unknown VNF case=" + self.case_name) + + try: + self.images = CONST.__getattribute__( + 'vnf_{}_tenant_images'.format(self.case_name)) + except: + self.logger.warn("No tenant image defined for this VNF") + + def execute(self): + self.start_time = time.time() + # Prepare the test (Create Tenant, User, ...) + self.logger.info("Create VNF Onboarding environment") + self.prepare() + + # Deploy orchestrator + try: + self.logger.info("Deploy orchestrator (if necessary)") + orchestrator_ready_time = time.time() + res_orchestrator = self.deploy_orchestrator() + # orchestrator is not mandatory + if res_orchestrator is not None: + self.details['orchestrator']['status'] = ( + res_orchestrator['status']) + self.details['orchestrator']['result'] = ( + res_orchestrator['result']) + self.details['orchestrator']['duration'] = round( + orchestrator_ready_time - self.start_time, 1) + except: + self.logger.warn("Problem with the Orchestrator") + + # Deploy VNF + try: + self.logger.info("Deploy VNF " + self.case_name) + res_deploy_vnf = self.deploy_vnf() + vnf_ready_time = time.time() + self.details['vnf']['status'] = res_deploy_vnf['status'] + self.details['vnf']['result'] = res_deploy_vnf['result'] + self.details['vnf']['duration'] = round( + vnf_ready_time - orchestrator_ready_time, 1) + except: + raise Exception("Error during VNF deployment") + + # Test VNF + try: + self.logger.info("Test VNF") + res_test_vnf = self.test_vnf() + test_vnf_done_time = time.time() + self.details['test_vnf']['status'] = res_test_vnf['status'] + self.details['test_vnf']['result'] = res_test_vnf['result'] + self.details['test_vnf']['duration'] = round( + test_vnf_done_time - vnf_ready_time, 1) + except: + raise Exception("Error when running VNF tests") + + # Clean the system + self.clean() + self.stop_time = time.time() + + exit_code = self.parse_results() + self.log_results() + return exit_code + + # prepare state could consist in the creation of the resources + # a dedicated user + # a dedictaed tenant + # dedicated images + def prepare(self): + self.creds = os_utils.get_credentials() + self.keystone_client = os_utils.get_keystone_client() + + self.logger.info("Prepare OpenStack plateform(create tenant and user)") + user_id = os_utils.get_user_id(self.keystone_client, + self.creds['username']) + if user_id == '': + self.step_failure("Failed to get id of " + + self.creds['username']) + + tenant_id = os_utils.create_tenant( + self.keystone_client, self.tenant_name, self.tenant_description) + if not tenant_id: + self.step_failure("Failed to create " + + self.tenant_name + " tenant") + + roles_name = ["admin", "Admin"] + role_id = '' + for role_name in roles_name: + if role_id == '': + role_id = os_utils.get_role_id(self.keystone_client, role_name) + + if role_id == '': + self.logger.error("Failed to get id for %s role" % role_name) + self.step_failure("Failed to get role id of " + role_name) + + if not os_utils.add_role_user(self.keystone_client, user_id, + role_id, tenant_id): + self.logger.error("Failed to add %s on tenant" % + self.creds['username']) + self.step_failure("Failed to add %s on tenant" % + self.creds['username']) + + user_id = os_utils.create_user(self.keystone_client, + self.tenant_name, + self.tenant_name, + None, + tenant_id) + if not user_id: + self.logger.error("Failed to create %s user" % self.tenant_name) + self.step_failure("Failed to create user ") + + self.logger.info("Update OpenStack creds informations") + self.creds.update({ + "tenant": self.tenant_name, + }) + self.neutron_client = os_utils.get_neutron_client(self.creds) + self.nova_client = os_utils.get_nova_client(self.creds) + self.creds.update({ + "username": self.tenant_name, + "password": self.tenant_name, + }) + self.glance_client = os_utils.get_glance_client(self.creds) + self.logger.info("Upload some OS images if it doesn't exist") + + temp_dir = os.path.join(self.data_dir, "tmp/") + for image_name, image_url in self.images.iteritems(): + image_id = os_utils.get_image_id(self.glance_client, image_name) + + if image_id == '': + self.logger.info("""%s image doesn't exist on glance repository. Try + downloading this image and upload on glance !""" % image_name) + image_id = os_utils.download_and_add_image_on_glance( + self.glance_client, image_name, image_url, temp_dir) + + if image_id == '': + self.step_failure( + "Failed to find or upload required OS " + "image for this deployment") + + self.logger.info("Update security group quota for this tenant") + + if not os_utils.update_sg_quota(self.neutron_client, + tenant_id, 50, 100): + self.step_failure("Failed to update security group quota" + + " for tenant " + self.tenant_name) + + # orchestrator is not mandatory to dpeloy and test VNF + def deploy_orchestrator(self, **kwargs): + pass + + # TODO see how to use built-in exception from releng module + def deploy_vnf(self): + self.logger.error("VNF must be deployed") + raise Exception("VNF not deployed") + + def test_vnf(self): + self.logger.error("VNF must be tested") + raise Exception("VNF not tested") + + def clean(self): + self.logger.info("test cleaning") + + self.logger.info("Removing %s tenant .." % self.tenant_name) + tenant_id = os_utils.get_tenant_id(self.keystone_client, + self.tenant_name) + if tenant_id == '': + self.logger.error("Error : Failed to get id of %s tenant" % + self.tenant_name) + else: + if not os_utils.delete_tenant(self.keystone_client, tenant_id): + self.logger.error("Error : Failed to remove %s tenant" % + self.tenant_name) + + self.logger.info("Removing %s user .." % self.tenant_name) + user_id = os_utils.get_user_id( + self.keystone_client, self.tenant_name) + if user_id == '': + self.logger.error("Error : Failed to get id of %s user" % + self.tenant_name) + else: + if not os_utils.delete_user(self.keystone_client, user_id): + self.logger.error("Error : Failed to remove %s user" % + self.tenant_name) + + def parse_results(self): + exit_code = self.EX_OK + self.criteria = "PASS" + self.logger.info(self.details) + # The 2 VNF steps must be OK to get a PASS result + if (self.details['vnf']['status'] is not "PASS" or + self.details['test_vnf']['status'] is not "PASS"): + exit_code = self.EX_RUN_ERROR + self.criteria = "FAIL" + return exit_code + + def log_results(self): + ft_utils.logger_test_results(self.project_name, + self.case_name, + self.criteria, + self.details) + + def step_failure(self, error_msg): + part = inspect.stack()[1][3] + self.details[part]['status'] = 'FAIL' + self.details[part]['result'] = error_msg + raise Exception(error_msg) diff --git a/functest/opnfv_tests/features/copper.py b/functest/opnfv_tests/features/copper.py index 8d5393c95..a10364e26 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 = 'bash %s/tests/run.sh' % self.repo diff --git a/functest/opnfv_tests/features/domino.py b/functest/opnfv_tests/features/domino.py index 341648f4b..b36220fa0 100755 --- a/functest/opnfv_tests/features/domino.py +++ b/functest/opnfv_tests/features/domino.py @@ -14,65 +14,12 @@ # 0.3: add report flag to push results when needed # 0.4: refactoring to match Test abstraction class -import argparse -import os -import sys -import time +import functest.core.feature_base as base -import functest.core.testcase_base as testcase_base -import functest.utils.functest_constants as ft_constants -import functest.utils.functest_logger as ft_logger -import functest.utils.functest_utils as ft_utils - - -class DominoCases(testcase_base.TestcaseBase): - DOMINO_REPO = ft_constants.DOMINO_REPO_DIR - RESULTS_DIR = ft_constants.FUNCTEST_RESULTS_DIR - logger = ft_logger.Logger("domino").getLogger() +class Domino(base.FeatureBase): def __init__(self): - super(DominoCases, self).__init__() - self.project_name = "domino" - self.case_name = "domino-multinode" - - def main(self, **kwargs): - cmd = 'cd %s && ./tests/run_multinode.sh' % self.DOMINO_REPO - log_file = os.path.join(self.RESULTS_DIR, "domino.log") - start_time = time.time() - - ret = ft_utils.execute_command(cmd, - output_file=log_file) - - stop_time = time.time() - if ret == 0: - self.logger.info("domino OK") - status = 'PASS' - else: - self.logger.info("domino FAILED") - status = "FAIL" - - # report status only if tests run (FAIL OR PASS) - self.criteria = status - self.start_time = start_time - self.stop_time = stop_time - self.details = {} - - def run(self): - kwargs = {} - return self.main(**kwargs) - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument("-r", "--report", - help="Create json result file", - action="store_true") - args = vars(parser.parse_args()) - domino = DominoCases() - try: - result = domino.main(**args) - if result != testcase_base.TestcaseBase.EX_OK: - sys.exit(result) - if args['report']: - sys.exit(domino.push_to_db()) - except Exception: - sys.exit(testcase_base.TestcaseBase.EX_RUN_ERROR) + super(Domino, self).__init__(project='domino', + case='domino-multinode', + repo='dir_repo_domino') + self.cmd = 'cd %s && ./tests/run_multinode.sh' % self.repo diff --git a/functest/opnfv_tests/features/odl_sfc.py b/functest/opnfv_tests/features/odl_sfc.py index b194b2840..3b68d4204 100644 --- a/functest/opnfv_tests/features/odl_sfc.py +++ b/functest/opnfv_tests/features/odl_sfc.py @@ -7,7 +7,6 @@ # # http://www.apache.org/licenses/LICENSE-2.0 # - import functest.core.feature_base as base @@ -17,4 +16,5 @@ class OpenDaylightSFC(base.FeatureBase): super(OpenDaylightSFC, self).__init__(project='sfc', case='functest-odl-sfc"', repo='dir_repo_sfc') - self.cmd = 'cd %s/tests/functest && python ./run_tests.py' % self.repo + dir_sfc_functest = '{}/sfc/tests/functest'.format(self.repo) + self.cmd = 'cd %s && python ./run_tests.py' % dir_sfc_functest diff --git a/functest/opnfv_tests/features/sdnvpn.py b/functest/opnfv_tests/features/sdnvpn.py index 451299eb3..1919a03c2 100755 --- a/functest/opnfv_tests/features/sdnvpn.py +++ b/functest/opnfv_tests/features/sdnvpn.py @@ -7,70 +7,14 @@ # # http://www.apache.org/licenses/LICENSE-2.0 # +import functest.core.feature_base as base -import argparse -import os -import sys -import time - -import functest.core.testcase_base as testcase_base -import functest.utils.functest_constants as ft_constants -import functest.utils.functest_logger as ft_logger -import functest.utils.functest_utils as ft_utils - - -class SdnVpnTests(testcase_base.TestcaseBase): - SDNVPN_REPO_TESTS = os.path.join( - ft_constants.SDNVPN_REPO_DIR, "tests/functest") - logger = ft_logger.Logger("sdnvpn").getLogger() +class SdnVpnTests(base.FeatureBase): def __init__(self): - super(SdnVpnTests, self).__init__() - self.project_name = "sdnvpn" - self.case_name = "bgpvpn" - - def main(self, **kwargs): - os.chdir(self.SDNVPN_REPO_TESTS) - cmd = 'run_tests.py' - log_file = os.path.join( - ft_constants.FUNCTEST_RESULTS_DIR, "sdnvpn.log") - start_time = time.time() - - ret = ft_utils.execute_command(cmd, - output_file=log_file) - - stop_time = time.time() - if ret == 0: - self.logger.info("%s OK" % self.case_name) - status = 'PASS' - else: - self.logger.info("%s FAILED" % self.case_name) - status = "FAIL" - - # report status only if tests run (FAIL OR PASS) - self.criteria = status - self.start_time = start_time - self.stop_time = stop_time - self.details = {} - - def run(self): - kwargs = {} - return self.main(**kwargs) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument("-r", "--report", - help="Create json result file", - action="store_true") - args = vars(parser.parse_args()) - sdnvpn = SdnVpnTests() - try: - result = sdnvpn.main(**args) - if result != testcase_base.TestcaseBase.EX_OK: - sys.exit(result) - if args['report']: - sys.exit(sdnvpn.push_to_db()) - except Exception: - sys.exit(testcase_base.TestcaseBase.EX_RUN_ERROR) + super(SdnVpnTests, self).__init__(project='sdnvpn', + case='bgpvpn', + repo='dir_repo_sdnvpn') + dir_sfc_functest = '{}/sdnvpn/test/functest'.format(self.repo) + self.cmd = 'cd %s && python ./run_tests.py' % dir_sfc_functest diff --git a/functest/opnfv_tests/mano/orchestra.py b/functest/opnfv_tests/mano/orchestra.py new file mode 100755 index 000000000..fd5e40d05 --- /dev/null +++ b/functest/opnfv_tests/mano/orchestra.py @@ -0,0 +1,24 @@ +#!/usr/bin/python +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import functest.core.feature_base as base + + +class Orchestra(base.FeatureBase): + def __init__(self): + super(Orchestra, self).__init__(project='orchestra', + case='orchestra', + repo='dir_repo_orchestra') + # TODO + # self.cmd = "%s/tests/run.sh %s/tests" % (self.repo, self.repo) diff --git a/functest/opnfv_tests/openstack/examples/create_instance_and_ip.py b/functest/opnfv_tests/openstack/examples/create_instance_and_ip.py index 4a9ff713b..b44008642 100755 --- a/functest/opnfv_tests/openstack/examples/create_instance_and_ip.py +++ b/functest/opnfv_tests/openstack/examples/create_instance_and_ip.py @@ -14,9 +14,9 @@ import argparse import os import sys +from functest.utils.constants import CONST import functest.utils.functest_logger as ft_logger import functest.utils.openstack_utils as os_utils -import functest.utils.functest_constants as ft_constants parser = argparse.ArgumentParser() @@ -29,26 +29,26 @@ args = parser.parse_args() """ logging configuration """ logger = ft_logger.Logger("create_instance_and_ip").getLogger() -HOME = ft_constants.HOME + "/" +HOME = CONST.dir_home + "/" VM_BOOT_TIMEOUT = 180 -EXAMPLE_INSTANCE_NAME = ft_constants.EXAMPLE_INSTANCE_NAME -EXAMPLE_FLAVOR = ft_constants.EXAMPLE_FLAVOR -EXAMPLE_IMAGE_NAME = ft_constants.EXAMPLE_IMAGE_NAME -IMAGE_FILENAME = ft_constants.GLANCE_IMAGE_FILENAME -IMAGE_FORMAT = ft_constants.GLANCE_IMAGE_FORMAT -IMAGE_PATH = os.path.join(ft_constants.FUNCTEST_DATA_DIR, IMAGE_FILENAME) +EXAMPLE_INSTANCE_NAME = CONST.example_vm_name +EXAMPLE_FLAVOR = CONST.example_flavor +EXAMPLE_IMAGE_NAME = CONST.example_image_name +IMAGE_FILENAME = CONST.openstack_image_file_name +IMAGE_FORMAT = CONST.openstack_image_disk_format +IMAGE_PATH = os.path.join(CONST.dir_functest_data, IMAGE_FILENAME) # NEUTRON Private Network parameters -EXAMPLE_PRIVATE_NET_NAME = ft_constants.EXAMPLE_PRIVATE_NET_NAME -EXAMPLE_PRIVATE_SUBNET_NAME = ft_constants.EXAMPLE_PRIVATE_SUBNET_NAME -EXAMPLE_PRIVATE_SUBNET_CIDR = ft_constants.EXAMPLE_PRIVATE_SUBNET_CIDR -EXAMPLE_ROUTER_NAME = ft_constants.EXAMPLE_ROUTER_NAME +EXAMPLE_PRIVATE_NET_NAME = CONST.example_private_net_name +EXAMPLE_PRIVATE_SUBNET_NAME = CONST.example_private_subnet_name +EXAMPLE_PRIVATE_SUBNET_CIDR = CONST.example_private_subnet_cidr +EXAMPLE_ROUTER_NAME = CONST.example_router_name -EXAMPLE_SECGROUP_NAME = ft_constants.EXAMPLE_SECGROUP_NAME -EXAMPLE_SECGROUP_DESCR = ft_constants.EXAMPLE_SECGROUP_DESCR +EXAMPLE_SECGROUP_NAME = CONST.example_sg_name +EXAMPLE_SECGROUP_DESCR = CONST.example_sg_desc def main(): diff --git a/functest/opnfv_tests/openstack/healthcheck/healthcheck.sh b/functest/opnfv_tests/openstack/healthcheck/healthcheck.sh index e27cf4b4b..57aa0c707 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 6d8f01602..b02fd4270 100755 --- a/functest/opnfv_tests/openstack/rally/run_rally-cert.py +++ b/functest/opnfv_tests/openstack/rally/run_rally-cert.py @@ -1,34 +1,27 @@ -#!/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 import os import re import subprocess import time -import argparse import iniparse import yaml +from functest.utils.constants import CONST import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils import functest.utils.openstack_utils as os_utils -import functest.utils.functest_constants as ft_constants tests = ['authenticate', 'glance', 'cinder', 'heat', 'keystone', 'neutron', 'nova', 'quotas', 'requests', 'vm', 'all'] @@ -71,8 +64,7 @@ else: """ logging configuration """ logger = ft_logger.Logger("run_rally-cert").getLogger() -RALLY_DIR = os.path.join(ft_constants.FUNCTEST_REPO_DIR, - ft_constants.RALLY_RELATIVE_PATH) +RALLY_DIR = os.path.join(CONST.dir_repo_functest, CONST.dir_rally) RALLY_SCENARIO_DIR = os.path.join(RALLY_DIR, "scenario") SANITY_MODE_DIR = os.path.join(RALLY_SCENARIO_DIR, "sanity") FULL_MODE_DIR = os.path.join(RALLY_SCENARIO_DIR, "full") @@ -87,19 +79,19 @@ TENANTS_AMOUNT = 3 ITERATIONS_AMOUNT = 10 CONCURRENCY = 4 -RESULTS_DIR = os.path.join(ft_constants.FUNCTEST_RESULTS_DIR, 'rally') -TEMPEST_CONF_FILE = os.path.join(ft_constants.FUNCTEST_RESULTS_DIR, +RESULTS_DIR = os.path.join(CONST.dir_results, 'rally') +TEMPEST_CONF_FILE = os.path.join(CONST.dir_results, 'tempest/tempest.conf') -RALLY_PRIVATE_NET_NAME = ft_constants.RALLY_PRIVATE_NET_NAME -RALLY_PRIVATE_SUBNET_NAME = ft_constants.RALLY_PRIVATE_SUBNET_NAME -RALLY_PRIVATE_SUBNET_CIDR = ft_constants.RALLY_PRIVATE_SUBNET_CIDR -RALLY_ROUTER_NAME = ft_constants.RALLY_ROUTER_NAME +RALLY_PRIVATE_NET_NAME = CONST.rally_network_name +RALLY_PRIVATE_SUBNET_NAME = CONST.rally_subnet_name +RALLY_PRIVATE_SUBNET_CIDR = CONST.rally_subnet_cidr +RALLY_ROUTER_NAME = CONST.rally_router_name -GLANCE_IMAGE_NAME = ft_constants.GLANCE_IMAGE_NAME -GLANCE_IMAGE_FILENAME = ft_constants.GLANCE_IMAGE_FILENAME -GLANCE_IMAGE_FORMAT = ft_constants.GLANCE_IMAGE_FORMAT -GLANCE_IMAGE_PATH = os.path.join(ft_constants.FUNCTEST_DATA_DIR, +GLANCE_IMAGE_NAME = CONST.openstack_image_name +GLANCE_IMAGE_FILENAME = CONST.openstack_image_file_name +GLANCE_IMAGE_FORMAT = CONST.openstack_image_disk_format +GLANCE_IMAGE_PATH = os.path.join(CONST.dir_functest_data, GLANCE_IMAGE_FILENAME) CINDER_VOLUME_TYPE_NAME = "volume_test" @@ -181,7 +173,7 @@ def build_task_args(test_file_name): net_id = GlobalVariables.network_dict['net_id'] task_args['netid'] = str(net_id) - auth_url = ft_constants.OS_AUTH_URL + auth_url = CONST.OS_AUTH_URL if auth_url is not None: task_args['request_url'] = auth_url.rsplit(":", 1)[0] else: @@ -271,8 +263,8 @@ def excl_scenario(): with open(BLACKLIST_FILE, 'r') as black_list_file: black_list_yaml = yaml.safe_load(black_list_file) - installer_type = ft_constants.CI_INSTALLER_TYPE - deploy_scenario = ft_constants.CI_SCENARIO + installer_type = CONST.INSTALLER_TYPE + deploy_scenario = CONST.DEPLOY_SCENARIO if (bool(installer_type) * bool(deploy_scenario)): if 'scenario' in black_list_yaml.keys(): for item in black_list_yaml['scenario']: @@ -392,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) @@ -405,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) @@ -426,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/snaps/api_check.py b/functest/opnfv_tests/openstack/snaps/api_check.py index 278892094..17d05b922 100644 --- a/functest/opnfv_tests/openstack/snaps/api_check.py +++ b/functest/opnfv_tests/openstack/snaps/api_check.py @@ -5,11 +5,13 @@ # # http://www.apache.org/licenses/LICENSE-2.0 -import functest.utils.functest_utils as ft_utils +import unittest + +from snaps import test_suite_builder + from functest.core.pytest_suite_runner import PyTestSuiteRunner from functest.opnfv_tests.openstack.snaps import snaps_utils -from snaps import test_suite_builder -import unittest +from functest.utils.constants import CONST class ApiCheck(PyTestSuiteRunner): @@ -23,10 +25,10 @@ class ApiCheck(PyTestSuiteRunner): self.suite = unittest.TestSuite() self.case_name = "api_check" - creds_file = ft_utils.get_functest_config('general.openstack.creds') - use_key = ft_utils.get_functest_config('snaps.use_keystone') ext_net_name = snaps_utils.get_ext_net_name() - test_suite_builder.add_openstack_api_tests(self.suite, creds_file, - ext_net_name, - use_keystone=use_key) + test_suite_builder.add_openstack_api_tests( + self.suite, + CONST.openstack_creds, + ext_net_name, + use_keystone=CONST.snaps_use_keystone) diff --git a/functest/opnfv_tests/openstack/snaps/connection_check.py b/functest/opnfv_tests/openstack/snaps/connection_check.py index c2f5b1027..11f8ad074 100644 --- a/functest/opnfv_tests/openstack/snaps/connection_check.py +++ b/functest/opnfv_tests/openstack/snaps/connection_check.py @@ -5,11 +5,13 @@ # # http://www.apache.org/licenses/LICENSE-2.0 -import functest.utils.functest_utils as ft_utils +import unittest + +from snaps import test_suite_builder + from functest.core.pytest_suite_runner import PyTestSuiteRunner from functest.opnfv_tests.openstack.snaps import snaps_utils -from snaps import test_suite_builder -import unittest +from functest.utils.constants import CONST class ConnectionCheck(PyTestSuiteRunner): @@ -23,10 +25,10 @@ class ConnectionCheck(PyTestSuiteRunner): self.suite = unittest.TestSuite() self.case_name = "connection_check" - creds_file = ft_utils.get_functest_config('general.openstack.creds') - use_key = ft_utils.get_functest_config('snaps.use_keystone') ext_net_name = snaps_utils.get_ext_net_name() - test_suite_builder.add_openstack_client_tests(self.suite, creds_file, - ext_net_name, - use_keystone=use_key) + test_suite_builder.add_openstack_client_tests( + self.suite, + CONST.openstack_creds, + ext_net_name, + use_keystone=CONST.snaps_use_keystone) diff --git a/functest/opnfv_tests/openstack/snaps/smoke.py b/functest/opnfv_tests/openstack/snaps/smoke.py index f66c17ff2..83eb6600c 100644 --- a/functest/opnfv_tests/openstack/snaps/smoke.py +++ b/functest/opnfv_tests/openstack/snaps/smoke.py @@ -5,12 +5,14 @@ # # http://www.apache.org/licenses/LICENSE-2.0 -import functest.utils.functest_utils as ft_utils +import os +import unittest + +from snaps import test_suite_builder + from functest.core.pytest_suite_runner import PyTestSuiteRunner from functest.opnfv_tests.openstack.snaps import snaps_utils -from snaps import test_suite_builder -import unittest -import os +from functest.utils.constants import CONST class SnapsSmoke(PyTestSuiteRunner): @@ -24,18 +26,18 @@ class SnapsSmoke(PyTestSuiteRunner): self.suite = unittest.TestSuite() self.case_name = "snaps_smoke" - creds_file = ft_utils.get_functest_config('general.openstack.creds') - use_key = ft_utils.get_functest_config('snaps.use_keystone') - use_fip = ft_utils.get_functest_config('snaps.use_floating_ips') + use_fip = CONST.snaps_use_floating_ips ext_net_name = snaps_utils.get_ext_net_name() # Tests requiring floating IPs leverage files contained within the # SNAPS repository and are found relative to that path if use_fip: - snaps_dir = ft_utils.get_functest_config( - 'general.directories.dir_repo_snaps') + '/snaps' + snaps_dir = CONST.dir_repo_snaps + '/snaps' os.chdir(snaps_dir) test_suite_builder.add_openstack_integration_tests( - self.suite, creds_file, ext_net_name, use_keystone=use_key, + self.suite, + CONST.openstack_creds, + ext_net_name, + use_keystone=CONST.snaps_use_keystone, use_floating_ips=use_fip) diff --git a/functest/opnfv_tests/openstack/snaps/snaps_utils.py b/functest/opnfv_tests/openstack/snaps/snaps_utils.py index a25ad3e0d..4ea1a04ad 100644 --- a/functest/opnfv_tests/openstack/snaps/snaps_utils.py +++ b/functest/opnfv_tests/openstack/snaps/snaps_utils.py @@ -5,17 +5,18 @@ # # http://www.apache.org/licenses/LICENSE-2.0 -import functest.utils.functest_utils as ft_utils from snaps.openstack.tests import openstack_tests from snaps.openstack.utils import neutron_utils +from functest.utils.constants import CONST + def get_ext_net_name(): """ Returns the first external network name :return: """ - os_env_file = ft_utils.get_functest_config('general.openstack.creds') + os_env_file = CONST.openstack_creds os_creds = openstack_tests.get_credentials(os_env_file=os_env_file) neutron = neutron_utils.neutron_client(os_creds) ext_nets = neutron_utils.get_external_networks(neutron) diff --git a/functest/opnfv_tests/openstack/tempest/conf_utils.py b/functest/opnfv_tests/openstack/tempest/conf_utils.py index 38b97e74e..67b527968 100644 --- a/functest/opnfv_tests/openstack/tempest/conf_utils.py +++ b/functest/opnfv_tests/openstack/tempest/conf_utils.py @@ -12,18 +12,20 @@ import os import re import shutil -import functest.utils.functest_constants as ft_constants -import functest.utils.functest_utils as ft_utils import opnfv.utils.constants as releng_constants +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 -REPO_PATH = ft_constants.FUNCTEST_REPO_DIR -GLANCE_IMAGE_PATH = os.path.join(ft_constants.FUNCTEST_DATA_DIR, - ft_constants.GLANCE_IMAGE_FILENAME) -TEMPEST_TEST_LIST_DIR = ft_constants.TEMPEST_TEST_LIST_DIR -TEMPEST_RESULTS_DIR = os.path.join(ft_constants.FUNCTEST_RESULTS_DIR, +REPO_PATH = CONST.dir_repo_functest +GLANCE_IMAGE_PATH = os.path.join(CONST.dir_functest_data, + CONST.openstack_image_file_name) +TEMPEST_TEST_LIST_DIR = CONST.dir_tempest_cases +TEMPEST_RESULTS_DIR = os.path.join(CONST.dir_results, 'tempest') TEMPEST_CUSTOM = os.path.join(REPO_PATH, TEMPEST_TEST_LIST_DIR, 'test_list.txt') @@ -34,24 +36,25 @@ TEMPEST_DEFCORE = os.path.join(REPO_PATH, TEMPEST_TEST_LIST_DIR, TEMPEST_RAW_LIST = os.path.join(TEMPEST_RESULTS_DIR, 'test_raw_list.txt') TEMPEST_LIST = os.path.join(TEMPEST_RESULTS_DIR, 'test_list.txt') -CI_INSTALLER_TYPE = ft_constants.CI_INSTALLER_TYPE -CI_INSTALLER_IP = ft_constants.CI_INSTALLER_IP +CI_INSTALLER_TYPE = CONST.INSTALLER_TYPE +CI_INSTALLER_IP = CONST.INSTALLER_IP 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) @@ -63,24 +66,24 @@ def configure_tempest(logger, deployment_dir, IMAGE_ID=None, FLAVOR_ID=None): config.set( 'compute', 'fixed_network_name', - ft_constants.TEMPEST_PRIVATE_NET_NAME) - if ft_constants.TEMPEST_USE_CUSTOM_IMAGES: + CONST.tempest_private_net_name) + if CONST.tempest_use_custom_images: if IMAGE_ID is not None: config.set('compute', 'image_ref', IMAGE_ID) if IMAGE_ID_ALT is not None: config.set('compute', 'image_ref_alt', IMAGE_ID_ALT) - if ft_constants.TEMPEST_USE_CUSTOM_FLAVORS: + if CONST.tempest_use_custom_flavors: if FLAVOR_ID is not None: config.set('compute', 'flavor_ref', FLAVOR_ID) if FLAVOR_ID_ALT is not None: config.set('compute', 'flavor_ref_alt', FLAVOR_ID_ALT) - config.set('identity', 'tenant_name', ft_constants.TEMPEST_TENANT_NAME) - config.set('identity', 'username', ft_constants.TEMPEST_USER_NAME) - config.set('identity', 'password', ft_constants.TEMPEST_USER_PASSWORD) + config.set('identity', 'tenant_name', CONST.tempest_identity_tenant_name) + config.set('identity', 'username', CONST.tempest_identity_user_name) + config.set('identity', 'password', CONST.tempest_identity_user_password) config.set( - 'validation', 'ssh_timeout', ft_constants.TEMPEST_SSH_TIMEOUT) + 'validation', 'ssh_timeout', CONST.tempest_validation_ssh_timeout) - if ft_constants.OS_ENDPOINT_TYPE is not None: + if CONST.OS_ENDPOINT_TYPE is not None: services_list = ['compute', 'volume', 'image', @@ -93,14 +96,14 @@ def configure_tempest(logger, deployment_dir, IMAGE_ID=None, FLAVOR_ID=None): if service not in sections: config.add_section(service) config.set(service, 'endpoint_type', - ft_constants.OS_ENDPOINT_TYPE) + CONST.OS_ENDPOINT_TYPE) with open(tempest_conf_file, 'wb') as config_file: 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,21 +132,21 @@ 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 kingbird_conf_path = "/etc/kingbird/kingbird.conf" installer_type = CI_INSTALLER_TYPE installer_ip = CI_INSTALLER_IP - installer_username = ft_utils.get_functest_config( - "multisite." + installer_type + - "_environment.installer_username") - installer_password = ft_utils.get_functest_config( - "multisite." + installer_type + - "_environment.installer_password") + installer_username = CONST.__getattribute__( + 'multisite_{}_installer_username'.format(installer_type)) + installer_password = CONST.__getattribute__( + 'multisite_{}_installer_password'.format(installer_type)) ssh_options = ("-o UserKnownHostsFile=/dev/null -o " "StrictHostKeyChecking=no") @@ -174,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 ec0ca766b..0014b7187 100644 --- a/functest/opnfv_tests/openstack/tempest/tempest.py +++ b/functest/opnfv_tests/openstack/tempest/tempest.py @@ -16,13 +16,12 @@ 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 import functest.utils.openstack_utils as os_utils -import functest.utils.functest_constants as ft_constants -import opnfv.utils.constants as releng_constants """ logging configuration """ logger = ft_logger.Logger("Tempest").getLogger() @@ -31,14 +30,80 @@ logger = ft_logger.Logger("Tempest").getLogger() class TempestCommon(testcase_base.TestcaseBase): def __init__(self): - self.case_name = "" + super(TempestCommon, self).__init__() self.MODE = "" self.OPTION = "" self.FLAVOR_ID = None self.IMAGE_ID = None - self.DEPLOYMENT_DIR = ft_utils.get_deployment_dir() - - def read_file(self, filename): + 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_verifier_id(): + """ + 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 + + "/ {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("Rally deployment not found.") + 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, + 'verification', + 'verifier-{}'.format(self.VERIFIER_ID), + 'for-deployment-{}'.format(self.DEPLOYMENT_ID)) + + @staticmethod + def read_file(filename): with open(filename) as src: return [line.strip() for line in src.readlines()] @@ -48,53 +113,52 @@ class TempestCommon(testcase_base.TestcaseBase): logger.debug("Creating tenant and user for Tempest suite") tenant_id = os_utils.create_tenant( keystone_client, - ft_constants.TEMPEST_TENANT_NAME, - ft_constants.TEMPEST_TENANT_DESCRIPTION) + CONST.tempest_identity_tenant_name, + CONST.tempest_identity_tenant_description) if not tenant_id: logger.error("Error : Failed to create %s tenant" - % ft_constants.TEMPEST_TENANT_NAME) + % CONST.tempest_identity_tenant_name) user_id = os_utils.create_user(keystone_client, - ft_constants.TEMPEST_USER_NAME, - ft_constants.TEMPEST_USER_PASSWORD, + CONST.tempest_identity_user_name, + CONST.tempest_identity_user_password, None, tenant_id) if not user_id: logger.error("Error : Failed to create %s user" % - ft_constants.TEMPEST_USER_NAME) + CONST.tempest_identity_user_name) logger.debug("Creating private network for Tempest suite") - network_dic = \ - os_utils.create_shared_network_full( - ft_constants.TEMPEST_PRIVATE_NET_NAME, - ft_constants.TEMPEST_PRIVATE_SUBNET_NAME, - ft_constants.TEMPEST_ROUTER_NAME, - ft_constants.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 releng_constants.EXIT_RUN_ERROR + return testcase_base.TestcaseBase.EX_RUN_ERROR - if ft_constants.TEMPEST_USE_CUSTOM_IMAGES: + if CONST.tempest_use_custom_images: # adding alternative image should be trivial should we need it logger.debug("Creating image for Tempest suite") _, self.IMAGE_ID = os_utils.get_or_create_image( - ft_constants.GLANCE_IMAGE_NAME, conf_utils.GLANCE_IMAGE_PATH, - ft_constants.GLANCE_IMAGE_FORMAT) + CONST.openstack_image_name, conf_utils.GLANCE_IMAGE_PATH, + CONST.openstack_image_disk_format) if not self.IMAGE_ID: - return releng_constants.EXIT_RUN_ERROR + return testcase_base.TestcaseBase.EX_RUN_ERROR - if ft_constants.TEMPEST_USE_CUSTOM_FLAVORS: + if CONST.tempest_use_custom_flavors: # adding alternative flavor should be trivial should we need it logger.debug("Creating flavor for Tempest suite") _, self.FLAVOR_ID = os_utils.get_or_create_flavor( - ft_constants.FLAVOR_NAME, - ft_constants.FLAVOR_RAM, - ft_constants.FLAVOR_DISK, - ft_constants.FLAVOR_VCPUS) + CONST.openstack_flavor_name, + CONST.openstack_flavor_ram, + CONST.openstack_flavor_disk, + CONST.openstack_flavor_vcpus) if not self.FLAVOR_ID: - return releng_constants.EXIT_RUN_ERROR + return testcase_base.TestcaseBase.EX_RUN_ERROR - return releng_constants.EXIT_OK + 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( @@ -106,7 +170,7 @@ class TempestCommon(testcase_base.TestcaseBase): else: logger.error("Tempest test list file %s NOT found." % conf_utils.TEMPEST_CUSTOM) - return releng_constants.EXIT_RUN_ERROR + return testcase_base.TestcaseBase.EX_RUN_ERROR else: if self.MODE == 'smoke': testr_mode = "smoke" @@ -116,11 +180,14 @@ 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 releng_constants.EXIT_OK + return testcase_base.TestcaseBase.EX_OK def apply_tempest_blacklist(self): logger.debug("Applying tempest blacklist...") @@ -128,8 +195,8 @@ class TempestCommon(testcase_base.TestcaseBase): result_file = open(conf_utils.TEMPEST_LIST, 'w') black_tests = [] try: - installer_type = ft_constants.CI_INSTALLER_TYPE - deploy_scenario = ft_constants.CI_SCENARIO + installer_type = CONST.INSTALLER_TYPE + deploy_scenario = CONST.DEPLOY_SCENARIO if (bool(installer_type) * bool(deploy_scenario)): # if INSTALLER_TYPE and DEPLOY_SCENARIO are set we read the # file @@ -145,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.") @@ -156,52 +223,35 @@ class TempestCommon(testcase_base.TestcaseBase): else: result_file.write(str(cases_line) + '\n') result_file.close() - return releng_constants.EXIT_OK + return testcase_base.TestcaseBase.EX_OK - def run(self): - if not os.path.exists(conf_utils.TEMPEST_RESULTS_DIR): - os.makedirs(conf_utils.TEMPEST_RESULTS_DIR) + def _parse_verification_id(line): + first_pos = line.index("UUID=") + len("UUID=") + last_pos = line.index(") for deployment") + return line[first_pos:last_pos] - # Pre-configuration - res = self.create_tempest_resources() - if res != releng_constants.EXIT_OK: - return res + def run_verifier_tests(self): + self.OPTION += (" --load-list {}".format(conf_utils.TEMPEST_LIST)) - res = conf_utils.configure_tempest(logger, - self.DEPLOYMENT_DIR, - self.IMAGE_ID, - self.FLAVOR_ID) - if res != releng_constants.EXIT_OK: - return res - - res = self.generate_test_list(self.DEPLOYMENT_DIR) - if res != releng_constants.EXIT_OK: - return res - - res = self.apply_tempest_blacklist() - if res != releng_constants.EXIT_OK: - return res - - self.OPTION += (" --tests-file %s " % 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" " Installer: %s\n Scenario: %s\n Node: %s\n Date: %s\n" % - (ft_constants.CI_INSTALLER_TYPE, - ft_constants.CI_SCENARIO, - ft_constants.CI_NODE, + (CONST.INSTALLER_TYPE, + CONST.DEPLOY_SCENARIO, + 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, @@ -212,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() @@ -219,56 +275,76 @@ 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 - if 'smoke' in self.MODE: - self.CASE_NAME = 'tempest_smoke_serial' - elif 'feature' in self.MODE: - self.CASE_NAME = self.MODE.replace( - "feature_", "") - else: - self.CASE_NAME = 'tempest_full_parallel' - - status = ft_utils.check_success_rate( - self.CASE_NAME, success_rate) + self.criteria = ft_utils.check_success_rate( + self.case_name, success_rate) logger.info("Tempest %s success_rate is %s%%, is marked as %s" - % (self.CASE_NAME, success_rate, status)) + % (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 status == "PASS": - return releng_constants.EXIT_OK + if self.criteria == "PASS": + return testcase_base.TestcaseBase.EX_OK else: - return releng_constants.EXIT_RUN_ERROR + return testcase_base.TestcaseBase.EX_TESTCASE_FAILED class TempestSmokeSerial(TempestCommon): @@ -277,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): @@ -303,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/openstack/vping/vping_base.py b/functest/opnfv_tests/openstack/vping/vping_base.py index e467dd9f5..8285d93f8 100644 --- a/functest/opnfv_tests/openstack/vping/vping_base.py +++ b/functest/opnfv_tests/openstack/vping/vping_base.py @@ -12,43 +12,38 @@ import pprint import time from datetime import datetime -import functest.utils.functest_utils as ft_utils -import functest.utils.functest_constants as ft_constants -import functest.utils.openstack_utils as os_utils import functest.core.testcase_base as testcase_base +import functest.utils.openstack_utils as os_utils +from functest.utils.constants import CONST class VPingBase(testcase_base.TestcaseBase): def __init__(self): - def get_conf(parameter): - return ft_utils.get_functest_config(parameter) - super(VPingBase, self).__init__() self.logger = None - self.functest_repo = ft_constants.FUNCTEST_REPO_DIR - self.repo = get_conf('general.directories.dir_vping') - self.vm1_name = get_conf('vping.vm_name_1') - self.vm2_name = get_conf('vping.vm_name_2') + self.functest_repo = CONST.dir_repo_functest + self.repo = CONST.dir_vping + self.vm1_name = CONST.vping_vm_name_1 + self.vm2_name = CONST.vping_vm_name_2 self.vm_boot_timeout = 180 self.vm_delete_timeout = 100 - self.ping_timeout = get_conf('vping.ping_timeout') + self.ping_timeout = CONST.vping_ping_timeout - self.image_name = get_conf('vping.image_name') - self.image_filename = get_conf('general.openstack.image_file_name') - self.image_format = get_conf('general.openstack.image_disk_format') - self.image_path = ("%s/%s" % - (get_conf('general.directories.dir_functest_data'), - self.image_filename)) + self.image_name = CONST.vping_image_name + self.image_filename = CONST.openstack_image_file_name + self.image_format = CONST.openstack_image_disk_format + self.image_path = os.path.join(CONST.dir_functest_data, + self.image_filename) - self.flavor_name = get_conf('vping.vm_flavor') + self.flavor_name = CONST.vping_vm_flavor # NEUTRON Private Network parameters - self.private_net_name = get_conf('vping.vping_private_net_name') - self.private_subnet_name = get_conf('vping.vping_private_subnet_name') - self.private_subnet_cidr = get_conf('vping.vping_private_subnet_cidr') - self.router_name = get_conf('vping.vping_router_name') - self.sg_name = get_conf('vping.vping_sg_name') - self.sg_desc = get_conf('vping.vping_sg_descr') + self.private_net_name = CONST.vping_private_net_name + self.private_subnet_name = CONST.vping_private_subnet_name + self.private_subnet_cidr = CONST.vping_private_subnet_cidr + self.router_name = CONST.vping_router_name + self.sg_name = CONST.vping_sg_name + self.sg_desc = CONST.vping_sg_desc self.neutron_client = os_utils.get_neutron_client() self.glance_client = os_utils.get_glance_client() self.nova_client = os_utils.get_nova_client() @@ -294,6 +289,6 @@ class VPingMain(object): if result != VPingBase.EX_OK: return result if kwargs['report']: - return self.vping.push_to_db() + return self.vping.publish_report() except Exception: return VPingBase.EX_RUN_ERROR diff --git a/functest/opnfv_tests/sdn/odl/odl.py b/functest/opnfv_tests/sdn/odl/odl.py index 0905e55cc..339c305ef 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,8 @@ 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' + kwargs['odlrestconfport'] = '8081' elif installer_type == 'joid': kwargs['odlip'] = os.environ['SDN_CONTROLLER'] elif installer_type == 'compass': @@ -180,49 +181,57 @@ 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: sys.exit(result) if args['pushtodb']: - sys.exit(odl.push_to_db()) + sys.exit(odl.publish_report()) except Exception: sys.exit(testcase_base.TestcaseBase.EX_RUN_ERROR) diff --git a/functest/opnfv_tests/sdn/onos/teston/onos.py b/functest/opnfv_tests/sdn/onos/teston/onos.py index 300f56d18..213bdb7dc 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/opnfv_tests/vnf/aaa/__init__.py b/functest/opnfv_tests/vnf/aaa/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/functest/opnfv_tests/vnf/aaa/__init__.py diff --git a/functest/opnfv_tests/vnf/aaa/aaa.py b/functest/opnfv_tests/vnf/aaa/aaa.py new file mode 100644 index 000000000..f1c265f47 --- /dev/null +++ b/functest/opnfv_tests/vnf/aaa/aaa.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +# Copyright (c) 2016 Orange and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +import sys + +import argparse + +import functest.core.testcase_base as testcase_base +import functest.core.vnf_base as vnf_base +import functest.utils.functest_logger as ft_logger + + +class AaaVnf(vnf_base.VnfOnBoardingBase): + + logger = ft_logger.Logger("VNF AAA").getLogger() + + def __init__(self): + super(AaaVnf, self).__init__(case="aaa") + + def deploy_orchestrator(self): + self.logger.info("No VNFM needed to deploy a free radius here") + return None + +# TODO see how to use build in exception form releng module + def deploy_vnf(self): + self.logger.info("Freeradius VNF deployment") + # TODO apt-get update + config tuning + deploy_vnf = {} + deploy_vnf['status'] = "PASS" + deploy_vnf['result'] = {} + return deploy_vnf + + def test_vnf(self): + self.logger.info("Run test towards freeradius") + # TODO: once the freeradius is deployed..make some tests + test_vnf = {} + test_vnf['status'] = "PASS" + test_vnf['result'] = {} + return test_vnf + + def main(self, **kwargs): + self.logger.info("AAA VNF onboarding") + self.execute() + if self.criteria is "PASS": + return self.EX_OK + else: + return self.EX_RUN_ERROR + + def run(self): + kwargs = {} + return self.main(**kwargs) + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + args = vars(parser.parse_args()) + aaa_vnf = AaaVnf() + try: + result = aaa_vnf.main(**args) + if result != testcase_base.TestcaseBase.EX_OK: + sys.exit(result) + if args['pushtodb']: + sys.exit(aaa_vnf.push_to_db()) + except Exception: + sys.exit(testcase_base.TestcaseBase.EX_RUN_ERROR) diff --git a/functest/opnfv_tests/vnf/ims/__init__.py b/functest/opnfv_tests/vnf/ims/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/functest/opnfv_tests/vnf/ims/__init__.py diff --git a/functest/opnfv_tests/vnf/ims/cloudify_ims.py b/functest/opnfv_tests/vnf/ims/cloudify_ims.py new file mode 100644 index 000000000..13a5af4fd --- /dev/null +++ b/functest/opnfv_tests/vnf/ims/cloudify_ims.py @@ -0,0 +1,278 @@ +#!/usr/bin/env python + +# Copyright (c) 2016 Orange and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +import json +import os +import requests +import subprocess +import time + +import functest.core.vnf_base as vnf_base +import functest.utils.functest_logger as ft_logger +import functest.utils.functest_utils as ft_utils +import functest.utils.openstack_utils as os_utils + +from clearwater import Clearwater +from functest.utils.constants import CONST +from orchestrator_cloudify import Orchestrator + + +class ImsVnf(vnf_base.VnfOnBoardingBase): + + def __init__(self, project='functest', case='cloudify_ims', + repo='', cmd=''): + super(ImsVnf, self).__init__(project, case, repo, cmd) + self.logger = ft_logger.Logger("vIMS").getLogger() + self.case_dir = os.path.join(CONST.functest_test, 'vnf/ims/') + self.data_dir = CONST.dir_vIMS_data + self.test_dir = CONST.dir_repo_vims_test + + self.orchestrator = dict( + requirements=CONST.cloudify_requirements, + blueprint=CONST.cloudify_blueprint, + inputs=CONST.cloudify_inputs + ) + + self.vnf = dict( + blueprint=CONST.clearwater_blueprint, + deployment_name=CONST.clearwater_deployment_name, + inputs=CONST.clearwater_inputs, + requirements=CONST.clearwater_requirements + ) + + # vIMS Data directory creation + if not os.path.exists(self.data_dir): + os.makedirs(self.data_dir) + + def deploy_orchestrator(self, **kwargs): + public_auth_url = os_utils.get_endpoint('identity') + + cfy = Orchestrator(self.data_dir, self.orchestrator.inputs) + self.orchestrator.object = cfy + + if 'tenant_name' in self.creds.keys(): + tenant_name = self.creds['tenant_name'] + elif 'project_name' in self.creds.keys(): + tenant_name = self.creds['project_name'] + + cfy.set_credentials(username=self.creds['username'], + password=self.creds['password'], + tenant_name=tenant_name, + auth_url=public_auth_url) + + # orchestrator VM flavor + flavor_id = self.get_flavor("m1.large", self.orchestrator.requirements) + if not flavor_id: + self.logger.info("Available flavors are: ") + self.pMsg(self.nova_client.flavor.list()) + self.step_failure("Failed to find required flavor" + "for this deployment") + cfy.set_flavor_id(flavor_id) + + # orchestrator VM image + if 'os_image' in self.orchestrator.requirements.keys(): + image_id = os_utils.get_image_id( + self.glance_client, self.orchestrator.requirements['os_image']) + if image_id == '': + self.step_failure("Failed to find required OS image" + " for cloudify manager") + else: + self.step_failure("Failed to find required OS image" + " for cloudify manager") + + cfy.set_image_id(image_id) + + ext_net = os_utils.get_external_net(self.neutron_client) + if not ext_net: + self.step_failure("Failed to get external network") + + cfy.set_external_network_name(ext_net) + + ns = ft_utils.get_resolvconf_ns() + if ns: + cfy.set_nameservers(ns) + + if 'compute' in self.nova_client.client.services_url: + cfy.set_nova_url(self.nova_client.client.services_url['compute']) + if self.neutron_client.httpclient.endpoint_url is not None: + cfy.set_neutron_url(self.neutron_client.httpclient.endpoint_url) + + self.logger.info("Prepare virtualenv for cloudify-cli") + cmd = "chmod +x " + self.case_dir + "create_venv.sh" + ft_utils.execute_command(cmd) + time.sleep(3) + cmd = self.case_dir + "create_venv.sh " + self.data_dir + ft_utils.execute_command(cmd) + + cfy.download_manager_blueprint(self.orchestrator.blueprint['url'], + self.orchestrator.blueprint['branch']) + + cfy.deploy_manager() + return {'status': 'PASS', 'result': ''} + + def deploy_vnf(self): + cw = Clearwater(self.vnf.inputs, self.orchestrator.object, self.logger) + self.vnf.object = cw + + self.logger.info("Collect flavor id for all clearwater vm") + flavor_id = self.get_flavor("m1.small", self.vnf.requirements) + if not flavor_id: + self.logger.info("Available flavors are: ") + self.pMsg(self.nova_client.flavor.list()) + self.step_failure("Failed to find required flavor" + " for this deployment") + + cw.set_flavor_id(flavor_id) + + # VMs image + if 'os_image' in self.vnf.requirements.keys(): + image_id = os_utils.get_image_id( + self.glance_client, self.vnf.requirements['os_image']) + if image_id == '': + self.step_failure("Failed to find required OS image" + " for clearwater VMs") + else: + self.step_failure("Failed to find required OS image" + " for clearwater VMs") + + cw.set_image_id(image_id) + + ext_net = os_utils.get_external_net(self.neutron_client) + if not ext_net: + self.step_failure("Failed to get external network") + + cw.set_external_network_name(ext_net) + + cw.deploy_vnf() + return {'status': 'PASS', 'result': ''} + + def test_vnf(self): + script = "source {0}venv_cloudify/bin/activate; " + script += "cd {0}; " + script += "cfy status | grep -Eo \"([0-9]{{1,3}}\.){{3}}[0-9]{{1,3}}\"" + cmd = "/bin/bash -c '" + script.format(self.data_dir) + "'" + + try: + self.logger.debug("Trying to get clearwater manager IP ... ") + mgr_ip = os.popen(cmd).read() + mgr_ip = mgr_ip.splitlines()[0] + except: + self.step_failure("Unable to retrieve the IP of the " + "cloudify manager server !") + + api_url = "http://" + mgr_ip + "/api/v2" + dep_outputs = requests.get(api_url + "/deployments/" + + self.vnf.deployment_name + "/outputs") + dns_ip = dep_outputs.json()['outputs']['dns_ip'] + ellis_ip = dep_outputs.json()['outputs']['ellis_ip'] + + ellis_url = "http://" + ellis_ip + "/" + url = ellis_url + "accounts" + + params = {"password": "functest", + "full_name": "opnfv functest user", + "email": "functest@opnfv.fr", + "signup_code": "secret"} + + rq = requests.post(url, data=params) + i = 20 + while rq.status_code != 201 and i > 0: + rq = requests.post(url, data=params) + i = i - 1 + time.sleep(10) + + if rq.status_code == 201: + url = ellis_url + "session" + rq = requests.post(url, data=params) + cookies = rq.cookies + + url = ellis_url + "accounts/" + params['email'] + "/numbers" + if cookies != "": + rq = requests.post(url, cookies=cookies) + i = 24 + while rq.status_code != 200 and i > 0: + rq = requests.post(url, cookies=cookies) + i = i - 1 + time.sleep(25) + + if rq.status_code != 200: + self.step_failure("Unable to create a number: %s" + % rq.json()['reason']) + + nameservers = ft_utils.get_resolvconf_ns() + resolvconf = "" + for ns in nameservers: + resolvconf += "\nnameserver " + ns + + if dns_ip != "": + script = ('echo -e "nameserver ' + dns_ip + resolvconf + + '" > /etc/resolv.conf; ') + script += 'source /etc/profile.d/rvm.sh; ' + script += 'cd {0}; ' + script += ('rake test[{1}] SIGNUP_CODE="secret"') + + cmd = ("/bin/bash -c '" + + script.format(self.data_dir, self.inputs["public_domain"]) + + "'") + output_file = "output.txt" + f = open(output_file, 'w+') + subprocess.call(cmd, shell=True, stdout=f, + stderr=subprocess.STDOUT) + f.close() + + f = open(output_file, 'r') + result = f.read() + if result != "": + self.logger.debug(result) + + vims_test_result = "" + tempFile = os.path.join(self.test_dir, "temp.json") + try: + self.logger.debug("Trying to load test results") + with open(tempFile) as f: + vims_test_result = json.load(f) + f.close() + except: + self.logger.error("Unable to retrieve test results") + + try: + os.remove(tempFile) + except: + self.logger.error("Deleting file failed") + + if vims_test_result != '': + return {'status': 'PASS', 'result': vims_test_result} + else: + return {'status': 'FAIL', 'result': ''} + + def clean(self): + self.vnf.object.undeploy_vnf() + self.orchestrator.object.undeploy_manager() + super(ImsVnf, self).clean() + + def get_flavor(self, flavor_name, requirements): + try: + flavor_id = os_utils.get_flavor_id(self.nova_client, flavor_name) + if 'ram_min' in requirements.keys(): + flavor_id = os_utils.get_flavor_id_by_ram_range( + self.nova_client, requirements['ram_min'], 7500) + + if flavor_id == '': + self.logger.error( + "Failed to find %s flavor. " + "Try with ram range default requirement !" % flavor_name) + flavor_id = os_utils.get_flavor_id_by_ram_range( + self.nova_client, + 4000, 10000) + return flavor_id + except: + self.logger.error("Flavor '%s' not found." % self.flavor_name) + self.logger.info("Available flavors are: ") + self.pMsg(self.nova_client.flavor.list()) + return None diff --git a/functest/opnfv_tests/vnf/ims/opera_ims.py b/functest/opnfv_tests/vnf/ims/opera_ims.py new file mode 100644 index 000000000..073a56c37 --- /dev/null +++ b/functest/opnfv_tests/vnf/ims/opera_ims.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python + +# Copyright (c) 2016 Orange and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +import json +import os +import requests +import subprocess +import time + +import functest.core.vnf_base as vnf_base +import functest.utils.functest_logger as ft_logger +import functest.utils.functest_utils as ft_utils +from functest.utils.constants import CONST + + +class ImsVnf(vnf_base.VnfOnBoardingBase): + + def __init__(self, project='functest', case='opera_ims', + repo='', cmd=''): + super(ImsVnf, self).__init__(project, case, repo, cmd) + self.logger = ft_logger.Logger("vIMS").getLogger() + self.case_dir = os.path.join(CONST.functest_test, 'vnf/ims/') + self.data_dir = CONST.dir_vIMS_data + self.test_dir = CONST.dir_repo_vims_test + + # vIMS Data directory creation + if not os.path.exists(self.data_dir): + os.makedirs(self.data_dir) + + def deploy_orchestrator(self, **kwargs): + # TODO + # deploy open-O from Functest docker located on the Jumphost + # you have admin rights on OpenStack SUT + # you can cretae a VM, spawn docker on the jumphost + # spawn docker on a VM in the SUT, ..up to you + # + # note: this step can be ignored + # if Open-O is part of the installer + self.logger.info("Deploy orchestrator: OK") + + def deploy_vnf(self): + # TODO + self.logger.info("Deploy VNF: OK") + + def test_vnf(self): + # Adaptations probably needed + # code used for cloudify_ims + # ruby client on jumphost calling the vIMS on the SUT + script = "source {0}venv_cloudify/bin/activate; " + script += "cd {0}; " + script += "cfy status | grep -Eo \"([0-9]{{1,3}}\.){{3}}[0-9]{{1,3}}\"" + cmd = "/bin/bash -c '" + script.format(self.data_dir) + "'" + + try: + self.logger.debug("Trying to get clearwater manager IP ... ") + mgr_ip = os.popen(cmd).read() + mgr_ip = mgr_ip.splitlines()[0] + except: + self.step_failure("Unable to retrieve the IP of the " + "cloudify manager server !") + + api_url = "http://" + mgr_ip + "/api/v2" + dep_outputs = requests.get(api_url + "/deployments/" + + self.vnf.deployment_name + "/outputs") + dns_ip = dep_outputs.json()['outputs']['dns_ip'] + ellis_ip = dep_outputs.json()['outputs']['ellis_ip'] + + ellis_url = "http://" + ellis_ip + "/" + url = ellis_url + "accounts" + + params = {"password": "functest", + "full_name": "opnfv functest user", + "email": "functest@opnfv.fr", + "signup_code": "secret"} + + rq = requests.post(url, data=params) + i = 20 + while rq.status_code != 201 and i > 0: + rq = requests.post(url, data=params) + i = i - 1 + time.sleep(10) + + if rq.status_code == 201: + url = ellis_url + "session" + rq = requests.post(url, data=params) + cookies = rq.cookies + + url = ellis_url + "accounts/" + params['email'] + "/numbers" + if cookies != "": + rq = requests.post(url, cookies=cookies) + i = 24 + while rq.status_code != 200 and i > 0: + rq = requests.post(url, cookies=cookies) + i = i - 1 + time.sleep(25) + + if rq.status_code != 200: + self.step_failure("Unable to create a number: %s" + % rq.json()['reason']) + + nameservers = ft_utils.get_resolvconf_ns() + resolvconf = "" + for ns in nameservers: + resolvconf += "\nnameserver " + ns + + if dns_ip != "": + script = ('echo -e "nameserver ' + dns_ip + resolvconf + + '" > /etc/resolv.conf; ') + script += 'source /etc/profile.d/rvm.sh; ' + script += 'cd {0}; ' + script += ('rake test[{1}] SIGNUP_CODE="secret"') + + cmd = ("/bin/bash -c '" + + script.format(self.data_dir, self.inputs["public_domain"]) + + "'") + output_file = "output.txt" + f = open(output_file, 'w+') + subprocess.call(cmd, shell=True, stdout=f, + stderr=subprocess.STDOUT) + f.close() + + f = open(output_file, 'r') + result = f.read() + if result != "": + self.logger.debug(result) + + vims_test_result = "" + tempFile = os.path.join(self.test_dir, "temp.json") + try: + self.logger.debug("Trying to load test results") + with open(tempFile) as f: + vims_test_result = json.load(f) + f.close() + except: + self.logger.error("Unable to retrieve test results") + + try: + os.remove(tempFile) + except: + self.logger.error("Deleting file failed") + + if vims_test_result != '': + return {'status': 'PASS', 'result': vims_test_result} + else: + return {'status': 'FAIL', 'result': ''} + + def clean(self): + # TODO + super(ImsVnf, self).clean() diff --git a/functest/opnfv_tests/vnf/ims/orchestra_ims.py b/functest/opnfv_tests/vnf/ims/orchestra_ims.py new file mode 100644 index 000000000..28f37f053 --- /dev/null +++ b/functest/opnfv_tests/vnf/ims/orchestra_ims.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python + +# Copyright (c) 2016 Orange and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +import json +import os +import requests +import subprocess +import time + +import functest.core.vnf_base as vnf_base +import functest.utils.functest_logger as ft_logger +import functest.utils.functest_utils as ft_utils +from functest.utils.constants import CONST + + +class ImsVnf(vnf_base.VnfOnBoardingBase): + + def __init__(self, project='functest', case='orchestra_ims', + repo='', cmd=''): + super(ImsVnf, self).__init__(project, case, repo, cmd) + self.logger = ft_logger.Logger("vIMS").getLogger() + self.case_dir = os.path.join(CONST.functest_test, 'vnf/ims/') + self.data_dir = CONST.dir_vIMS_data + self.test_dir = CONST.dir_repo_vims_test + + # vIMS Data directory creation + if not os.path.exists(self.data_dir): + os.makedirs(self.data_dir) + + def deploy_orchestrator(self, **kwargs): + # TODO + # put your code here to deploy openbaton + # from the functest docker located on the jumphost + # you have admin rights on OpenStack SUT + # you can cretae a VM, spawn docker on the jumphost + # spawn docker on a VM in the SUT, ..up to you + # + # note: this step can be ignored + # if OpenBaton is part of the installer + self.logger.info("Deploy orchestrator: OK") + + def deploy_vnf(self): + # deploy the VNF + # call openbaton to deploy the vIMS + self.logger.info("Deploy VNF: OK") + + def test_vnf(self): + # Adaptations probably needed + # code used for cloudify_ims + # ruby client on jumphost calling the vIMS on the SUT + script = "source {0}venv_cloudify/bin/activate; " + script += "cd {0}; " + script += "cfy status | grep -Eo \"([0-9]{{1,3}}\.){{3}}[0-9]{{1,3}}\"" + cmd = "/bin/bash -c '" + script.format(self.data_dir) + "'" + + try: + self.logger.debug("Trying to get clearwater manager IP ... ") + mgr_ip = os.popen(cmd).read() + mgr_ip = mgr_ip.splitlines()[0] + except: + self.step_failure("Unable to retrieve the IP of the " + "cloudify manager server !") + + api_url = "http://" + mgr_ip + "/api/v2" + dep_outputs = requests.get(api_url + "/deployments/" + + self.vnf.deployment_name + "/outputs") + dns_ip = dep_outputs.json()['outputs']['dns_ip'] + ellis_ip = dep_outputs.json()['outputs']['ellis_ip'] + + ellis_url = "http://" + ellis_ip + "/" + url = ellis_url + "accounts" + + params = {"password": "functest", + "full_name": "opnfv functest user", + "email": "functest@opnfv.fr", + "signup_code": "secret"} + + rq = requests.post(url, data=params) + i = 20 + while rq.status_code != 201 and i > 0: + rq = requests.post(url, data=params) + i = i - 1 + time.sleep(10) + + if rq.status_code == 201: + url = ellis_url + "session" + rq = requests.post(url, data=params) + cookies = rq.cookies + + url = ellis_url + "accounts/" + params['email'] + "/numbers" + if cookies != "": + rq = requests.post(url, cookies=cookies) + i = 24 + while rq.status_code != 200 and i > 0: + rq = requests.post(url, cookies=cookies) + i = i - 1 + time.sleep(25) + + if rq.status_code != 200: + self.step_failure("Unable to create a number: %s" + % rq.json()['reason']) + + nameservers = ft_utils.get_resolvconf_ns() + resolvconf = "" + for ns in nameservers: + resolvconf += "\nnameserver " + ns + + if dns_ip != "": + script = ('echo -e "nameserver ' + dns_ip + resolvconf + + '" > /etc/resolv.conf; ') + script += 'source /etc/profile.d/rvm.sh; ' + script += 'cd {0}; ' + script += ('rake test[{1}] SIGNUP_CODE="secret"') + + cmd = ("/bin/bash -c '" + + script.format(self.data_dir, self.inputs["public_domain"]) + + "'") + output_file = "output.txt" + f = open(output_file, 'w+') + subprocess.call(cmd, shell=True, stdout=f, + stderr=subprocess.STDOUT) + f.close() + + f = open(output_file, 'r') + result = f.read() + if result != "": + self.logger.debug(result) + + vims_test_result = "" + tempFile = os.path.join(self.test_dir, "temp.json") + try: + self.logger.debug("Trying to load test results") + with open(tempFile) as f: + vims_test_result = json.load(f) + f.close() + except: + self.logger.error("Unable to retrieve test results") + + try: + os.remove(tempFile) + except: + self.logger.error("Deleting file failed") + + if vims_test_result != '': + return {'status': 'PASS', 'result': vims_test_result} + else: + return {'status': 'FAIL', 'result': ''} + + def clean(self): + # TODO + super(ImsVnf, self).clean() diff --git a/functest/opnfv_tests/vnf/ims/orchestrator.py b/functest/opnfv_tests/vnf/ims/orchestrator_cloudify.py index f3838f871..f3838f871 100644 --- a/functest/opnfv_tests/vnf/ims/orchestrator.py +++ b/functest/opnfv_tests/vnf/ims/orchestrator_cloudify.py diff --git a/functest/opnfv_tests/vnf/ims/vims.py b/functest/opnfv_tests/vnf/ims/vims.py deleted file mode 100755 index fe888b698..000000000 --- a/functest/opnfv_tests/vnf/ims/vims.py +++ /dev/null @@ -1,521 +0,0 @@ -#!/usr/bin/python -# coding: utf8 -####################################################################### -# -# Copyright (c) 2015 Orange -# valentin.boucher@orange.com -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -######################################################################## - -import datetime -import json -import os -import pprint -import subprocess -import time - -import argparse -import keystoneclient.v2_0.client as ksclient -import novaclient.client as nvclient -import requests -from neutronclient.v2_0 import client as ntclient - -import functest.utils.functest_logger as ft_logger -import functest.utils.functest_utils as ft_utils -import functest.utils.openstack_utils as os_utils -from clearwater import Clearwater -from orchestrator import Orchestrator -import functest.utils.functest_constants as ft_constants - -pp = pprint.PrettyPrinter(indent=4) - - -parser = argparse.ArgumentParser() -parser.add_argument("-d", "--debug", help="Debug mode", action="store_true") -parser.add_argument("-r", "--report", - help="Create json result file", - action="store_true") -parser.add_argument("-n", "--noclean", - help="Don't clean the created resources for this test.", - action="store_true") -args = parser.parse_args() - -""" logging configuration """ -logger = ft_logger.Logger("vIMS").getLogger() - - -# Cloudify parameters -VIMS_DIR = os.path.join(ft_constants.FUNCTEST_TEST_DIR, 'vnf/ims/') -VIMS_DATA_DIR = ft_constants.VIMS_DATA_DIR -VIMS_TEST_DIR = ft_constants.VIMS_TEST_DIR -VIMS_TENANT_NAME = ft_constants.VIMS_TENANT_NAME -VIMS_TENANT_DESCRIPTION = ft_constants.VIMS_TENANT_DESCRIPTION -VIMS_IMAGES = ft_constants.VIMS_IMAGES - -CFY_MANAGER_BLUEPRINT = ft_constants.CFY_MANAGER_BLUEPRINT -CFY_MANAGER_REQUIERMENTS = ft_constants.CFY_MANAGER_REQUIERMENTS -CFY_INPUTS = ft_constants.CFY_INPUTS - -CW_BLUEPRINT = ft_constants.CW_BLUEPRINT -CW_DEPLOYMENT_NAME = ft_constants.CW_DEPLOYMENT_NAME -CW_INPUTS = ft_constants.CW_INPUTS -CW_REQUIERMENTS = ft_constants.CW_REQUIERMENTS - -CFY_DEPLOYMENT_DURATION = 0 -CW_DEPLOYMENT_DURATION = 0 - -TESTCASE_START_TIME = time.time() -RESULTS = {'orchestrator': {'duration': 0, 'result': ''}, - 'vIMS': {'duration': 0, 'result': ''}, - 'sig_test': {'duration': 0, 'result': ''}} - - -def download_and_add_image_on_glance(glance, image_name, image_url): - dest_path = os.path.join(VIMS_DATA_DIR, "tmp/") - if not os.path.exists(dest_path): - os.makedirs(dest_path) - file_name = image_url.rsplit('/')[-1] - if not ft_utils.download_url(image_url, dest_path): - logger.error("Failed to download image %s" % file_name) - return False - - image = os_utils.create_glance_image( - glance, image_name, dest_path + file_name) - if not image: - logger.error("Failed to upload image on glance") - return False - - return image - - -def step_failure(step_name, error_msg): - logger.error(error_msg) - set_result(step_name, 0, error_msg) - status = "FAIL" - # in case of failure starting and stoping time are not correct - stop_time = time.time() - if step_name == "sig_test": - status = "PASS" - ft_utils.push_results_to_db("functest", - "vims", - TESTCASE_START_TIME, - stop_time, - status, - RESULTS) - exit(-1) - - -def set_result(step_name, duration=0, result=""): - RESULTS[step_name] = {'duration': duration, 'result': result} - - -def test_clearwater(): - script = "source " + VIMS_DATA_DIR + "venv_cloudify/bin/activate; " - script += "cd " + VIMS_DATA_DIR + "; " - script += "cfy status | grep -Eo \"([0-9]{1,3}\.){3}[0-9]{1,3}\"" - cmd = "/bin/bash -c '" + script + "'" - - try: - logger.debug("Trying to get clearwater manager IP ... ") - mgr_ip = os.popen(cmd).read() - mgr_ip = mgr_ip.splitlines()[0] - except: - step_failure("sig_test", "Unable to retrieve the IP of the " - "cloudify manager server !") - - api_url = "http://" + mgr_ip + "/api/v2" - dep_outputs = requests.get(api_url + "/deployments/" + - CW_DEPLOYMENT_NAME + "/outputs") - dns_ip = dep_outputs.json()['outputs']['dns_ip'] - ellis_ip = dep_outputs.json()['outputs']['ellis_ip'] - - ellis_url = "http://" + ellis_ip + "/" - url = ellis_url + "accounts" - - params = {"password": "functest", - "full_name": "opnfv functest user", - "email": "functest@opnfv.fr", - "signup_code": "secret"} - - rq = requests.post(url, data=params) - i = 20 - while rq.status_code != 201 and i > 0: - rq = requests.post(url, data=params) - i = i - 1 - time.sleep(10) - - if rq.status_code == 201: - url = ellis_url + "session" - rq = requests.post(url, data=params) - cookies = rq.cookies - - url = ellis_url + "accounts/" + params['email'] + "/numbers" - if cookies != "": - rq = requests.post(url, cookies=cookies) - i = 24 - while rq.status_code != 200 and i > 0: - rq = requests.post(url, cookies=cookies) - i = i - 1 - time.sleep(25) - - if rq.status_code != 200: - step_failure("sig_test", "Unable to create a number: %s" - % rq.json()['reason']) - - start_time_ts = time.time() - end_time_ts = start_time_ts - logger.info("vIMS functional test Start Time:'%s'" % ( - datetime.datetime.fromtimestamp(start_time_ts).strftime( - '%Y-%m-%d %H:%M:%S'))) - nameservers = ft_utils.get_resolvconf_ns() - resolvconf = "" - for ns in nameservers: - resolvconf += "\nnameserver " + ns - - if dns_ip != "": - script = ('echo -e "nameserver ' + dns_ip + resolvconf + - '" > /etc/resolv.conf; ') - script += 'source /etc/profile.d/rvm.sh; ' - script += 'cd ' + VIMS_TEST_DIR + '; ' - script += ('rake test[' + CW_INPUTS["public_domain"] + - '] SIGNUP_CODE="secret"') - - cmd = "/bin/bash -c '" + script + "'" - output_file = "output.txt" - f = open(output_file, 'w+') - subprocess.call(cmd, shell=True, stdout=f, - stderr=subprocess.STDOUT) - f.close() - end_time_ts = time.time() - duration = round(end_time_ts - start_time_ts, 1) - logger.info("vIMS functional test duration:'%s'" % duration) - f = open(output_file, 'r') - result = f.read() - if result != "" and logger: - logger.debug(result) - - vims_test_result = "" - tempFile = os.path.join(VIMS_TEST_DIR, "temp.json") - try: - logger.debug("Trying to load test results") - with open(tempFile) as f: - vims_test_result = json.load(f) - f.close() - except: - logger.error("Unable to retrieve test results") - - set_result("sig_test", duration, vims_test_result) - - # success criteria for vIMS (for Brahmaputra) - # - orchestrator deployed - # - VNF deployed - # TODO use test criteria defined in config file - status = "FAIL" - try: - if (RESULTS['orchestrator']['duration'] > 0 and - RESULTS['vIMS']['duration'] > 0): - status = "PASS" - except: - logger.error("Unable to set test status") - - ft_utils.push_results_to_db("functest", - "vims", - TESTCASE_START_TIME, - end_time_ts, - status, - RESULTS) - - try: - os.remove(tempFile) - except: - logger.error("Deleting file failed") - - -def main(): - - # ###############Â GENERAL INITIALISATION ################ - - if not os.path.exists(VIMS_DATA_DIR): - os.makedirs(VIMS_DATA_DIR) - - ks_creds = os_utils.get_credentials("keystone") - nv_creds = os_utils.get_credentials("nova") - nt_creds = os_utils.get_credentials("neutron") - - logger.info("Prepare OpenStack plateform (create tenant and user)") - keystone = ksclient.Client(**ks_creds) - - user_id = os_utils.get_user_id(keystone, ks_creds['username']) - if user_id == '': - step_failure("init", "Error : Failed to get id of " + - ks_creds['username']) - - tenant_id = os_utils.create_tenant( - keystone, VIMS_TENANT_NAME, VIMS_TENANT_DESCRIPTION) - if not tenant_id: - step_failure("init", "Error : Failed to create " + - VIMS_TENANT_NAME + " tenant") - - roles_name = ["admin", "Admin"] - role_id = '' - for role_name in roles_name: - if role_id == '': - role_id = os_utils.get_role_id(keystone, role_name) - - if role_id == '': - logger.error("Error : Failed to get id for %s role" % role_name) - - if not os_utils.add_role_user(keystone, user_id, role_id, tenant_id): - logger.error("Error : Failed to add %s on tenant" % - ks_creds['username']) - - user_id = os_utils.create_user( - keystone, VIMS_TENANT_NAME, VIMS_TENANT_NAME, None, tenant_id) - if not user_id: - logger.error("Error : Failed to create %s user" % VIMS_TENANT_NAME) - - logger.info("Update OpenStack creds informations") - ks_creds.update({ - "username": VIMS_TENANT_NAME, - "password": VIMS_TENANT_NAME, - "tenant_name": VIMS_TENANT_NAME, - }) - - nt_creds.update({ - "tenant_name": VIMS_TENANT_NAME, - }) - - nv_creds.update({ - "project_id": VIMS_TENANT_NAME, - }) - - logger.info("Upload some OS images if it doesn't exist") - glance = os_utils.get_glance_client() - - for img in VIMS_IMAGES.keys(): - image_name = VIMS_IMAGES[img]['image_name'] - image_url = VIMS_IMAGES[img]['image_url'] - - image_id = os_utils.get_image_id(glance, image_name) - - if image_id == '': - logger.info("""%s image doesn't exist on glance repository. Try - downloading this image and upload on glance !""" % image_name) - image_id = download_and_add_image_on_glance( - glance, image_name, image_url) - - if image_id == '': - step_failure( - "init", - "Error : Failed to find or upload required OS " - "image for this deployment") - - nova = nvclient.Client("2", **nv_creds) - - logger.info("Update security group quota for this tenant") - neutron = ntclient.Client(**nt_creds) - if not os_utils.update_sg_quota(neutron, tenant_id, 50, 100): - step_failure( - "init", - "Failed to update security group quota for tenant " + - VIMS_TENANT_NAME) - - # ###############Â CLOUDIFY INITIALISATION ################ - public_auth_url = keystone.service_catalog.url_for( - service_type='identity', endpoint_type='publicURL') - - cfy = Orchestrator(VIMS_DATA_DIR, CFY_INPUTS) - - cfy.set_credentials(username=ks_creds['username'], password=ks_creds[ - 'password'], tenant_name=ks_creds['tenant_name'], - auth_url=public_auth_url) - - logger.info("Collect flavor id for cloudify manager server") - nova = nvclient.Client("2", **nv_creds) - - flavor_name = "m1.large" - flavor_id = os_utils.get_flavor_id(nova, flavor_name) - for requirement in CFY_MANAGER_REQUIERMENTS: - if requirement == 'ram_min': - flavor_id = os_utils.get_flavor_id_by_ram_range( - nova, CFY_MANAGER_REQUIERMENTS['ram_min'], 10000) - - if flavor_id == '': - logger.error( - "Failed to find %s flavor. " - "Try with ram range default requirement !" % flavor_name) - flavor_id = os_utils.get_flavor_id_by_ram_range(nova, 4000, 8196) - - if flavor_id == '': - step_failure("orchestrator", - "Failed to find required flavor for this deployment") - - cfy.set_flavor_id(flavor_id) - - image_name = "centos_7" - image_id = os_utils.get_image_id(glance, image_name) - for requirement in CFY_MANAGER_REQUIERMENTS: - if requirement == 'os_image': - image_id = os_utils.get_image_id( - glance, CFY_MANAGER_REQUIERMENTS['os_image']) - - if image_id == '': - step_failure( - "orchestrator", - "Error : Failed to find required OS image for cloudify manager") - - cfy.set_image_id(image_id) - - ext_net = os_utils.get_external_net(neutron) - if not ext_net: - step_failure("orchestrator", "Failed to get external network") - - cfy.set_external_network_name(ext_net) - - ns = ft_utils.get_resolvconf_ns() - if ns: - cfy.set_nameservers(ns) - - if 'compute' in nova.client.services_url: - cfy.set_nova_url(nova.client.services_url['compute']) - if neutron.httpclient.endpoint_url is not None: - cfy.set_neutron_url(neutron.httpclient.endpoint_url) - - logger.info("Prepare virtualenv for cloudify-cli") - cmd = "chmod +x " + VIMS_DIR + "create_venv.sh" - ft_utils.execute_command(cmd) - time.sleep(3) - cmd = VIMS_DIR + "create_venv.sh " + VIMS_DATA_DIR - ft_utils.execute_command(cmd) - - cfy.download_manager_blueprint( - CFY_MANAGER_BLUEPRINT['url'], CFY_MANAGER_BLUEPRINT['branch']) - - # ###############Â CLOUDIFY DEPLOYMENT ################ - start_time_ts = time.time() - end_time_ts = start_time_ts - logger.info("Cloudify deployment Start Time:'%s'" % ( - datetime.datetime.fromtimestamp(start_time_ts).strftime( - '%Y-%m-%d %H:%M:%S'))) - - error = cfy.deploy_manager() - if error: - step_failure("orchestrator", error) - - end_time_ts = time.time() - duration = round(end_time_ts - start_time_ts, 1) - logger.info("Cloudify deployment duration:'%s'" % duration) - set_result("orchestrator", duration, "") - - # ###############Â CLEARWATER INITIALISATION ################ - - cw = Clearwater(CW_INPUTS, cfy, logger) - - logger.info("Collect flavor id for all clearwater vm") - nova = nvclient.Client("2", **nv_creds) - - flavor_name = "m1.small" - flavor_id = os_utils.get_flavor_id(nova, flavor_name) - for requirement in CW_REQUIERMENTS: - if requirement == 'ram_min' and flavor_id == '': - flavor_id = os_utils.get_flavor_id_by_ram_range( - nova, CW_REQUIERMENTS['ram_min'], 4500) - - if flavor_id == '': - logger.error( - "Failed to find %s flavor. Try with ram range " - "default requirement !" % flavor_name) - flavor_id = os_utils.get_flavor_id_by_ram_range(nova, 4000, 8196) - - if flavor_id == '': - step_failure( - "vIMS", "Failed to find required flavor for this deployment") - - cw.set_flavor_id(flavor_id) - - image_name = "ubuntu_14.04" - image_id = os_utils.get_image_id(glance, image_name) - for requirement in CW_REQUIERMENTS: - if requirement == 'os_image': - image_id = os_utils.get_image_id( - glance, CW_REQUIERMENTS['os_image']) - - if image_id == '': - step_failure( - "vIMS", - "Error : Failed to find required OS image for cloudify manager") - - cw.set_image_id(image_id) - - ext_net = os_utils.get_external_net(neutron) - if not ext_net: - step_failure("vIMS", "Failed to get external network") - - cw.set_external_network_name(ext_net) - - # ###############Â CLEARWATER DEPLOYMENT ################ - - start_time_ts = time.time() - end_time_ts = start_time_ts - logger.info("vIMS VNF deployment Start Time:'%s'" % ( - datetime.datetime.fromtimestamp(start_time_ts).strftime( - '%Y-%m-%d %H:%M:%S'))) - - error = cw.deploy_vnf(CW_BLUEPRINT) - if error: - step_failure("vIMS", error) - - end_time_ts = time.time() - duration = round(end_time_ts - start_time_ts, 1) - logger.info("vIMS VNF deployment duration:'%s'" % duration) - set_result("vIMS", duration, "") - - # ###############Â CLEARWATER TEST ################ - - test_clearwater() - - # ##########Â CLEARWATER UNDEPLOYMENT ############ - - cw.undeploy_vnf() - - # ###########Â CLOUDIFY UNDEPLOYMENT ############# - - cfy.undeploy_manager() - - # ############## GENERAL CLEANUP ################ - if args.noclean: - exit(0) - - ks_creds = os_utils.get_credentials("keystone") - - keystone = ksclient.Client(**ks_creds) - - logger.info("Removing %s tenant .." % CFY_INPUTS['keystone_tenant_name']) - tenant_id = os_utils.get_tenant_id( - keystone, CFY_INPUTS['keystone_tenant_name']) - if tenant_id == '': - logger.error("Error : Failed to get id of %s tenant" % - CFY_INPUTS['keystone_tenant_name']) - else: - if not os_utils.delete_tenant(keystone, tenant_id): - logger.error("Error : Failed to remove %s tenant" % - CFY_INPUTS['keystone_tenant_name']) - - logger.info("Removing %s user .." % CFY_INPUTS['keystone_username']) - user_id = os_utils.get_user_id( - keystone, CFY_INPUTS['keystone_username']) - if user_id == '': - logger.error("Error : Failed to get id of %s user" % - CFY_INPUTS['keystone_username']) - else: - if not os_utils.delete_user(keystone, user_id): - logger.error("Error : Failed to remove %s user" % - CFY_INPUTS['keystone_username']) - - -if __name__ == '__main__': - main() diff --git a/functest/tests/unit/cli/__init__.py b/functest/tests/unit/cli/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/functest/tests/unit/cli/__init__.py diff --git a/functest/tests/unit/cli/commands/__init__.py b/functest/tests/unit/cli/commands/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/functest/tests/unit/cli/commands/__init__.py diff --git a/functest/tests/unit/cli/commands/test_cli_env.py b/functest/tests/unit/cli/commands/test_cli_env.py new file mode 100644 index 000000000..f70761dcd --- /dev/null +++ b/functest/tests/unit/cli/commands/test_cli_env.py @@ -0,0 +1,131 @@ +#!/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 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 + + +class CliEnvTesting(unittest.TestCase): + + logging.disable(logging.CRITICAL) + + def setUp(self): + self.cli_environ = cli_env.CliEnv() + + @mock.patch('functest.cli.commands.cli_testcase.os.path.isfile', + return_value=False) + @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command') + def test_prepare_default(self, mock_ft_utils, mock_os): + cmd = ("python %s/functest/ci/prepare_env.py start" % + CONST.dir_repo_functest) + self.cli_environ.prepare() + mock_ft_utils.assert_called_with(cmd) + + @mock.patch('functest.cli.commands.cli_testcase.os.path.isfile', + return_value=True) + @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command') + def test_prepare_missing_status(self, mock_ft_utils, mock_os): + with mock.patch('__builtin__.raw_input', return_value="y"), \ + mock.patch('functest.cli.commands.cli_testcase.os.remove') \ + as mock_os_remove: + cmd = ("python %s/functest/ci/prepare_env.py start" % + CONST.dir_repo_functest) + self.cli_environ.prepare() + mock_os_remove.assert_called_once_with(CONST.env_active) + mock_ft_utils.assert_called_with(cmd) + + def _test_show_missing_env_var(self, var, *args): + if var == 'INSTALLER_TYPE': + CONST.INSTALLER_TYPE = None + reg_string = "| INSTALLER: Unknown, \S+\s*|" + elif var == 'INSTALLER_IP': + CONST.INSTALLER_IP = None + reg_string = "| INSTALLER: \S+, Unknown\s*|" + elif var == 'SCENARIO': + CONST.DEPLOY_SCENARIO = None + reg_string = "| SCENARIO: Unknown\s*|" + elif var == 'NODE': + CONST.NODE_NAME = None + reg_string = "| POD: Unknown\s*|" + elif var == 'BUILD_TAG': + CONST.BUILD_TAG = None + reg_string = "| BUILD TAG: None|" + elif var == 'DEBUG': + CONST.CI_DEBUG = None + reg_string = "| DEBUG FLAG: false\s*|" + elif var == 'STATUS': + reg_string = "| STATUS: not ready\s*|" + + with mock.patch('functest.cli.commands.cli_env.click.echo') \ + as mock_click_echo: + self.cli_environ.show() + mock_click_echo.assert_called_with(test_utils. + RegexMatch(reg_string)) + + @mock.patch('functest.cli.commands.cli_env.git.Repo') + def test_show_missing_ci_installer_type(self, *args): + self._test_show_missing_env_var('INSTALLER_TYPE', *args) + + @mock.patch('functest.cli.commands.cli_env.git.Repo') + def test_show_missing_ci_installer_ip(self, *args): + self._test_show_missing_env_var('INSTALLER_IP', *args) + + @mock.patch('functest.cli.commands.cli_env.git.Repo') + def test_show_missing_ci_scenario(self, *args): + self._test_show_missing_env_var('SCENARIO', *args) + + @mock.patch('functest.cli.commands.cli_env.git.Repo') + def test_show_missing_ci_node(self, *args): + self._test_show_missing_env_var('NODE', *args) + + @mock.patch('functest.cli.commands.cli_env.git.Repo') + def test_show_missing_ci_build_tag(self, *args): + self._test_show_missing_env_var('BUILD_TAG', *args) + + @mock.patch('functest.cli.commands.cli_env.git.Repo') + def test_show_missing_ci_debug(self, *args): + self._test_show_missing_env_var('DEBUG', *args) + + @mock.patch('functest.cli.commands.cli_env.git.Repo') + @mock.patch('functest.cli.commands.cli_env.os.path.isfile', + return_value=False) + def test_show_missing_environment(self, *args): + self._test_show_missing_env_var('STATUS', *args) + + @mock.patch('functest.cli.commands.cli_env.os.path.exists', + return_value=False) + def test_show_missing_git_repo_dir(self, *args): + CONST.dir_repo_functest = None + self.assertRaises(NoSuchPathError, lambda: self.cli_environ.show()) + + @mock.patch('functest.cli.commands.cli_env.click.echo') + @mock.patch('functest.cli.commands.cli_env.os.path.isfile', + return_value=True) + def test_status_environment_present(self, mock_path, mock_click_echo): + self.assertEqual(self.cli_environ.status(), 0) + mock_click_echo.assert_called_with("Functest environment" + " ready to run tests.\n") + + @mock.patch('functest.cli.commands.cli_env.click.echo') + @mock.patch('functest.cli.commands.cli_env.os.path.isfile', + return_value=False) + def test_status_environment_absent(self, mock_path, mock_click_echo): + self.assertEqual(self.cli_environ.status(), 1) + mock_click_echo.assert_called_with("Functest environment" + " is not installed.\n") + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/functest/tests/unit/cli/commands/test_cli_os.py b/functest/tests/unit/cli/commands/test_cli_os.py new file mode 100644 index 000000000..f0e58c676 --- /dev/null +++ b/functest/tests/unit/cli/commands/test_cli_os.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python +# +# jose.lausuch@ericsson.com +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +# + +import logging +import unittest +import os + +import mock + +from functest.cli.commands import cli_os +from functest.utils.constants import CONST + + +class CliOpenStackTesting(unittest.TestCase): + logging.disable(logging.CRITICAL) + + def setUp(self): + self.endpoint_ip = 'test_ip' + self.os_auth_url = 'http://test_ip:test_port/v2.0' + self.installer_type = 'test_installer_type' + self.installer_ip = 'test_installer_ip' + self.openstack_creds = 'test_openstack_creds' + self.dir_repo_functest = 'test_dir_repo_functest' + self.snapshot_file = 'test_snapshot_file' + self.cli_os = cli_os.CliOpenStack() + + def test_ping_endpoint_default(self): + self.cli_os.os_auth_url = self.os_auth_url + self.cli_os.endpoint_ip = self.endpoint_ip + with mock.patch('functest.cli.commands.cli_os.os.system', + return_value=0): + self.assertEqual(self.cli_os.ping_endpoint(), 0) + + @mock.patch('functest.cli.commands.cli_os.exit', side_effect=Exception) + @mock.patch('functest.cli.commands.cli_os.click.echo') + def test_ping_endpoint_missing_auth_url(self, mock_click_echo, + mock_exit): + with self.assertRaises(Exception): + self.cli_os.os_auth_url = None + self.cli_os.ping_endpoint() + mock_click_echo.assert_called_once_with("Source the OpenStack " + "credentials first '. " + "$creds'") + + @mock.patch('functest.cli.commands.cli_os.exit') + @mock.patch('functest.cli.commands.cli_os.click.echo') + def test_ping_endpoint_os_system_fails(self, mock_click_echo, + mock_exit): + self.cli_os.os_auth_url = self.os_auth_url + self.cli_os.endpoint_ip = self.endpoint_ip + with mock.patch('functest.cli.commands.cli_os.os.system', + return_value=1): + self.cli_os.ping_endpoint() + mock_click_echo.assert_called_once_with("Cannot talk to the " + "endpoint %s\n" % + self.endpoint_ip) + mock_exit.assert_called_once_with(0) + + @mock.patch('functest.cli.commands.cli_os.ft_utils.execute_command') + @mock.patch('functest.cli.commands.cli_os.os.path.isfile', + return_value=False) + @mock.patch('functest.cli.commands.cli_os.click.echo') + def test_fetch_credentials_default(self, mock_click_echo, + mock_os_path, + mock_ftutils_execute): + CONST.INSTALLER_TYPE = self.installer_type + CONST.INSTALLER_IP = self.installer_ip + cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s" + % (CONST.dir_repos, + self.openstack_creds, + self.installer_type, + self.installer_ip)) + self.cli_os.openstack_creds = self.openstack_creds + self.cli_os.fetch_credentials() + mock_click_echo.assert_called_once_with("Fetching credentials from " + "installer node '%s' with " + "IP=%s.." % + (self.installer_type, + self.installer_ip)) + mock_ftutils_execute.assert_called_once_with(cmd, verbose=False) + + @mock.patch('functest.cli.commands.cli_os.ft_utils.execute_command') + @mock.patch('functest.cli.commands.cli_os.os.path.isfile', + return_value=False) + @mock.patch('functest.cli.commands.cli_os.click.echo') + def test_fetch_credentials_missing_installer_type(self, mock_click_echo, + mock_os_path, + mock_ftutils_execute): + installer_type = None + installer_ip = self.installer_ip + CONST.INSTALLER_TYPE = installer_type + CONST.INSTALLER_IP = installer_ip + cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s" + % (CONST.dir_repos, + self.openstack_creds, + installer_type, + installer_ip)) + self.cli_os.openstack_creds = self.openstack_creds + self.cli_os.fetch_credentials() + mock_click_echo.assert_any_call("The environment variable " + "'INSTALLER_TYPE' is not" + "defined. Please export it") + mock_click_echo.assert_any_call("Fetching credentials from " + "installer node '%s' with " + "IP=%s.." % + (installer_type, + installer_ip)) + mock_ftutils_execute.assert_called_once_with(cmd, verbose=False) + + @mock.patch('functest.cli.commands.cli_os.ft_utils.execute_command') + @mock.patch('functest.cli.commands.cli_os.os.path.isfile', + return_value=False) + @mock.patch('functest.cli.commands.cli_os.click.echo') + def test_fetch_credentials_missing_installer_ip(self, mock_click_echo, + mock_os_path, + mock_ftutils_execute): + installer_type = self.installer_type + installer_ip = None + CONST.INSTALLER_TYPE = installer_type + CONST.INSTALLER_IP = installer_ip + cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s" + % (CONST.dir_repos, + self.openstack_creds, + installer_type, + installer_ip)) + self.cli_os.openstack_creds = self.openstack_creds + self.cli_os.fetch_credentials() + mock_click_echo.assert_any_call("The environment variable " + "'INSTALLER_IP' is not" + "defined. Please export it") + mock_click_echo.assert_any_call("Fetching credentials from " + "installer node '%s' with " + "IP=%s.." % + (installer_type, + installer_ip)) + mock_ftutils_execute.assert_called_once_with(cmd, verbose=False) + + @mock.patch('functest.cli.commands.cli_os.ft_utils.execute_command') + def test_check(self, mock_ftutils_execute): + with mock.patch.object(self.cli_os, 'ping_endpoint'): + CONST.dir_repo_functest = self.dir_repo_functest + cmd = CONST.dir_repo_functest + "/functest/ci/check_os.sh" + self.cli_os.check() + mock_ftutils_execute.assert_called_once_with(cmd, verbose=False) + + @mock.patch('functest.cli.commands.cli_os.os.path.isfile', + return_value=False) + @mock.patch('functest.cli.commands.cli_os.click.echo') + def test_snapshot_create(self, mock_click_echo, mock_os_path): + with mock.patch.object(self.cli_os, 'ping_endpoint'), \ + mock.patch('functest.cli.commands.cli_os.os_snapshot.main') \ + as mock_os_snapshot: + self.cli_os.snapshot_create() + mock_click_echo.assert_called_once_with("Generating Openstack " + "snapshot...") + self.assertTrue(mock_os_snapshot.called) + + @mock.patch('functest.cli.commands.cli_os.os.path.isfile', + return_value=True) + @mock.patch('functest.cli.commands.cli_os.click.echo') + def test_snapshot_create_overwrite(self, mock_click_echo, mock_os_path): + with mock.patch('__builtin__.raw_input', return_value="y") \ + as mock_raw_input, \ + mock.patch.object(self.cli_os, 'ping_endpoint'), \ + mock.patch('functest.cli.commands.cli_os.os_snapshot.main') \ + as mock_os_snapshot: + self.cli_os.snapshot_create() + mock_click_echo.assert_called_once_with("Generating Openstack " + "snapshot...") + mock_raw_input.assert_any_call("It seems there is already an " + "OpenStack snapshot. Do you want " + "to overwrite it with the current " + "OpenStack status? [y|n]\n") + self.assertTrue(mock_os_snapshot.called) + + @mock.patch('functest.cli.commands.cli_os.os.path.isfile', + return_value=False) + @mock.patch('functest.cli.commands.cli_os.click.echo') + def test_snapshot_show_missing_snap(self, mock_click_echo, mock_os_path): + self.cli_os.snapshot_show() + mock_click_echo.assert_called_once_with("There is no OpenStack " + "snapshot created. To create " + "one run the command " + "'functest openstack " + "snapshot-create'") + + @mock.patch('functest.cli.commands.cli_os.os.path.isfile', + return_value=True) + @mock.patch('functest.cli.commands.cli_os.click.echo') + def test_snapshot_show_default(self, mock_click_echo, mock_os_path): + with mock.patch('__builtin__.open', mock.mock_open(read_data='0')) \ + as m: + self.cli_os.snapshot_file = self.snapshot_file + self.cli_os.snapshot_show() + m.assert_called_once_with(self.snapshot_file, 'r') + mock_click_echo.assert_called_once_with("\n0") + + @mock.patch('functest.cli.commands.cli_os.os.path.isfile', + return_value=True) + @mock.patch('functest.cli.commands.cli_os.click.echo') + def test_clean(self, mock_click_echo, mock_os_path): + with mock.patch.object(self.cli_os, 'ping_endpoint'), \ + mock.patch('functest.cli.commands.cli_os.os_clean.main') \ + as mock_os_clean: + self.cli_os.clean() + self.assertTrue(mock_os_clean.called) + + @mock.patch('functest.cli.commands.cli_os.os.path.isfile', + return_value=False) + @mock.patch('functest.cli.commands.cli_os.click.echo') + def test_clean_missing_file(self, mock_click_echo, mock_os_path): + with mock.patch.object(self.cli_os, 'ping_endpoint'): + self.cli_os.clean() + mock_click_echo.assert_called_once_with("Not possible to clean " + "OpenStack without a " + "snapshot. This could " + "cause problems. " + "Run first the command " + "'functest openstack " + "snapshot-create'") + + @mock.patch('functest.cli.commands.cli_os.click.echo') + def test_show_credentials(self, mock_click_echo): + key = 'OS_KEY' + value = 'OS_VALUE' + with mock.patch.dict(os.environ, {key: value}): + self.cli_os.show_credentials() + mock_click_echo.assert_any_call("{}={}".format(key, value)) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/functest/tests/unit/cli/commands/test_cli_testcase.py b/functest/tests/unit/cli/commands/test_cli_testcase.py new file mode 100644 index 000000000..39c8139d7 --- /dev/null +++ b/functest/tests/unit/cli/commands/test_cli_testcase.py @@ -0,0 +1,103 @@ +#!/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 unittest + +import mock + +from functest.cli.commands import cli_testcase +from functest.utils.constants import CONST + + +class CliTestCasesTesting(unittest.TestCase): + + logging.disable(logging.CRITICAL) + + def setUp(self): + self.testname = 'testname' + with mock.patch('functest.cli.commands.cli_testcase.tb'): + self.cli_tests = cli_testcase.CliTestcase() + + @mock.patch('functest.cli.commands.cli_testcase.vacation.main') + def test_run_vacation(self, mock_method): + self.cli_tests.run('vacation') + self.assertTrue(mock_method.called) + + @mock.patch('functest.cli.commands.cli_testcase.os.path.isfile', + return_value=False) + @mock.patch('functest.cli.commands.cli_testcase.click.echo') + def test_run_missing_env_file(self, mock_click_echo, mock_os): + self.cli_tests.run(self.testname) + mock_click_echo.assert_called_with("Functest environment is not ready." + " Run first 'functest env prepare'") + + @mock.patch('functest.cli.commands.cli_testcase.os.path.isfile', + return_value=True) + @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command') + def test_run_default(self, mock_ft_utils, mock_os): + cmd = ("python %s/functest/ci/run_tests.py " + "%s -t %s" % (CONST.dir_repo_functest, "-n -r ", self.testname)) + self.cli_tests.run(self.testname, noclean=True, report=True) + mock_ft_utils.assert_called_with(cmd) + + @mock.patch('functest.cli.commands.cli_testcase.os.path.isfile', + return_value=True) + @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command') + def test_run_noclean_missing_report(self, mock_ft_utils, mock_os): + cmd = ("python %s/functest/ci/run_tests.py " + "%s -t %s" % (CONST.dir_repo_functest, "-n ", self.testname)) + self.cli_tests.run(self.testname, noclean=True, report=False) + mock_ft_utils.assert_called_with(cmd) + + @mock.patch('functest.cli.commands.cli_testcase.os.path.isfile', + return_value=True) + @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command') + def test_run_report_missing_noclean(self, mock_ft_utils, mock_os): + cmd = ("python %s/functest/ci/run_tests.py " + "%s -t %s" % (CONST.dir_repo_functest, "-r ", self.testname)) + self.cli_tests.run(self.testname, noclean=False, report=True) + mock_ft_utils.assert_called_with(cmd) + + @mock.patch('functest.cli.commands.cli_testcase.os.path.isfile', + return_value=True) + @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command') + def test_run_missing_noclean_report(self, mock_ft_utils, mock_os): + cmd = ("python %s/functest/ci/run_tests.py " + "%s -t %s" % (CONST.dir_repo_functest, "", self.testname)) + self.cli_tests.run(self.testname, noclean=False, report=False) + mock_ft_utils.assert_called_with(cmd) + + @mock.patch('functest.cli.commands.cli_testcase.click.echo') + def test_list(self, mock_click_echo): + with mock.patch.object(self.cli_tests.tiers, 'get_tiers', + return_value=[]): + self.cli_tests.list() + mock_click_echo.assert_called_with("") + + @mock.patch('functest.cli.commands.cli_testcase.click.echo') + def test_show_default_desc_none(self, mock_click_echo): + with mock.patch.object(self.cli_tests.tiers, 'get_test', + return_value=None): + self.cli_tests.show(self.testname) + mock_click_echo.assert_any_call("The test case '%s' " + "does not exist or is" + " not supported." + % self.testname) + + @mock.patch('functest.cli.commands.cli_testcase.click.echo') + def test_show_default(self, mock_click_echo): + mock_obj = mock.Mock() + with mock.patch.object(self.cli_tests.tiers, 'get_test', + return_value=mock_obj): + self.cli_tests.show(self.testname) + mock_click_echo.assert_called_with(mock_obj) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/functest/tests/unit/cli/commands/test_cli_tier.py b/functest/tests/unit/cli/commands/test_cli_tier.py new file mode 100644 index 000000000..802359f16 --- /dev/null +++ b/functest/tests/unit/cli/commands/test_cli_tier.py @@ -0,0 +1,130 @@ +#!/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 unittest + +import mock + +from functest.cli.commands import cli_tier +from functest.utils.constants import CONST + + +class CliTierTesting(unittest.TestCase): + + logging.disable(logging.CRITICAL) + + def setUp(self): + self.tiername = 'tiername' + self.testnames = 'testnames' + with mock.patch('functest.cli.commands.cli_tier.tb'): + self.cli_tier = cli_tier.CliTier() + + @mock.patch('functest.cli.commands.cli_tier.click.echo') + def test_list(self, mock_click_echo): + with mock.patch.object(self.cli_tier.tiers, 'get_tiers', + return_value=[]): + self.cli_tier.list() + mock_click_echo.assert_called_with("") + + @mock.patch('functest.cli.commands.cli_tier.click.echo') + def test_show_default(self, mock_click_echo): + with mock.patch.object(self.cli_tier.tiers, 'get_tier', + return_value=self.tiername): + self.cli_tier.show(self.tiername) + mock_click_echo.assert_called_with(self.tiername) + + @mock.patch('functest.cli.commands.cli_tier.click.echo') + def test_show_missing_tier(self, mock_click_echo): + with mock.patch.object(self.cli_tier.tiers, 'get_tier', + return_value=None), \ + mock.patch.object(self.cli_tier.tiers, 'get_tier_names', + return_value='tiernames'): + self.cli_tier.show(self.tiername) + mock_click_echo.assert_called_with("The tier with name '%s' does " + "not exist. Available tiers are" + ":\n %s\n" % (self.tiername, + 'tiernames')) + + @mock.patch('functest.cli.commands.cli_tier.click.echo') + def test_gettests_default(self, mock_click_echo): + mock_obj = mock.Mock() + attrs = {'get_test_names.return_value': self.testnames} + mock_obj.configure_mock(**attrs) + + with mock.patch.object(self.cli_tier.tiers, 'get_tier', + return_value=mock_obj): + self.cli_tier.gettests(self.tiername) + mock_click_echo.assert_called_with("Test cases in tier " + "'%s':\n %s\n" % (self.tiername, + self.testnames + )) + + @mock.patch('functest.cli.commands.cli_tier.click.echo') + def test_gettests_missing_tier(self, mock_click_echo): + with mock.patch.object(self.cli_tier.tiers, 'get_tier', + return_value=None), \ + mock.patch.object(self.cli_tier.tiers, 'get_tier_names', + return_value='tiernames'): + self.cli_tier.gettests(self.tiername) + mock_click_echo.assert_called_with("The tier with name '%s' does " + "not exist. Available tiers are" + ":\n %s\n" % (self.tiername, + 'tiernames')) + + @mock.patch('functest.cli.commands.cli_tier.os.path.isfile', + return_value=False) + @mock.patch('functest.cli.commands.cli_tier.click.echo') + def test_run_missing_env_file(self, mock_click_echo, mock_os): + self.cli_tier.run(self.tiername) + mock_click_echo.assert_called_with("Functest environment is not ready." + " Run first 'functest env prepare'") + + @mock.patch('functest.cli.commands.cli_tier.os.path.isfile', + return_value=True) + @mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command') + def test_run_default(self, mock_ft_utils, mock_os): + cmd = ("python %s/functest/ci/run_tests.py " + "%s -t %s" % (CONST.dir_repo_functest, "-n -r ", + self.tiername)) + self.cli_tier.run(self.tiername, noclean=True, report=True) + mock_ft_utils.assert_called_with(cmd) + + @mock.patch('functest.cli.commands.cli_tier.os.path.isfile', + return_value=True) + @mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command') + def test_run_report_missing_noclean(self, mock_ft_utils, mock_os): + cmd = ("python %s/functest/ci/run_tests.py " + "%s -t %s" % (CONST.dir_repo_functest, "-r ", + self.tiername)) + self.cli_tier.run(self.tiername, noclean=False, report=True) + mock_ft_utils.assert_called_with(cmd) + + @mock.patch('functest.cli.commands.cli_tier.os.path.isfile', + return_value=True) + @mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command') + def test_run_noclean_missing_report(self, mock_ft_utils, mock_os): + cmd = ("python %s/functest/ci/run_tests.py " + "%s -t %s" % (CONST.dir_repo_functest, "-n ", + self.tiername)) + self.cli_tier.run(self.tiername, noclean=True, report=False) + mock_ft_utils.assert_called_with(cmd) + + @mock.patch('functest.cli.commands.cli_tier.os.path.isfile', + return_value=True) + @mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command') + def test_run_missing_noclean_report(self, mock_ft_utils, mock_os): + cmd = ("python %s/functest/ci/run_tests.py " + "%s -t %s" % (CONST.dir_repo_functest, "", + self.tiername)) + self.cli_tier.run(self.tiername, noclean=False, report=False) + mock_ft_utils.assert_called_with(cmd) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/functest/tests/unit/cli/test_cli_base.py b/functest/tests/unit/cli/test_cli_base.py new file mode 100644 index 000000000..fe065c2aa --- /dev/null +++ b/functest/tests/unit/cli/test_cli_base.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python + +# Copyright (c) 2016 Orange and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +import logging +import unittest + +import mock +from click.testing import CliRunner + +with mock.patch('functest.cli.commands.cli_testcase.CliTestcase.__init__', + mock.Mock(return_value=None)), \ + mock.patch('functest.cli.commands.cli_tier.CliTier.__init__', + mock.Mock(return_value=None)): + from functest.cli import cli_base + + +class CliBaseTesting(unittest.TestCase): + + logging.disable(logging.CRITICAL) + + def setUp(self): + self.runner = CliRunner() + self._openstack = cli_base._openstack + self._env = cli_base._env + self._testcase = cli_base._testcase + self._tier = cli_base._tier + + def test_os_check(self): + with mock.patch.object(self._openstack, 'check') as mock_method: + result = self.runner.invoke(cli_base.os_check) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_os_snapshot_create(self): + with mock.patch.object(self._openstack, 'snapshot_create') \ + as mock_method: + result = self.runner.invoke(cli_base.os_snapshot_create) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_os_snapshot_show(self): + with mock.patch.object(self._openstack, 'snapshot_show') \ + as mock_method: + result = self.runner.invoke(cli_base.os_snapshot_show) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_os_clean(self): + with mock.patch.object(self._openstack, 'clean') as mock_method: + result = self.runner.invoke(cli_base.os_clean) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_os_show_credentials(self): + with mock.patch.object(self._openstack, 'show_credentials') \ + as mock_method: + result = self.runner.invoke(cli_base.os_show_credentials) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_os_fetch_rc(self): + with mock.patch.object(self._openstack, 'fetch_credentials') \ + as mock_method: + result = self.runner.invoke(cli_base.os_fetch_rc) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_env_prepare(self): + with mock.patch.object(self._env, 'prepare') as mock_method: + result = self.runner.invoke(cli_base.env_prepare) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_env_show(self): + with mock.patch.object(self._env, 'show') as mock_method: + result = self.runner.invoke(cli_base.env_show) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_env_status(self): + with mock.patch.object(self._env, 'status') as mock_method: + result = self.runner.invoke(cli_base.env_status) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_testcase_list(self): + with mock.patch.object(self._testcase, 'list') as mock_method: + result = self.runner.invoke(cli_base.testcase_list) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_testcase_show(self): + with mock.patch.object(self._testcase, 'show') as mock_method: + result = self.runner.invoke(cli_base.testcase_show, ['testname']) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_testcase_run(self): + with mock.patch.object(self._testcase, 'run') as mock_method: + result = self.runner.invoke(cli_base.testcase_run, + ['testname', '--noclean']) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_tier_list(self): + with mock.patch.object(self._tier, 'list') as mock_method: + result = self.runner.invoke(cli_base.tier_list) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_tier_show(self): + with mock.patch.object(self._tier, 'show') as mock_method: + result = self.runner.invoke(cli_base.tier_show, ['tiername']) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_tier_gettests(self): + with mock.patch.object(self._tier, 'gettests') as mock_method: + result = self.runner.invoke(cli_base.tier_gettests, ['tiername']) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + def test_tier_run(self): + with mock.patch.object(self._tier, 'run') as mock_method: + result = self.runner.invoke(cli_base.tier_run, + ['tiername', '--noclean']) + self.assertEqual(result.exit_code, 0) + self.assertTrue(mock_method.called) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/functest/tests/unit/core/test_testcase_base.py b/functest/tests/unit/core/test_testcase_base.py index b7c81d87c..8df524b0f 100644 --- a/functest/tests/unit/core/test_testcase_base.py +++ b/functest/tests/unit/core/test_testcase_base.py @@ -9,8 +9,11 @@ import logging import mock +import os import unittest +mock.patch('logging.FileHandler').start() # noqa + from functest.core import testcase_base @@ -31,11 +34,12 @@ class TestcaseBaseTesting(unittest.TestCase): self.assertEqual(self.test.run(), testcase_base.TestcaseBase.EX_RUN_ERROR) + @mock.patch.dict(os.environ, {}) @mock.patch('functest.utils.functest_utils.push_results_to_db', return_value=False) def _test_missing_attribute(self, mock_function): - self.assertEqual(self.test.push_to_db(), - testcase_base.TestcaseBase.EX_PUSH_TO_DB_ERROR) + self.assertEqual(self.test.publish_report(), + testcase_base.TestcaseBase.EX_PUBLISH_RESULT_FAILED) mock_function.assert_not_called() def test_missing_case_name(self): @@ -68,7 +72,7 @@ class TestcaseBaseTesting(unittest.TestCase): return_value=False) def test_push_to_db_failed(self, mock_function): self.assertEqual(self.test.push_to_db(), - testcase_base.TestcaseBase.EX_PUSH_TO_DB_ERROR) + testcase_base.TestcaseBase.EX_PUBLISH_RESULT_FAILED) mock_function.assert_called_once_with( self.test.project, self.test.case_name, self.test.start_time, self.test.stop_time, self.test.criteria, self.test.details) diff --git a/functest/tests/unit/core/test_vnf_base.py b/functest/tests/unit/core/test_vnf_base.py new file mode 100644 index 000000000..e27f2164b --- /dev/null +++ b/functest/tests/unit/core/test_vnf_base.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +# Copyright (c) 2016 Orange and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +import logging +import unittest + +from functest.core import vnf_base + + +class VnfBaseTesting(unittest.TestCase): + + logging.disable(logging.CRITICAL) + + def setUp(self): + self.test = vnf_base.VnfOnBoardingBase(project='functest', + case='aaa') + self.test.project = "functest" + self.test.case_name = "aaa" + self.test.start_time = "1" + self.test.stop_time = "5" + self.test.criteria = "" + self.test.details = {"orchestrator": {"status": "PASS", + "result": "", + "duration": 20}, + "vnf": {"status": "PASS", + "result": "", + "duration": 15}, + "test_vnf": {"status": "FAIL", + "result": "", + "duration": 5}} + + def test_deploy_vnf_unimplemented(self): + with self.assertRaises(Exception) as context: + self.test.deploy_vnf() + self.assertTrue('VNF not deployed' in context.exception) + + def test_test_vnf_unimplemented(self): + with self.assertRaises(Exception) as context: + self.test.test_vnf()() + self.assertTrue('VNF not tested' in context.exception) + + def test_parse_results(self): + self.assertNotEqual(self.test.parse_results(), 0) + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/functest/tests/unit/odl/test_odl.py b/functest/tests/unit/odl/test_odl.py index d8c7f84ec..59ab2c654 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) @@ -260,7 +337,8 @@ class ODLTesting(unittest.TestCase): testcase_base.TestcaseBase.EX_RUN_ERROR) def _test_run(self, status=testcase_base.TestcaseBase.EX_OK, - exception=None, odlip="127.0.0.3", odlwebport="8080"): + exception=None, odlip="127.0.0.3", odlwebport="8080", + odlrestconfport="8181"): with mock.patch('functest.utils.openstack_utils.get_endpoint', side_effect=self._fake_url_for): if exception: @@ -271,7 +349,7 @@ class ODLTesting(unittest.TestCase): self.test.main.assert_called_once_with( keystoneip=self._keystone_ip, neutronip=self._neutron_ip, odlip=odlip, odlpassword=self._odl_password, - odlrestconfport=self._odl_restconfport, + odlrestconfport=odlrestconfport, odlusername=self._odl_username, odlwebport=odlwebport, ospassword=self._os_password, ostenantname=self._os_tenantname, osusername=self._os_username) @@ -333,7 +411,8 @@ 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', + odlrestconfport='8081') def test_run_joid_missing_sdn_controller(self): with mock.patch('functest.utils.openstack_utils.get_endpoint', @@ -353,6 +432,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/test_utils.py b/functest/tests/unit/test_utils.py new file mode 100644 index 000000000..e171db022 --- /dev/null +++ b/functest/tests/unit/test_utils.py @@ -0,0 +1,23 @@ +#!/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 re + + +class RegexMatch(str): + def __eq__(self, other): + match = re.search(self, other) + if match: + return True + return False + + +class SubstrMatch(str): + def __eq__(self, other): + if self in other: + return True + return False diff --git a/functest/tests/unit/utils/test_functest_utils.py b/functest/tests/unit/utils/test_functest_utils.py new file mode 100644 index 000000000..c4b566608 --- /dev/null +++ b/functest/tests/unit/utils/test_functest_utils.py @@ -0,0 +1,600 @@ +#!/usr/bin/env python + +# Copyright (c) 2016 Orange and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +import logging +import os +import time +import unittest +import urllib2 + +from git.exc import NoSuchPathError +import mock +import requests + +from functest.tests.unit import test_utils +mock.patch('logging.FileHandler').start() # noqa +from functest.utils import functest_utils + + +class FunctestUtilsTesting(unittest.TestCase): + + logging.disable(logging.CRITICAL) + + def setUp(self): + self.url = 'http://www.opnfv.org/' + self.timeout = 5 + self.dest_path = 'test_path' + self.repo_path = 'test_repo_path' + self.installer = 'test_installer' + self.scenario = 'test_scenario' + self.build_tag = 'jenkins-functest-fuel-opnfv-jump-2-daily-master-190' + self.version = 'master' + self.node_name = 'test_node_name' + self.project = 'test_project' + self.case_name = 'test_case_name' + self.status = 'test_status' + self.details = 'test_details' + self.db_url = 'test_db_url' + self.success_rate = 2.0 + self.criteria = 'test_criteria==2.0' + self.start_date = 1482624000 + self.stop_date = 1482624000 + self.start_time = time.time() + self.stop_time = time.time() + self.readline = -1 + self.test_ip = ['10.1.23.4', '10.1.14.15', '10.1.16.15'] + self.test_file = 'test_file' + self.error_msg = 'test_error_msg' + self.cmd = 'test_cmd' + self.output_file = 'test_output_file' + self.testname = 'testname' + self.testcase_dict = {'name': 'testname', 'criteria': self.criteria} + self.parameter = 'general.openstack.image_name' + self.config_yaml = 'test_config_yaml-' + self.file_yaml = {'general': {'openstack': {'image_name': + 'test_image_name'}}} + + @mock.patch('urllib2.urlopen', + side_effect=urllib2.URLError('no host given')) + def test_check_internet_connectivity_failed(self, mock_method): + self.assertFalse(functest_utils.check_internet_connectivity()) + mock_method.assert_called_once_with(self.url, timeout=self.timeout) + + @mock.patch('urllib2.urlopen') + def test_check_internet_connectivity_default(self, mock_method): + self.assertTrue(functest_utils.check_internet_connectivity()) + mock_method.assert_called_once_with(self.url, timeout=self.timeout) + + @mock.patch('urllib2.urlopen') + def test_check_internet_connectivity_debian(self, mock_method): + self.url = "https://www.debian.org/" + self.assertTrue(functest_utils.check_internet_connectivity(self.url)) + mock_method.assert_called_once_with(self.url, timeout=self.timeout) + + @mock.patch('urllib2.urlopen', + side_effect=urllib2.URLError('no host given')) + def test_download_url_failed(self, mock_url): + self.assertFalse(functest_utils.download_url(self.url, self.dest_path)) + + @mock.patch('urllib2.urlopen') + def test_download_url_default(self, mock_url): + with mock.patch("__builtin__.open", mock.mock_open()) as m, \ + mock.patch('functest.utils.functest_utils.shutil.copyfileobj')\ + as mock_sh: + name = self.url.rsplit('/')[-1] + dest = self.dest_path + "/" + name + self.assertTrue(functest_utils.download_url(self.url, + self.dest_path)) + m.assert_called_once_with(dest, 'wb') + self.assertTrue(mock_sh.called) + + def test_get_git_branch(self): + with mock.patch('functest.utils.functest_utils.Repo') as mock_repo: + mock_obj2 = mock.Mock() + attrs = {'name': 'test_branch'} + mock_obj2.configure_mock(**attrs) + + mock_obj = mock.Mock() + attrs = {'active_branch': mock_obj2} + mock_obj.configure_mock(**attrs) + + mock_repo.return_value = mock_obj + self.assertEqual(functest_utils.get_git_branch(self.repo_path), + 'test_branch') + + @mock.patch('functest.utils.functest_utils.Repo', + side_effect=NoSuchPathError) + def test_get_git_branch_failed(self, mock_repo): + self.assertRaises(NoSuchPathError, + lambda: functest_utils.get_git_branch(self.repo_path + )) + + @mock.patch('functest.utils.functest_utils.logger.error') + def test_get_installer_type_failed(self, mock_logger_error): + with mock.patch.dict(os.environ, + {}, + clear=True): + self.assertEqual(functest_utils.get_installer_type(), + "Unknown_installer") + mock_logger_error.assert_called_once_with("Impossible to retrieve" + " the installer type") + + def test_get_installer_type_default(self): + with mock.patch.dict(os.environ, + {'INSTALLER_TYPE': 'test_installer'}, + clear=True): + self.assertEqual(functest_utils.get_installer_type(), + self.installer) + + @mock.patch('functest.utils.functest_utils.logger.error') + def test_get_scenario_failed(self, mock_logger_error): + with mock.patch.dict(os.environ, + {}, + clear=True): + self.assertEqual(functest_utils.get_scenario(), + "Unknown_scenario") + mock_logger_error.assert_called_once_with("Impossible to retrieve" + " the scenario") + + def test_get_scenario_default(self): + with mock.patch.dict(os.environ, + {'DEPLOY_SCENARIO': 'test_scenario'}, + clear=True): + self.assertEqual(functest_utils.get_scenario(), + self.scenario) + + @mock.patch('functest.utils.functest_utils.get_build_tag') + def test_get_version_default(self, mock_get_build_tag): + mock_get_build_tag.return_value = self.build_tag + self.assertEqual(functest_utils.get_version(), self.version) + + @mock.patch('functest.utils.functest_utils.get_build_tag') + def test_get_version_unknown(self, mock_get_build_tag): + mock_get_build_tag.return_value = "unknown_build_tag" + self.assertEqual(functest_utils.get_version(), "unknown") + + @mock.patch('functest.utils.functest_utils.logger.error') + def test_get_pod_name_failed(self, mock_logger_error): + with mock.patch.dict(os.environ, + {}, + clear=True): + self.assertEqual(functest_utils.get_pod_name(), + "unknown-pod") + mock_logger_error.assert_called_once_with("Unable to retrieve " + "the POD name from " + "environment. Using " + "pod name 'unknown-pod'") + + def test_get_pod_name_default(self): + with mock.patch.dict(os.environ, + {'NODE_NAME': 'test_node_name'}, + clear=True): + self.assertEqual(functest_utils.get_pod_name(), + self.node_name) + + @mock.patch('functest.utils.functest_utils.logger.error') + def test_get_build_tag_failed(self, mock_logger_error): + with mock.patch.dict(os.environ, + {}, + clear=True): + self.assertEqual(functest_utils.get_build_tag(), + "unknown_build_tag") + mock_logger_error.assert_called_once_with("Impossible to retrieve" + " the build tag") + + def test_get_build_tag_default(self): + with mock.patch.dict(os.environ, + {'BUILD_TAG': self.build_tag}, + clear=True): + self.assertEqual(functest_utils.get_build_tag(), + self.build_tag) + + @mock.patch('functest.utils.functest_utils.get_functest_config') + def test_get_db_url(self, mock_get_functest_config): + mock_get_functest_config.return_value = self.db_url + self.assertEqual(functest_utils.get_db_url(), self.db_url) + mock_get_functest_config.assert_called_once_with('results.test_db_url') + + @mock.patch('functest.utils.functest_utils.logger.info') + def test_logger_test_results(self, mock_logger_info): + with mock.patch('functest.utils.functest_utils.get_pod_name', + return_value=self.node_name), \ + mock.patch('functest.utils.functest_utils.get_scenario', + return_value=self.scenario), \ + mock.patch('functest.utils.functest_utils.get_version', + return_value=self.version), \ + mock.patch('functest.utils.functest_utils.get_build_tag', + return_value=self.build_tag), \ + mock.patch('functest.utils.functest_utils.get_db_url', + return_value=self.db_url): + functest_utils.logger_test_results(self.project, self.case_name, + self.status, self.details) + mock_logger_info.assert_called_once_with( + "\n" + "****************************************\n" + "\t %(p)s/%(n)s results \n\n" + "****************************************\n" + "DB:\t%(db)s\n" + "pod:\t%(pod)s\n" + "version:\t%(v)s\n" + "scenario:\t%(s)s\n" + "status:\t%(c)s\n" + "build tag:\t%(b)s\n" + "details:\t%(d)s\n" + % {'p': self.project, + 'n': self.case_name, + 'db': self.db_url, + 'pod': self.node_name, + 'v': self.version, + 's': self.scenario, + 'c': self.status, + 'b': self.build_tag, + 'd': self.details}) + + def _get_env_dict(self, var): + dic = {'INSTALLER_TYPE': self.installer, + 'DEPLOY_SCENARIO': self.scenario, + 'NODE_NAME': self.node_name, + 'BUILD_TAG': self.build_tag} + dic.pop(var, None) + return dic + + def _test_push_results_to_db_missing_env(self, env_var): + dic = self._get_env_dict(env_var) + with mock.patch('functest.utils.functest_utils.get_db_url', + return_value=self.db_url), \ + mock.patch.dict(os.environ, + dic, + clear=True), \ + mock.patch('functest.utils.functest_utils.logger.error') \ + as mock_logger_error: + functest_utils.push_results_to_db(self.project, self.case_name, + self.start_date, self.stop_date, + self.criteria, self.details) + mock_logger_error.assert_called_once_with("Please set env var: " + + str("\'" + env_var + + "\'")) + + def test_push_results_to_db_missing_installer(self): + self._test_push_results_to_db_missing_env('INSTALLER_TYPE') + + def test_push_results_to_db_missing_scenario(self): + self._test_push_results_to_db_missing_env('DEPLOY_SCENARIO') + + def test_push_results_to_db_missing_nodename(self): + self._test_push_results_to_db_missing_env('NODE_NAME') + + def test_push_results_to_db_missing_buildtag(self): + self._test_push_results_to_db_missing_env('BUILD_TAG') + + def test_push_results_to_db_incorrect_buildtag(self): + dic = self._get_env_dict(None) + dic['BUILD_TAG'] = 'incorrect_build_tag' + with mock.patch('functest.utils.functest_utils.get_db_url', + return_value=self.db_url), \ + mock.patch.dict(os.environ, + dic, + clear=True), \ + mock.patch('functest.utils.functest_utils.logger.error') \ + as mock_logger_error: + self.assertFalse(functest_utils. + push_results_to_db(self.project, self.case_name, + self.start_date, + self.stop_date, + self.criteria, self.details)) + mock_logger_error.assert_called_once_with("Please fix BUILD_TAG" + " env var: incorrect_" + "build_tag") + + def test_push_results_to_db_request_post_failed(self): + dic = self._get_env_dict(None) + with mock.patch('functest.utils.functest_utils.get_db_url', + return_value=self.db_url), \ + mock.patch.dict(os.environ, + dic, + clear=True), \ + mock.patch('functest.utils.functest_utils.logger.error') \ + as mock_logger_error, \ + mock.patch('functest.utils.functest_utils.requests.post', + side_effect=requests.RequestException): + self.assertFalse(functest_utils. + push_results_to_db(self.project, self.case_name, + self.start_date, + self.stop_date, + self.criteria, self.details)) + mock_logger_error.assert_called_once_with(test_utils. + RegexMatch("Pushing " + "Result to" + " DB" + "(\S+\s*) " + "failed:")) + + def test_push_results_to_db_request_post_exception(self): + dic = self._get_env_dict(None) + with mock.patch('functest.utils.functest_utils.get_db_url', + return_value=self.db_url), \ + mock.patch.dict(os.environ, + dic, + clear=True), \ + mock.patch('functest.utils.functest_utils.logger.error') \ + as mock_logger_error, \ + mock.patch('functest.utils.functest_utils.requests.post', + side_effect=Exception): + self.assertFalse(functest_utils. + push_results_to_db(self.project, self.case_name, + self.start_date, + self.stop_date, + self.criteria, self.details)) + self.assertTrue(mock_logger_error.called) + + def test_push_results_to_db_default(self): + dic = self._get_env_dict(None) + with mock.patch('functest.utils.functest_utils.get_db_url', + return_value=self.db_url), \ + mock.patch.dict(os.environ, + dic, + clear=True), \ + mock.patch('functest.utils.functest_utils.requests.post'): + self.assertTrue(functest_utils. + push_results_to_db(self.project, self.case_name, + self.start_date, + self.stop_date, + self.criteria, self.details)) + readline = 0 + test_ip = ['10.1.23.4', '10.1.14.15', '10.1.16.15'] + + @staticmethod + def readline_side(): + if FunctestUtilsTesting.readline == \ + len(FunctestUtilsTesting.test_ip) - 1: + return False + FunctestUtilsTesting.readline += 1 + return FunctestUtilsTesting.test_ip[FunctestUtilsTesting.readline] + + # TODO: get_resolvconf_ns + @mock.patch('functest.utils.functest_utils.dns.resolver.Resolver') + def test_get_resolvconf_ns_default(self, mock_dns_resolve): + attrs = {'query.return_value': ["test"]} + mock_dns_resolve.configure_mock(**attrs) + + m = mock.Mock() + attrs = {'readline.side_effect': self.readline_side} + m.configure_mock(**attrs) + + with mock.patch("__builtin__.open") as mo: + mo.return_value = m + self.assertEqual(functest_utils.get_resolvconf_ns(), + self.test_ip[1:]) + + def _get_environ(self, var): + if var == 'INSTALLER_TYPE': + return self.installer + elif var == 'DEPLOY_SCENARIO': + return self.scenario + return var + + def test_get_ci_envvars_default(self): + with mock.patch('os.environ.get', + side_effect=self._get_environ): + dic = {"installer": self.installer, + "scenario": self.scenario} + self.assertDictEqual(functest_utils.get_ci_envvars(), dic) + + def cmd_readline(self): + return 'test_value\n' + + @mock.patch('functest.utils.functest_utils.logger.error') + @mock.patch('functest.utils.functest_utils.logger.info') + def test_execute_command_args_present_with_error(self, mock_logger_info, + mock_logger_error): + with mock.patch('functest.utils.functest_utils.subprocess.Popen') \ + as mock_subproc_open, \ + mock.patch('__builtin__.open', mock.mock_open()) as mopen: + + FunctestUtilsTesting.readline = 0 + + mock_obj = mock.Mock() + attrs = {'readline.side_effect': self.cmd_readline()} + mock_obj.configure_mock(**attrs) + + mock_obj2 = mock.Mock() + attrs = {'stdout': mock_obj, 'wait.return_value': 1} + mock_obj2.configure_mock(**attrs) + + mock_subproc_open.return_value = mock_obj2 + + resp = functest_utils.execute_command(self.cmd, info=True, + error_msg=self.error_msg, + verbose=True, + output_file=self.output_file) + self.assertEqual(resp, 1) + msg_exec = ("Executing command: '%s'" % self.cmd) + mock_logger_info.assert_called_once_with(msg_exec) + mopen.assert_called_once_with(self.output_file, "w") + mock_logger_error.assert_called_once_with(self.error_msg) + + @mock.patch('functest.utils.functest_utils.logger.info') + def test_execute_command_args_present_with_success(self, mock_logger_info, + ): + with mock.patch('functest.utils.functest_utils.subprocess.Popen') \ + as mock_subproc_open, \ + mock.patch('__builtin__.open', mock.mock_open()) as mopen: + + FunctestUtilsTesting.readline = 0 + + mock_obj = mock.Mock() + attrs = {'readline.side_effect': self.cmd_readline()} + mock_obj.configure_mock(**attrs) + + mock_obj2 = mock.Mock() + attrs = {'stdout': mock_obj, 'wait.return_value': 0} + mock_obj2.configure_mock(**attrs) + + mock_subproc_open.return_value = mock_obj2 + + resp = functest_utils.execute_command(self.cmd, info=True, + error_msg=self.error_msg, + verbose=True, + output_file=self.output_file) + self.assertEqual(resp, 0) + msg_exec = ("Executing command: '%s'" % self.cmd) + mock_logger_info.assert_called_once_with(msg_exec) + mopen.assert_called_once_with(self.output_file, "w") + + @mock.patch('functest.utils.functest_utils.logger.info') + def test_execute_command_args_missing_with_success(self, mock_logger_info, + ): + with mock.patch('functest.utils.functest_utils.subprocess.Popen') \ + as mock_subproc_open: + + FunctestUtilsTesting.readline = 2 + + mock_obj = mock.Mock() + attrs = {'readline.side_effect': self.cmd_readline()} + mock_obj.configure_mock(**attrs) + + mock_obj2 = mock.Mock() + attrs = {'stdout': mock_obj, 'wait.return_value': 0} + mock_obj2.configure_mock(**attrs) + + mock_subproc_open.return_value = mock_obj2 + + resp = functest_utils.execute_command(self.cmd, info=False, + error_msg="", + verbose=False, + output_file=None) + self.assertEqual(resp, 0) + + @mock.patch('functest.utils.functest_utils.logger.error') + def test_execute_command_args_missing_with_error(self, mock_logger_error, + ): + with mock.patch('functest.utils.functest_utils.subprocess.Popen') \ + as mock_subproc_open: + + FunctestUtilsTesting.readline = 2 + mock_obj = mock.Mock() + attrs = {'readline.side_effect': self.cmd_readline()} + mock_obj.configure_mock(**attrs) + + mock_obj2 = mock.Mock() + attrs = {'stdout': mock_obj, 'wait.return_value': 1} + mock_obj2.configure_mock(**attrs) + + mock_subproc_open.return_value = mock_obj2 + + resp = functest_utils.execute_command(self.cmd, info=False, + error_msg="", + verbose=False, + output_file=None) + self.assertEqual(resp, 1) + + def _get_functest_config(self, var): + return var + + @mock.patch('functest.utils.functest_utils.logger.error') + def test_get_dict_by_test(self, mock_logger_error): + with mock.patch('__builtin__.open', mock.mock_open()), \ + mock.patch('functest.utils.functest_utils.yaml.safe_load') \ + as mock_yaml, \ + mock.patch('functest.utils.functest_utils.get_testcases_' + 'file_dir'): + mock_obj = mock.Mock() + attrs = {'get.return_value': [{'testcases': [self.testcase_dict]}]} + mock_obj.configure_mock(**attrs) + + mock_yaml.return_value = mock_obj + + self.assertDictEqual(functest_utils. + get_dict_by_test(self.testname), + self.testcase_dict) + + @mock.patch('functest.utils.functest_utils.get_dict_by_test') + def test_get_criteria_by_test_default(self, mock_get_dict_by_test): + mock_get_dict_by_test.return_value = self.testcase_dict + self.assertEqual(functest_utils.get_criteria_by_test(self.testname), + self.criteria) + + @mock.patch('functest.utils.functest_utils.get_dict_by_test') + def test_get_criteria_by_test_failed(self, mock_get_dict_by_test): + mock_get_dict_by_test.return_value = None + self.assertIsNone(functest_utils.get_criteria_by_test(self.testname)) + + def test_get_parameter_from_yaml_failed(self): + self.file_yaml['general'] = None + with mock.patch('__builtin__.open', mock.mock_open()), \ + mock.patch('functest.utils.functest_utils.yaml.safe_load') \ + as mock_yaml, \ + self.assertRaises(ValueError) as excep: + mock_yaml.return_value = self.file_yaml + functest_utils.get_parameter_from_yaml(self.parameter, + self.test_file) + self.assertTrue(("The parameter %s is not" + " defined in config_functest.yaml" % + self.parameter) in excep.exception) + + def test_get_parameter_from_yaml_default(self): + with mock.patch('__builtin__.open', mock.mock_open()), \ + mock.patch('functest.utils.functest_utils.yaml.safe_load') \ + as mock_yaml: + mock_yaml.return_value = self.file_yaml + self.assertEqual(functest_utils. + get_parameter_from_yaml(self.parameter, + self.test_file), + 'test_image_name') + + @mock.patch('functest.utils.functest_utils.get_parameter_from_yaml') + def test_get_functest_config_default(self, mock_get_parameter_from_yaml): + with mock.patch.dict(os.environ, + {'CONFIG_FUNCTEST_YAML': self.config_yaml}): + functest_utils.get_functest_config(self.parameter) + mock_get_parameter_from_yaml. \ + assert_called_once_with(self.parameter, + self.config_yaml) + + def test_check_success_rate_default(self): + with mock.patch('functest.utils.functest_utils.get_criteria_by_test') \ + as mock_criteria: + mock_criteria.return_value = self.criteria + resp = functest_utils.check_success_rate(self.case_name, + self.success_rate) + self.assertEqual(resp, 'PASS') + + def test_check_success_rate_failed(self): + with mock.patch('functest.utils.functest_utils.get_criteria_by_test') \ + as mock_criteria: + mock_criteria.return_value = self.criteria + resp = functest_utils.check_success_rate(self.case_name, + 3.0) + self.assertEqual(resp, 'FAIL') + + # TODO: merge_dicts + + def test_get_testcases_file_dir(self): + resp = functest_utils.get_testcases_file_dir() + self.assertEqual(resp, + "/home/opnfv/repos/functest/" + "functest/ci/testcases.yaml") + + def test_get_functest_yaml(self): + with mock.patch('__builtin__.open', mock.mock_open()), \ + mock.patch('functest.utils.functest_utils.yaml.safe_load') \ + as mock_yaml: + mock_yaml.return_value = self.file_yaml + resp = functest_utils.get_functest_yaml() + self.assertEqual(resp, self.file_yaml) + + @mock.patch('functest.utils.functest_utils.logger.info') + def test_print_separator(self, mock_logger_info): + functest_utils.print_separator() + mock_logger_info.assert_called_once_with("=======================" + "=======================") + + +if __name__ == "__main__": + unittest.main(verbosity=2) 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 000000000..28eab4f8a --- /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 000000000..52744db1c --- /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 000000000..a8330c0ed --- /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 000000000..0f510414b --- /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/tests/unit/utils/test_utils.py b/functest/tests/unit/utils/test_utils.py deleted file mode 100644 index 8b6c5e1b9..000000000 --- a/functest/tests/unit/utils/test_utils.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2016 Orange and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 - -import logging -import mock -import unittest -import urllib2 - -from functest.utils import functest_utils - - -class FunctestUtilsTesting(unittest.TestCase): - - logging.disable(logging.CRITICAL) - - def setUp(self): - self.url = 'http://www.opnfv.org/' - self.timeout = 5 - - @mock.patch('urllib2.urlopen', - side_effect=urllib2.URLError('no host given')) - def test_check_internet_connectivity_failed(self, mock_method): - self.assertFalse(functest_utils.check_internet_connectivity()) - mock_method.assert_called_once_with(self.url, timeout=self.timeout) - - @mock.patch('urllib2.urlopen') - def test_check_internet_connectivity_default(self, mock_method): - self.assertTrue(functest_utils.check_internet_connectivity()) - mock_method.assert_called_once_with(self.url, timeout=self.timeout) - - @mock.patch('urllib2.urlopen') - def test_check_internet_connectivity_debian(self, mock_method): - self.url = "https://www.debian.org/" - self.assertTrue(functest_utils.check_internet_connectivity(self.url)) - mock_method.assert_called_once_with(self.url, timeout=self.timeout) - - -if __name__ == "__main__": - unittest.main(verbosity=2) diff --git a/functest/utils/config.py b/functest/utils/config.py index 4cee63494..84166c1d3 100644 --- a/functest/utils/config.py +++ b/functest/utils/config.py @@ -11,20 +11,25 @@ class Config(object): try: with open(self.config_functest) as f: self.functest_yaml = yaml.safe_load(f) - self.parse(None, self.functest_yaml) + self._parse(None, self.functest_yaml) except: raise Exception('Parse {} failed'.format(self.config_functest)) + self._set_others() - def parse(self, attr_now, left_parametes): + def _parse(self, attr_now, left_parametes): for param_n, param_v in left_parametes.iteritems(): - attr_further = self.get_attr_further(attr_now, param_n) + attr_further = self._get_attr_further(attr_now, param_n) if not isinstance(param_v, dict): self.__setattr__(attr_further, param_v) else: - self.parse(attr_further, param_v) + self._parse(attr_further, param_v) - def get_attr_further(self, attr_now, next): + def _get_attr_further(self, attr_now, next): return attr_now if next == 'general' else ( '{}_{}'.format(attr_now, next) if attr_now else next) + def _set_others(self): + self.env_active = os.path.join(self.dir_functest_conf, "env_active") + + CONF = Config() diff --git a/functest/utils/env.py b/functest/utils/env.py index b6af767da..fa5245fb6 100644 --- a/functest/utils/env.py +++ b/functest/utils/env.py @@ -1,18 +1,41 @@ import os +import re default_envs = { 'NODE_NAME': 'unknown_pod', - 'CI_DEBUG': 'true' + 'CI_DEBUG': 'true', + 'DEPLOY_SCENARIO': 'os-nosdn-nofeature-noha', + 'DEPLOY_TYPE': 'virt', + 'INSTALLER_TYPE': None, + 'INSTALLER_IP': None, + 'BUILD_TAG': None, + 'OS_ENDPOINT_TYPE': None, + 'OS_AUTH_URL': None } class Environment(object): + def __init__(self): for k, v in os.environ.iteritems(): self.__setattr__(k, v) for k, v in default_envs.iteritems(): if k not in os.environ: self.__setattr__(k, v) + self._set_ci_run() + self._set_ci_loop() + + def _set_ci_run(self): + if self.BUILD_TAG: + self.IS_CI_RUN = True + else: + self.IS_CI_RUN = False + + def _set_ci_loop(self): + if self.BUILD_TAG and re.search("daily", self.BUILD_TAG): + self.CI_LOOP = "daily" + else: + self.CI_LOOP = "weekly" ENV = Environment() diff --git a/functest/utils/functest_constants.py b/functest/utils/functest_constants.py index 2664ace1f..7fb03e8a2 100644 --- a/functest/utils/functest_constants.py +++ b/functest/utils/functest_constants.py @@ -7,8 +7,9 @@ # http://www.apache.org/licenses/LICENSE-2.0 # import os -import functest.utils.functest_utils as ft_utils + import functest.utils.functest_logger as ft_logger +import functest.utils.functest_utils as ft_utils logger = ft_logger.Logger("functest_constants").getLogger() @@ -60,25 +61,25 @@ def get_value(functest_config_key, env_variable): return constant -HOME = get_value('general.directories.dir_home', 'HOME') -REPOS_DIR = get_value('general.directories.dir_repos', 'REPOS_DIR') -FUNCTEST_BASE_DIR = get_value('general.directories.dir_functest', +HOME = get_value('general.dir.home', 'HOME') +REPOS_DIR = get_value('general.dir.repos', 'REPOS_DIR') +FUNCTEST_BASE_DIR = get_value('general.dir.functest', 'FUNCTEST_BASE_DIR') -FUNCTEST_REPO_DIR = get_value('general.directories.dir_repo_functest', +FUNCTEST_REPO_DIR = get_value('general.dir.repo_functest', 'FUNCTEST_REPO_DIR') -FUNCTEST_TEST_DIR = get_value('general.directories.dir_functest_test', +FUNCTEST_TEST_DIR = get_value('general.dir.functest_test', 'FUNCTEST_TEST_DIR') -FUNCTEST_CONF_DIR = get_value('general.directories.dir_functest_conf', +FUNCTEST_CONF_DIR = get_value('general.dir.functest_conf', 'FUNCTEST_CONF_DIR') -FUNCTEST_DATA_DIR = get_value('general.directories.dir_functest_data', +FUNCTEST_DATA_DIR = get_value('general.dir.functest_data', 'FUNCTEST_DATA_DIR') -FUNCTEST_RESULTS_DIR = get_value('general.directories.dir_results', +FUNCTEST_RESULTS_DIR = get_value('general.dir.results', 'FUNCTEST_RESULTS_DIR') FUNCTEST_TESTCASES_YAML = get_value('general.functest.testcases_yaml', 'FUNCTEST_TESTCASES_YAML') RALLY_DEPLOYMENT_NAME = get_value('rally.deployment_name', 'RALLY_DEPLOYMENT_NAME') -TEMPEST_REPO_DIR = get_value('general.directories.dir_repo_tempest', +TEMPEST_REPO_DIR = get_value('general.dir.repo_tempest', 'TEMPEST_REPO_DIR') ENV_FILE = os.path.join(FUNCTEST_CONF_DIR, "env_active") @@ -87,22 +88,22 @@ OPENSTACK_CREDS = get_value('general.openstack.creds', 'creds') OPENSTACK_SNAPSHOT_FILE = get_value('general.openstack.snapshot_file', 'OPENSTACK_SNAPSHOT_FILE') -DOMINO_REPO_DIR = get_value('general.directories.dir_repo_domino', +DOMINO_REPO_DIR = get_value('general.dir.repo_domino', 'DOMINO_REPO_DIR') -SDNVPN_REPO_DIR = get_value('general.directories.dir_repo_sdnvpn', +SDNVPN_REPO_DIR = get_value('general.dir.repo_sdnvpn', 'SDNVPN_REPO_DIR') -SFC_REPO_DIR = get_value('general.directories.dir_repo_sfc', +SFC_REPO_DIR = get_value('general.dir.repo_sfc', 'SFC_REPO_DIR') ONOS_SFC_IMAGE_NAME = get_value('onos_sfc.image_name', 'ONOS_SFC_IMAGE_NAME') ONOS_SFC_IMAGE_FILENAME = get_value('onos_sfc.image_file_name', 'ONOS_SFC_IMAGE_FILENAME') -ONOS_SFC_RELATIVE_PATH = get_value('general.directories.dir_onos_sfc', +ONOS_SFC_RELATIVE_PATH = get_value('general.dir.dir_onos_sfc', 'ONOS_SFC_RELATIVE_PATH') ONOS_SFC_IMAGE_BASE_URL = get_value('onos_sfc.image_base_url', 'ONOS_SFC_IMAGE_BASE_URL') -RALLY_RELATIVE_PATH = get_value('general.directories.dir_rally', +RALLY_RELATIVE_PATH = get_value('general.dir.rally', 'RALLY_RELATIVE_PATH') RALLY_PRIVATE_NET_NAME = get_value('rally.network_name', 'RALLY_PRIVATE_NET_NAME') @@ -111,7 +112,7 @@ RALLY_PRIVATE_SUBNET_NAME = get_value('rally.subnet_name', RALLY_PRIVATE_SUBNET_CIDR = get_value('rally.subnet_cidr', 'RALLY_PRIVATE_SUBNET_CIDR') RALLY_ROUTER_NAME = get_value('rally.router_name', 'RALLY_ROUTER_NAME') -RALLY_INSTALLATION_DIR = get_value('general.directories.dir_rally_inst', +RALLY_INSTALLATION_DIR = get_value('general.dir.rally_inst', 'RALLY_INSTALLATION_DIR') GLANCE_IMAGE_NAME = get_value('general.openstack.image_name', 'GLANCE_IMAGE_NAME') @@ -149,24 +150,24 @@ TEMPEST_USE_CUSTOM_IMAGES = get_value('tempest.use_custom_images', 'TEMPEST_USE_CUSTOM_IMAGES') TEMPEST_USE_CUSTOM_FLAVORS = get_value('tempest.use_custom_flavors', 'TEMPEST_USE_CUSTOM_FLAVORS') -TEMPEST_TEST_LIST_DIR = get_value('general.directories.dir_tempest_cases', +TEMPEST_TEST_LIST_DIR = get_value('general.dir.tempest_cases', 'TEMPEST_TEST_LIST_DIR') NAME_VM_1 = get_value('vping.vm_name_1', 'NAME_VM_1') NAME_VM_2 = get_value('vping.vm_name_2', 'NAME_VM_2') PING_TIMEOUT = get_value('vping.ping_timeout', 'PING_TIMEOUT') VPING__IMAGE_NAME = get_value('vping.image_name', 'VPING__IMAGE_NAME') VPING_VM_FLAVOR = get_value('vping.vm_flavor', 'VPING_VM_FLAVOR') -VPING_PRIVATE_NET_NAME = get_value('vping.vping_private_net_name', +VPING_PRIVATE_NET_NAME = get_value('vping.private_net_name', 'VPING_PRIVATE_NET_NAME') -VPING_PRIVATE_SUBNET_NAME = get_value('vping.vping_private_subnet_name', +VPING_PRIVATE_SUBNET_NAME = get_value('vping.private_subnet_name', 'VPING_PRIVATE_SUBNET_NAME') -VPING_PRIVATE_SUBNET_CIDR = get_value('vping.vping_private_subnet_cidr', +VPING_PRIVATE_SUBNET_CIDR = get_value('vping.private_subnet_cidr', 'VPING_PRIVATE_SUBNET_CIDR') -VPING_ROUTER_NAME = get_value('vping.vping_router_name', +VPING_ROUTER_NAME = get_value('vping.router_name', 'VPING_ROUTER_NAME') -VPING_SECGROUP_NAME = get_value('vping.vping_sg_name', +VPING_SECGROUP_NAME = get_value('vping.sg_name', 'VPING_SECGROUP_NAME') -VPING_SECGROUP_DESCR = get_value('vping.vping_sg_descr', +VPING_SECGROUP_DESCR = get_value('vping.sg_desc', 'VPING_SECGROUP_DESCR') ONOSBENCH_USERNAME = get_value('ONOS.general.onosbench_username', 'ONOSBENCH_USERNAME') @@ -192,7 +193,7 @@ ONOS_INSTALLER_MASTER_USERNAME = get_value( ONOS_INSTALLER_MASTER_PASSWORD = get_value( 'ONOS.environment.installer_master_password', 'ONOS_INSTALLER_MASTER_PASSWORD') -PROMISE_REPO_DIR = get_value('general.directories.dir_repo_promise', +PROMISE_REPO_DIR = get_value('general.dir.dir_repo_promise', 'PROMISE_REPO_DIR') PROMISE_TENANT_NAME = get_value('promise.tenant_name', 'PROMISE_TENANT_NAME') @@ -217,48 +218,28 @@ PROMISE_SUBNET_CIDR = get_value('promise.subnet_cidr', 'PROMISE_SUBNET_CIDR') PROMISE_ROUTER_NAME = get_value('promise.router_name', 'PROMISE_ROUTER_NAME') -DOCTOR_REPO_DIR = get_value('general.directories.dir_repo_doctor', +DOCTOR_REPO_DIR = get_value('general.dir.dir_repo_doctor', 'DOCTOR_REPO_DIR') -COPPER_REPO_DIR = get_value('general.directories.dir_repo_copper', +COPPER_REPO_DIR = get_value('general.dir.repo_copper', 'COPPER_REPO_DIR') -EXAMPLE_INSTANCE_NAME = get_value('example.example_vm_name', +EXAMPLE_INSTANCE_NAME = get_value('example.vm_name', 'EXAMPLE_INSTANCE_NAME') -EXAMPLE_FLAVOR = get_value('example.example_flavor', 'EXAMPLE_FLAVOR') -EXAMPLE_IMAGE_NAME = get_value('example.example_image_name', +EXAMPLE_FLAVOR = get_value('example.flavor', 'EXAMPLE_FLAVOR') +EXAMPLE_IMAGE_NAME = get_value('example.image_name', 'EXAMPLE_IMAGE_NAME') -EXAMPLE_PRIVATE_NET_NAME = get_value('example.example_private_net_name', +EXAMPLE_PRIVATE_NET_NAME = get_value('example.private_net_name', 'EXAMPLE_PRIVATE_NET_NAME') EXAMPLE_PRIVATE_SUBNET_NAME = get_value( - 'example.example_private_subnet_name', + 'example.private_subnet_name', 'EXAMPLE_PRIVATE_SUBNET_NAME') EXAMPLE_PRIVATE_SUBNET_CIDR = get_value( - 'example.example_private_subnet_cidr', + 'example.private_subnet_cidr', 'EXAMPLE_PRIVATE_SUBNET_CIDR') -EXAMPLE_ROUTER_NAME = get_value('example.example_router_name', +EXAMPLE_ROUTER_NAME = get_value('example.router_name', 'EXAMPLE_ROUTER_NAME') -EXAMPLE_SECGROUP_NAME = get_value('example.example_sg_name', +EXAMPLE_SECGROUP_NAME = get_value('example.sg_name', 'EXAMPLE_SECGROUP_NAME') -EXAMPLE_SECGROUP_DESCR = get_value('example.example_sg_descr', +EXAMPLE_SECGROUP_DESCR = get_value('example.sg_desc', 'EXAMPLE_SECGROUP_DESCR') -VIMS_DATA_DIR = get_value('general.directories.dir_vIMS_data', - 'VIMS_DATA_DIR') -VIMS_TEST_DIR = get_value('general.directories.dir_repo_vims_test', - 'VIMS_TEST_DIR') -VIMS_TENANT_NAME = get_value('vIMS.general.tenant_name', - 'VIMS_TENANT_NAME') -VIMS_TENANT_DESCRIPTION = get_value('vIMS.general.tenant_description', - 'VIMS_TENANT_DESCRIPTION') -VIMS_IMAGES = get_value('vIMS.general.images', 'VIMS_IMAGES') -CFY_MANAGER_BLUEPRINT = get_value('vIMS.cloudify.blueprint', - 'CFY_MANAGER_BLUEPRINT') -CFY_MANAGER_REQUIERMENTS = get_value('vIMS.cloudify.requierments', - 'CFY_MANAGER_REQUIERMENTS') -CFY_INPUTS = get_value('vIMS.cloudify.inputs', 'CFY_INPUTS') -CW_BLUEPRINT = get_value('vIMS.clearwater.blueprint', 'CW_BLUEPRINT') -CW_DEPLOYMENT_NAME = get_value('vIMS.clearwater.deployment-name', - 'CW_DEPLOYMENT_NAME') -CW_INPUTS = get_value('vIMS.clearwater.inputs', 'CW_INPUTS') -CW_REQUIERMENTS = get_value('vIMS.clearwater.requierments', - 'CW_REQUIERMENTS') -PARSER_REPO_DIR = get_value('general.directories.dir_repo_parser', +PARSER_REPO_DIR = get_value('general.dir.repo_parser', 'PARSER_REPO_DIR') diff --git a/functest/utils/functest_logger.py b/functest/utils/functest_logger.py index b154f563d..c0fba082a 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/functest/utils/functest_utils.py b/functest/utils/functest_utils.py index b1e4d3cdb..2bf87a05c 100644 --- a/functest/utils/functest_utils.py +++ b/functest/utils/functest_utils.py @@ -7,12 +7,14 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 # +import functools import json import os import re import shutil import subprocess import sys +import time import urllib2 from datetime import datetime as dt @@ -21,11 +23,10 @@ import requests import yaml from git import Repo -import time -import functools - +from functest.utils.constants import CONST import functest.utils.functest_logger as ft_logger + logger = ft_logger.Logger("functest_utils").getLogger() @@ -182,13 +183,43 @@ def logger_test_results(project, case_name, status, details): 'd': details}) +def write_results_to_file(project, case_name, start_date, + stop_date, criteria, details): + file_path = re.split(r'://', CONST.results_test_db_url)[1] + + try: + installer = os.environ['INSTALLER_TYPE'] + scenario = os.environ['DEPLOY_SCENARIO'] + pod_name = os.environ['NODE_NAME'] + except KeyError as e: + logger.error("Please set env var: " + str(e)) + return False + + test_start = dt.fromtimestamp(start_date).strftime('%Y-%m-%d %H:%M:%S') + test_stop = dt.fromtimestamp(stop_date).strftime('%Y-%m-%d %H:%M:%S') + + params = {"project_name": project, "case_name": case_name, + "pod_name": pod_name, "installer": installer, + "scenario": scenario, "criteria": criteria, + "start_date": test_start, "stop_date": test_stop, + "details": details} + try: + with open(file_path, "a+w") as outfile: + json.dump(params, outfile) + outfile.write("\n") + return True + except Exception as e: + logger.error("write result data into a file failed: %s" % e) + return False + + def push_results_to_db(project, case_name, start_date, stop_date, criteria, details): """ POST results to the Result target DB """ # Retrieve params from CI and conf - url = get_db_url() + "/results" + url = CONST.results_test_db_url + "/results" try: installer = os.environ['INSTALLER_TYPE'] @@ -321,26 +352,6 @@ def execute_command(cmd, info=False, error_msg="", return returncode -def get_deployment_dir(): - """ - Returns current Rally deployment directory - """ - deployment_name = get_functest_config('rally.deployment_name') - rally_dir = get_functest_config('general.directories.dir_rally_inst') - cmd = ("rally deployment list | awk '/" + 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("Rally deployment not found.") - exit(-1) - deployment_dir = (rally_dir + "/tempest/for-deployment-" + - deployment_uuid) - return deployment_dir - - def get_dict_by_test(testname): with open(get_testcases_file_dir()) as f: testcases_yaml = yaml.safe_load(f) diff --git a/functest/utils/openstack_clean.py b/functest/utils/openstack_clean.py index c08568bde..15a8f33d5 100755 --- a/functest/utils/openstack_clean.py +++ b/functest/utils/openstack_clean.py @@ -23,14 +23,16 @@ # import time + +import yaml + import functest.utils.functest_logger as ft_logger import functest.utils.openstack_utils as os_utils -import yaml -import functest.utils.functest_constants as ft_constants +from functest.utils.constants import CONST logger = ft_logger.Logger("openstack_clean").getLogger() -OS_SNAPSHOT_FILE = ft_constants.OPENSTACK_SNAPSHOT_FILE +OS_SNAPSHOT_FILE = CONST.openstack_snapshot_file def separator(): @@ -395,7 +397,7 @@ def main(): default_security_groups = snapshot_yaml.get('secgroups') default_floatingips = snapshot_yaml.get('floatingips') default_users = snapshot_yaml.get('users') - # default_tenants = snapshot_yaml.get('tenants') + default_tenants = snapshot_yaml.get('tenants') if not os_utils.check_credentials(): logger.error("Please source the openrc credentials and run " @@ -416,10 +418,8 @@ def main(): separator() remove_users(keystone_client, default_users) separator() - # TODO (Helen) tenant does not exist in V3 - # need to figure our anohter general verification point - # remove_tenants(keystone_client, default_tenants) - # separator() + remove_tenants(keystone_client, default_tenants) + separator() if __name__ == '__main__': diff --git a/functest/utils/openstack_snapshot.py b/functest/utils/openstack_snapshot.py index 5b50ffa50..e64030f75 100755 --- a/functest/utils/openstack_snapshot.py +++ b/functest/utils/openstack_snapshot.py @@ -20,15 +20,16 @@ # http://www.apache.org/licenses/LICENSE-2.0 # +import yaml + import functest.utils.functest_logger as ft_logger import functest.utils.openstack_utils as os_utils -import yaml -import functest.utils.functest_constants as ft_constants +from functest.utils.constants import CONST logger = ft_logger.Logger("openstack_snapshot").getLogger() -OS_SNAPSHOT_FILE = ft_constants.OPENSTACK_SNAPSHOT_FILE +OS_SNAPSHOT_FILE = CONST.openstack_snapshot_file def separator(): @@ -149,7 +150,7 @@ def main(): snapshot.update(get_security_groups(neutron_client)) snapshot.update(get_floatinips(nova_client)) snapshot.update(get_users(keystone_client)) - # snapshot.update(get_tenants(keystone_client)) + snapshot.update(get_tenants(keystone_client)) with open(OS_SNAPSHOT_FILE, 'w+') as yaml_file: yaml_file.write(yaml.safe_dump(snapshot, default_flow_style=False)) diff --git a/functest/utils/openstack_utils.py b/functest/utils/openstack_utils.py index ec784121b..64f18504d 100755 --- a/functest/utils/openstack_utils.py +++ b/functest/utils/openstack_utils.py @@ -52,14 +52,13 @@ def is_keystone_v3(): def get_rc_env_vars(): - keystone_v3 = is_keystone_v3() env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD'] - if keystone_v3 is False: - env_vars.extend(['OS_TENANT_NAME']) - else: + if is_keystone_v3(): env_vars.extend(['OS_PROJECT_NAME', 'OS_USER_DOMAIN_NAME', 'OS_PROJECT_DOMAIN_NAME']) + else: + env_vars.extend(['OS_TENANT_NAME']) return env_vars @@ -86,7 +85,7 @@ def get_env_cred_dict(): return env_cred_dict -def get_credentials(): +def get_credentials(other_creds={}): """Returns a creds dictionary filled with parsed from env """ creds = {} @@ -99,6 +98,16 @@ def get_credentials(): else: creds_key = env_cred_dict.get(envvar) creds.update({creds_key: os.getenv(envvar)}) + + if 'tenant' in other_creds.keys(): + if is_keystone_v3(): + tenant = 'project_name' + else: + tenant = 'tenant_name' + other_creds[tenant] = other_creds.pop('tenant') + + creds.update(other_creds) + return creds @@ -138,9 +147,9 @@ def get_credentials_for_rally(): return rally_conf -def get_session_auth(): +def get_session_auth(other_creds={}): loader = loading.get_plugin_loader('password') - creds = get_credentials() + creds = get_credentials(other_creds) auth = loader.load_from_options(**creds) return auth @@ -152,8 +161,8 @@ def get_endpoint(service_type, endpoint_type='publicURL'): endpoint_type=endpoint_type) -def get_session(): - auth = get_session_auth() +def get_session(other_creds={}): + auth = get_session_auth(other_creds) return session.Session(auth=auth) @@ -169,8 +178,8 @@ def get_keystone_client_version(): return DEFAULT_API_VERSION -def get_keystone_client(): - sess = get_session() +def get_keystone_client(other_creds={}): + sess = get_session(other_creds) return keystoneclient.Client(get_keystone_client_version(), session=sess) @@ -183,8 +192,8 @@ def get_nova_client_version(): return DEFAULT_API_VERSION -def get_nova_client(): - sess = get_session() +def get_nova_client(other_creds={}): + sess = get_session(other_creds) return novaclient.Client(get_nova_client_version(), session=sess) @@ -197,8 +206,8 @@ def get_cinder_client_version(): return DEFAULT_API_VERSION -def get_cinder_client(): - sess = get_session() +def get_cinder_client(other_creds={}): + sess = get_session(other_creds) return cinderclient.Client(get_cinder_client_version(), session=sess) @@ -211,8 +220,8 @@ def get_neutron_client_version(): return DEFAULT_API_VERSION -def get_neutron_client(): - sess = get_session() +def get_neutron_client(other_creds={}): + sess = get_session(other_creds) return neutronclient.Client(get_neutron_client_version(), session=sess) @@ -224,8 +233,8 @@ def get_glance_client_version(): return DEFAULT_API_VERSION -def get_glance_client(): - sess = get_session() +def get_glance_client(other_creds={}): + sess = get_session(other_creds) return glanceclient.Client(get_glance_client_version(), session=sess) @@ -1244,7 +1253,10 @@ def delete_volume_type(cinder_client, volume_type): # ********************************************* def get_tenants(keystone_client): try: - tenants = keystone_client.tenants.list() + if is_keystone_v3(): + tenants = keystone_client.projects.list() + else: + tenants = keystone_client.tenants.list() return tenants except Exception, e: logger.error("Error [get_tenants(keystone_client)]: %s" % e) @@ -1261,7 +1273,7 @@ def get_users(keystone_client): def get_tenant_id(keystone_client, tenant_name): - tenants = keystone_client.tenants.list() + tenants = get_tenants(keystone_client) id = '' for t in tenants: if t.name == tenant_name: @@ -1271,7 +1283,7 @@ def get_tenant_id(keystone_client, tenant_name): def get_user_id(keystone_client, user_name): - users = keystone_client.users.list() + users = get_users(keystone_client) id = '' for u in users: if u.name == user_name: @@ -1292,9 +1304,16 @@ def get_role_id(keystone_client, role_name): def create_tenant(keystone_client, tenant_name, tenant_description): try: - tenant = keystone_client.tenants.create(tenant_name, - tenant_description, - enabled=True) + if is_keystone_v3(): + tenant = keystone_client.projects.create( + name=tenant_name, + description=tenant_description, + domain="default", + enabled=True) + else: + tenant = keystone_client.tenants.create(tenant_name, + tenant_description, + enabled=True) return tenant.id except Exception, e: logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s" @@ -1305,9 +1324,18 @@ def create_tenant(keystone_client, tenant_name, tenant_description): def create_user(keystone_client, user_name, user_password, user_email, tenant_id): try: - user = keystone_client.users.create(user_name, user_password, - user_email, tenant_id, - enabled=True) + if is_keystone_v3(): + user = keystone_client.users.create(name=user_name, + password=user_password, + email=user_email, + project_id=tenant_id, + enabled=True) + else: + user = keystone_client.users.create(user_name, + user_password, + user_email, + tenant_id, + enabled=True) return user.id except Exception, e: logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'" @@ -1318,7 +1346,12 @@ def create_user(keystone_client, user_name, user_password, def add_role_user(keystone_client, user_id, role_id, tenant_id): try: - keystone_client.roles.add_user_role(user_id, role_id, tenant_id) + if is_keystone_v3(): + keystone_client.roles.grant(role=role_id, + user=user_id, + project=tenant_id) + else: + keystone_client.roles.add_user_role(user_id, role_id, tenant_id) return True except Exception, e: logger.error("Error [add_role_user(keystone_client, '%s', '%s'" @@ -1328,7 +1361,10 @@ def add_role_user(keystone_client, user_id, role_id, tenant_id): def delete_tenant(keystone_client, tenant_id): try: - keystone_client.tenants.delete(tenant_id) + if is_keystone_v3(): + keystone_client.projects.delete(tenant_id) + else: + keystone_client.tenants.delete(tenant_id) return True except Exception, e: logger.error("Error [delete_tenant(keystone_client, '%s')]: %s" diff --git a/run_unit_tests.sh b/run_unit_tests.sh index 71d21c9db..79d05d3d1 100755 --- a/run_unit_tests.sh +++ b/run_unit_tests.sh @@ -2,28 +2,6 @@ set -o errexit set -o pipefail -# ****************************** -# 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 -if [ -d "/home/opnfv/functest/results" ] -then - sudo rm -rf /home/opnfv/functest -fi - -# 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 @@ -54,8 +32,10 @@ nosetests --with-xunit \ --with-coverage \ --cover-erase \ --cover-tests \ + --cover-package=functest.cli \ --cover-package=functest.core.testcase_base \ --cover-package=functest.opnfv_tests.sdn.odl.odl \ + --cover-package=functest.utils \ --cover-xml \ --cover-html \ functest/tests/unit @@ -63,13 +43,4 @@ rc=$? deactivate -# ******* -# clean -# ******* -# Clean useless logs -if [ -d "/home/opnfv/functest/results" ] -then - sudo rm -rf /home/opnfv/functest/results -fi - exit $rc diff --git a/test-requirements.txt b/test-requirements.txt index 8be8e2033..2bf297ba8 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,6 +5,7 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 # +click==6.6 coverage==4.1 dnspython==1.15.0 gitpython==1.0.1 @@ -15,9 +16,10 @@ 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 robotframework-requests==0.3.8 robotframework-sshlibrary==2.1.1 -virtualenv==15.1.0
\ No newline at end of file +virtualenv==15.1.0 |