da79c2c9aab929388cc53fa14679b35d7544fbf4
[functest.git] / testcases / functest_utils.py
1 #!/usr/bin/env python
2 #
3 # jose.lausuch@ericsson.com
4 # valentin.boucher@orange.com
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
11 import json
12 import os
13 import os.path
14 import re
15 import requests
16 import shutil
17 import socket
18 import subprocess
19 import sys
20 import urllib2
21 import yaml
22 from git import Repo
23
24
25 # ----------------------------------------------------------
26 #
27 #               OPENSTACK UTILS
28 #
29 # -----------------------------------------------------------
30
31
32 #*********************************************
33 #   CREDENTIALS
34 #*********************************************
35 def check_credentials():
36     """
37     Check if the OpenStack credentials (openrc) are sourced
38     """
39     env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD', 'OS_TENANT_NAME']
40     return all(map(lambda v: v in os.environ and os.environ[v], env_vars))
41
42 def get_credentials(service):
43     """Returns a creds dictionary filled with the following keys:
44     * username
45     * password/api_key (depending on the service)
46     * tenant_name/project_id (depending on the service)
47     * auth_url
48     :param service: a string indicating the name of the service
49                     requesting the credentials.
50     """
51     creds = {}
52     # Unfortunately, each of the OpenStack client will request slightly
53     # different entries in their credentials dict.
54     if service.lower() in ("nova", "cinder"):
55         password = "api_key"
56         tenant = "project_id"
57     else:
58         password = "password"
59         tenant = "tenant_name"
60
61     # The most common way to pass these info to the script is to do it through
62     # environment variables.
63     creds.update({
64         "username": os.environ.get('OS_USERNAME', "admin"),
65         password: os.environ.get("OS_PASSWORD", 'admin'),
66         "auth_url": os.environ.get("OS_AUTH_URL",
67                                    "http://192.168.20.71:5000/v2.0"),
68         tenant: os.environ.get("OS_TENANT_NAME", "admin"),
69     })
70     return creds
71
72
73
74 #*********************************************
75 #   NOVA
76 #*********************************************
77 def get_instances(nova_client):
78     try:
79         instances = nova_client.servers.list(search_opts={'all_tenants': 1})
80         return instances
81     except Exception, e:
82         print "Error [get_instances(nova_client)]:", e
83         return None
84
85
86 def get_instance_status(nova_client, instance):
87     try:
88         instance = nova_client.servers.get(instance.id)
89         return instance.status
90     except Exception, e:
91         print "Error [get_instance_status(nova_client, '%s')]:" % \
92             str(instance), e
93         return None
94
95
96 def get_instance_by_name(nova_client, instance_name):
97     try:
98         instance = nova_client.servers.find(name=instance_name)
99         return instance
100     except Exception, e:
101         print "Error [get_instance_by_name(nova_client, '%s')]:" % \
102             instance_name, e
103         return None
104
105
106 def get_flavor_id(nova_client, flavor_name):
107     flavors = nova_client.flavors.list(detailed=True)
108     id = ''
109     for f in flavors:
110         if f.name == flavor_name:
111             id = f.id
112             break
113     return id
114
115
116 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
117     flavors = nova_client.flavors.list(detailed=True)
118     id = ''
119     for f in flavors:
120         if min_ram <= f.ram and f.ram <= max_ram:
121             id = f.id
122             break
123     return id
124
125
126 def get_floating_ips(nova_client):
127     try:
128         floating_ips = nova_client.floating_ips.list()
129         return floating_ips
130     except Exception, e:
131         print "Error [get_floating_ips(nova_client)]:", e
132         return None
133
134
135 def create_flavor(nova_client, flavor_name, ram, disk, vcpus):
136     try:
137         flavor = nova_client.flavors.create(flavor_name,ram,vcpus,disk)
138     except Exception, e:
139         print "Error [create_flavor(nova_client, '%s', '%s', '%s', "\
140             "'%s')]:" %(flavor_name,ram, disk, vcpus), e
141         return None
142     return flavor.id
143
144
145 def create_floating_ip(neutron_client):
146     extnet_id = get_external_net_id(neutron_client)
147     props = {'floating_network_id': extnet_id}
148     try:
149         ip_json = neutron_client.create_floatingip({'floatingip': props})
150         floating_ip = ip_json['floatingip']['floating_ip_address']
151     except Exception, e:
152         print "Error [create_floating_ip(neutron_client)]:", e
153         return None
154     return floating_ip
155
156
157 def add_floating_ip(nova_client, server_id, floatingip_id):
158     try:
159         nova_client.servers.add_floating_ip(server_id,floatingip_id)
160         return True
161     except Exception, e:
162         print "Error [add_floating_ip(nova_client, '%s', '%s')]:" % \
163             (server_id, floatingip_id), e
164         return False
165
166
167 def delete_instance(nova_client, instance_id):
168     try:
169         nova_client.servers.force_delete(instance_id)
170         return True
171     except Exception, e:
172         print "Error [delete_instance(nova_client, '%s')]:" % instance_id, e
173         return False
174
175
176 def delete_floating_ip(nova_client, floatingip_id):
177     try:
178         nova_client.floating_ips.delete(floatingip_id)
179         return True
180     except Exception, e:
181         print "Error [delete_floating_ip(nova_client, '%s')]:" % floatingip_id, e
182         return False
183
184
185
186
187 #*********************************************
188 #   NEUTRON
189 #*********************************************
190 def get_network_list(neutron_client):
191     network_list = neutron_client.list_networks()['networks']
192     if len(network_list) == 0:
193         return None
194     else:
195         return network_list
196
197
198 def get_router_list(neutron_client):
199     router_list = neutron_client.list_routers()['routers']
200     if len(router_list) == 0:
201         return None
202     else:
203         return router_list
204
205
206 def get_port_list(neutron_client):
207     port_list = neutron_client.list_ports()['ports']
208     if len(port_list) == 0:
209         return None
210     else:
211         return port_list
212
213
214 def get_network_id(neutron_client, network_name):
215     networks = neutron_client.list_networks()['networks']
216     id = ''
217     for n in networks:
218         if n['name'] == network_name:
219             id = n['id']
220             break
221     return id
222
223
224 def get_private_net(neutron_client):
225     # Checks if there is an existing shared private network
226     networks = neutron_client.list_networks()['networks']
227     if len(networks) == 0:
228         return None
229     for net in networks:
230         if (net['router:external'] is False) and (net['shared'] is True):
231             return net
232     return None
233
234
235 def get_external_net(neutron_client):
236     for network in neutron_client.list_networks()['networks']:
237         if network['router:external']:
238             return network['name']
239     return False
240
241
242 def get_external_net_id(neutron_client):
243     for network in neutron_client.list_networks()['networks']:
244         if network['router:external']:
245             return network['id']
246     return False
247
248
249 def check_neutron_net(neutron_client, net_name):
250     for network in neutron_client.list_networks()['networks']:
251         if network['name'] == net_name:
252             for subnet in network['subnets']:
253                 return True
254     return False
255
256
257 def create_neutron_net(neutron_client, name):
258     json_body = {'network': {'name': name,
259                              'admin_state_up': True}}
260     try:
261         network = neutron_client.create_network(body=json_body)
262         network_dict = network['network']
263         return network_dict['id']
264     except Exception, e:
265         print "Error [create_neutron_net(neutron_client, '%s')]:" % name, e
266         return False
267
268
269 def create_neutron_subnet(neutron_client, name, cidr, net_id):
270     json_body = {'subnets': [{'name': name, 'cidr': cidr,
271                               'ip_version': 4, 'network_id': net_id}]}
272     try:
273         subnet = neutron_client.create_subnet(body=json_body)
274         return subnet['subnets'][0]['id']
275     except Exception, e:
276         print "Error [create_neutron_subnet(neutron_client, '%s', '%s', "\
277             "'%s')]:" %(name,cidr, net_id), e
278         return False
279
280
281 def create_neutron_router(neutron_client, name):
282     json_body = {'router': {'name': name, 'admin_state_up': True}}
283     try:
284         router = neutron_client.create_router(json_body)
285         return router['router']['id']
286     except Exception, e:
287         print "Error [create_neutron_router(neutron_client, '%s')]:" % name, e
288         return False
289
290
291 def create_neutron_port(neutron_client, name, network_id, ip):
292     json_body = {'port': {
293                  'admin_state_up': True,
294                  'name': name,
295                  'network_id': network_id,
296                  'fixed_ips': [{"ip_address": ip}]
297                  }}
298     try:
299         port = neutron_client.create_port(body=json_body)
300         return port['port']['id']
301     except Exception, e:
302         print "Error [create_neutron_port(neutron_client, '%s', '%s', "\
303             "'%s')]:" %(name,network_id, ip), e
304         return False
305
306
307 def update_neutron_net(neutron_client, network_id, shared=False):
308     json_body = {'network': {'shared': shared}}
309     try:
310         neutron_client.update_network(network_id, body=json_body)
311         return True
312     except Exception, e:
313         print "Error [update_neutron_net(neutron_client, '%s', '%s')]:" % \
314             (network_id,str(shared)), e
315         return False
316
317
318 def update_neutron_port(neutron_client, port_id, device_owner):
319     json_body = {'port': {
320                  'device_owner': device_owner,
321                  }}
322     try:
323         port = neutron_client.update_port(port=port_id,
324                                           body=json_body)
325         return port['port']['id']
326     except Exception, e:
327         print "Error [update_neutron_port(neutron_client, '%s', '%s')]:" % \
328             (port_id,device_owner), e
329         return False
330
331
332 def add_interface_router(neutron_client, router_id, subnet_id):
333     json_body = {"subnet_id": subnet_id}
334     try:
335         neutron_client.add_interface_router(router=router_id, body=json_body)
336         return True
337     except Exception, e:
338         print "Error [add_interface_router(neutron_client, '%s', '%s')]:" % \
339             (router_id,subnet_id), e
340         return False
341
342 def add_gateway_router(neutron_client, router_id):
343     ext_net_id = get_external_net_id(neutron_client)
344     router_dict = {'network_id': ext_net_id}
345     try:
346         neutron_client.add_gateway_router(router_id,router_dict)
347         return True
348     except Exception, e:
349         print "Error [add_gateway_router(neutron_client, '%s')]:" % router_id, e
350         return False
351
352
353 def delete_neutron_net(neutron_client, network_id):
354     try:
355         neutron_client.delete_network(network_id)
356         return True
357     except Exception, e:
358         print "Error [delete_neutron_net(neutron_client, '%s')]:" % network_id, e
359         return False
360
361
362 def delete_neutron_subnet(neutron_client, subnet_id):
363     try:
364         neutron_client.delete_subnet(subnet_id)
365         return True
366     except Exception, e:
367         print "Error [delete_neutron_subnet(neutron_client, '%s')]:" % subnet_id, e
368         return False
369
370
371 def delete_neutron_router(neutron_client, router_id):
372     json_body = {'router': {'id': router_id}}
373     try:
374         neutron_client.delete_router(router=router_id)
375         return True
376     except Exception, e:
377         print "Error [delete_neutron_router(neutron_client, '%s')]:" % \
378             router_id, e
379         return False
380
381
382 def delete_neutron_port(neutron_client, port_id):
383     try:
384         neutron_client.delete_port(port_id)
385         return True
386     except Exception, e:
387         print "Error [delete_neutron_port(neutron_client, '%s')]:" % port_id, e
388         return False
389
390
391 def remove_interface_router(neutron_client, router_id, subnet_id):
392     json_body = {"subnet_id": subnet_id}
393     try:
394         neutron_client.remove_interface_router(router=router_id,
395                                                body=json_body)
396         return True
397     except Exception, e:
398         print "Error [remove_interface_router(neutron_client, '%s', '%s')]:" % \
399             (router_id,subnet_id), e
400         return False
401
402
403 def remove_gateway_router(neutron_client, router_id):
404     try:
405         neutron_client.remove_gateway_router(router_id)
406         return True
407     except Exception, e:
408         print "Error [remove_gateway_router(neutron_client, '%s')]:" % router_id, e
409         return False
410
411
412
413 #*********************************************
414 #   SEC GROUPS
415 #*********************************************
416 def get_security_groups(neutron_client):
417     try:
418         security_groups = neutron_client.list_security_groups()[
419             'security_groups']
420         return security_groups
421     except Exception, e:
422         print "Error [get_security_groups(neutron_client)]:", e
423         return None
424
425
426 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
427     json_body = {"quota": {
428         "security_group": sg_quota,
429         "security_group_rule": sg_rule_quota
430     }}
431
432     try:
433         quota = neutron_client.update_quota(tenant_id=tenant_id,
434                                             body=json_body)
435         return True
436     except Exception, e:
437         print "Error [update_sg_quota(neutron_client, '%s', '%s', "\
438             "'%s')]:" %(tenant_id, sg_quota, sg_rule_quota), e
439         return False
440
441
442 def delete_security_group(neutron_client, secgroup_id):
443     try:
444         neutron_client.delete_security_group(secgroup_id)
445         return True
446     except Exception, e:
447         print "Error [delete_security_group(neutron_client, '%s')]:" % secgroup_id, e
448         return False
449
450
451
452 #*********************************************
453 #   GLANCE
454 #*********************************************
455 def get_images(nova_client):
456     try:
457         images = nova_client.images.list()
458         return images
459     except Exception, e:
460         print "Error [get_images]:", e
461         return None
462
463
464 def get_image_id(glance_client, image_name):
465     images = glance_client.images.list()
466     id = ''
467     for i in images:
468         if i.name == image_name:
469             id = i.id
470             break
471     return id
472
473
474 def create_glance_image(glance_client, image_name, file_path, public=True):
475     if not os.path.isfile(file_path):
476         print "Error: file " + file_path + " does not exist."
477         return False
478     try:
479         with open(file_path) as fimage:
480             image = glance_client.images.create(name=image_name,
481                                                 is_public=public,
482                                                 disk_format="qcow2",
483                                                 container_format="bare",
484                                                 data=fimage)
485         return image.id
486     except Exception, e:
487         print "Error [create_glance_image(glance_client, '%s', '%s', "\
488             "'%s')]:" %(image_name, file_path, str(public)), e
489         return False
490
491
492 def delete_glance_image(nova_client, image_id):
493     try:
494         nova_client.images.delete(image_id)
495         return True
496     except Exception, e:
497         print "Error [delete_glance_image(nova_client, '%s')]:" % image_id, e
498         return False
499
500
501
502 #*********************************************
503 #   CINDER
504 #*********************************************
505 def get_volumes(cinder_client):
506     try:
507         volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
508         return volumes
509     except Exception, e:
510         print "Error [get_volumes(cinder_client)]:", e
511         return None
512
513
514 def list_volume_types(cinder_client, public=True, private=True):
515     try:
516         volume_types = cinder_client.volume_types.list()
517         if not public:
518             volume_types = [vt for vt in volume_types if not vt.is_public]
519         if not private:
520             volume_types = [vt for vt in volume_types if vt.is_public]
521         return volume_types
522     except Exception, e:
523         print "Error [list_volume_types(cinder_client)]:", e
524         return None
525
526
527 def create_volume_type(cinder_client, name):
528     try:
529         volume_type = cinder_client.volume_types.create(name)
530         return volume_type
531     except Exception, e:
532         print "Error [create_volume_type(cinder_client, '%s')]:" % name, e
533         return None
534
535
536 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
537                         snapshots_quota, gigabytes_quota):
538     quotas_values = {"volumes": vols_quota,
539                      "snapshots": snapshots_quota,
540                      "gigabytes": gigabytes_quota}
541
542     try:
543         quotas_default = cinder_client.quotas.update(tenant_id,
544                                                       **quotas_values)
545         return True
546     except Exception, e:
547         print "Error [update_cinder_quota(cinder_client, '%s', '%s', '%s'" \
548             "'%s')]:" %(tenant_id, vols_quota, snapshots_quota, gigabytes_quota), e
549         return False
550
551
552 def delete_volume(cinder_client, volume_id, forced=False):
553     try:
554         if forced:
555             try:
556                 cinder_client.volumes.detach(volume_id)
557             except:
558                 print "Error:", sys.exc_info()[0]
559             cinder_client.volumes.force_delete(volume_id)
560         else:
561             cinder_client.volumes.delete(volume_id)
562         return True
563     except Exception, e:
564         print "Error [delete_volume(cinder_client, '%s', '%s')]:" % \
565             (volume_id, str(forced)), e
566         return False
567
568
569 def delete_volume_type(cinder_client, volume_type):
570     try:
571         cinder_client.volume_types.delete(volume_type)
572         return True
573     except Exception, e:
574         print "Error [delete_volume_type(cinder_client, '%s')]:" % volume_type, e
575         return False
576
577
578
579 #*********************************************
580 #   KEYSTONE
581 #*********************************************
582 def get_tenants(keystone_client):
583     try:
584         tenants = keystone_client.tenants.list()
585         return tenants
586     except Exception, e:
587         print "Error [get_tenants(keystone_client)]:", e
588         return None
589
590
591 def get_users(keystone_client):
592     try:
593         users = keystone_client.users.list()
594         return users
595     except Exception, e:
596         print "Error [get_users(keystone_client)]:", e
597         return None
598
599
600 def get_tenant_id(keystone_client, tenant_name):
601     tenants = keystone_client.tenants.list()
602     id = ''
603     for t in tenants:
604         if t.name == tenant_name:
605             id = t.id
606             break
607     return id
608
609
610 def get_user_id(keystone_client, user_name):
611     users = keystone_client.users.list()
612     id = ''
613     for u in users:
614         if u.name == user_name:
615             id = u.id
616             break
617     return id
618
619
620 def get_role_id(keystone_client, role_name):
621     roles = keystone_client.roles.list()
622     id = ''
623     for r in roles:
624         if r.name == role_name:
625             id = r.id
626             break
627     return id
628
629
630 def create_tenant(keystone_client, tenant_name, tenant_description):
631     try:
632         tenant = keystone_client.tenants.create(tenant_name,
633                                                 tenant_description,
634                                                 enabled=True)
635         return tenant.id
636     except Exception, e:
637         print "Error [create_tenant(cinder_client, '%s', '%s')]:" % \
638             (tenant_name, tenant_description), e
639         return False
640
641
642 def create_user(keystone_client, user_name, user_password,
643                 user_email, tenant_id):
644     try:
645         user = keystone_client.users.create(user_name, user_password,
646                                             user_email, tenant_id,
647                                             enabled=True)
648         return user.id
649     except Exception, e:
650         print "Error [create_user(keystone_client, '%s', '%s', '%s'" \
651             "'%s')]:" %(user_name, user_password, user_email, tenant_id), e
652         return False
653
654
655 def add_role_user(keystone_client, user_id, role_id, tenant_id):
656     try:
657         keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
658         return True
659     except Exception, e:
660         print "Error [add_role_user(keystone_client, '%s', '%s'" \
661             "'%s')]:" %(user_id, role_id, tenant_id), e
662         return False
663
664
665 def delete_tenant(keystone_client, tenant_id):
666     try:
667         tenant = keystone_client.tenants.delete(tenant_id)
668         return True
669     except Exception, e:
670         print "Error [delete_tenant(keystone_client, '%s')]:" % tenant_id, e
671         return False
672
673
674 def delete_user(keystone_client, user_id):
675     try:
676         tenant = keystone_client.users.delete(user_id)
677         return True
678     except Exception, e:
679         print "Error [delete_user(keystone_client, '%s')]:" % user_id, e
680         return False
681
682
683
684
685
686
687
688 # ----------------------------------------------------------
689 #
690 #               INTERNET UTILS
691 #
692 # -----------------------------------------------------------
693 def check_internet_connectivity(url='http://www.opnfv.org/'):
694     """
695     Check if there is access to the internet
696     """
697     try:
698         urllib2.urlopen(url, timeout=5)
699         return True
700     except urllib2.URLError:
701         return False
702
703
704 def download_url(url, dest_path):
705     """
706     Download a file to a destination path given a URL
707     """
708     name = url.rsplit('/')[-1]
709     dest = dest_path + "/" + name
710     try:
711         response = urllib2.urlopen(url)
712     except (urllib2.HTTPError, urllib2.URLError):
713         return False
714
715     with open(dest, 'wb') as f:
716         shutil.copyfileobj(response, f)
717     return True
718
719
720
721
722 # ----------------------------------------------------------
723 #
724 #               CI UTILS
725 #
726 # -----------------------------------------------------------
727 def get_git_branch(repo_path):
728     """
729     Get git branch name
730     """
731     repo = Repo(repo_path)
732     branch = repo.active_branch
733     return branch.name
734
735
736 def get_installer_type(logger=None):
737     """
738     Get installer type (fuel, apex, joid, compass)
739     """
740     try:
741         installer = os.environ['INSTALLER_TYPE']
742     except KeyError:
743         if logger:
744             logger.error("Impossible to retrieve the installer type")
745         installer = "Unknown_installer"
746
747     return installer
748
749
750 def get_scenario(logger=None):
751     """
752     Get scenario
753     """
754     try:
755         scenario = os.environ['DEPLOY_SCENARIO']
756     except KeyError:
757         if logger:
758             logger.error("Impossible to retrieve the scenario")
759         scenario = "Unknown_scenario"
760
761     return scenario
762
763
764 def get_pod_name(logger=None):
765     """
766     Get PoD Name from env variable NODE_NAME
767     """
768     try:
769         return os.environ['NODE_NAME']
770     except KeyError:
771         if logger:
772             logger.error(
773                 "Unable to retrieve the POD name from environment.Using pod name 'unknown-pod'")
774         return "unknown-pod"
775
776
777 def push_results_to_db(db_url, case_name, logger, pod_name,
778                        version, payload):
779     """
780     POST results to the Result target DB
781     """
782     url = db_url + "/results"
783     installer = get_installer_type(logger)
784     params = {"project_name": "functest", "case_name": case_name,
785               "pod_name": pod_name, "installer": installer,
786               "version": version, "details": payload}
787
788     headers = {'Content-Type': 'application/json'}
789     try:
790         r = requests.post(url, data=json.dumps(params), headers=headers)
791         if logger:
792             logger.debug(r)
793         return True
794     except Exception, e:
795         print "Error [push_results_to_db('%s', '%s', '%s', '%s', '%s')]:" \
796             % (db_url, case_name, pod_name, version, payload), e
797         return False
798
799
800 def get_resolvconf_ns():
801     """
802     Get nameservers from current resolv.conf
803     """
804     nameservers = []
805     rconf = open("/etc/resolv.conf", "r")
806     line = rconf.readline()
807     while line:
808         ip = re.search(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b", line)
809         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
810         if ip:
811             result = sock.connect_ex((ip.group(),53))
812             if result == 0:
813                 nameservers.append(ip.group())
814         line = rconf.readline()
815     return nameservers
816
817
818 def getTestEnv(test, functest_yaml):
819     """
820     Get the config of the testcase based on functest_config.yaml
821       2 options
822         - test = test project e.g; ovno
823         - test = testcase e.g. functest/odl
824        look for the / to see if it is a test project or a testcase
825     """
826     try:
827         TEST_ENV = functest_yaml.get("test-dependencies")
828
829         if test.find("/") < 0:
830             config_test = TEST_ENV[test]
831         else:
832             test_split = test.split("/")
833             testproject = test_split[0]
834             testcase = test_split[1]
835             config_test = TEST_ENV[testproject][testcase]
836     except KeyError:
837         # if not defined in dependencies => no dependencies
838         config_test = ""
839     except Exception, e:
840         print "Error [getTestEnv]:", e
841
842     return config_test
843
844
845 def get_ci_envvars():
846     """
847     Get the CI env variables
848     """
849     ci_env_var = {
850         "installer": os.environ.get('INSTALLER_TYPE'),
851         "scenario": os.environ.get('DEPLOY_SCENARIO')}
852     return ci_env_var
853
854
855 def isTestRunnable(test, functest_yaml):
856     """
857     Return True if the test is runnable in the current scenario
858     """
859     # By default we assume that all the tests are always runnable...
860     is_runnable = True
861     # Retrieve CI environment
862     ci_env = get_ci_envvars()
863     # Retrieve test environement from config file
864     test_env = getTestEnv(test, functest_yaml)
865
866     # if test_env not empty => dependencies to be checked
867     if test_env is not None and len(test_env) > 0:
868         # possible criteria = ["installer", "scenario"]
869         # consider test criteria from config file
870         # compare towards CI env through CI en variable
871         for criteria in test_env:
872             if re.search(test_env[criteria], ci_env[criteria]) is None:
873                 # print "Test "+ test + " cannot be run on the environment"
874                 is_runnable = False
875     return is_runnable
876
877
878 def generateTestcaseList(functest_yaml):
879     """
880     Generate a test file with the runnable test according to
881     the current scenario
882     """
883     test_list = ""
884     # get testcases
885     testcase_list = functest_yaml.get("test-dependencies")
886     projects = testcase_list.keys()
887
888     for project in projects:
889         testcases = testcase_list[project]
890         # 1 or 2 levels for testcases project[/case]l
891         # if only project name without controller or scenario
892         # => shall be runnable on any controller/scenario
893         if testcases is None:
894             test_list += project + " "
895         else:
896             for testcase in testcases:
897                 if testcase == "installer" or testcase == "scenario":
898                     # project (1 level)
899                     if isTestRunnable(project, functest_yaml):
900                         test_list += project + " "
901                 else:
902                     # project/testcase (2 levels)
903                     thetest = project + "/" + testcase
904                     if isTestRunnable(thetest, functest_yaml):
905                         test_list += testcase + " "
906
907     # sort the list to execute the test in the right order
908     test_order_list = functest_yaml.get("test_exec_priority")
909     test_sorted_list = ""
910     for test in test_order_list:
911         if test_order_list[test] in test_list:
912             test_sorted_list += test_order_list[test] + " "
913
914     # create a file that could be consumed by run-test.sh
915     # this method is used only for CI
916     # so it can be run only in container
917     # reuse default conf directory to store the list of runnable tests
918     file = open("/home/opnfv/functest/conf/testcase-list.txt", 'w')
919     file.write(test_sorted_list)
920     file.close()
921
922     return test_sorted_list
923
924
925 def execute_command(cmd, logger=None, exit_on_error=True):
926     """
927     Execute Linux command
928         prints stdout to a file and depending on if there
929         is a logger defined, it will print it or not.
930     """
931     if logger:
932         logger.debug('Executing command : {}'.format(cmd))
933     output_file = "output.txt"
934     f = open(output_file, 'w+')
935     p = subprocess.call(cmd, shell=True, stdout=f, stderr=subprocess.STDOUT)
936     f.close()
937     f = open(output_file, 'r')
938     result = f.read()
939     if result != "" and logger:
940         logger.debug(result)
941     if p == 0:
942         return True
943     else:
944         if logger:
945             logger.error("Error when executing command %s" % cmd)
946         if exit_on_error:
947             exit(-1)
948         return False