Conform heat_ims subnets with other testcases
[functest.git] / functest / opnfv_tests / vnf / ims / heat_ims.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2018 Kontron, Orange and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9
10 """HeatIms testcase implementation."""
11
12 from __future__ import division
13
14 import logging
15 import os
16 import re
17 import time
18
19 import pkg_resources
20 from xtesting.core import testcase
21
22 from functest.core import singlevm
23 from functest.opnfv_tests.vnf.ims import clearwater
24 from functest.utils import config
25 from functest.utils import env
26 from functest.utils import functest_utils
27
28 __author__ = "Valentin Boucher <valentin.boucher@kontron.com>"
29
30
31 class HeatIms(singlevm.VmReady2):
32     # pylint: disable=too-many-instance-attributes
33     """Clearwater vIMS deployed with Heat Orchestrator Case."""
34
35     __logger = logging.getLogger(__name__)
36
37     filename = ('/home/opnfv/functest/images/'
38                 'ubuntu-14.04-server-cloudimg-amd64-disk1.img')
39
40     flavor_ram = 1024
41     flavor_vcpus = 1
42     flavor_disk = 3
43
44     quota_security_group = 20
45     quota_security_group_rule = 100
46     quota_port = 50
47
48     parameters = {
49         'private_mgmt_net_cidr': '192.168.100.0/24',
50         'private_mgmt_net_gateway': '192.168.100.254',
51         'private_mgmt_net_pool_start': '192.168.100.1',
52         'private_mgmt_net_pool_end': '192.168.100.253',
53         'private_sig_net_cidr': '192.168.101.0/24',
54         'private_sig_net_gateway': '192.168.101.254',
55         'private_sig_net_pool_start': '192.168.101.1',
56         'private_sig_net_pool_end': '192.168.101.253'}
57
58     def __init__(self, **kwargs):
59         """Initialize HeatIms testcase object."""
60         if "case_name" not in kwargs:
61             kwargs["case_name"] = "heat_ims"
62         super(HeatIms, self).__init__(**kwargs)
63
64         # Retrieve the configuration
65         try:
66             self.config = getattr(
67                 config.CONF, 'vnf_{}_config'.format(self.case_name))
68         except Exception:
69             raise Exception("VNF config file not found")
70
71         self.case_dir = pkg_resources.resource_filename(
72             'functest', 'opnfv_tests/vnf/ims')
73         config_file = os.path.join(self.case_dir, self.config)
74
75         self.vnf = dict(
76             descriptor=functest_utils.get_parameter_from_yaml(
77                 "vnf.descriptor", config_file),
78             parameters=functest_utils.get_parameter_from_yaml(
79                 "vnf.inputs", config_file)
80         )
81         self.details['vnf'] = dict(
82             descriptor_version=self.vnf['descriptor']['version'],
83             name=functest_utils.get_parameter_from_yaml(
84                 "vnf.name", config_file),
85             version=functest_utils.get_parameter_from_yaml(
86                 "vnf.version", config_file),
87         )
88         self.__logger.debug("VNF configuration: %s", self.vnf)
89         self.keypair = None
90         self.stack = None
91         self.clearwater = None
92         self.role = None
93
94     def execute(self):
95         # pylint: disable=too-many-locals,too-many-statements
96         """
97         Prepare Tenant/User
98
99         network, security group, fip, VM creation
100         """
101         self.orig_cloud.set_network_quotas(
102             self.project.project.name,
103             security_group=self.quota_security_group,
104             security_group_rule=self.quota_security_group_rule,
105             port=self.quota_port)
106         if not self.orig_cloud.get_role("heat_stack_owner"):
107             self.role = self.orig_cloud.create_role("heat_stack_owner")
108         self.orig_cloud.grant_role(
109             "heat_stack_owner", user=self.project.user.id,
110             project=self.project.project.id,
111             domain=self.project.domain.id)
112         self.keypair = self.cloud.create_keypair(
113             '{}-kp_{}'.format(self.case_name, self.guid))
114         self.__logger.info("keypair:\n%s", self.keypair.private_key)
115
116         if self.deploy_vnf() and self.test_vnf():
117             self.result = 100
118             return 0
119         self.result = 1/3 * 100
120         return 1
121
122     def run(self, **kwargs):
123         """Deploy and test clearwater
124
125         Here are the main actions:
126         - deploy clearwater stack via heat
127         - test the vnf instance
128
129         Returns:
130         - TestCase.EX_OK
131         - TestCase.EX_RUN_ERROR on error
132         """
133         status = testcase.TestCase.EX_RUN_ERROR
134         try:
135             assert self.cloud
136             assert super(HeatIms, self).run(
137                 **kwargs) == testcase.TestCase.EX_OK
138             self.result = 0
139             if not self.execute():
140                 self.result = 100
141                 status = testcase.TestCase.EX_OK
142         except Exception:  # pylint: disable=broad-except
143             self.__logger.exception('Cannot run %s', self.case_name)
144         finally:
145             self.stop_time = time.time()
146         return status
147
148     def deploy_vnf(self):
149         """Deploy Clearwater IMS."""
150         start_time = time.time()
151         descriptor = self.vnf['descriptor']
152         parameters = self.vnf['parameters']
153
154         parameters['public_mgmt_net_id'] = self.ext_net.id
155         parameters['public_sig_net_id'] = self.ext_net.id
156         parameters['flavor'] = self.flavor.name
157         parameters['image'] = self.image.name
158         parameters['key_name'] = self.keypair.name
159         parameters['external_mgmt_dns_ip'] = env.get('NAMESERVER')
160         parameters['external_sig_dns_ip'] = env.get('NAMESERVER')
161         parameters.update(self.parameters)
162
163         self.__logger.info("Create Heat Stack")
164         self.stack = self.cloud.create_stack(
165             name=descriptor.get('name'),
166             template_file=descriptor.get('file_name'),
167             wait=True, **parameters)
168         self.__logger.debug("stack: %s", self.stack)
169
170         servers = self.cloud.list_servers(detailed=True)
171         self.__logger.debug("servers: %s", servers)
172         for server in servers:
173             if not self.check_regex_in_console(
174                     server.name, regex='Cloud-init .* finished at ', loop=240):
175                 return False
176             if 'ellis' in server.name:
177                 self.__logger.debug("server: %s", server)
178                 ellis_ip = server.public_v4
179
180         assert ellis_ip
181         self.clearwater = clearwater.ClearwaterTesting(self.case_name,
182                                                        ellis_ip)
183         # This call can take time and many retry because Heat is
184         # an infrastructure orchestrator so when Heat say "stack created"
185         # it means that all OpenStack ressources are created but not that
186         # Clearwater are up and ready (Cloud-Init script still running)
187         self.clearwater.availability_check()
188
189         duration = time.time() - start_time
190
191         self.details['vnf'].update(status='PASS', duration=duration)
192         self.result += 1/3 * 100
193
194         return True
195
196     def test_vnf(self):
197         """Run test on clearwater ims instance."""
198         start_time = time.time()
199
200         outputs = self.cloud.get_stack(self.stack.id).outputs
201         self.__logger.debug("stack outputs: %s", outputs)
202         dns_ip = re.findall(r'[0-9]+(?:\.[0-9]+){3}', str(outputs))[0]
203
204         if not dns_ip:
205             return False
206
207         short_result = self.clearwater.run_clearwater_live_test(
208             dns_ip=dns_ip,
209             public_domain=self.vnf['parameters']["zone"])
210         duration = time.time() - start_time
211         self.__logger.info(short_result)
212         self.details['test_vnf'] = dict(result=short_result,
213                                         duration=duration)
214         try:
215             vnf_test_rate = short_result['passed'] / (
216                 short_result['total'] - short_result['skipped'])
217             # orchestrator + vnf + test_vnf
218             self.result += vnf_test_rate / 3 * 100
219         except ZeroDivisionError:
220             self.__logger.error("No test has been executed")
221             self.details['test_vnf'].update(status='FAIL')
222             return False
223         except Exception:  # pylint: disable=broad-except
224             self.__logger.exception("Cannot calculate results")
225             self.details['test_vnf'].update(status='FAIL')
226             return False
227         return True if vnf_test_rate > 0 else False
228
229     def clean(self):
230         """Clean created objects/functions."""
231         assert self.cloud
232         try:
233             if self.stack:
234                 self.cloud.delete_stack(self.stack.id, wait=True)
235         except TypeError:
236             # shade raises TypeError exceptions when checking stack status
237             pass
238         except Exception:  # pylint: disable=broad-except
239             self.__logger.exception("Cannot clean stack ressources")
240         super(HeatIms, self).clean()
241         if self.role:
242             self.orig_cloud.delete_role(self.role.id)