Merge "Promote Linda Wang as a committer"
[functest.git] / functest / opnfv_tests / vnf / ims / cloudify_ims.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2016 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 import logging
11 import os
12 import sys
13 import time
14
15 import requests
16 import yaml
17
18 from functest.opnfv_tests.vnf.ims.clearwater import Clearwater
19 import functest.opnfv_tests.vnf.ims.clearwater_ims_base as clearwater_ims_base
20 from functest.opnfv_tests.vnf.ims.orchestrator_cloudify import Orchestrator
21 from functest.utils.constants import CONST
22 import functest.utils.functest_utils as ft_utils
23 import functest.utils.openstack_utils as os_utils
24
25 __author__ = "Valentin Boucher <valentin.boucher@orange.com>"
26
27
28 class CloudifyIms(clearwater_ims_base.ClearwaterOnBoardingBase):
29     """Clearwater vIMS deployed with Cloudify Orchestrator Case"""
30
31     def __init__(self, **kwargs):
32         if "case_name" not in kwargs:
33             kwargs["case_name"] = "cloudify_ims"
34         super(CloudifyIms, self).__init__(**kwargs)
35         self.logger = logging.getLogger(__name__)
36         self.neutron_client = ''
37         self.glance_client = ''
38         self.keystone_client = ''
39         self.nova_client = ''
40
41         # Retrieve the configuration
42         try:
43             self.config = CONST.__getattribute__(
44                 'vnf_{}_config'.format(self.case_name))
45         except Exception:
46             raise Exception("VNF config file not found")
47
48         config_file = os.path.join(self.case_dir, self.config)
49         self.orchestrator = dict(
50             requirements=get_config("cloudify.requirements", config_file),
51             blueprint=get_config("cloudify.blueprint", config_file),
52             inputs=get_config("cloudify.inputs", config_file)
53         )
54         self.logger.debug("Orchestrator configuration: %s", self.orchestrator)
55         self.vnf = dict(
56             blueprint=get_config("clearwater.blueprint", config_file),
57             deployment_name=get_config("clearwater.deployment_name",
58                                        config_file),
59             inputs=get_config("clearwater.inputs", config_file),
60             requirements=get_config("clearwater.requirements", config_file)
61         )
62         self.logger.debug("VNF configuration: %s", self.vnf)
63
64         self.images = get_config("tenant_images", config_file)
65         self.logger.info("Images needed for vIMS: %s", self.images)
66
67     def deploy_orchestrator(self):
68
69         self.logger.info("Additional pre-configuration steps")
70         self.neutron_client = os_utils.get_neutron_client(self.admin_creds)
71         self.glance_client = os_utils.get_glance_client(self.admin_creds)
72         self.keystone_client = os_utils.get_keystone_client(self.admin_creds)
73         self.nova_client = os_utils.get_nova_client(self.admin_creds)
74
75         # needs some images
76         self.logger.info("Upload some OS images if it doesn't exist")
77         temp_dir = os.path.join(self.data_dir, "tmp/")
78         for image_name, image_url in self.images.iteritems():
79             self.logger.info("image: %s, url: %s", image_name, image_url)
80             try:
81                 image_id = os_utils.get_image_id(self.glance_client,
82                                                  image_name)
83                 self.logger.debug("image_id: %s", image_id)
84             except Exception:
85                 self.logger.error("Unexpected error: %s", sys.exc_info()[0])
86
87             if image_id == '':
88                 self.logger.info("""%s image does not exist on glance repo.
89                                  Try downloading this image
90                                  and upload on glance !""",
91                                  image_name)
92                 image_id = os_utils.download_and_add_image_on_glance(
93                     self.glance_client,
94                     image_name,
95                     image_url,
96                     temp_dir)
97         # Need to extend quota
98         self.logger.info("Update security group quota for this tenant")
99         tenant_id = os_utils.get_tenant_id(self.keystone_client,
100                                            self.tenant_name)
101         self.logger.debug("Tenant id found %s", tenant_id)
102         if not os_utils.update_sg_quota(self.neutron_client,
103                                         tenant_id, 50, 100):
104             self.logger.error("Failed to update security group quota"
105                               " for tenant " + self.tenant_name)
106
107         self.logger.debug("group quota extended")
108
109         # start the deployment of cloudify
110         public_auth_url = os_utils.get_endpoint('identity')
111
112         self.logger.debug("CFY inputs: %s", self.orchestrator['inputs'])
113         cfy = Orchestrator(self.data_dir, self.orchestrator['inputs'])
114         self.orchestrator['object'] = cfy
115         self.logger.debug("Orchestrator object created")
116
117         self.logger.debug("Tenant name: %s", self.tenant_name)
118
119         cfy.set_credentials(username=self.tenant_name,
120                             password=self.tenant_name,
121                             tenant_name=self.tenant_name,
122                             auth_url=public_auth_url)
123         self.logger.info("Credentials set in CFY")
124
125         # orchestrator VM flavor
126         self.logger.info("Check Flavor is available, if not create one")
127         self.logger.debug("Flavor details %s ",
128                           self.orchestrator['requirements']['ram_min'])
129         flavor_exist, flavor_id = os_utils.get_or_create_flavor(
130             "m1.large",
131             self.orchestrator['requirements']['ram_min'],
132             '50',
133             '2',
134             public=True)
135         self.logger.debug("Flavor id: %s", flavor_id)
136
137         if not flavor_id:
138             self.logger.info("Available flavors are: ")
139             self.logger.info(self.nova_client.flavor.list())
140
141         cfy.set_flavor_id(flavor_id)
142         self.logger.debug("Flavor OK")
143
144         # orchestrator VM image
145         self.logger.debug("Orchestrator image")
146         if 'os_image' in self.orchestrator['requirements'].keys():
147             image_id = os_utils.get_image_id(
148                 self.glance_client,
149                 self.orchestrator['requirements']['os_image'])
150             self.logger.debug("Orchestrator image id: %s", image_id)
151             if image_id == '':
152                 self.logger.error("CFY image not found")
153
154         cfy.set_image_id(image_id)
155         self.logger.debug("Orchestrator image set")
156
157         self.logger.debug("Get External network")
158         ext_net = os_utils.get_external_net(self.neutron_client)
159         self.logger.debug("External network: %s", ext_net)
160
161         cfy.set_external_network_name(ext_net)
162         self.logger.debug("CFY External network set")
163
164         self.logger.debug("get resolvconf")
165         ns = ft_utils.get_resolvconf_ns()
166         if ns:
167             cfy.set_nameservers(ns)
168             self.logger.debug("Resolvconf set")
169
170         self.logger.info("Prepare virtualenv for cloudify-cli")
171         venv_scrit_dir = os.path.join(self.case_dir, "create_venv.sh")
172         cmd = "chmod +x " + venv_scrit_dir
173         ft_utils.execute_command(cmd)
174         time.sleep(3)
175         cmd = venv_scrit_dir + " " + self.data_dir
176         ft_utils.execute_command(cmd)
177
178         cfy.download_manager_blueprint(
179             self.orchestrator['blueprint']['url'],
180             self.orchestrator['blueprint']['branch'])
181
182         error = cfy.deploy_manager()
183         if error:
184             self.logger.error(error)
185             return {'status': 'FAIL', 'result': error}
186         else:
187             return {'status': 'PASS', 'result': ''}
188
189     def deploy_vnf(self):
190         cw = Clearwater(self.vnf['inputs'], self.orchestrator['object'],
191                         self.logger)
192         self.vnf['object'] = cw
193
194         self.logger.info("Collect flavor id for all clearwater vm")
195         flavor_exist, flavor_id = os_utils.get_or_create_flavor(
196             "m1.small",
197             self.vnf['requirements']['ram_min'],
198             '30',
199             '1',
200             public=True)
201         self.logger.debug("Flavor id: %s", flavor_id)
202         if not flavor_id:
203             self.logger.info("Available flavors are: ")
204             self.logger.info(self.nova_client.flavor.list())
205
206         cw.set_flavor_id(flavor_id)
207
208         # VMs image
209         if 'os_image' in self.vnf['requirements'].keys():
210             image_id = os_utils.get_image_id(
211                 self.glance_client, self.vnf['requirements']['os_image'])
212
213         cw.set_image_id(image_id)
214         ext_net = os_utils.get_external_net(self.neutron_client)
215         cw.set_external_network_name(ext_net)
216
217         error = cw.deploy_vnf(self.vnf['blueprint'])
218         if error:
219             self.logger.error(error)
220             return {'status': 'FAIL', 'result': error}
221         else:
222             return {'status': 'PASS', 'result': ''}
223
224     def test_vnf(self):
225         script = "source {0}venv_cloudify/bin/activate; "
226         script += "cd {0}; "
227         script += "cfy status | grep -Eo \"([0-9]{{1,3}}\.){{3}}[0-9]{{1,3}}\""
228         cmd = "/bin/bash -c '" + script.format(self.data_dir) + "'"
229
230         try:
231             self.logger.debug("Trying to get clearwater manager IP ... ")
232             mgr_ip = os.popen(cmd).read()
233             mgr_ip = mgr_ip.splitlines()[0]
234         except Exception:
235             self.logger.exception("Unable to retrieve the IP of the "
236                                   "cloudify manager server !")
237
238         self.logger.info('Cloudify Manager: %s', mgr_ip)
239         api_url = 'http://{0}/api/v2/deployments/{1}/outputs'.format(
240                   mgr_ip, self.vnf['deployment_name'])
241         dep_outputs = requests.get(api_url)
242         self.logger.info(api_url)
243         outputs = dep_outputs.json()['outputs']
244         self.logger.info("Deployment outputs: %s", outputs)
245         dns_ip = outputs['dns_ip']
246         ellis_ip = outputs['ellis_ip']
247         self.config_ellis(ellis_ip)
248
249         if dns_ip != "":
250             vims_test_result = self.run_clearwater_live_test(
251                 dns_ip=dns_ip,
252                 public_domain="")  # self.inputs["public_domain"]
253             if vims_test_result != '':
254                 return {'status': 'PASS', 'result': vims_test_result}
255             else:
256                 return {'status': 'FAIL', 'result': ''}
257
258     def clean(self):
259         self.vnf['object'].undeploy_vnf()
260         self.orchestrator['object'].undeploy_manager()
261         super(CloudifyIms, self).clean()
262
263
264 # ----------------------------------------------------------
265 #
266 #               YAML UTILS
267 #
268 # -----------------------------------------------------------
269 def get_config(parameter, file):
270     """
271     Returns the value of a given parameter in file.yaml
272     parameter must be given in string format with dots
273     Example: general.openstack.image_name
274     """
275     with open(file) as f:
276         file_yaml = yaml.safe_load(f)
277     f.close()
278     value = file_yaml
279     for element in parameter.split("."):
280         value = value.get(element)
281         if value is None:
282             raise ValueError("The parameter %s is not defined in"
283                              " reporting.yaml" % parameter)
284     return value