Merge "Refactoring of args and parser variable in ci/run_tests, prepare_env"
[functest.git] / functest / opnfv_tests / vnf / ims / vims.py
1 #!/usr/bin/python
2 # coding: utf8
3 #######################################################################
4 #
5 #   Copyright (c) 2015 Orange
6 #   valentin.boucher@orange.com
7 #
8 # All rights reserved. This program and the accompanying materials
9 # are made available under the terms of the Apache License, Version 2.0
10 # which accompanies this distribution, and is available at
11 # http://www.apache.org/licenses/LICENSE-2.0
12 ########################################################################
13
14 import datetime
15 import json
16 import os
17 import pprint
18 import subprocess
19 import time
20
21 import argparse
22 import requests
23
24 import functest.utils.functest_logger as ft_logger
25 import functest.utils.functest_utils as ft_utils
26 import functest.utils.openstack_utils as os_utils
27 from clearwater import Clearwater
28 from orchestrator import Orchestrator
29 import functest.utils.functest_constants as ft_constants
30
31 pp = pprint.PrettyPrinter(indent=4)
32
33
34 parser = argparse.ArgumentParser()
35 parser.add_argument("-d", "--debug", help="Debug mode", action="store_true")
36 parser.add_argument("-r", "--report",
37                     help="Create json result file",
38                     action="store_true")
39 parser.add_argument("-n", "--noclean",
40                     help="Don't clean the created resources for this test.",
41                     action="store_true")
42 args = parser.parse_args()
43
44 """ logging configuration """
45 logger = ft_logger.Logger("vIMS").getLogger()
46
47
48 # Cloudify parameters
49 VIMS_DIR = os.path.join(ft_constants.FUNCTEST_TEST_DIR, 'vnf/ims/')
50 VIMS_DATA_DIR = ft_constants.VIMS_DATA_DIR
51 VIMS_TEST_DIR = ft_constants.VIMS_TEST_DIR
52 VIMS_TENANT_NAME = ft_constants.VIMS_TENANT_NAME
53 VIMS_TENANT_DESCRIPTION = ft_constants.VIMS_TENANT_DESCRIPTION
54 VIMS_IMAGES = ft_constants.VIMS_IMAGES
55
56 CFY_MANAGER_BLUEPRINT = ft_constants.CFY_MANAGER_BLUEPRINT
57 CFY_MANAGER_REQUIERMENTS = ft_constants.CFY_MANAGER_REQUIERMENTS
58 CFY_INPUTS = ft_constants.CFY_INPUTS
59
60 CW_BLUEPRINT = ft_constants.CW_BLUEPRINT
61 CW_DEPLOYMENT_NAME = ft_constants.CW_DEPLOYMENT_NAME
62 CW_INPUTS = ft_constants.CW_INPUTS
63 CW_REQUIERMENTS = ft_constants.CW_REQUIERMENTS
64
65 CFY_DEPLOYMENT_DURATION = 0
66 CW_DEPLOYMENT_DURATION = 0
67
68 TESTCASE_START_TIME = time.time()
69 RESULTS = {'orchestrator': {'duration': 0, 'result': ''},
70            'vIMS': {'duration': 0, 'result': ''},
71            'sig_test': {'duration': 0, 'result': ''}}
72
73
74 def download_and_add_image_on_glance(glance, image_name, image_url):
75     dest_path = os.path.join(VIMS_DATA_DIR, "tmp/")
76     if not os.path.exists(dest_path):
77         os.makedirs(dest_path)
78     file_name = image_url.rsplit('/')[-1]
79     if not ft_utils.download_url(image_url, dest_path):
80         logger.error("Failed to download image %s" % file_name)
81         return False
82
83     image = os_utils.create_glance_image(
84         glance, image_name, dest_path + file_name)
85     if not image:
86         logger.error("Failed to upload image on glance")
87         return False
88
89     return image
90
91
92 def step_failure(step_name, error_msg):
93     logger.error(error_msg)
94     set_result(step_name, 0, error_msg)
95     status = "FAIL"
96     # in case of failure starting and stoping time are not correct
97     stop_time = time.time()
98     if step_name == "sig_test":
99         status = "PASS"
100     ft_utils.push_results_to_db("functest",
101                                 "vims",
102                                 TESTCASE_START_TIME,
103                                 stop_time,
104                                 status,
105                                 RESULTS)
106     exit(-1)
107
108
109 def set_result(step_name, duration=0, result=""):
110     RESULTS[step_name] = {'duration': duration, 'result': result}
111
112
113 def test_clearwater():
114     script = "source " + VIMS_DATA_DIR + "venv_cloudify/bin/activate; "
115     script += "cd " + VIMS_DATA_DIR + "; "
116     script += "cfy status | grep -Eo \"([0-9]{1,3}\.){3}[0-9]{1,3}\""
117     cmd = "/bin/bash -c '" + script + "'"
118
119     try:
120         logger.debug("Trying to get clearwater manager IP ... ")
121         mgr_ip = os.popen(cmd).read()
122         mgr_ip = mgr_ip.splitlines()[0]
123     except:
124         step_failure("sig_test", "Unable to retrieve the IP of the "
125                      "cloudify manager server !")
126
127     api_url = "http://" + mgr_ip + "/api/v2"
128     dep_outputs = requests.get(api_url + "/deployments/" +
129                                CW_DEPLOYMENT_NAME + "/outputs")
130     dns_ip = dep_outputs.json()['outputs']['dns_ip']
131     ellis_ip = dep_outputs.json()['outputs']['ellis_ip']
132
133     ellis_url = "http://" + ellis_ip + "/"
134     url = ellis_url + "accounts"
135
136     params = {"password": "functest",
137               "full_name": "opnfv functest user",
138               "email": "functest@opnfv.fr",
139               "signup_code": "secret"}
140
141     rq = requests.post(url, data=params)
142     i = 20
143     while rq.status_code != 201 and i > 0:
144         rq = requests.post(url, data=params)
145         i = i - 1
146         time.sleep(10)
147
148     if rq.status_code == 201:
149         url = ellis_url + "session"
150         rq = requests.post(url, data=params)
151         cookies = rq.cookies
152
153     url = ellis_url + "accounts/" + params['email'] + "/numbers"
154     if cookies != "":
155         rq = requests.post(url, cookies=cookies)
156         i = 24
157         while rq.status_code != 200 and i > 0:
158             rq = requests.post(url, cookies=cookies)
159             i = i - 1
160             time.sleep(25)
161
162     if rq.status_code != 200:
163         step_failure("sig_test", "Unable to create a number: %s"
164                      % rq.json()['reason'])
165
166     start_time_ts = time.time()
167     end_time_ts = start_time_ts
168     logger.info("vIMS functional test Start Time:'%s'" % (
169         datetime.datetime.fromtimestamp(start_time_ts).strftime(
170             '%Y-%m-%d %H:%M:%S')))
171     nameservers = ft_utils.get_resolvconf_ns()
172     resolvconf = ""
173     for ns in nameservers:
174         resolvconf += "\nnameserver " + ns
175
176     if dns_ip != "":
177         script = ('echo -e "nameserver ' + dns_ip + resolvconf +
178                   '" > /etc/resolv.conf; ')
179         script += 'source /etc/profile.d/rvm.sh; '
180         script += 'cd ' + VIMS_TEST_DIR + '; '
181         script += ('rake test[' + CW_INPUTS["public_domain"] +
182                    '] SIGNUP_CODE="secret"')
183
184         cmd = "/bin/bash -c '" + script + "'"
185         output_file = "output.txt"
186         f = open(output_file, 'w+')
187         subprocess.call(cmd, shell=True, stdout=f,
188                         stderr=subprocess.STDOUT)
189         f.close()
190         end_time_ts = time.time()
191         duration = round(end_time_ts - start_time_ts, 1)
192         logger.info("vIMS functional test duration:'%s'" % duration)
193         f = open(output_file, 'r')
194         result = f.read()
195         if result != "" and logger:
196             logger.debug(result)
197
198         vims_test_result = ""
199         tempFile = os.path.join(VIMS_TEST_DIR, "temp.json")
200         try:
201             logger.debug("Trying to load test results")
202             with open(tempFile) as f:
203                 vims_test_result = json.load(f)
204             f.close()
205         except:
206             logger.error("Unable to retrieve test results")
207
208         set_result("sig_test", duration, vims_test_result)
209
210         # success criteria for vIMS (for Brahmaputra)
211         # - orchestrator deployed
212         # - VNF deployed
213         # TODO use test criteria defined in config file
214         status = "FAIL"
215         try:
216             if (RESULTS['orchestrator']['duration'] > 0 and
217                     RESULTS['vIMS']['duration'] > 0):
218                 status = "PASS"
219         except:
220             logger.error("Unable to set test status")
221
222         ft_utils.push_results_to_db("functest",
223                                     "vims",
224                                     TESTCASE_START_TIME,
225                                     end_time_ts,
226                                     status,
227                                     RESULTS)
228
229         try:
230             os.remove(tempFile)
231         except:
232             logger.error("Deleting file failed")
233
234
235 def main():
236
237     # ############### GENERAL INITIALISATION ################
238
239     if not os.path.exists(VIMS_DATA_DIR):
240         os.makedirs(VIMS_DATA_DIR)
241
242     creds = os_utils.get_credentials()
243
244     logger.info("Prepare OpenStack plateform (create tenant and user)")
245     keystone = os_utils.get_keystone_client()
246
247     user_id = os_utils.get_user_id(keystone, creds['username'])
248     if user_id == '':
249         step_failure("init", "Error : Failed to get id of " +
250                      creds['username'])
251
252     tenant_id = os_utils.create_tenant(
253         keystone, VIMS_TENANT_NAME, VIMS_TENANT_DESCRIPTION)
254     if not tenant_id:
255         step_failure("init", "Error : Failed to create " +
256                      VIMS_TENANT_NAME + " tenant")
257
258     roles_name = ["admin", "Admin"]
259     role_id = ''
260     for role_name in roles_name:
261         if role_id == '':
262             role_id = os_utils.get_role_id(keystone, role_name)
263
264     if role_id == '':
265         logger.error("Error : Failed to get id for %s role" % role_name)
266
267     if not os_utils.add_role_user(keystone, user_id, role_id, tenant_id):
268         logger.error("Error : Failed to add %s on tenant" %
269                      creds['username'])
270
271     user_id = os_utils.create_user(
272         keystone, VIMS_TENANT_NAME, VIMS_TENANT_NAME, None, tenant_id)
273     if not user_id:
274         logger.error("Error : Failed to create %s user" % VIMS_TENANT_NAME)
275
276     logger.info("Update OpenStack creds informations")
277     creds.update({
278         "username": VIMS_TENANT_NAME,
279         "password": VIMS_TENANT_NAME,
280         "tenant": VIMS_TENANT_NAME,
281     })
282
283     logger.info("Upload some OS images if it doesn't exist")
284     glance = os_utils.get_glance_client()
285
286     for img in VIMS_IMAGES.keys():
287         image_name = VIMS_IMAGES[img]['image_name']
288         image_url = VIMS_IMAGES[img]['image_url']
289
290         image_id = os_utils.get_image_id(glance, image_name)
291
292         if image_id == '':
293             logger.info("""%s image doesn't exist on glance repository. Try
294             downloading this image and upload on glance !""" % image_name)
295             image_id = download_and_add_image_on_glance(
296                 glance, image_name, image_url)
297
298         if image_id == '':
299             step_failure(
300                 "init",
301                 "Error : Failed to find or upload required OS "
302                 "image for this deployment")
303
304     logger.info("Update security group quota for this tenant")
305     neutron = os_utils.get_neutron_client(creds)
306     if not os_utils.update_sg_quota(neutron, tenant_id, 50, 100):
307         step_failure(
308             "init",
309             "Failed to update security group quota for tenant " +
310             VIMS_TENANT_NAME)
311
312     # ############### CLOUDIFY INITIALISATION ################
313     public_auth_url = os_utils.get_endpoint('identity')
314
315     cfy = Orchestrator(VIMS_DATA_DIR, CFY_INPUTS)
316
317     if 'tenant_name' in creds.keys():
318         tenant_name = creds['tenant_name']
319     elif 'project_name' in creds.keys():
320         tenant_name = creds['project_name']
321
322     cfy.set_credentials(username=creds['username'],
323                         password=creds['password'],
324                         tenant_name=tenant_name,
325                         auth_url=public_auth_url)
326
327     logger.info("Collect flavor id for cloudify manager server")
328     nova = os_utils.get_nova_client(creds)
329
330     flavor_name = "m1.large"
331     flavor_id = os_utils.get_flavor_id(nova, flavor_name)
332     for requirement in CFY_MANAGER_REQUIERMENTS:
333         if requirement == 'ram_min':
334             flavor_id = os_utils.get_flavor_id_by_ram_range(
335                 nova, CFY_MANAGER_REQUIERMENTS['ram_min'], 10000)
336
337     if flavor_id == '':
338         logger.error(
339             "Failed to find %s flavor. "
340             "Try with ram range default requirement !" % flavor_name)
341         flavor_id = os_utils.get_flavor_id_by_ram_range(nova, 4000, 8196)
342
343     if flavor_id == '':
344         step_failure("orchestrator",
345                      "Failed to find required flavor for this deployment")
346
347     cfy.set_flavor_id(flavor_id)
348
349     image_name = "centos_7"
350     image_id = os_utils.get_image_id(glance, image_name)
351     for requirement in CFY_MANAGER_REQUIERMENTS:
352         if requirement == 'os_image':
353             image_id = os_utils.get_image_id(
354                 glance, CFY_MANAGER_REQUIERMENTS['os_image'])
355
356     if image_id == '':
357         step_failure(
358             "orchestrator",
359             "Error : Failed to find required OS image for cloudify manager")
360
361     cfy.set_image_id(image_id)
362
363     ext_net = os_utils.get_external_net(neutron)
364     if not ext_net:
365         step_failure("orchestrator", "Failed to get external network")
366
367     cfy.set_external_network_name(ext_net)
368
369     ns = ft_utils.get_resolvconf_ns()
370     if ns:
371         cfy.set_nameservers(ns)
372
373     if 'compute' in nova.client.services_url:
374         cfy.set_nova_url(nova.client.services_url['compute'])
375     if neutron.httpclient.endpoint_url is not None:
376         cfy.set_neutron_url(neutron.httpclient.endpoint_url)
377
378     logger.info("Prepare virtualenv for cloudify-cli")
379     cmd = "chmod +x " + VIMS_DIR + "create_venv.sh"
380     ft_utils.execute_command(cmd)
381     time.sleep(3)
382     cmd = VIMS_DIR + "create_venv.sh " + VIMS_DATA_DIR
383     ft_utils.execute_command(cmd)
384
385     cfy.download_manager_blueprint(
386         CFY_MANAGER_BLUEPRINT['url'], CFY_MANAGER_BLUEPRINT['branch'])
387
388     # ############### CLOUDIFY DEPLOYMENT ################
389     start_time_ts = time.time()
390     end_time_ts = start_time_ts
391     logger.info("Cloudify deployment Start Time:'%s'" % (
392         datetime.datetime.fromtimestamp(start_time_ts).strftime(
393             '%Y-%m-%d %H:%M:%S')))
394
395     error = cfy.deploy_manager()
396     if error:
397         step_failure("orchestrator", error)
398
399     end_time_ts = time.time()
400     duration = round(end_time_ts - start_time_ts, 1)
401     logger.info("Cloudify deployment duration:'%s'" % duration)
402     set_result("orchestrator", duration, "")
403
404     # ############### CLEARWATER INITIALISATION ################
405
406     cw = Clearwater(CW_INPUTS, cfy, logger)
407
408     logger.info("Collect flavor id for all clearwater vm")
409
410     flavor_name = "m1.small"
411     flavor_id = os_utils.get_flavor_id(nova, flavor_name)
412     for requirement in CW_REQUIERMENTS:
413         if requirement == 'ram_min' and flavor_id == '':
414             flavor_id = os_utils.get_flavor_id_by_ram_range(
415                 nova, CW_REQUIERMENTS['ram_min'], 4500)
416
417     if flavor_id == '':
418         logger.error(
419             "Failed to find %s flavor. Try with ram range "
420             "default requirement !" % flavor_name)
421         flavor_id = os_utils.get_flavor_id_by_ram_range(nova, 4000, 8196)
422
423     if flavor_id == '':
424         step_failure(
425             "vIMS", "Failed to find required flavor for this deployment")
426
427     cw.set_flavor_id(flavor_id)
428
429     image_name = "ubuntu_14.04"
430     image_id = os_utils.get_image_id(glance, image_name)
431     for requirement in CW_REQUIERMENTS:
432         if requirement == 'os_image':
433             image_id = os_utils.get_image_id(
434                 glance, CW_REQUIERMENTS['os_image'])
435
436     if image_id == '':
437         step_failure(
438             "vIMS",
439             "Error : Failed to find required OS image for cloudify manager")
440
441     cw.set_image_id(image_id)
442
443     ext_net = os_utils.get_external_net(neutron)
444     if not ext_net:
445         step_failure("vIMS", "Failed to get external network")
446
447     cw.set_external_network_name(ext_net)
448
449     # ############### CLEARWATER DEPLOYMENT ################
450
451     start_time_ts = time.time()
452     end_time_ts = start_time_ts
453     logger.info("vIMS VNF deployment Start Time:'%s'" % (
454         datetime.datetime.fromtimestamp(start_time_ts).strftime(
455             '%Y-%m-%d %H:%M:%S')))
456
457     error = cw.deploy_vnf(CW_BLUEPRINT)
458     if error:
459         step_failure("vIMS", error)
460
461     end_time_ts = time.time()
462     duration = round(end_time_ts - start_time_ts, 1)
463     logger.info("vIMS VNF deployment duration:'%s'" % duration)
464     set_result("vIMS", duration, "")
465
466     # ############### CLEARWATER TEST ################
467
468     test_clearwater()
469
470     # ########## CLEARWATER UNDEPLOYMENT ############
471
472     cw.undeploy_vnf()
473
474     # ########### CLOUDIFY UNDEPLOYMENT #############
475
476     cfy.undeploy_manager()
477
478     # ############## GENERAL CLEANUP ################
479     if args.noclean:
480         exit(0)
481
482     logger.info("Removing %s tenant .." % CFY_INPUTS['keystone_tenant_name'])
483     tenant_id = os_utils.get_tenant_id(
484         keystone, CFY_INPUTS['keystone_tenant_name'])
485     if tenant_id == '':
486         logger.error("Error : Failed to get id of %s tenant" %
487                      CFY_INPUTS['keystone_tenant_name'])
488     else:
489         if not os_utils.delete_tenant(keystone, tenant_id):
490             logger.error("Error : Failed to remove %s tenant" %
491                          CFY_INPUTS['keystone_tenant_name'])
492
493     logger.info("Removing %s user .." % CFY_INPUTS['keystone_username'])
494     user_id = os_utils.get_user_id(
495         keystone, CFY_INPUTS['keystone_username'])
496     if user_id == '':
497         logger.error("Error : Failed to get id of %s user" %
498                      CFY_INPUTS['keystone_username'])
499     else:
500         if not os_utils.delete_user(keystone, user_id):
501             logger.error("Error : Failed to remove %s user" %
502                          CFY_INPUTS['keystone_username'])
503
504
505 if __name__ == '__main__':
506     main()