diff options
-rw-r--r-- | docker/Dockerfile | 2 | ||||
-rw-r--r-- | docker/core/Dockerfile | 3 | ||||
-rw-r--r-- | docker/vnf/testcases.yaml | 2 | ||||
-rw-r--r-- | functest/api/resources/v1/envs.py | 9 | ||||
-rw-r--r-- | functest/api/resources/v1/tasks.py | 14 | ||||
-rw-r--r-- | functest/api/resources/v1/testcases.py | 16 | ||||
-rw-r--r-- | functest/api/resources/v1/tiers.py | 11 | ||||
-rw-r--r-- | functest/ci/config_aarch64_patch.yaml | 4 | ||||
-rw-r--r-- | functest/ci/download_images.sh | 1 | ||||
-rw-r--r-- | functest/ci/testcases.yaml | 2 | ||||
-rw-r--r-- | functest/core/vnf.py | 3 | ||||
-rw-r--r-- | functest/opnfv_tests/openstack/rally/rally.py | 7 | ||||
-rw-r--r-- | functest/opnfv_tests/openstack/snaps/snaps_utils.py | 13 | ||||
-rw-r--r-- | functest/opnfv_tests/openstack/tempest/conf_utils.py | 15 | ||||
-rw-r--r-- | functest/opnfv_tests/openstack/tempest/tempest.py | 5 | ||||
-rw-r--r-- | functest/opnfv_tests/vnf/ims/cloudify_ims.py | 8 | ||||
-rw-r--r-- | functest/tests/unit/openstack/tempest/test_conf_utils.py | 16 | ||||
-rw-r--r-- | functest/tests/unit/openstack/tempest/test_tempest.py | 15 | ||||
-rw-r--r-- | functest/utils/openstack_utils.py | 20 |
19 files changed, 129 insertions, 37 deletions
diff --git a/docker/Dockerfile b/docker/Dockerfile index 51d28b90..abb9b0d7 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -110,3 +110,5 @@ RUN sh -c 'curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -' \ && cd /src/promise/source && npm install RUN echo ". ${FUNCTEST_DIR}/cli/functest-complete.sh" >> /root/.bashrc + +CMD ["functest_restapi"] diff --git a/docker/core/Dockerfile b/docker/core/Dockerfile index 0ab809aa..172dbb9f 100644 --- a/docker/core/Dockerfile +++ b/docker/core/Dockerfile @@ -13,9 +13,6 @@ RUN apk --no-cache add --update \ wget -q -O- https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt?h=$OPENSTACK_TAG | \ sed -E s/^tempest==+\(.*\)$/-e\ git+https:\\/\\/github.com\\/openstack\\/tempest@\\1#egg=tempest/ \ > upper-constraints.txt && \ - pip install -U --no-cache-dir -cupper-constraints.txt \ - -chttps://git.opnfv.org/functest/plain/upper-constraints.txt?h=$BRANCH \ - git+https://github.com/pypa/pip.git && \ pip install --no-cache-dir --src /src -cupper-constraints.txt \ -chttps://git.opnfv.org/functest/plain/upper-constraints.txt?h=$BRANCH \ -e git+https://github.com/openstack/requirements@stable/ocata#egg=openstack_requirements && \ diff --git a/docker/vnf/testcases.yaml b/docker/vnf/testcases.yaml index c0eba822..dea4a1ea 100644 --- a/docker/vnf/testcases.yaml +++ b/docker/vnf/testcases.yaml @@ -23,6 +23,7 @@ tiers: - case_name: orchestra_openims project_name: functest + enabled: false criteria: 100 blocking: false description: >- @@ -37,6 +38,7 @@ tiers: - case_name: orchestra_clearwaterims project_name: functest + enabled: false criteria: 100 blocking: false description: >- diff --git a/functest/api/resources/v1/envs.py b/functest/api/resources/v1/envs.py index fb76fa63..8020544f 100644 --- a/functest/api/resources/v1/envs.py +++ b/functest/api/resources/v1/envs.py @@ -33,10 +33,11 @@ class V1Envs(ApiResource): def prepare(self, args): # pylint: disable=no-self-use, unused-argument """ Prepare environment """ - try: - ft_utils.execute_command("prepare_env start") - except Exception as err: # pylint: disable=broad-except - return api_utils.result_handler(status=1, data=str(err)) + + result_env = ft_utils.execute_command("prepare_env start") + if not result_env == 0: + return api_utils.result_handler( + status=1, data="Failed to prepare env") return api_utils.result_handler( status=0, data="Prepare env successfully") diff --git a/functest/api/resources/v1/tasks.py b/functest/api/resources/v1/tasks.py index e05db51b..f099918f 100644 --- a/functest/api/resources/v1/tasks.py +++ b/functest/api/resources/v1/tasks.py @@ -50,12 +50,15 @@ class V1Task(ApiResource): if status not in ['IN PROGRESS', 'FAIL', 'FINISHED']: return api_utils.result_handler(status=1, data='internal server error') + + switcher = {'IN PROGRESS': 0, 'FAIL': 1, 'FINISHED': 2} if status == 'IN PROGRESS': - result = {'status': status, 'result': ''} + result = {'status': switcher.get(status), 'result': ''} elif status == 'FAIL': - result = {'status': status, 'error': task.error} + result = {'status': switcher.get(status), 'error': task.error} else: - result = {'status': status, 'result': json.loads(task.result)} + result = {'status': switcher.get(status), + 'result': json.loads(task.result)} return jsonify(result) @@ -92,4 +95,7 @@ class V1TaskLog(ApiResource): return_data = {'data': data} - return api_utils.result_handler(status=task.status, data=return_data) + switcher = {'IN PROGRESS': 0, 'FAIL': 1, 'FINISHED': 2} + + return api_utils.result_handler(status=switcher.get(task.status), + data=return_data) diff --git a/functest/api/resources/v1/testcases.py b/functest/api/resources/v1/testcases.py index d708cf37..b7d7b4aa 100644 --- a/functest/api/resources/v1/testcases.py +++ b/functest/api/resources/v1/testcases.py @@ -17,7 +17,7 @@ import pkg_resources import uuid import ConfigParser -from flask import abort, jsonify +from flask import jsonify from functest.api.base import ApiResource from functest.api.common import api_utils, thread @@ -46,8 +46,11 @@ class V1Testcase(ApiResource): """ GET the info of one testcase""" testcase = Testcase().show(testcase_name) if not testcase: - abort(404, "The test case '%s' does not exist or is not supported" - % testcase_name) + return api_utils.result_handler( + status=1, + data="The test case '%s' does not exist or is not supported" + % testcase_name) + testcase_info = api_utils.change_obj_to_dict(testcase) dependency_dict = api_utils.change_obj_to_dict( testcase_info.get('dependency')) @@ -70,6 +73,13 @@ class V1Testcase(ApiResource): return api_utils.result_handler( status=1, data='testcase name must be provided') + testcase = Testcase().show(case_name) + if not testcase: + return api_utils.result_handler( + status=1, + data="The test case '%s' does not exist or is not supported" + % case_name) + task_id = str(uuid.uuid4()) task_args = {'testcase': case_name, 'task_id': task_id} diff --git a/functest/api/resources/v1/tiers.py b/functest/api/resources/v1/tiers.py index 71a98bea..4f4849e9 100644 --- a/functest/api/resources/v1/tiers.py +++ b/functest/api/resources/v1/tiers.py @@ -13,9 +13,10 @@ Resources to handle tier related requests import re -from flask import abort, jsonify +from flask import jsonify from functest.api.base import ApiResource +from functest.api.common import api_utils from functest.cli.commands.cli_tier import Tier @@ -46,7 +47,9 @@ class V1Tier(ApiResource): """ GET the info of one tier """ testcases = Tier().gettests(tier_name) if not testcases: - abort(404, "The tier with name '%s' does not exist." % tier_name) + return api_utils.result_handler( + status=1, + data="The tier with name '%s' does not exist." % tier_name) tier_info = Tier().show(tier_name) tier_info.__dict__.pop('name') tier_info.__dict__.pop('tests_array') @@ -62,6 +65,8 @@ class V1TestcasesinTier(ApiResource): """ GET all testcases within given tier """ testcases = Tier().gettests(tier_name) if not testcases: - abort(404, "The tier with name '%s' does not exist." % tier_name) + return api_utils.result_handler( + status=1, + data="The tier with name '%s' does not exist." % tier_name) result = {'tier': tier_name, 'testcases': testcases} return jsonify(result) diff --git a/functest/ci/config_aarch64_patch.yaml b/functest/ci/config_aarch64_patch.yaml index 6b3699b4..44df3cad 100644 --- a/functest/ci/config_aarch64_patch.yaml +++ b/functest/ci/config_aarch64_patch.yaml @@ -4,6 +4,10 @@ os: image_name: TestVM image_file_name: cirros-d161201-aarch64-disk.img image_password: gocubsgo + extra_properties: + hw_firmware_type: 'uefi' + hw_video_model: 'vga' + short_id: 'ubuntu16.04' snaps: images: glance_tests: diff --git a/functest/ci/download_images.sh b/functest/ci/download_images.sh index 367ad8d9..236b763c 100644 --- a/functest/ci/download_images.sh +++ b/functest/ci/download_images.sh @@ -10,7 +10,6 @@ https://cloud-images.ubuntu.com/releases/14.04/release/ubuntu-14.04-server-cloud https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2 https://cloud-images.ubuntu.com/releases/16.04/release/ubuntu-16.04-server-cloudimg-amd64-disk1.img http://repository.cloudifysource.org/cloudify/4.0.1/sp-release/cloudify-manager-premium-4.0.1.qcow2 -http://marketplace.openbaton.org:8082/api/v1/images/52e2ccc0-1dce-4663-894d-28aab49323aa/img http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-lxc.tar.gz http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-disk.img diff --git a/functest/ci/testcases.yaml b/functest/ci/testcases.yaml index cb28f8a9..64bcf616 100644 --- a/functest/ci/testcases.yaml +++ b/functest/ci/testcases.yaml @@ -449,6 +449,7 @@ tiers: - case_name: orchestra_openims project_name: functest + enabled: false criteria: 100 blocking: false description: >- @@ -463,6 +464,7 @@ tiers: - case_name: orchestra_clearwaterims project_name: functest + enabled: false criteria: 100 blocking: false description: >- diff --git a/functest/core/vnf.py b/functest/core/vnf.py index bbdd80a0..868b8b48 100644 --- a/functest/core/vnf.py +++ b/functest/core/vnf.py @@ -120,10 +120,9 @@ class VnfOnBoarding(base.TestCase): UserSettings( name=self.tenant_name, password=self.tenant_name)) - user_creator.create() self.created_object.append(user_creator) - project_creator.assoc_user(user_creator.user_settings) + project_creator.assoc_user(user_creator.create()) self.snaps_creds = user_creator.get_os_creds(self.tenant_name) diff --git a/functest/opnfv_tests/openstack/rally/rally.py b/functest/opnfv_tests/openstack/rally/rally.py index fdef8bed..2042b2d1 100644 --- a/functest/opnfv_tests/openstack/rally/rally.py +++ b/functest/opnfv_tests/openstack/rally/rally.py @@ -42,6 +42,10 @@ class RallyBase(testcase.OSGCTestCase): CONST.__getattribute__('dir_functest_images'), GLANCE_IMAGE_FILENAME) GLANCE_IMAGE_FORMAT = CONST.__getattribute__('openstack_image_disk_format') + GLANCE_IMAGE_EXTRA_PROPERTIES = {} + if hasattr(CONST, 'openstack_extra_properties'): + GLANCE_IMAGE_EXTRA_PROPERTIES = CONST.__getattribute__( + 'openstack_extra_properties') FLAVOR_NAME = "m1.tiny" RALLY_DIR = pkg_resources.resource_filename( @@ -462,7 +466,8 @@ class RallyBase(testcase.OSGCTestCase): self.image_exists, self.image_id = os_utils.get_or_create_image( self.GLANCE_IMAGE_NAME, self.GLANCE_IMAGE_PATH, - self.GLANCE_IMAGE_FORMAT) + self.GLANCE_IMAGE_FORMAT, + self.GLANCE_IMAGE_EXTRA_PROPERTIES) if self.image_id is None: raise Exception("Failed to get or create image '%s'" % self.GLANCE_IMAGE_NAME) diff --git a/functest/opnfv_tests/openstack/snaps/snaps_utils.py b/functest/opnfv_tests/openstack/snaps/snaps_utils.py index 309f9db1..956b104a 100644 --- a/functest/opnfv_tests/openstack/snaps/snaps_utils.py +++ b/functest/opnfv_tests/openstack/snaps/snaps_utils.py @@ -5,7 +5,7 @@ # # http://www.apache.org/licenses/LICENSE-2.0 -from snaps.openstack.utils import neutron_utils +from snaps.openstack.utils import neutron_utils, nova_utils def get_ext_net_name(os_creds): @@ -17,3 +17,14 @@ def get_ext_net_name(os_creds): neutron = neutron_utils.neutron_client(os_creds) ext_nets = neutron_utils.get_external_networks(neutron) return ext_nets[0].name + + +def get_active_compute_cnt(os_creds): + """ + Returns the number of active compute servers + :param: os_creds: an instance of snaps OSCreds object + :return: the number of active compute servers + """ + nova = nova_utils.nova_client(os_creds) + computes = nova_utils.get_availability_zone_hosts(nova, zone_name='nova') + return len(computes) diff --git a/functest/opnfv_tests/openstack/tempest/conf_utils.py b/functest/opnfv_tests/openstack/tempest/conf_utils.py index 52fa6003..72ea5ce7 100644 --- a/functest/opnfv_tests/openstack/tempest/conf_utils.py +++ b/functest/opnfv_tests/openstack/tempest/conf_utils.py @@ -130,18 +130,21 @@ def backup_tempest_config(conf_file): """ Copy config file to tempest results directory """ + if not os.path.exists(TEMPEST_RESULTS_DIR): + os.makedirs(TEMPEST_RESULTS_DIR) shutil.copyfile(conf_file, os.path.join(TEMPEST_RESULTS_DIR, 'tempest.conf')) def configure_tempest(deployment_dir, image_id=None, flavor_id=None, - mode=None): + compute_cnt=None): """ Calls rally verify and updates the generated tempest.conf with given parameters """ conf_file = configure_verifier(deployment_dir) - configure_tempest_update_params(conf_file, image_id, flavor_id) + configure_tempest_update_params(conf_file, image_id, flavor_id, + compute_cnt) def configure_tempest_defcore(deployment_dir, image_id, flavor_id, @@ -197,8 +200,8 @@ def generate_test_accounts_file(tenant_id): yaml.dump(accounts_list, f, default_flow_style=False) -def configure_tempest_update_params(tempest_conf_file, - image_id=None, flavor_id=None): +def configure_tempest_update_params(tempest_conf_file, image_id=None, + flavor_id=None, compute_cnt=1): """ Add/update needed parameters into tempest.conf file """ @@ -221,6 +224,10 @@ def configure_tempest_update_params(tempest_conf_file, config.set('compute', 'flavor_ref', flavor_id) if FLAVOR_ID_ALT is not None: config.set('compute', 'flavor_ref_alt', FLAVOR_ID_ALT) + if compute_cnt > 1: + # enable multinode tests + config.set('compute', 'min_compute_nodes', compute_cnt) + config.set('identity', 'region', 'RegionOne') if os_utils.is_keystone_v3(): auth_version = 'v3' diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py index b8a4e9ad..c204d52b 100644 --- a/functest/opnfv_tests/openstack/tempest/tempest.py +++ b/functest/opnfv_tests/openstack/tempest/tempest.py @@ -20,6 +20,7 @@ import time import yaml from functest.core import testcase +from functest.opnfv_tests.openstack.snaps import snaps_utils from functest.opnfv_tests.openstack.tempest import conf_utils from functest.utils.constants import CONST import functest.utils.functest_utils as ft_utils @@ -234,11 +235,13 @@ class TempestCommon(testcase.TestCase): if not os.path.exists(conf_utils.TEMPEST_RESULTS_DIR): os.makedirs(conf_utils.TEMPEST_RESULTS_DIR) resources = self.resources.create() + compute_cnt = snaps_utils.get_active_compute_cnt( + self.resources.os_creds) conf_utils.configure_tempest( self.DEPLOYMENT_DIR, image_id=resources.get("image_id"), flavor_id=resources.get("flavor_id"), - mode=self.MODE) + compute_cnt=compute_cnt) self.generate_test_list(self.VERIFIER_REPO_DIR) self.apply_tempest_blacklist() self.run_verifier_tests() diff --git a/functest/opnfv_tests/vnf/ims/cloudify_ims.py b/functest/opnfv_tests/vnf/ims/cloudify_ims.py index b98cbe9a..c8c2c509 100644 --- a/functest/opnfv_tests/vnf/ims/cloudify_ims.py +++ b/functest/opnfv_tests/vnf/ims/cloudify_ims.py @@ -103,15 +103,15 @@ class CloudifyIms(clearwater_ims_base.ClearwaterOnBoardingBase): network_quotas = self.os_project.get_network_quotas() for key, value in ( - self.orchestrator['requirements']['compute_quotas'].items()): + self.vnf['requirements']['compute_quotas'].items()): setattr(compute_quotas, key, value) for key, value in ( - self.orchestrator['requirements']['network_quotas'].items()): + self.vnf['requirements']['network_quotas'].items()): setattr(network_quotas, key, value) - compute_quotas = self.project_ims.update_compute_quotas(compute_quotas) - network_quotas = self.project_ims.update_network_quotas(network_quotas) + compute_quotas = self.os_project.update_compute_quotas(compute_quotas) + network_quotas = self.os_project.update_network_quotas(network_quotas) # needs some images self.__logger.info("Upload some OS images if it doesn't exist") diff --git a/functest/tests/unit/openstack/tempest/test_conf_utils.py b/functest/tests/unit/openstack/tempest/test_conf_utils.py index 77558086..22017a7a 100644 --- a/functest/tests/unit/openstack/tempest/test_conf_utils.py +++ b/functest/tests/unit/openstack/tempest/test_conf_utils.py @@ -170,9 +170,23 @@ class OSTempestConfUtilsTesting(unittest.TestCase): def test_backup_tempest_config_default(self): with mock.patch('functest.opnfv_tests.openstack.tempest.' - 'conf_utils.shutil.copyfile') as m1: + 'conf_utils.os.path.exists', + return_value=False), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.os.makedirs') as m1, \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.shutil.copyfile') as m2: conf_utils.backup_tempest_config('test_conf_file') self.assertTrue(m1.called) + self.assertTrue(m2.called) + + with mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.os.path.exists', + return_value=True), \ + mock.patch('functest.opnfv_tests.openstack.tempest.' + 'conf_utils.shutil.copyfile') as m2: + conf_utils.backup_tempest_config('test_conf_file') + self.assertTrue(m2.called) def test_configure_tempest_default(self): with mock.patch('functest.opnfv_tests.openstack.tempest.' diff --git a/functest/tests/unit/openstack/tempest/test_tempest.py b/functest/tests/unit/openstack/tempest/test_tempest.py index 54d7d49b..6fe103f1 100644 --- a/functest/tests/unit/openstack/tempest/test_tempest.py +++ b/functest/tests/unit/openstack/tempest/test_tempest.py @@ -171,6 +171,19 @@ class OSTempestTesting(unittest.TestCase): @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.os.makedirs') @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' 'TempestResourcesManager.create', return_value={}) + @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.' + 'get_active_compute_cnt', side_effect=Exception) + def test_run_get_active_compute_cnt_ko(self, *args): + self.assertEqual(self.tempestcommon.run(), + testcase.TestCase.EX_RUN_ERROR) + + @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' + 'os.path.exists', return_value=False) + @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.os.makedirs') + @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' + 'TempestResourcesManager.create', return_value={}) + @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.' + 'get_active_compute_cnt', return_value=2) @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' 'conf_utils.configure_tempest', side_effect=Exception) def test_run_configure_tempest_ko(self, *args): @@ -182,6 +195,8 @@ class OSTempestTesting(unittest.TestCase): @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.os.makedirs') @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' 'TempestResourcesManager.create', return_value={}) + @mock.patch('functest.opnfv_tests.openstack.snaps.snaps_utils.' + 'get_active_compute_cnt', return_value=2) @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' 'conf_utils.configure_tempest') def _test_run(self, status, *args): diff --git a/functest/utils/openstack_utils.py b/functest/utils/openstack_utils.py index 73d1cde4..def0539b 100644 --- a/functest/utils/openstack_utils.py +++ b/functest/utils/openstack_utils.py @@ -1195,8 +1195,13 @@ def get_image_id(glance_client, image_name): return id -def create_glance_image(glance_client, image_name, file_path, disk="qcow2", - container="bare", public="public"): +def create_glance_image(glance_client, + image_name, + file_path, + disk="qcow2", + extra_properties={}, + container="bare", + public="public"): if not os.path.isfile(file_path): logger.error("Error: file %s does not exist." % file_path) return None @@ -1211,7 +1216,8 @@ def create_glance_image(glance_client, image_name, file_path, disk="qcow2", image = glance_client.images.create(name=image_name, visibility=public, disk_format=disk, - container_format=container) + container_format=container, + **extra_properties) image_id = image.id with open(file_path) as image_data: glance_client.images.upload(image_id, image_data) @@ -1222,7 +1228,7 @@ def create_glance_image(glance_client, image_name, file_path, disk="qcow2", return None -def get_or_create_image(name, path, format): +def get_or_create_image(name, path, format, extra_properties): image_exists = False glance_client = get_glance_client() @@ -1232,7 +1238,11 @@ def get_or_create_image(name, path, format): image_exists = True else: logger.info("Creating image '%s' from '%s'..." % (name, path)) - image_id = create_glance_image(glance_client, name, path, format) + image_id = create_glance_image(glance_client, + name, + path, + format, + extra_properties) if not image_id: logger.error("Failed to create a Glance image...") else: |