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