diff options
author | Valentin Boucher <valentin.boucher@kontron.com> | 2018-07-19 11:35:50 -0400 |
---|---|---|
committer | Cédric Ollivier <cedric.ollivier@orange.com> | 2018-07-23 22:17:34 +0200 |
commit | 026a9bfaa656d0e5ade327feda64f17796d6f209 (patch) | |
tree | 83e722c0c39885ba3355e86185fde2b698a4b076 /functest/opnfv_tests/vnf/ims/heat_ims.py | |
parent | c5b8affdabf4de9f758d0ba47547aa78fb004801 (diff) |
New Heat IMS testcase
In order to validate OpenStack Master deployment
we create this new testcase using OpenStack Heat
as an Orchestrator for Clearwater VNF
JIRA: FUNCTEST-995
Change-Id: I8b7b74a3753c2d4d4614e9a2798283bd3f99d5d2
Signed-off-by: Valentin Boucher <valentin.boucher@kontron.com>
Diffstat (limited to 'functest/opnfv_tests/vnf/ims/heat_ims.py')
-rw-r--r-- | functest/opnfv_tests/vnf/ims/heat_ims.py | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/functest/opnfv_tests/vnf/ims/heat_ims.py b/functest/opnfv_tests/vnf/ims/heat_ims.py new file mode 100644 index 000000000..32783dae7 --- /dev/null +++ b/functest/opnfv_tests/vnf/ims/heat_ims.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python + +# Copyright (c) 2018 Kontron, 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 + +"""HeatIms testcase implementation.""" + +from __future__ import division + +import logging +import os +import re +import time +import yaml + +import pkg_resources +from xtesting.core import testcase + +from functest.core import singlevm +from functest.opnfv_tests.vnf.ims import clearwater +from functest.utils import config +from functest.utils import env + +__author__ = "Valentin Boucher <valentin.boucher@kontron.com>" + + +class HeatIms(singlevm.VmReady2): + # pylint: disable=too-many-instance-attributes + """Clearwater vIMS deployed with Heat Orchestrator Case.""" + + __logger = logging.getLogger(__name__) + + filename_alt = ('/home/opnfv/functest/images/' + 'ubuntu-14.04-server-cloudimg-amd64-disk1.img') + + flavor_alt_ram = 2048 + flavor_alt_vcpus = 2 + flavor_alt_disk = 25 + + quota_security_group = 20 + quota_security_group_rule = 100 + quota_port = 50 + + def __init__(self, **kwargs): + """Initialize HeatIms testcase object.""" + if "case_name" not in kwargs: + kwargs["case_name"] = "heat_ims" + super(HeatIms, self).__init__(**kwargs) + + # Retrieve the configuration + try: + self.config = getattr( + config.CONF, 'vnf_{}_config'.format(self.case_name)) + except Exception: + raise Exception("VNF config file not found") + + self.case_dir = pkg_resources.resource_filename( + 'functest', 'opnfv_tests/vnf/ims') + config_file = os.path.join(self.case_dir, self.config) + + self.vnf = dict( + descriptor=get_config("vnf.descriptor", config_file), + parameters=get_config("vnf.inputs", config_file) + ) + self.details['vnf'] = dict( + descriptor_version=self.vnf['descriptor']['version'], + name=get_config("vnf.name", config_file), + version=get_config("vnf.version", config_file), + ) + self.__logger.debug("VNF configuration: %s", self.vnf) + + self.image_alt = None + self.flavor_alt = None + self.keypair = None + self.stack = None + self.clearwater = None + self.role = None + + def execute(self): + # pylint: disable=too-many-locals,too-many-statements + """ + Prepare Tenant/User + + network, security group, fip, VM creation + """ + self.orig_cloud.set_network_quotas( + self.project.project.name, + security_group=self.quota_security_group, + security_group_rule=self.quota_security_group_rule, + port=self.quota_port) + if not self.orig_cloud.get_role("heat_stack_owner"): + self.role = self.orig_cloud.create_role("heat_stack_owner") + self.orig_cloud.grant_role( + "heat_stack_owner", user=self.project.user.id, + project=self.project.project.id, + domain=self.project.domain.id) + self.keypair = self.cloud.create_keypair( + '{}-kp_{}'.format(self.case_name, self.guid)) + self.__logger.debug("keypair: %s", self.keypair) + + if (self.deploy_vnf() and self.test_vnf()): + self.result = 100 + return 0 + self.result = 1/3 * 100 + return 1 + + def run(self, **kwargs): + """Deploy and test clearwater + + Here are the main actions: + - deploy clearwater stack via heat + - test the vnf instance + + Returns: + - TestCase.EX_OK + - TestCase.EX_RUN_ERROR on error + """ + status = testcase.TestCase.EX_RUN_ERROR + try: + assert self.cloud + self.start_time = time.time() + self.result = 0 + if not self.execute(): + self.result = 100 + status = testcase.TestCase.EX_OK + except Exception: # pylint: disable=broad-except + self.__logger.exception('Cannot run %s', self.case_name) + finally: + self.stop_time = time.time() + return status + + def deploy_vnf(self): + """Deploy Clearwater IMS.""" + start_time = time.time() + + self.image_alt = self.publish_image_alt() + self.flavor_alt = self.create_flavor_alt() + # KeyPair + Image + Flavor OK + + descriptor = self.vnf['descriptor'] + parameters = self.vnf['parameters'] + + parameters['public_mgmt_net_id'] = self.ext_net.id + parameters['public_sig_net_id'] = self.ext_net.id + parameters['flavor'] = self.flavor_alt.name + parameters['image'] = self.image_alt.name + parameters['key_name'] = self.keypair.name + parameters['external_mgmt_dns_ip'] = env.get('NAMESERVER') + parameters['external_sig_dns_ip'] = env.get('NAMESERVER') + + self.__logger.info("Create Heat Stack") + self.stack = self.cloud.create_stack( + name=descriptor.get('name'), + template_file=descriptor.get('file_name'), + wait=True, **parameters) + self.__logger.debug("stack: %s", self.stack) + + servers = self.cloud.list_servers(detailed=True) + self.__logger.debug("servers: %s", servers) + for server in servers: + if not self.check_regex_in_console( + server.name, regex='Cloud-init .* finished at ', loop=60): + return False + if 'ellis' in server.name: + self.__logger.debug("server: %s", server) + ellis_ip = server.public_v4 + + assert ellis_ip + self.clearwater = clearwater.ClearwaterTesting(self.case_name, + ellis_ip) + # This call can take time and many retry because Heat is + # an infrastructure orchestrator so when Heat say "stack created" + # it means that all OpenStack ressources are created but not that + # Clearwater are up and ready (Cloud-Init script still running) + self.clearwater.availability_check_by_creating_numbers() + + duration = time.time() - start_time + + self.details['vnf'].update(status='PASS', duration=duration) + self.result += 1/3 * 100 + + return True + + def test_vnf(self): + """Run test on clearwater ims instance.""" + start_time = time.time() + + outputs = self.cloud.get_stack(self.stack.id).outputs + self.__logger.debug("stack outputs: %s", outputs) + dns_ip = re.findall(r'[0-9]+(?:\.[0-9]+){3}', str(outputs))[0] + + if not dns_ip: + return False + + short_result = self.clearwater.run_clearwater_live_test( + dns_ip=dns_ip, + public_domain=self.vnf['parameters']["zone"]) + duration = time.time() - start_time + self.__logger.info(short_result) + self.details['test_vnf'] = dict(result=short_result, + duration=duration) + try: + vnf_test_rate = short_result['passed'] / ( + short_result['total'] - short_result['skipped']) + # orchestrator + vnf + test_vnf + self.result += vnf_test_rate / 3 * 100 + except ZeroDivisionError: + self.__logger.error("No test has been executed") + self.details['test_vnf'].update(status='FAIL') + return False + except Exception: # pylint: disable=broad-except + self.__logger.exception("Cannot calculate results") + self.details['test_vnf'].update(status='FAIL') + return False + return True if vnf_test_rate > 0 else False + + def clean(self): + """Clean created objects/functions.""" + assert self.cloud + try: + if self.stack: + self.cloud.delete_stack(self.stack.id, wait=True) + except Exception: # pylint: disable=broad-except + self.__logger.exception("Cannot clean stack ressources") + super(HeatIms, self).clean() + if self.role: + self.orig_cloud.delete_role(self.role.id) + + +# ---------------------------------------------------------- +# +# YAML UTILS +# +# ----------------------------------------------------------- +def get_config(parameter, file_path): + """ + Get config parameter. + + Returns the value of a given parameter in file.yaml + parameter must be given in string format with dots + Example: general.openstack.image_name + """ + with open(file_path) as config_file: + file_yaml = yaml.safe_load(config_file) + config_file.close() + value = file_yaml + for element in parameter.split("."): + value = value.get(element) + if value is None: + raise ValueError("The parameter %s is not defined in" + " reporting.yaml" % parameter) + return value |