Enable odl-sfc in CI
[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 import time
16
17 from cinderclient import client as cinderclient
18 import functest.utils.functest_logger as ft_logger
19 from glanceclient import client as glanceclient
20 from keystoneclient.v2_0 import client as keystoneclient
21 from neutronclient.v2_0 import client as neutronclient
22 from novaclient import client as novaclient
23
24 logger = ft_logger.Logger("openstack_utils").getLogger()
25
26
27 # *********************************************
28 #   CREDENTIALS
29 # *********************************************
30 def check_credentials():
31     """
32     Check if the OpenStack credentials (openrc) are sourced
33     """
34     env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD', 'OS_TENANT_NAME']
35     return all(map(lambda v: v in os.environ and os.environ[v], env_vars))
36
37
38 def get_credentials(service):
39     """Returns a creds dictionary filled with the following keys:
40     * username
41     * password/api_key (depending on the service)
42     * tenant_name/project_id (depending on the service)
43     * auth_url
44     :param service: a string indicating the name of the service
45                     requesting the credentials.
46     """
47     creds = {}
48
49     # Check that the env vars exists:
50     envvars = ('OS_USERNAME', 'OS_PASSWORD', 'OS_AUTH_URL', 'OS_TENANT_NAME')
51     for envvar in envvars:
52         if os.getenv(envvar) is None:
53             logger.error("'%s' is not exported as an env variable." % envvar)
54             exit(-1)
55
56     # Unfortunately, each of the OpenStack client will request slightly
57     # different entries in their credentials dict.
58     if service.lower() in ("nova", "cinder"):
59         password = "api_key"
60         tenant = "project_id"
61     else:
62         password = "password"
63         tenant = "tenant_name"
64
65     # The most common way to pass these info to the script is to do it through
66     # environment variables.
67     creds.update({
68         "username": os.environ.get("OS_USERNAME"),
69         password: os.environ.get("OS_PASSWORD"),
70         "auth_url": os.environ.get("OS_AUTH_URL"),
71         tenant: os.environ.get("OS_TENANT_NAME")
72     })
73     cacert = os.environ.get("OS_CACERT")
74     if cacert is not None:
75         # each openstack client uses differnt kwargs for this
76         creds.update({"cacert": cacert,
77                       "ca_cert": cacert,
78                       "https_ca_cert": cacert,
79                       "https_cacert": cacert,
80                       "ca_file": cacert})
81         creds.update({"insecure": "True", "https_insecure": "True"})
82         if not os.path.isfile(cacert):
83             logger.info("WARNING: The 'OS_CACERT' environment variable is "
84                         "set to %s but the file does not exist." % cacert)
85     return creds
86
87
88 def source_credentials(rc_file):
89     pipe = subprocess.Popen(". %s; env" % rc_file, stdout=subprocess.PIPE,
90                             shell=True)
91     output = pipe.communicate()[0]
92     env = dict((line.split("=", 1) for line in output.splitlines()))
93     os.environ.update(env)
94     return env
95
96
97 # *********************************************
98 #   CLIENTS
99 # *********************************************
100 def get_keystone_client():
101     creds_keystone = get_credentials("keystone")
102     return keystoneclient.Client(**creds_keystone)
103
104
105 def get_nova_client():
106     creds_nova = get_credentials("nova")
107     return novaclient.Client('2', **creds_nova)
108
109
110 def get_cinder_client():
111     creds_cinder = get_credentials("cinder")
112     return cinderclient.Client('2', creds_cinder['username'],
113                                creds_cinder['api_key'],
114                                creds_cinder['project_id'],
115                                creds_cinder['auth_url'],
116                                service_type="volume")
117
118
119 def get_neutron_client():
120     creds_neutron = get_credentials("neutron")
121     return neutronclient.Client(**creds_neutron)
122
123
124 def get_glance_client():
125     keystone_client = get_keystone_client()
126     glance_endpoint = keystone_client.service_catalog.url_for(
127         service_type='image', endpoint_type='publicURL')
128     return glanceclient.Client(1, glance_endpoint,
129                                token=keystone_client.auth_token)
130
131 # *********************************************
132 #   NOVA
133 # *********************************************
134
135
136 def get_instances(nova_client):
137     try:
138         instances = nova_client.servers.list(search_opts={'all_tenants': 1})
139         return instances
140     except Exception, e:
141         logger.error("Error [get_instances(nova_client)]: %s" % e)
142         return None
143
144
145 def get_instance_status(nova_client, instance):
146     try:
147         instance = nova_client.servers.get(instance.id)
148         return instance.status
149     except Exception, e:
150         logger.error("Error [get_instance_status(nova_client)]: %s" % e)
151         return None
152
153
154 def get_instance_by_name(nova_client, instance_name):
155     try:
156         instance = nova_client.servers.find(name=instance_name)
157         return instance
158     except Exception, e:
159         logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
160                      % (instance_name, e))
161         return None
162
163
164 def get_flavor_id(nova_client, flavor_name):
165     flavors = nova_client.flavors.list(detailed=True)
166     id = ''
167     for f in flavors:
168         if f.name == flavor_name:
169             id = f.id
170             break
171     return id
172
173
174 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
175     flavors = nova_client.flavors.list(detailed=True)
176     id = ''
177     for f in flavors:
178         if min_ram <= f.ram and f.ram <= max_ram:
179             id = f.id
180             break
181     return id
182
183
184 def get_floating_ips(nova_client):
185     try:
186         floating_ips = nova_client.floating_ips.list()
187         return floating_ips
188     except Exception, e:
189         logger.error("Error [get_floating_ips(nova_client)]: %s" % e)
190         return None
191
192
193 def get_hypervisors(nova_client):
194     try:
195         nodes = []
196         hypervisors = nova_client.hypervisors.list()
197         for hypervisor in hypervisors:
198             if hypervisor.state == "up":
199                 nodes.append(hypervisor.hypervisor_hostname)
200         return nodes
201     except Exception, e:
202         logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
203         return None
204
205
206 def create_flavor(nova_client, flavor_name, ram, disk, vcpus):
207     try:
208         flavor = nova_client.flavors.create(flavor_name, ram, vcpus, disk)
209     except Exception, e:
210         logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
211                      "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
212         return None
213     return flavor.id
214
215
216 def create_instance(flavor_name,
217                     image_id,
218                     network_id,
219                     instance_name="functest-vm",
220                     confdrive=True,
221                     userdata=None,
222                     av_zone='',
223                     fixed_ip=None,
224                     files=None):
225     nova_client = get_nova_client()
226     try:
227         flavor = nova_client.flavors.find(name=flavor_name)
228     except:
229         flavors = nova_client.flavors.list()
230         logger.error("Error: Flavor '%s' not found. Available flavors are: "
231                      "\n%s" % (flavor_name, flavors))
232         return -1
233     if fixed_ip is not None:
234         nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
235     else:
236         nics = {"net-id": network_id}
237     if userdata is None:
238         instance = nova_client.servers.create(
239             name=instance_name,
240             flavor=flavor,
241             image=image_id,
242             nics=[nics],
243             availability_zone=av_zone,
244             files=files
245         )
246     else:
247         instance = nova_client.servers.create(
248             name=instance_name,
249             flavor=flavor,
250             image=image_id,
251             nics=[nics],
252             config_drive=confdrive,
253             userdata=userdata,
254             availability_zone=av_zone,
255             files=files
256         )
257     return instance
258
259
260 def create_instance_and_wait_for_active(flavor_name,
261                                         image_id,
262                                         network_id,
263                                         instance_name="",
264                                         config_drive=False,
265                                         userdata="",
266                                         av_zone='',
267                                         fixed_ip=None,
268                                         files=None):
269     SLEEP = 3
270     VM_BOOT_TIMEOUT = 180
271     nova_client = get_nova_client()
272     instance = create_instance(flavor_name,
273                                image_id,
274                                network_id,
275                                instance_name,
276                                config_drive,
277                                userdata,
278                                av_zone=av_zone,
279                                fixed_ip=fixed_ip,
280                                files=files)
281     count = VM_BOOT_TIMEOUT / SLEEP
282     for n in range(count, -1, -1):
283         status = get_instance_status(nova_client, instance)
284         if status.lower() == "active":
285             return instance
286         elif status.lower() == "error":
287             logger.error("The instance %s went to ERROR status."
288                          % instance_name)
289             return None
290         time.sleep(SLEEP)
291     logger.error("Timeout booting the instance %s." % instance_name)
292     return None
293
294
295 def create_floating_ip(neutron_client):
296     extnet_id = get_external_net_id(neutron_client)
297     props = {'floating_network_id': extnet_id}
298     try:
299         ip_json = neutron_client.create_floatingip({'floatingip': props})
300         fip_addr = ip_json['floatingip']['floating_ip_address']
301         fip_id = ip_json['floatingip']['id']
302     except Exception, e:
303         logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
304         return None
305     return {'fip_addr': fip_addr, 'fip_id': fip_id}
306
307
308 def add_floating_ip(nova_client, server_id, floatingip_id):
309     try:
310         nova_client.servers.add_floating_ip(server_id, floatingip_id)
311         return True
312     except Exception, e:
313         logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
314                      % (server_id, floatingip_id, e))
315         return False
316
317
318 def delete_instance(nova_client, instance_id):
319     try:
320         nova_client.servers.force_delete(instance_id)
321         return True
322     except Exception, e:
323         logger.error("Error [delete_instance(nova_client, '%s')]: %s"
324                      % (instance_id, e))
325         return False
326
327
328 def delete_floating_ip(nova_client, floatingip_id):
329     try:
330         nova_client.floating_ips.delete(floatingip_id)
331         return True
332     except Exception, e:
333         logger.error("Error [delete_floating_ip(nova_client, '%s')]:"
334                      % (floatingip_id, e))
335         return False
336
337
338 # *********************************************
339 #   NEUTRON
340 # *********************************************
341 def get_network_list(neutron_client):
342     network_list = neutron_client.list_networks()['networks']
343     if len(network_list) == 0:
344         return None
345     else:
346         return network_list
347
348
349 def get_router_list(neutron_client):
350     router_list = neutron_client.list_routers()['routers']
351     if len(router_list) == 0:
352         return None
353     else:
354         return router_list
355
356
357 def get_port_list(neutron_client):
358     port_list = neutron_client.list_ports()['ports']
359     if len(port_list) == 0:
360         return None
361     else:
362         return port_list
363
364
365 def get_network_id(neutron_client, network_name):
366     networks = neutron_client.list_networks()['networks']
367     id = ''
368     for n in networks:
369         if n['name'] == network_name:
370             id = n['id']
371             break
372     return id
373
374
375 def get_subnet_id(neutron_client, subnet_name):
376     subnets = neutron_client.list_subnets()['subnets']
377     id = ''
378     for s in subnets:
379         if s['name'] == subnet_name:
380             id = s['id']
381             break
382     return id
383
384
385 def get_router_id(neutron_client, router_name):
386     routers = neutron_client.list_routers()['routers']
387     id = ''
388     for r in routers:
389         if r['name'] == router_name:
390             id = r['id']
391             break
392     return id
393
394
395 def get_private_net(neutron_client):
396     # Checks if there is an existing shared private network
397     networks = neutron_client.list_networks()['networks']
398     if len(networks) == 0:
399         return None
400     for net in networks:
401         if (net['router:external'] is False) and (net['shared'] is True):
402             return net
403     return None
404
405
406 def get_external_net(neutron_client):
407     for network in neutron_client.list_networks()['networks']:
408         if network['router:external']:
409             return network['name']
410     return False
411
412
413 def get_external_net_id(neutron_client):
414     for network in neutron_client.list_networks()['networks']:
415         if network['router:external']:
416             return network['id']
417     return False
418
419
420 def check_neutron_net(neutron_client, net_name):
421     for network in neutron_client.list_networks()['networks']:
422         if network['name'] == net_name:
423             for subnet in network['subnets']:
424                 return True
425     return False
426
427
428 def create_neutron_net(neutron_client, name):
429     json_body = {'network': {'name': name,
430                              'admin_state_up': True}}
431     try:
432         network = neutron_client.create_network(body=json_body)
433         network_dict = network['network']
434         return network_dict['id']
435     except Exception, e:
436         logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
437                      % (name, e))
438         return False
439
440
441 def create_neutron_subnet(neutron_client, name, cidr, net_id):
442     json_body = {'subnets': [{'name': name, 'cidr': cidr,
443                               'ip_version': 4, 'network_id': net_id}]}
444     try:
445         subnet = neutron_client.create_subnet(body=json_body)
446         return subnet['subnets'][0]['id']
447     except Exception, e:
448         logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
449                      "'%s', '%s')]: %s" % (name, cidr, net_id, e))
450         return False
451
452
453 def create_neutron_router(neutron_client, name):
454     json_body = {'router': {'name': name, 'admin_state_up': True}}
455     try:
456         router = neutron_client.create_router(json_body)
457         return router['router']['id']
458     except Exception, e:
459         logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
460                      % (name, e))
461         return False
462
463
464 def create_neutron_port(neutron_client, name, network_id, ip):
465     json_body = {'port': {
466                  'admin_state_up': True,
467                  'name': name,
468                  'network_id': network_id,
469                  'fixed_ips': [{"ip_address": ip}]
470                  }}
471     try:
472         port = neutron_client.create_port(body=json_body)
473         return port['port']['id']
474     except Exception, e:
475         logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
476                      "'%s')]: %s" % (name, network_id, ip, e))
477         return False
478
479
480 def update_neutron_net(neutron_client, network_id, shared=False):
481     json_body = {'network': {'shared': shared}}
482     try:
483         neutron_client.update_network(network_id, body=json_body)
484         return True
485     except Exception, e:
486         logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
487                      "%s" % (network_id, str(shared), e))
488         return False
489
490
491 def update_neutron_port(neutron_client, port_id, device_owner):
492     json_body = {'port': {
493                  'device_owner': device_owner,
494                  }}
495     try:
496         port = neutron_client.update_port(port=port_id,
497                                           body=json_body)
498         return port['port']['id']
499     except Exception, e:
500         logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
501                      " %s" % (port_id, device_owner, e))
502         return False
503
504
505 def add_interface_router(neutron_client, router_id, subnet_id):
506     json_body = {"subnet_id": subnet_id}
507     try:
508         neutron_client.add_interface_router(router=router_id, body=json_body)
509         return True
510     except Exception, e:
511         logger.error("Error [add_interface_router(neutron_client, '%s', "
512                      "'%s')]: %s" % (router_id, subnet_id, e))
513         return False
514
515
516 def add_gateway_router(neutron_client, router_id):
517     ext_net_id = get_external_net_id(neutron_client)
518     router_dict = {'network_id': ext_net_id}
519     try:
520         neutron_client.add_gateway_router(router_id, router_dict)
521         return True
522     except Exception, e:
523         logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
524                      % (router_id, e))
525         return False
526
527
528 def delete_neutron_net(neutron_client, network_id):
529     try:
530         neutron_client.delete_network(network_id)
531         return True
532     except Exception, e:
533         logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
534                      % (network_id, e))
535         return False
536
537
538 def delete_neutron_subnet(neutron_client, subnet_id):
539     try:
540         neutron_client.delete_subnet(subnet_id)
541         return True
542     except Exception, e:
543         logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
544                      % (subnet_id, e))
545         return False
546
547
548 def delete_neutron_router(neutron_client, router_id):
549     try:
550         neutron_client.delete_router(router=router_id)
551         return True
552     except Exception, e:
553         logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
554                      % (router_id, e))
555         return False
556
557
558 def delete_neutron_port(neutron_client, port_id):
559     try:
560         neutron_client.delete_port(port_id)
561         return True
562     except Exception, e:
563         logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
564                      % (port_id, e))
565         return False
566
567
568 def remove_interface_router(neutron_client, router_id, subnet_id):
569     json_body = {"subnet_id": subnet_id}
570     try:
571         neutron_client.remove_interface_router(router=router_id,
572                                                body=json_body)
573         return True
574     except Exception, e:
575         logger.error("Error [remove_interface_router(neutron_client, '%s', "
576                      "'%s')]: %s" % (router_id, subnet_id, e))
577         return False
578
579
580 def remove_gateway_router(neutron_client, router_id):
581     try:
582         neutron_client.remove_gateway_router(router_id)
583         return True
584     except Exception, e:
585         logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
586                      % (router_id, e))
587         return False
588
589
590 def create_network_full(neutron_client,
591                         net_name,
592                         subnet_name,
593                         router_name,
594                         cidr):
595
596     # Check if the network already exists
597     network_id = get_network_id(neutron_client, net_name)
598     subnet_id = get_subnet_id(neutron_client, subnet_name)
599     router_id = get_router_id(neutron_client, router_name)
600
601     if network_id != '' and subnet_id != '' and router_id != '':
602         logger.info("A network with name '%s' already exists..." % net_name)
603     else:
604         neutron_client.format = 'json'
605         logger.info('Creating neutron network %s...' % net_name)
606         network_id = create_neutron_net(neutron_client, net_name)
607
608         if not network_id:
609             return False
610
611         logger.debug("Network '%s' created successfully" % network_id)
612         logger.debug('Creating Subnet....')
613         subnet_id = create_neutron_subnet(neutron_client, subnet_name,
614                                           cidr, network_id)
615         if not subnet_id:
616             return False
617
618         logger.debug("Subnet '%s' created successfully" % subnet_id)
619         logger.debug('Creating Router...')
620         router_id = create_neutron_router(neutron_client, router_name)
621
622         if not router_id:
623             return False
624
625         logger.debug("Router '%s' created successfully" % router_id)
626         logger.debug('Adding router to subnet...')
627
628         if not add_interface_router(neutron_client, router_id, subnet_id):
629             return False
630
631         logger.debug("Interface added successfully.")
632
633         logger.debug('Adding gateway to router...')
634         if not add_gateway_router(neutron_client, router_id):
635             return False
636
637         logger.debug("Gateway added successfully.")
638
639     network_dic = {'net_id': network_id,
640                    'subnet_id': subnet_id,
641                    'router_id': router_id}
642     return network_dic
643
644
645 def create_bgpvpn(neutron_client, **kwargs):
646     # route_distinguishers
647     # route_targets
648     json_body = {"bgpvpn": kwargs}
649     return neutron_client.create_bgpvpn(json_body)
650
651
652 def create_network_association(neutron_client, bgpvpn_id, neutron_network_id):
653     json_body = {"network_association": {"network_id": neutron_network_id}}
654     return neutron_client.create_network_association(bgpvpn_id, json_body)
655
656
657 def update_bgpvpn(neutron_client, bgpvpn_id, **kwargs):
658     json_body = {"bgpvpn": kwargs}
659     return neutron_client.update_bgpvpn(bgpvpn_id, json_body)
660
661
662 def delete_bgpvpn(neutron_client, bgpvpn_id):
663     return neutron_client.delete_bgpvpn(bgpvpn_id)
664
665 # *********************************************
666 #   SEC GROUPS
667 # *********************************************
668
669
670 def get_security_groups(neutron_client):
671     try:
672         security_groups = neutron_client.list_security_groups()[
673             'security_groups']
674         return security_groups
675     except Exception, e:
676         logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
677         return None
678
679
680 def get_security_group_id(neutron_client, sg_name):
681     security_groups = get_security_groups(neutron_client)
682     id = ''
683     for sg in security_groups:
684         if sg['name'] == sg_name:
685             id = sg['id']
686             break
687     return id
688
689
690 def create_security_group(neutron_client, sg_name, sg_description):
691     json_body = {'security_group': {'name': sg_name,
692                                     'description': sg_description}}
693     try:
694         secgroup = neutron_client.create_security_group(json_body)
695         return secgroup['security_group']
696     except Exception, e:
697         logger.error("Error [create_security_group(neutron_client, '%s', "
698                      "'%s')]: %s" % (sg_name, sg_description, e))
699         return False
700
701
702 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
703                          port_range_min=None, port_range_max=None):
704     if port_range_min is None and port_range_max is None:
705         json_body = {'security_group_rule': {'direction': direction,
706                                              'security_group_id': sg_id,
707                                              'protocol': protocol}}
708     elif port_range_min is not None and port_range_max is not None:
709         json_body = {'security_group_rule': {'direction': direction,
710                                              'security_group_id': sg_id,
711                                              'port_range_min': port_range_min,
712                                              'port_range_max': port_range_max,
713                                              'protocol': protocol}}
714     else:
715         logger.error("Error [create_secgroup_rule(neutron_client, '%s', '%s', "
716                      "'%s', '%s', '%s', '%s')]:" % (neutron_client,
717                                                     sg_id, direction,
718                                                     port_range_min,
719                                                     port_range_max,
720                                                     protocol),
721                      " Invalid values for port_range_min, port_range_max")
722         return False
723     try:
724         neutron_client.create_security_group_rule(json_body)
725         return True
726     except Exception, e:
727         logger.error("Error [create_secgroup_rule(neutron_client, '%s', '%s', "
728                      "'%s', '%s', '%s', '%s')]: %s" % (neutron_client,
729                                                        sg_id,
730                                                        direction,
731                                                        port_range_min,
732                                                        port_range_max,
733                                                        protocol, e))
734         return False
735
736
737 def create_security_group_full(neutron_client,
738                                sg_name, sg_description):
739     sg_id = get_security_group_id(neutron_client, sg_name)
740     if sg_id != '':
741         logger.info("Using existing security group '%s'..." % sg_name)
742     else:
743         logger.info("Creating security group  '%s'..." % sg_name)
744         SECGROUP = create_security_group(neutron_client,
745                                          sg_name,
746                                          sg_description)
747         if not SECGROUP:
748             logger.error("Failed to create the security group...")
749             return False
750
751         sg_id = SECGROUP['id']
752
753         logger.debug("Security group '%s' with ID=%s created successfully."
754                      % (SECGROUP['name'], sg_id))
755
756         logger.debug("Adding ICMP rules in security group '%s'..."
757                      % sg_name)
758         if not create_secgroup_rule(neutron_client, sg_id,
759                                     'ingress', 'icmp'):
760             logger.error("Failed to create the security group rule...")
761             return False
762
763         logger.debug("Adding SSH rules in security group '%s'..."
764                      % sg_name)
765         if not create_secgroup_rule(
766                 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
767             logger.error("Failed to create the security group rule...")
768             return False
769
770         if not create_secgroup_rule(
771                 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
772             logger.error("Failed to create the security group rule...")
773             return False
774     return sg_id
775
776
777 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
778     try:
779         nova_client.servers.add_security_group(instance_id, secgroup_id)
780         return True
781     except Exception, e:
782         logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
783                      "'%s')]: %s" % (instance_id, secgroup_id, e))
784         return False
785
786
787 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
788     json_body = {"quota": {
789         "security_group": sg_quota,
790         "security_group_rule": sg_rule_quota
791     }}
792
793     try:
794         neutron_client.update_quota(tenant_id=tenant_id,
795                                     body=json_body)
796         return True
797     except Exception, e:
798         logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
799                      "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
800         return False
801
802
803 def delete_security_group(neutron_client, secgroup_id):
804     try:
805         neutron_client.delete_security_group(secgroup_id)
806         return True
807     except Exception, e:
808         logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
809                      % (secgroup_id, e))
810         return False
811
812
813 # *********************************************
814 #   GLANCE
815 # *********************************************
816 def get_images(nova_client):
817     try:
818         images = nova_client.images.list()
819         return images
820     except Exception, e:
821         logger.error("Error [get_images]: %s" % e)
822         return None
823
824
825 def get_image_id(glance_client, image_name):
826     images = glance_client.images.list()
827     id = ''
828     for i in images:
829         if i.name == image_name:
830             id = i.id
831             break
832     return id
833
834
835 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
836                         container="bare", public=True):
837     if not os.path.isfile(file_path):
838         logger.error("Error: file %s does not exist." % file_path)
839         return False
840     try:
841         image_id = get_image_id(glance_client, image_name)
842         if image_id != '':
843             if logger:
844                 logger.info("Image %s already exists." % image_name)
845         else:
846             if logger:
847                 logger.info("Creating image '%s' from '%s'..." % (image_name,
848                                                                   file_path))
849             with open(file_path) as fimage:
850                 image = glance_client.images.create(name=image_name,
851                                                     is_public=public,
852                                                     disk_format=disk,
853                                                     container_format=container,
854                                                     data=fimage)
855             image_id = image.id
856         return image_id
857     except Exception, e:
858         logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
859                      "'%s')]: %s" % (image_name, file_path, str(public), e))
860         return False
861
862
863 def delete_glance_image(nova_client, image_id):
864     try:
865         nova_client.images.delete(image_id)
866         return True
867     except Exception, e:
868         logger.error("Error [delete_glance_image(nova_client, '%s')]: %s"
869                      % (image_id, e))
870         return False
871
872
873 # *********************************************
874 #   CINDER
875 # *********************************************
876 def get_volumes(cinder_client):
877     try:
878         volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
879         return volumes
880     except Exception, e:
881         logger.error("Error [get_volumes(cinder_client)]: %s" % e)
882         return None
883
884
885 def list_volume_types(cinder_client, public=True, private=True):
886     try:
887         volume_types = cinder_client.volume_types.list()
888         if not public:
889             volume_types = [vt for vt in volume_types if not vt.is_public]
890         if not private:
891             volume_types = [vt for vt in volume_types if vt.is_public]
892         return volume_types
893     except Exception, e:
894         logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
895         return None
896
897
898 def create_volume_type(cinder_client, name):
899     try:
900         volume_type = cinder_client.volume_types.create(name)
901         return volume_type
902     except Exception, e:
903         logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
904                      % (name, e))
905         return None
906
907
908 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
909                         snapshots_quota, gigabytes_quota):
910     quotas_values = {"volumes": vols_quota,
911                      "snapshots": snapshots_quota,
912                      "gigabytes": gigabytes_quota}
913
914     try:
915         cinder_client.quotas.update(tenant_id, **quotas_values)
916         return True
917     except Exception, e:
918         logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
919                      "'%s' '%s')]: %s" % (tenant_id, vols_quota,
920                                           snapshots_quota, gigabytes_quota, e))
921         return False
922
923
924 def delete_volume(cinder_client, volume_id, forced=False):
925     try:
926         if forced:
927             try:
928                 cinder_client.volumes.detach(volume_id)
929             except:
930                 logger.error(sys.exc_info()[0])
931             cinder_client.volumes.force_delete(volume_id)
932         else:
933             cinder_client.volumes.delete(volume_id)
934         return True
935     except Exception, e:
936         logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
937                      % (volume_id, str(forced), e))
938         return False
939
940
941 def delete_volume_type(cinder_client, volume_type):
942     try:
943         cinder_client.volume_types.delete(volume_type)
944         return True
945     except Exception, e:
946         logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
947                      % (volume_type, e))
948         return False
949
950
951 # *********************************************
952 #   KEYSTONE
953 # *********************************************
954 def get_tenants(keystone_client):
955     try:
956         tenants = keystone_client.tenants.list()
957         return tenants
958     except Exception, e:
959         logger.error("Error [get_tenants(keystone_client)]: %s" % e)
960         return None
961
962
963 def get_users(keystone_client):
964     try:
965         users = keystone_client.users.list()
966         return users
967     except Exception, e:
968         logger.error("Error [get_users(keystone_client)]: %s" % e)
969         return None
970
971
972 def get_tenant_id(keystone_client, tenant_name):
973     tenants = keystone_client.tenants.list()
974     id = ''
975     for t in tenants:
976         if t.name == tenant_name:
977             id = t.id
978             break
979     return id
980
981
982 def get_user_id(keystone_client, user_name):
983     users = keystone_client.users.list()
984     id = ''
985     for u in users:
986         if u.name == user_name:
987             id = u.id
988             break
989     return id
990
991
992 def get_role_id(keystone_client, role_name):
993     roles = keystone_client.roles.list()
994     id = ''
995     for r in roles:
996         if r.name == role_name:
997             id = r.id
998             break
999     return id
1000
1001
1002 def create_tenant(keystone_client, tenant_name, tenant_description):
1003     try:
1004         tenant = keystone_client.tenants.create(tenant_name,
1005                                                 tenant_description,
1006                                                 enabled=True)
1007         return tenant.id
1008     except Exception, e:
1009         logger.error("Error [create_tenant(cinder_client, '%s', '%s')]: %s"
1010                      % (tenant_name, tenant_description, e))
1011         return False
1012
1013
1014 def create_user(keystone_client, user_name, user_password,
1015                 user_email, tenant_id):
1016     try:
1017         user = keystone_client.users.create(user_name, user_password,
1018                                             user_email, tenant_id,
1019                                             enabled=True)
1020         return user.id
1021     except Exception, e:
1022         logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1023                      "'%s')]: %s" % (user_name, user_password,
1024                                      user_email, tenant_id, e))
1025         return False
1026
1027
1028 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1029     try:
1030         keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1031         return True
1032     except Exception, e:
1033         logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1034                      "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1035         return False
1036
1037
1038 def delete_tenant(keystone_client, tenant_id):
1039     try:
1040         keystone_client.tenants.delete(tenant_id)
1041         return True
1042     except Exception, e:
1043         logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1044                      % (tenant_id, e))
1045         return False
1046
1047
1048 def delete_user(keystone_client, user_id):
1049     try:
1050         keystone_client.users.delete(user_id)
1051         return True
1052     except Exception, e:
1053         logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1054                      % (user_id, e))
1055         return False