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