Merge "Refactor Rally to adopt OO"
[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 json
11 import os
12 import requests
13 import subprocess
14 import time
15
16 import functest.core.vnf_base as vnf_base
17 import functest.utils.functest_logger as ft_logger
18 import functest.utils.functest_utils as ft_utils
19 import functest.utils.openstack_utils as os_utils
20
21 from clearwater import Clearwater
22 from functest.utils.constants import CONST
23 from orchestrator_cloudify import Orchestrator
24
25
26 class ImsVnf(vnf_base.VnfOnBoardingBase):
27
28     def __init__(self, project='functest', case='cloudify_ims',
29                  repo='', cmd=''):
30         super(ImsVnf, self).__init__(project, case, repo, cmd)
31         self.logger = ft_logger.Logger("vIMS").getLogger()
32         self.case_dir = os.path.join(CONST.functest_test, 'vnf/ims/')
33         self.data_dir = CONST.dir_vIMS_data
34         self.test_dir = CONST.dir_repo_vims_test
35
36         self.orchestrator = dict(
37             requirements=CONST.cloudify_requirements,
38             blueprint=CONST.cloudify_blueprint,
39             inputs=CONST.cloudify_inputs
40         )
41
42         self.vnf = dict(
43             blueprint=CONST.clearwater_blueprint,
44             deployment_name=CONST.clearwater_deployment_name,
45             inputs=CONST.clearwater_inputs,
46             requirements=CONST.clearwater_requirements
47         )
48
49         # vIMS Data directory creation
50         if not os.path.exists(self.data_dir):
51             os.makedirs(self.data_dir)
52
53     def deploy_orchestrator(self, **kwargs):
54         public_auth_url = os_utils.get_endpoint('identity')
55
56         cfy = Orchestrator(self.data_dir, self.orchestrator.inputs)
57         self.orchestrator.object = cfy
58
59         if 'tenant_name' in self.creds.keys():
60             tenant_name = self.creds['tenant_name']
61         elif 'project_name' in self.creds.keys():
62             tenant_name = self.creds['project_name']
63
64         cfy.set_credentials(username=self.creds['username'],
65                             password=self.creds['password'],
66                             tenant_name=tenant_name,
67                             auth_url=public_auth_url)
68
69         # orchestrator VM flavor
70         flavor_id = self.get_flavor("m1.large", self.orchestrator.requirements)
71         if not flavor_id:
72             self.logger.info("Available flavors are: ")
73             self.pMsg(self.nova_client.flavor.list())
74             self.step_failure("Failed to find required flavor"
75                               "for this deployment")
76         cfy.set_flavor_id(flavor_id)
77
78         # orchestrator VM image
79         if 'os_image' in self.orchestrator.requirements.keys():
80             image_id = os_utils.get_image_id(
81                 self.glance_client, self.orchestrator.requirements['os_image'])
82             if image_id == '':
83                 self.step_failure("Failed to find required OS image"
84                                   " for cloudify manager")
85         else:
86             self.step_failure("Failed to find required OS image"
87                               " for cloudify manager")
88
89         cfy.set_image_id(image_id)
90
91         ext_net = os_utils.get_external_net(self.neutron_client)
92         if not ext_net:
93             self.step_failure("Failed to get external network")
94
95         cfy.set_external_network_name(ext_net)
96
97         ns = ft_utils.get_resolvconf_ns()
98         if ns:
99             cfy.set_nameservers(ns)
100
101         if 'compute' in self.nova_client.client.services_url:
102             cfy.set_nova_url(self.nova_client.client.services_url['compute'])
103         if self.neutron_client.httpclient.endpoint_url is not None:
104             cfy.set_neutron_url(self.neutron_client.httpclient.endpoint_url)
105
106         self.logger.info("Prepare virtualenv for cloudify-cli")
107         cmd = "chmod +x " + self.case_dir + "create_venv.sh"
108         ft_utils.execute_command(cmd)
109         time.sleep(3)
110         cmd = self.case_dir + "create_venv.sh " + self.data_dir
111         ft_utils.execute_command(cmd)
112
113         cfy.download_manager_blueprint(self.orchestrator.blueprint['url'],
114                                        self.orchestrator.blueprint['branch'])
115
116         cfy.deploy_manager()
117         return {'status': 'PASS', 'result': ''}
118
119     def deploy_vnf(self):
120         cw = Clearwater(self.vnf.inputs, self.orchestrator.object, self.logger)
121         self.vnf.object = cw
122
123         self.logger.info("Collect flavor id for all clearwater vm")
124         flavor_id = self.get_flavor("m1.small", self.vnf.requirements)
125         if not flavor_id:
126             self.logger.info("Available flavors are: ")
127             self.pMsg(self.nova_client.flavor.list())
128             self.step_failure("Failed to find required flavor"
129                               " for this deployment")
130
131         cw.set_flavor_id(flavor_id)
132
133         # VMs image
134         if 'os_image' in self.vnf.requirements.keys():
135             image_id = os_utils.get_image_id(
136                 self.glance_client, self.vnf.requirements['os_image'])
137             if image_id == '':
138                 self.step_failure("Failed to find required OS image"
139                                   " for clearwater VMs")
140         else:
141             self.step_failure("Failed to find required OS image"
142                               " for clearwater VMs")
143
144         cw.set_image_id(image_id)
145
146         ext_net = os_utils.get_external_net(self.neutron_client)
147         if not ext_net:
148             self.step_failure("Failed to get external network")
149
150         cw.set_external_network_name(ext_net)
151
152         cw.deploy_vnf()
153         return {'status': 'PASS', 'result': ''}
154
155     def test_vnf(self):
156         script = "source {0}venv_cloudify/bin/activate; "
157         script += "cd {0}; "
158         script += "cfy status | grep -Eo \"([0-9]{{1,3}}\.){{3}}[0-9]{{1,3}}\""
159         cmd = "/bin/bash -c '" + script.format(self.data_dir) + "'"
160
161         try:
162             self.logger.debug("Trying to get clearwater manager IP ... ")
163             mgr_ip = os.popen(cmd).read()
164             mgr_ip = mgr_ip.splitlines()[0]
165         except:
166             self.step_failure("Unable to retrieve the IP of the "
167                               "cloudify manager server !")
168
169         api_url = "http://" + mgr_ip + "/api/v2"
170         dep_outputs = requests.get(api_url + "/deployments/" +
171                                    self.vnf.deployment_name + "/outputs")
172         dns_ip = dep_outputs.json()['outputs']['dns_ip']
173         ellis_ip = dep_outputs.json()['outputs']['ellis_ip']
174
175         ellis_url = "http://" + ellis_ip + "/"
176         url = ellis_url + "accounts"
177
178         params = {"password": "functest",
179                   "full_name": "opnfv functest user",
180                   "email": "functest@opnfv.fr",
181                   "signup_code": "secret"}
182
183         rq = requests.post(url, data=params)
184         i = 20
185         while rq.status_code != 201 and i > 0:
186             rq = requests.post(url, data=params)
187             i = i - 1
188             time.sleep(10)
189
190         if rq.status_code == 201:
191             url = ellis_url + "session"
192             rq = requests.post(url, data=params)
193             cookies = rq.cookies
194
195         url = ellis_url + "accounts/" + params['email'] + "/numbers"
196         if cookies != "":
197             rq = requests.post(url, cookies=cookies)
198             i = 24
199             while rq.status_code != 200 and i > 0:
200                 rq = requests.post(url, cookies=cookies)
201                 i = i - 1
202                 time.sleep(25)
203
204         if rq.status_code != 200:
205             self.step_failure("Unable to create a number: %s"
206                               % rq.json()['reason'])
207
208         nameservers = ft_utils.get_resolvconf_ns()
209         resolvconf = ""
210         for ns in nameservers:
211             resolvconf += "\nnameserver " + ns
212
213         if dns_ip != "":
214             script = ('echo -e "nameserver ' + dns_ip + resolvconf +
215                       '" > /etc/resolv.conf; ')
216             script += 'source /etc/profile.d/rvm.sh; '
217             script += 'cd {0}; '
218             script += ('rake test[{1}] SIGNUP_CODE="secret"')
219
220             cmd = ("/bin/bash -c '" +
221                    script.format(self.data_dir, self.inputs["public_domain"]) +
222                    "'")
223             output_file = "output.txt"
224             f = open(output_file, 'w+')
225             subprocess.call(cmd, shell=True, stdout=f,
226                             stderr=subprocess.STDOUT)
227             f.close()
228
229             f = open(output_file, 'r')
230             result = f.read()
231             if result != "":
232                 self.logger.debug(result)
233
234             vims_test_result = ""
235             tempFile = os.path.join(self.test_dir, "temp.json")
236             try:
237                 self.logger.debug("Trying to load test results")
238                 with open(tempFile) as f:
239                     vims_test_result = json.load(f)
240                 f.close()
241             except:
242                 self.logger.error("Unable to retrieve test results")
243
244             try:
245                 os.remove(tempFile)
246             except:
247                 self.logger.error("Deleting file failed")
248
249             if vims_test_result != '':
250                 return {'status': 'PASS', 'result': vims_test_result}
251             else:
252                 return {'status': 'FAIL', 'result': ''}
253
254     def clean(self):
255         self.vnf.object.undeploy_vnf()
256         self.orchestrator.object.undeploy_manager()
257         super(ImsVnf, self).clean()
258
259     def get_flavor(self, flavor_name, requirements):
260         try:
261             flavor_id = os_utils.get_flavor_id(self.nova_client, flavor_name)
262             if 'ram_min' in requirements.keys():
263                 flavor_id = os_utils.get_flavor_id_by_ram_range(
264                     self.nova_client, requirements['ram_min'], 7500)
265
266             if flavor_id == '':
267                 self.logger.error(
268                     "Failed to find %s flavor. "
269                     "Try with ram range default requirement !" % flavor_name)
270                 flavor_id = os_utils.get_flavor_id_by_ram_range(
271                                     self.nova_client,
272                                     4000, 10000)
273             return flavor_id
274         except:
275             self.logger.error("Flavor '%s' not found." % self.flavor_name)
276             self.logger.info("Available flavors are: ")
277             self.pMsg(self.nova_client.flavor.list())
278             return None