Add timeout for cloudify-manager deployment
[functest.git] / testcases / vIMS / CI / 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 os
15 import time
16 import subprocess
17 import logging
18 import argparse
19 import yaml
20 import pprint
21 import sys
22 import shutil
23 import json
24 import datetime
25 from git import Repo
26 import keystoneclient.v2_0.client as ksclient
27 import glanceclient.client as glclient
28 import novaclient.client as nvclient
29 from neutronclient.v2_0 import client as ntclient
30
31 from orchestrator import *
32 from clearwater import *
33
34 import urllib
35 pp = pprint.PrettyPrinter(indent=4)
36
37
38 parser = argparse.ArgumentParser()
39 parser.add_argument("-d", "--debug", help="Debug mode",  action="store_true")
40 parser.add_argument("-r", "--report",
41                     help="Create json result file",
42                     action="store_true")
43 args = parser.parse_args()
44
45 """ logging configuration """
46 logger = logging.getLogger('vIMS')
47 logger.setLevel(logging.DEBUG)
48
49 ch = logging.StreamHandler()
50 if args.debug:
51     ch.setLevel(logging.DEBUG)
52 else:
53     ch.setLevel(logging.INFO)
54 formatter = logging.Formatter(
55     '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
56 ch.setFormatter(formatter)
57 logger.addHandler(ch)
58
59 REPO_PATH = os.environ['repos_dir'] + '/functest/'
60 if not os.path.exists(REPO_PATH):
61     logger.error("Functest repository directory not found '%s'" % REPO_PATH)
62     exit(-1)
63 sys.path.append(REPO_PATH + "testcases/")
64 import functest_utils
65
66 with open(REPO_PATH + "testcases/config_functest.yaml") as f:
67     functest_yaml = yaml.safe_load(f)
68 f.close()
69
70 # Cloudify parameters
71 VIMS_DIR = REPO_PATH + \
72     functest_yaml.get("general").get("directories").get("dir_vIMS")
73 VIMS_DATA_DIR = functest_yaml.get("general").get(
74     "directories").get("dir_vIMS_data") + "/"
75 VIMS_TEST_DIR = functest_yaml.get("general").get(
76     "directories").get("dir_repo_vims_test") + "/"
77 TEST_DB = functest_yaml.get("results").get("test_db_url")
78
79 TENANT_NAME = functest_yaml.get("vIMS").get("general").get("tenant_name")
80 TENANT_DESCRIPTION = functest_yaml.get("vIMS").get(
81     "general").get("tenant_description")
82 IMAGES = functest_yaml.get("vIMS").get("general").get("images")
83
84 CFY_MANAGER_BLUEPRINT = functest_yaml.get(
85     "vIMS").get("cloudify").get("blueprint")
86 CFY_MANAGER_REQUIERMENTS = functest_yaml.get(
87     "vIMS").get("cloudify").get("requierments")
88 CFY_INPUTS = functest_yaml.get("vIMS").get("cloudify").get("inputs")
89
90 CW_BLUEPRINT = functest_yaml.get("vIMS").get("clearwater").get("blueprint")
91 CW_DEPLOYMENT_NAME = functest_yaml.get("vIMS").get(
92     "clearwater").get("deployment-name")
93 CW_INPUTS = functest_yaml.get("vIMS").get("clearwater").get("inputs")
94 CW_REQUIERMENTS = functest_yaml.get("vIMS").get(
95     "clearwater").get("requierments")
96
97 CFY_DEPLOYMENT_DURATION = 0
98 CW_DEPLOYMENT_DURATION = 0
99
100
101 def download_and_add_image_on_glance(glance, image_name, image_url):
102     dest_path = VIMS_DATA_DIR + "tmp/"
103     if not os.path.exists(dest_path):
104         os.makedirs(dest_path)
105     file_name = image_url.rsplit('/')[-1]
106     if not functest_utils.download_url(image_url, dest_path):
107         logger.error("Failed to download image %s" % file_name)
108         return False
109
110     image = functest_utils.create_glance_image(
111         glance, image_name, dest_path + file_name)
112     if not image:
113         logger.error("Failed to upload image on glance")
114         return False
115
116     return image
117
118
119 def test_clearwater():
120
121     time.sleep(180)
122
123     script = "source " + VIMS_DATA_DIR + "venv_cloudify/bin/activate; "
124     script += "cd " + VIMS_DATA_DIR + "; "
125     script += "cfy deployments outputs -d " + CW_DEPLOYMENT_NAME + \
126         " | grep Value: | sed \"s/ *Value: //g\";"
127     cmd = "/bin/bash -c '" + script + "'"
128
129     try:
130         logger.debug("Trying to get clearwater nameserver IP ... ")
131         dns_ip = os.popen(cmd).read()
132         dns_ip = dns_ip.splitlines()[0]
133     except:
134         logger.error("Unable to retrieve the IP of the DNS server !")
135
136     start_time_ts = time.time()
137     end_time_ts = start_time_ts
138     logger.info("vIMS functional test Start Time:'%s'" % (
139         datetime.datetime.fromtimestamp(start_time_ts).strftime(
140             '%Y-%m-%d %H:%M:%S')))
141
142     if dns_ip != "":
143         script = 'echo -e "nameserver ' + dns_ip + \
144             '\nnameserver 8.8.8.8\nnameserver 8.8.4.4" > /etc/resolv.conf; '
145         script += 'source /etc/profile.d/rvm.sh; '
146         script += 'cd ' + VIMS_TEST_DIR + '; '
147         script += 'rake test[' + \
148             CW_INPUTS["public_domain"] + '] SIGNUP_CODE="secret"'
149
150         cmd = "/bin/bash -c '" + script + "'"
151         output_file = "output.txt"
152         f = open(output_file, 'w+')
153         p = subprocess.call(cmd, shell=True, stdout=f,
154                             stderr=subprocess.STDOUT)
155         f.close()
156         end_time_ts = time.time()
157         duration = round(end_time_ts - start_time_ts, 1)
158         logger.info("vIMS functional test duration:'%s'" % duration)
159         f = open(output_file, 'r')
160         result = f.read()
161         if result != "" and logger:
162             logger.debug(result)
163
164         vims_test_result = ""
165         try:
166             logger.debug("Trying to load test results")
167             with open(VIMS_TEST_DIR + "temp.json") as f:
168                 vims_test_result = json.load(f)
169             f.close()
170         except:
171             logger.error("Unable to retrieve test results")
172
173         if vims_test_result != "":
174             if args.report:
175                 logger.debug("Push result into DB")
176                 logger.debug("Pushing results to DB....")
177                 git_version = functest_utils.get_git_branch(REPO_PATH)
178                 functest_utils.push_results_to_db(db_url=TEST_DB, case_name="vIMS",
179                                                   logger=logger, pod_name="opnfv-jump-2", git_version=git_version,
180                                                   payload={'orchestrator': {'duration': CFY_DEPLOYMENT_DURATION,
181                                                                             'result': ""},
182                                                            'vIMS': {'duration': CW_DEPLOYMENT_DURATION,
183                                                                     'result': ""},
184                                                            'sig_test': {'duration': duration,
185                                                                         'result': vims_test_result}})
186         try:
187             os.remove(VIMS_TEST_DIR + "temp.json")
188         except:
189             logger.error("Deleting file failed")
190
191
192 def main():
193
194     ################ GENERAL INITIALISATION ################
195
196     if not os.path.exists(VIMS_DATA_DIR):
197         os.makedirs(VIMS_DATA_DIR)
198
199     ks_creds = functest_utils.get_credentials("keystone")
200     nv_creds = functest_utils.get_credentials("nova")
201     nt_creds = functest_utils.get_credentials("neutron")
202
203     logger.info("Prepare OpenStack plateform (create tenant and user)")
204     keystone = ksclient.Client(**ks_creds)
205
206     user_id = functest_utils.get_user_id(keystone, ks_creds['username'])
207     if user_id == '':
208         logger.error("Error : Failed to get id of %s user" %
209                      ks_creds['username'])
210         exit(-1)
211
212     tenant_id = functest_utils.create_tenant(
213         keystone, TENANT_NAME, TENANT_DESCRIPTION)
214     if tenant_id == '':
215         logger.error("Error : Failed to create %s tenant" % TENANT_NAME)
216         exit(-1)
217
218     roles_name = ["admin", "Admin"]
219     role_id = ''
220     for role_name in roles_name:
221         if role_id == '':
222             role_id = functest_utils.get_role_id(keystone, role_name)
223
224     if role_id == '':
225         logger.error("Error : Failed to get id for %s role" % role_name)
226
227     if not functest_utils.add_role_user(keystone, user_id, role_id, tenant_id):
228         logger.error("Error : Failed to add %s on tenant" %
229                      ks_creds['username'])
230
231     user_id = functest_utils.create_user(
232         keystone, TENANT_NAME, TENANT_NAME, None, tenant_id)
233     if user_id == '':
234         logger.error("Error : Failed to create %s user" % TENANT_NAME)
235
236     logger.info("Update OpenStack creds informations")
237     ks_creds.update({
238         "username": TENANT_NAME,
239         "password": TENANT_NAME,
240         "tenant_name": TENANT_NAME,
241     })
242
243     nt_creds.update({
244         "tenant_name": TENANT_NAME,
245     })
246
247     nv_creds.update({
248         "project_id": TENANT_NAME,
249     })
250
251     logger.info("Upload some OS images if it doesn't exist")
252     glance_endpoint = keystone.service_catalog.url_for(service_type='image',
253                                                        endpoint_type='publicURL')
254     glance = glclient.Client(1, glance_endpoint, token=keystone.auth_token)
255
256     for img in IMAGES.keys():
257         image_name = IMAGES[img]['image_name']
258         image_url = IMAGES[img]['image_url']
259
260         image_id = functest_utils.get_image_id(glance, image_name)
261
262         if image_id == '':
263             logger.info("""%s image doesn't exist on glance repository.
264                             Try downloading this image and upload on glance !""" % image_name)
265             image_id = download_and_add_image_on_glance(
266                 glance, image_name, image_url)
267
268         if image_id == '':
269             logger.error(
270                 "Error : Failed to find or upload required OS image for this deployment")
271             exit(-1)
272
273     nova = nvclient.Client("2", **nv_creds)
274
275     logger.info("Update security group quota for this tenant")
276     neutron = ntclient.Client(**nt_creds)
277     if not functest_utils.update_sg_quota(neutron, tenant_id, 50, 100):
278         logger.error(
279             "Failed to update security group quota for tenant %s" % TENANT_NAME)
280         exit(-1)
281
282     logger.info("Update cinder quota for this tenant")
283     from cinderclient import client as cinderclient
284
285     creds_cinder = functest_utils.get_credentials("cinder")
286     cinder_client = cinderclient.Client('1', creds_cinder['username'],
287                                         creds_cinder['api_key'],
288                                         creds_cinder['project_id'],
289                                         creds_cinder['auth_url'],
290                                         service_type="volume")
291     if not functest_utils.update_cinder_quota(cinder_client, tenant_id, 20, 50, 1500):
292         logger.error("Failed to update cinder quota for tenant %s" %
293                      TENANT_NAME)
294         exit(-1)
295
296     ################ CLOUDIFY INITIALISATION ################
297
298     cfy = orchestrator(VIMS_DATA_DIR, CFY_INPUTS, logger)
299
300     cfy.set_credentials(username=ks_creds['username'], password=ks_creds[
301                         'password'], tenant_name=ks_creds['tenant_name'], auth_url=ks_creds['auth_url'])
302
303     logger.info("Collect flavor id for cloudify manager server")
304     nova = nvclient.Client("2", **nv_creds)
305
306     flavor_name = "m1.medium"
307     flavor_id = functest_utils.get_flavor_id(nova, flavor_name)
308     for requirement in CFY_MANAGER_REQUIERMENTS:
309         if requirement == 'ram_min':
310             flavor_id = functest_utils.get_flavor_id_by_ram_range(
311                 nova, CFY_MANAGER_REQUIERMENTS['ram_min'], 8196)
312
313     if flavor_id == '':
314         logger.error(
315             "Failed to find %s flavor. Try with ram range default requirement !" % flavor_name)
316         flavor_id = functest_utils.get_flavor_id_by_ram_range(nova, 4000, 8196)
317
318     if flavor_id == '':
319         logger.error(
320             "Failed to find required flavor for this deployment" % flavor_name)
321         exit(-1)
322
323     cfy.set_flavor_id(flavor_id)
324
325     image_name = "centos_7"
326     image_id = functest_utils.get_image_id(glance, image_name)
327     for requirement in CFY_MANAGER_REQUIERMENTS:
328         if requirement == 'os_image':
329             image_id = functest_utils.get_image_id(
330                 glance, CFY_MANAGER_REQUIERMENTS['os_image'])
331
332     if image_id == '':
333         logger.error(
334             "Error : Failed to find required OS image for cloudify manager")
335         exit(-1)
336
337     cfy.set_image_id(image_id)
338
339     ext_net = functest_utils.get_external_net(neutron)
340     if not ext_net:
341         logger.error("Failed to get external network")
342         exit(-1)
343
344     cfy.set_external_network_name(ext_net)
345
346     logger.info("Prepare virtualenv for cloudify-cli")
347     cmd = "chmod +x " + VIMS_DIR + "create_venv.sh"
348     functest_utils.execute_command(cmd, logger)
349     cmd = VIMS_DIR + "create_venv.sh " + VIMS_DATA_DIR
350     functest_utils.execute_command(cmd, logger)
351
352     cfy.download_manager_blueprint(
353         CFY_MANAGER_BLUEPRINT['url'], CFY_MANAGER_BLUEPRINT['branch'])
354
355     ################ CLOUDIFY DEPLOYMENT ################
356     start_time_ts = time.time()
357     end_time_ts = start_time_ts
358     logger.info("Cloudify deployment Start Time:'%s'" % (
359         datetime.datetime.fromtimestamp(start_time_ts).strftime(
360             '%Y-%m-%d %H:%M:%S')))
361
362     cfy.deploy_manager()
363
364     global CFY_DEPLOYMENT_DURATION
365     end_time_ts = time.time()
366     CFY_DEPLOYMENT_DURATION = round(end_time_ts - start_time_ts, 1)
367     logger.info("Cloudify deployment duration:'%s'" % CFY_DEPLOYMENT_DURATION)
368
369     ################ CLEARWATER INITIALISATION ################
370
371     cw = clearwater(CW_INPUTS, cfy, logger)
372
373     logger.info("Collect flavor id for all clearwater vm")
374     nova = nvclient.Client("2", **nv_creds)
375
376     flavor_name = "m1.small"
377     flavor_id = functest_utils.get_flavor_id(nova, flavor_name)
378     for requirement in CW_REQUIERMENTS:
379         if requirement == 'ram_min':
380             flavor_id = functest_utils.get_flavor_id_by_ram_range(
381                 nova, CW_REQUIERMENTS['ram_min'], 8196)
382
383     if flavor_id == '':
384         logger.error(
385             "Failed to find %s flavor. Try with ram range default requirement !" % flavor_name)
386         flavor_id = functest_utils.get_flavor_id_by_ram_range(nova, 4000, 8196)
387
388     if flavor_id == '':
389         logger.error(
390             "Failed to find required flavor for this deployment" % flavor_name)
391         exit(-1)
392
393     cw.set_flavor_id(flavor_id)
394
395     image_name = "ubuntu_14.04"
396     image_id = functest_utils.get_image_id(glance, image_name)
397     for requirement in CW_REQUIERMENTS:
398         if requirement == 'os_image':
399             image_id = functest_utils.get_image_id(
400                 glance, CW_REQUIERMENTS['os_image'])
401
402     if image_id == '':
403         logger.error(
404             "Error : Failed to find required OS image for cloudify manager")
405         exit(-1)
406
407     cw.set_image_id(image_id)
408
409     ext_net = functest_utils.get_external_net(neutron)
410     if not ext_net:
411         logger.error("Failed to get external network")
412         exit(-1)
413
414     cw.set_external_network_name(ext_net)
415
416     ################ CLEARWATER DEPLOYMENT ################
417
418     start_time_ts = time.time()
419     end_time_ts = start_time_ts
420     logger.info("vIMS VNF deployment Start Time:'%s'" % (
421         datetime.datetime.fromtimestamp(start_time_ts).strftime(
422             '%Y-%m-%d %H:%M:%S')))
423
424     cw.deploy_vnf(CW_BLUEPRINT)
425
426     global CW_DEPLOYMENT_DURATION
427     end_time_ts = time.time()
428     CW_DEPLOYMENT_DURATION = round(end_time_ts - start_time_ts, 1)
429     logger.info("vIMS VNF deployment duration:'%s'" % CW_DEPLOYMENT_DURATION)
430
431     ################ CLEARWATER TEST ################
432
433     test_clearwater()
434
435     ########### CLEARWATER UNDEPLOYMENT ############
436
437     cw.undeploy_vnf()
438
439     ############ CLOUDIFY UNDEPLOYMENT #############
440
441     cfy.undeploy_manager()
442
443     ############### GENERAL CLEANUP ################
444
445     ks_creds = functest_utils.get_credentials("keystone")
446
447     keystone = ksclient.Client(**ks_creds)
448
449     logger.info("Removing %s tenant .." % CFY_INPUTS['keystone_tenant_name'])
450     tenant_id = functest_utils.get_tenant_id(
451         keystone, CFY_INPUTS['keystone_tenant_name'])
452     if tenant_id == '':
453         logger.error("Error : Failed to get id of %s tenant" %
454                      CFY_INPUTS['keystone_tenant_name'])
455     else:
456         if not functest_utils.delete_tenant(keystone, tenant_id):
457             logger.error("Error : Failed to remove %s tenant" %
458                          CFY_INPUTS['keystone_tenant_name'])
459
460     logger.info("Removing %s user .." % CFY_INPUTS['keystone_username'])
461     user_id = functest_utils.get_user_id(
462         keystone, CFY_INPUTS['keystone_username'])
463     if user_id == '':
464         logger.error("Error : Failed to get id of %s user" %
465                      CFY_INPUTS['keystone_username'])
466     else:
467         if not functest_utils.delete_user(keystone, user_id):
468             logger.error("Error : Failed to remove %s user" %
469                          CFY_INPUTS['keystone_username'])
470
471
472 if __name__ == '__main__':
473     main()