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