2ae2842d4facd13b880d8e6a9ac5e9fc343a472b
[functest.git] / utils / openstack_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 os
12 import os.path
13 import subprocess
14 import sys
15
16 # ----------------------------------------------------------
17 #
18 #               OPENSTACK UTILS
19 #
20 # -----------------------------------------------------------
21
22
23 # *********************************************
24 #   CREDENTIALS
25 # *********************************************
26 def check_credentials():
27     """
28     Check if the OpenStack credentials (openrc) are sourced
29     """
30     env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD', 'OS_TENANT_NAME']
31     return all(map(lambda v: v in os.environ and os.environ[v], env_vars))
32
33
34 def get_credentials(service):
35     """Returns a creds dictionary filled with the following keys:
36     * username
37     * password/api_key (depending on the service)
38     * tenant_name/project_id (depending on the service)
39     * auth_url
40     :param service: a string indicating the name of the service
41                     requesting the credentials.
42     """
43     creds = {}
44     # Unfortunately, each of the OpenStack client will request slightly
45     # different entries in their credentials dict.
46     if service.lower() in ("nova", "cinder"):
47         password = "api_key"
48         tenant = "project_id"
49     else:
50         password = "password"
51         tenant = "tenant_name"
52
53     # The most common way to pass these info to the script is to do it through
54     # environment variables.
55     creds.update({
56         "username": os.environ.get('OS_USERNAME', "admin"),
57         password: os.environ.get("OS_PASSWORD", 'admin'),
58         "auth_url": os.environ.get("OS_AUTH_URL",
59                                    "http://192.168.20.71:5000/v2.0"),
60         tenant: os.environ.get("OS_TENANT_NAME", "admin"),
61     })
62     cacert = os.environ.get("OS_CACERT")
63     if cacert is not None:
64         # each openstack client uses differnt kwargs for this
65         creds.update({"cacert": cacert,
66                       "ca_cert": cacert,
67                       "https_ca_cert": cacert,
68                       "https_cacert": cacert,
69                       "ca_file": cacert})
70         creds.update({"insecure": "True", "https_insecure": "True"})
71         if not os.path.isfile(cacert):
72             print ("WARNING: The 'OS_CACERT' environment variable is " +
73                    "set to %s but the file does not exist." % cacert)
74     return creds
75
76
77 def source_credentials(rc_file):
78     pipe = subprocess.Popen(". %s; env" % rc_file, stdout=subprocess.PIPE,
79                             shell=True)
80     output = pipe.communicate()[0]
81     env = dict((line.split("=", 1) for line in output.splitlines()))
82     os.environ.update(env)
83     return env
84
85
86 # *********************************************
87 #   NOVA
88 # *********************************************
89 def get_instances(nova_client):
90     try:
91         instances = nova_client.servers.list(search_opts={'all_tenants': 1})
92         return instances
93     except Exception, e:
94         print "Error [get_instances(nova_client)]:", e
95         return None
96
97
98 def get_instance_status(nova_client, instance):
99     try:
100         instance = nova_client.servers.get(instance.id)
101         return instance.status
102     except:
103         # print ("Error [get_instance_status(nova_client, '%s')]:" %
104         #        str(instance), e)
105         return None
106
107
108 def get_instance_by_name(nova_client, instance_name):
109     try:
110         instance = nova_client.servers.find(name=instance_name)
111         return instance
112     except Exception, e:
113         print ("Error [get_instance_by_name(nova_client, '%s')]:" %
114                instance_name, e)
115         return None
116
117
118 def get_flavor_id(nova_client, flavor_name):
119     flavors = nova_client.flavors.list(detailed=True)
120     id = ''
121     for f in flavors:
122         if f.name == flavor_name:
123             id = f.id
124             break
125     return id
126
127
128 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
129     flavors = nova_client.flavors.list(detailed=True)
130     id = ''
131     for f in flavors:
132         if min_ram <= f.ram and f.ram <= max_ram:
133             id = f.id
134             break
135     return id
136
137
138 def get_floating_ips(nova_client):
139     try:
140         floating_ips = nova_client.floating_ips.list()
141         return floating_ips
142     except Exception, e:
143         print "Error [get_floating_ips(nova_client)]:", e
144         return None
145
146
147 def create_flavor(nova_client, flavor_name, ram, disk, vcpus):
148     try:
149         flavor = nova_client.flavors.create(flavor_name, ram, vcpus, disk)
150     except Exception, e:
151         print ("Error [create_flavor(nova_client, '%s', '%s', '%s', "
152                "'%s')]:" % (flavor_name, ram, disk, vcpus), e)
153         return None
154     return flavor.id
155
156
157 def create_floating_ip(neutron_client):
158     extnet_id = get_external_net_id(neutron_client)
159     props = {'floating_network_id': extnet_id}
160     try:
161         ip_json = neutron_client.create_floatingip({'floatingip': props})
162         fip_addr = ip_json['floatingip']['floating_ip_address']
163         fip_id = ip_json['floatingip']['id']
164     except Exception, e:
165         print "Error [create_floating_ip(neutron_client)]:", e
166         return None
167     return {'fip_addr': fip_addr, 'fip_id': fip_id}
168
169
170 def add_floating_ip(nova_client, server_id, floatingip_id):
171     try:
172         nova_client.servers.add_floating_ip(server_id, floatingip_id)
173         return True
174     except Exception, e:
175         print ("Error [add_floating_ip(nova_client, '%s', '%s')]:" %
176                (server_id, floatingip_id), e)
177         return False
178
179
180 def delete_instance(nova_client, instance_id):
181     try:
182         nova_client.servers.force_delete(instance_id)
183         return True
184     except Exception, e:
185         print "Error [delete_instance(nova_client, '%s')]:" % instance_id, e
186         return False
187
188
189 def delete_floating_ip(nova_client, floatingip_id):
190     try:
191         nova_client.floating_ips.delete(floatingip_id)
192         return True
193     except Exception, e:
194         print ("Error [delete_floating_ip(nova_client, '%s')]:" %
195                floatingip_id, e)
196         return False
197
198
199 # *********************************************
200 #   NEUTRON
201 # *********************************************
202 def get_network_list(neutron_client):
203     network_list = neutron_client.list_networks()['networks']
204     if len(network_list) == 0:
205         return None
206     else:
207         return network_list
208
209
210 def get_router_list(neutron_client):
211     router_list = neutron_client.list_routers()['routers']
212     if len(router_list) == 0:
213         return None
214     else:
215         return router_list
216
217
218 def get_port_list(neutron_client):
219     port_list = neutron_client.list_ports()['ports']
220     if len(port_list) == 0:
221         return None
222     else:
223         return port_list
224
225
226 def get_network_id(neutron_client, network_name):
227     networks = neutron_client.list_networks()['networks']
228     id = ''
229     for n in networks:
230         if n['name'] == network_name:
231             id = n['id']
232             break
233     return id
234
235
236 def get_subnet_id(neutron_client, subnet_name):
237     subnets = neutron_client.list_subnets()['subnets']
238     id = ''
239     for s in subnets:
240         if s['name'] == subnet_name:
241             id = s['id']
242             break
243     return id
244
245
246 def get_router_id(neutron_client, router_name):
247     routers = neutron_client.list_routers()['routers']
248     id = ''
249     for r in routers:
250         if r['name'] == router_name:
251             id = r['id']
252             break
253     return id
254
255
256 def get_private_net(neutron_client):
257     # Checks if there is an existing shared private network
258     networks = neutron_client.list_networks()['networks']
259     if len(networks) == 0:
260         return None
261     for net in networks:
262         if (net['router:external'] is False) and (net['shared'] is True):
263             return net
264     return None
265
266
267 def get_external_net(neutron_client):
268     for network in neutron_client.list_networks()['networks']:
269         if network['router:external']:
270             return network['name']
271     return False
272
273
274 def get_external_net_id(neutron_client):
275     for network in neutron_client.list_networks()['networks']:
276         if network['router:external']:
277             return network['id']
278     return False
279
280
281 def check_neutron_net(neutron_client, net_name):
282     for network in neutron_client.list_networks()['networks']:
283         if network['name'] == net_name:
284             for subnet in network['subnets']:
285                 return True
286     return False
287
288
289 def create_neutron_net(neutron_client, name):
290     json_body = {'network': {'name': name,
291                              'admin_state_up': True}}
292     try:
293         network = neutron_client.create_network(body=json_body)
294         network_dict = network['network']
295         return network_dict['id']
296     except Exception, e:
297         print "Error [create_neutron_net(neutron_client, '%s')]:" % name, e
298         return False
299
300
301 def create_neutron_subnet(neutron_client, name, cidr, net_id):
302     json_body = {'subnets': [{'name': name, 'cidr': cidr,
303                               'ip_version': 4, 'network_id': net_id}]}
304     try:
305         subnet = neutron_client.create_subnet(body=json_body)
306         return subnet['subnets'][0]['id']
307     except Exception, e:
308         print ("Error [create_neutron_subnet(neutron_client, '%s', '%s', "
309                "'%s')]:" % (name, cidr, net_id), e)
310         return False
311
312
313 def create_neutron_router(neutron_client, name):
314     json_body = {'router': {'name': name, 'admin_state_up': True}}
315     try:
316         router = neutron_client.create_router(json_body)
317         return router['router']['id']
318     except Exception, e:
319         print "Error [create_neutron_router(neutron_client, '%s')]:" % name, e
320         return False
321
322
323 def create_neutron_port(neutron_client, name, network_id, ip):
324     json_body = {'port': {
325                  'admin_state_up': True,
326                  'name': name,
327                  'network_id': network_id,
328                  'fixed_ips': [{"ip_address": ip}]
329                  }}
330     try:
331         port = neutron_client.create_port(body=json_body)
332         return port['port']['id']
333     except Exception, e:
334         print ("Error [create_neutron_port(neutron_client, '%s', '%s', "
335                "'%s')]:" % (name, network_id, ip), e)
336         return False
337
338
339 def update_neutron_net(neutron_client, network_id, shared=False):
340     json_body = {'network': {'shared': shared}}
341     try:
342         neutron_client.update_network(network_id, body=json_body)
343         return True
344     except Exception, e:
345         print ("Error [update_neutron_net(neutron_client, '%s', '%s')]:" %
346                (network_id, str(shared)), e)
347         return False
348
349
350 def update_neutron_port(neutron_client, port_id, device_owner):
351     json_body = {'port': {
352                  'device_owner': device_owner,
353                  }}
354     try:
355         port = neutron_client.update_port(port=port_id,
356                                           body=json_body)
357         return port['port']['id']
358     except Exception, e:
359         print ("Error [update_neutron_port(neutron_client, '%s', '%s')]:" %
360                (port_id, device_owner), e)
361         return False
362
363
364 def add_interface_router(neutron_client, router_id, subnet_id):
365     json_body = {"subnet_id": subnet_id}
366     try:
367         neutron_client.add_interface_router(router=router_id, body=json_body)
368         return True
369     except Exception, e:
370         print ("Error [add_interface_router(neutron_client, '%s', '%s')]:" %
371                (router_id, subnet_id), e)
372         return False
373
374
375 def add_gateway_router(neutron_client, router_id):
376     ext_net_id = get_external_net_id(neutron_client)
377     router_dict = {'network_id': ext_net_id}
378     try:
379         neutron_client.add_gateway_router(router_id, router_dict)
380         return True
381     except Exception, e:
382         print ("Error [add_gateway_router(neutron_client, '%s')]:" %
383                router_id, e)
384         return False
385
386
387 def delete_neutron_net(neutron_client, network_id):
388     try:
389         neutron_client.delete_network(network_id)
390         return True
391     except Exception, e:
392         print ("Error [delete_neutron_net(neutron_client, '%s')]:" %
393                network_id, e)
394         return False
395
396
397 def delete_neutron_subnet(neutron_client, subnet_id):
398     try:
399         neutron_client.delete_subnet(subnet_id)
400         return True
401     except Exception, e:
402         print ("Error [delete_neutron_subnet(neutron_client, '%s')]:" %
403                subnet_id, e)
404         return False
405
406
407 def delete_neutron_router(neutron_client, router_id):
408     try:
409         neutron_client.delete_router(router=router_id)
410         return True
411     except Exception, e:
412         print ("Error [delete_neutron_router(neutron_client, '%s')]:" %
413                router_id, e)
414         return False
415
416
417 def delete_neutron_port(neutron_client, port_id):
418     try:
419         neutron_client.delete_port(port_id)
420         return True
421     except Exception, e:
422         print "Error [delete_neutron_port(neutron_client, '%s')]:" % port_id, e
423         return False
424
425
426 def remove_interface_router(neutron_client, router_id, subnet_id):
427     json_body = {"subnet_id": subnet_id}
428     try:
429         neutron_client.remove_interface_router(router=router_id,
430                                                body=json_body)
431         return True
432     except Exception, e:
433         print ("Error [remove_interface_router(neutron_client, '%s', '%s')]:" %
434                (router_id, subnet_id), e)
435         return False
436
437
438 def remove_gateway_router(neutron_client, router_id):
439     try:
440         neutron_client.remove_gateway_router(router_id)
441         return True
442     except Exception, e:
443         print ("Error [remove_gateway_router(neutron_client, '%s')]:" %
444                router_id, e)
445         return False
446
447
448 # *********************************************
449 #   SEC GROUPS
450 # *********************************************
451 def get_security_groups(neutron_client):
452     try:
453         security_groups = neutron_client.list_security_groups()[
454             'security_groups']
455         return security_groups
456     except Exception, e:
457         print "Error [get_security_groups(neutron_client)]:", e
458         return None
459
460
461 def get_security_group_id(neutron_client, sg_name):
462     security_groups = get_security_groups(neutron_client)
463     id = ''
464     for sg in security_groups:
465         if sg['name'] == sg_name:
466             id = sg['id']
467             break
468     return id
469
470
471 def create_security_group(neutron_client, sg_name, sg_description):
472     json_body = {'security_group': {'name': sg_name,
473                                     'description': sg_description}}
474     try:
475         secgroup = neutron_client.create_security_group(json_body)
476         return secgroup['security_group']
477     except Exception, e:
478         print ("Error [create_security_group(neutron_client, '%s', '%s')]:" %
479                (sg_name, sg_description), e)
480         return False
481
482
483 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
484                          port_range_min=None, port_range_max=None):
485     if port_range_min is None and port_range_max is None:
486         json_body = {'security_group_rule': {'direction': direction,
487                                              'security_group_id': sg_id,
488                                              'protocol': protocol}}
489     elif port_range_min is not None and port_range_max is not None:
490         json_body = {'security_group_rule': {'direction': direction,
491                                              'security_group_id': sg_id,
492                                              'port_range_min': port_range_min,
493                                              'port_range_max': port_range_max,
494                                              'protocol': protocol}}
495     else:
496         print ("Error [create_secgroup_rule(neutron_client, '%s', '%s', "
497                "'%s', '%s', '%s', '%s')]:" % (neutron_client, sg_id, direction,
498                                               port_range_min, port_range_max,
499                                               protocol),
500                " Invalid values for port_range_min, port_range_max")
501         return False
502     try:
503         neutron_client.create_security_group_rule(json_body)
504         return True
505     except Exception, e:
506         print ("Error [create_secgroup_rule(neutron_client, '%s', '%s', "
507                "'%s', '%s', '%s', '%s')]:" % (neutron_client, sg_id, direction,
508                                               port_range_min, port_range_max,
509                                               protocol), e)
510         return False
511
512
513 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
514     try:
515         nova_client.servers.add_security_group(instance_id, secgroup_id)
516         return True
517     except Exception, e:
518         print ("Error [add_secgroup_to_instance(nova_client, '%s', '%s')]: " %
519                (instance_id, secgroup_id), e)
520         return False
521
522
523 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
524     json_body = {"quota": {
525         "security_group": sg_quota,
526         "security_group_rule": sg_rule_quota
527     }}
528
529     try:
530         neutron_client.update_quota(tenant_id=tenant_id,
531                                     body=json_body)
532         return True
533     except Exception, e:
534         print ("Error [update_sg_quota(neutron_client, '%s', '%s', "
535                "'%s')]:" % (tenant_id, sg_quota, sg_rule_quota), e)
536         return False
537
538
539 def delete_security_group(neutron_client, secgroup_id):
540     try:
541         neutron_client.delete_security_group(secgroup_id)
542         return True
543     except Exception, e:
544         print ("Error [delete_security_group(neutron_client, '%s')]:" %
545                secgroup_id, e)
546         return False
547
548
549 # *********************************************
550 #   GLANCE
551 # *********************************************
552 def get_images(nova_client):
553     try:
554         images = nova_client.images.list()
555         return images
556     except Exception, e:
557         print "Error [get_images]:", e
558         return None
559
560
561 def get_image_id(glance_client, image_name):
562     images = glance_client.images.list()
563     id = ''
564     for i in images:
565         if i.name == image_name:
566             id = i.id
567             break
568     return id
569
570
571 def create_glance_image(glance_client, image_name, file_path, public=True):
572     if not os.path.isfile(file_path):
573         print "Error: file " + file_path + " does not exist."
574         return False
575     try:
576         with open(file_path) as fimage:
577             image = glance_client.images.create(name=image_name,
578                                                 is_public=public,
579                                                 disk_format="qcow2",
580                                                 container_format="bare",
581                                                 data=fimage)
582         return image.id
583     except Exception, e:
584         print ("Error [create_glance_image(glance_client, '%s', '%s', "
585                "'%s')]:" % (image_name, file_path, str(public)), e)
586         return False
587
588
589 def delete_glance_image(nova_client, image_id):
590     try:
591         nova_client.images.delete(image_id)
592         return True
593     except Exception, e:
594         print ("Error [delete_glance_image(nova_client, '%s')]:" % image_id, e)
595         return False
596
597
598 # *********************************************
599 #   CINDER
600 # *********************************************
601 def get_volumes(cinder_client):
602     try:
603         volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
604         return volumes
605     except Exception, e:
606         print "Error [get_volumes(cinder_client)]:", e
607         return None
608
609
610 def list_volume_types(cinder_client, public=True, private=True):
611     try:
612         volume_types = cinder_client.volume_types.list()
613         if not public:
614             volume_types = [vt for vt in volume_types if not vt.is_public]
615         if not private:
616             volume_types = [vt for vt in volume_types if vt.is_public]
617         return volume_types
618     except Exception, e:
619         print "Error [list_volume_types(cinder_client)]:", e
620         return None
621
622
623 def create_volume_type(cinder_client, name):
624     try:
625         volume_type = cinder_client.volume_types.create(name)
626         return volume_type
627     except Exception, e:
628         print "Error [create_volume_type(cinder_client, '%s')]:" % name, e
629         return None
630
631
632 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
633                         snapshots_quota, gigabytes_quota):
634     quotas_values = {"volumes": vols_quota,
635                      "snapshots": snapshots_quota,
636                      "gigabytes": gigabytes_quota}
637
638     try:
639         cinder_client.quotas.update(tenant_id, **quotas_values)
640         return True
641     except Exception, e:
642         print ("Error [update_cinder_quota(cinder_client, '%s', '%s', '%s'"
643                "'%s')]:" % (tenant_id, vols_quota,
644                             snapshots_quota, gigabytes_quota), e)
645         return False
646
647
648 def delete_volume(cinder_client, volume_id, forced=False):
649     try:
650         if forced:
651             try:
652                 cinder_client.volumes.detach(volume_id)
653             except:
654                 print "Error:", sys.exc_info()[0]
655             cinder_client.volumes.force_delete(volume_id)
656         else:
657             cinder_client.volumes.delete(volume_id)
658         return True
659     except Exception, e:
660         print ("Error [delete_volume(cinder_client, '%s', '%s')]:" %
661                (volume_id, str(forced)), e)
662         return False
663
664
665 def delete_volume_type(cinder_client, volume_type):
666     try:
667         cinder_client.volume_types.delete(volume_type)
668         return True
669     except Exception, e:
670         print ("Error [delete_volume_type(cinder_client, '%s')]:" %
671                volume_type, e)
672         return False
673
674
675 # *********************************************
676 #   KEYSTONE
677 # *********************************************
678 def get_tenants(keystone_client):
679     try:
680         tenants = keystone_client.tenants.list()
681         return tenants
682     except Exception, e:
683         print "Error [get_tenants(keystone_client)]:", e
684         return None
685
686
687 def get_users(keystone_client):
688     try:
689         users = keystone_client.users.list()
690         return users
691     except Exception, e:
692         print "Error [get_users(keystone_client)]:", e
693         return None
694
695
696 def get_tenant_id(keystone_client, tenant_name):
697     tenants = keystone_client.tenants.list()
698     id = ''
699     for t in tenants:
700         if t.name == tenant_name:
701             id = t.id
702             break
703     return id
704
705
706 def get_user_id(keystone_client, user_name):
707     users = keystone_client.users.list()
708     id = ''
709     for u in users:
710         if u.name == user_name:
711             id = u.id
712             break
713     return id
714
715
716 def get_role_id(keystone_client, role_name):
717     roles = keystone_client.roles.list()
718     id = ''
719     for r in roles:
720         if r.name == role_name:
721             id = r.id
722             break
723     return id
724
725
726 def create_tenant(keystone_client, tenant_name, tenant_description):
727     try:
728         tenant = keystone_client.tenants.create(tenant_name,
729                                                 tenant_description,
730                                                 enabled=True)
731         return tenant.id
732     except Exception, e:
733         print ("Error [create_tenant(cinder_client, '%s', '%s')]:" %
734                (tenant_name, tenant_description), e)
735         return False
736
737
738 def create_user(keystone_client, user_name, user_password,
739                 user_email, tenant_id):
740     try:
741         user = keystone_client.users.create(user_name, user_password,
742                                             user_email, tenant_id,
743                                             enabled=True)
744         return user.id
745     except Exception, e:
746         print ("Error [create_user(keystone_client, '%s', '%s', '%s'"
747                "'%s')]:" % (user_name, user_password, user_email, tenant_id),
748                e)
749         return False
750
751
752 def add_role_user(keystone_client, user_id, role_id, tenant_id):
753     try:
754         keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
755         return True
756     except Exception, e:
757         print ("Error [add_role_user(keystone_client, '%s', '%s'"
758                "'%s')]:" % (user_id, role_id, tenant_id), e)
759         return False
760
761
762 def delete_tenant(keystone_client, tenant_id):
763     try:
764         keystone_client.tenants.delete(tenant_id)
765         return True
766     except Exception, e:
767         print "Error [delete_tenant(keystone_client, '%s')]:" % tenant_id, e
768         return False
769
770
771 def delete_user(keystone_client, user_id):
772     try:
773         keystone_client.users.delete(user_id)
774         return True
775     except Exception, e:
776         print "Error [delete_user(keystone_client, '%s')]:" % user_id, e
777         return False