Merge "refactor create or get image process to eliminate reduplicate"
[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_bgpvpn(neutron_client, **kwargs):
675     # route_distinguishers
676     # route_targets
677     json_body = {"bgpvpn": kwargs}
678     return neutron_client.create_bgpvpn(json_body)
679
680
681 def create_network_association(neutron_client, bgpvpn_id, neutron_network_id):
682     json_body = {"network_association": {"network_id": neutron_network_id}}
683     return neutron_client.create_network_association(bgpvpn_id, json_body)
684
685
686 def update_bgpvpn(neutron_client, bgpvpn_id, **kwargs):
687     json_body = {"bgpvpn": kwargs}
688     return neutron_client.update_bgpvpn(bgpvpn_id, json_body)
689
690
691 def delete_bgpvpn(neutron_client, bgpvpn_id):
692     return neutron_client.delete_bgpvpn(bgpvpn_id)
693
694 # *********************************************
695 #   SEC GROUPS
696 # *********************************************
697
698
699 def get_security_groups(neutron_client):
700     try:
701         security_groups = neutron_client.list_security_groups()[
702             'security_groups']
703         return security_groups
704     except Exception, e:
705         logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
706         return None
707
708
709 def get_security_group_id(neutron_client, sg_name):
710     security_groups = get_security_groups(neutron_client)
711     id = ''
712     for sg in security_groups:
713         if sg['name'] == sg_name:
714             id = sg['id']
715             break
716     return id
717
718
719 def create_security_group(neutron_client, sg_name, sg_description):
720     json_body = {'security_group': {'name': sg_name,
721                                     'description': sg_description}}
722     try:
723         secgroup = neutron_client.create_security_group(json_body)
724         return secgroup['security_group']
725     except Exception, e:
726         logger.error("Error [create_security_group(neutron_client, '%s', "
727                      "'%s')]: %s" % (sg_name, sg_description, e))
728         return None
729
730
731 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
732                          port_range_min=None, port_range_max=None):
733     if port_range_min is None and port_range_max is None:
734         json_body = {'security_group_rule': {'direction': direction,
735                                              'security_group_id': sg_id,
736                                              'protocol': protocol}}
737     elif port_range_min is not None and port_range_max is not None:
738         json_body = {'security_group_rule': {'direction': direction,
739                                              'security_group_id': sg_id,
740                                              'port_range_min': port_range_min,
741                                              'port_range_max': port_range_max,
742                                              'protocol': protocol}}
743     else:
744         logger.error("Error [create_secgroup_rule(neutron_client, '%s', '%s', "
745                      "'%s', '%s', '%s', '%s')]:" % (neutron_client,
746                                                     sg_id, direction,
747                                                     port_range_min,
748                                                     port_range_max,
749                                                     protocol),
750                      " Invalid values for port_range_min, port_range_max")
751         return False
752     try:
753         neutron_client.create_security_group_rule(json_body)
754         return True
755     except Exception, e:
756         logger.error("Error [create_secgroup_rule(neutron_client, '%s', '%s', "
757                      "'%s', '%s', '%s', '%s')]: %s" % (neutron_client,
758                                                        sg_id,
759                                                        direction,
760                                                        port_range_min,
761                                                        port_range_max,
762                                                        protocol, e))
763         return False
764
765
766 def create_security_group_full(neutron_client,
767                                sg_name, sg_description):
768     sg_id = get_security_group_id(neutron_client, sg_name)
769     if sg_id != '':
770         logger.info("Using existing security group '%s'..." % sg_name)
771     else:
772         logger.info("Creating security group  '%s'..." % sg_name)
773         SECGROUP = create_security_group(neutron_client,
774                                          sg_name,
775                                          sg_description)
776         if not SECGROUP:
777             logger.error("Failed to create the security group...")
778             return None
779
780         sg_id = SECGROUP['id']
781
782         logger.debug("Security group '%s' with ID=%s created successfully."
783                      % (SECGROUP['name'], sg_id))
784
785         logger.debug("Adding ICMP rules in security group '%s'..."
786                      % sg_name)
787         if not create_secgroup_rule(neutron_client, sg_id,
788                                     'ingress', 'icmp'):
789             logger.error("Failed to create the security group rule...")
790             return None
791
792         logger.debug("Adding SSH rules in security group '%s'..."
793                      % sg_name)
794         if not create_secgroup_rule(
795                 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
796             logger.error("Failed to create the security group rule...")
797             return None
798
799         if not create_secgroup_rule(
800                 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
801             logger.error("Failed to create the security group rule...")
802             return None
803     return sg_id
804
805
806 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
807     try:
808         nova_client.servers.add_security_group(instance_id, secgroup_id)
809         return True
810     except Exception, e:
811         logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
812                      "'%s')]: %s" % (instance_id, secgroup_id, e))
813         return False
814
815
816 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
817     json_body = {"quota": {
818         "security_group": sg_quota,
819         "security_group_rule": sg_rule_quota
820     }}
821
822     try:
823         neutron_client.update_quota(tenant_id=tenant_id,
824                                     body=json_body)
825         return True
826     except Exception, e:
827         logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
828                      "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
829         return False
830
831
832 def delete_security_group(neutron_client, secgroup_id):
833     try:
834         neutron_client.delete_security_group(secgroup_id)
835         return True
836     except Exception, e:
837         logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
838                      % (secgroup_id, e))
839         return False
840
841
842 # *********************************************
843 #   GLANCE
844 # *********************************************
845 def get_images(nova_client):
846     try:
847         images = nova_client.images.list()
848         return images
849     except Exception, e:
850         logger.error("Error [get_images]: %s" % e)
851         return None
852
853
854 def get_image_id(glance_client, image_name):
855     images = glance_client.images.list()
856     id = ''
857     for i in images:
858         if i.name == image_name:
859             id = i.id
860             break
861     return id
862
863
864 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
865                         container="bare", public=True):
866     if not os.path.isfile(file_path):
867         logger.error("Error: file %s does not exist." % file_path)
868         return None
869     try:
870         image_id = get_image_id(glance_client, image_name)
871         if image_id != '':
872             if logger:
873                 logger.info("Image %s already exists." % image_name)
874         else:
875             if logger:
876                 logger.info("Creating image '%s' from '%s'..." % (image_name,
877                                                                   file_path))
878             with open(file_path) as fimage:
879                 image = glance_client.images.create(name=image_name,
880                                                     is_public=public,
881                                                     disk_format=disk,
882                                                     container_format=container,
883                                                     data=fimage)
884             image_id = image.id
885         return image_id
886     except Exception, e:
887         logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
888                      "'%s')]: %s" % (image_name, file_path, str(public), e))
889         return None
890
891
892 def get_or_create_image(name, path, format):
893     image_exists = False
894     glance_client = get_glance_client()
895
896     image_id = get_image_id(glance_client, name)
897     if image_id != '':
898         logger.info("Using existing image '%s'..." % name)
899         image_exists = True
900     else:
901         logger.info("Creating image '%s' from '%s'..." % (name, path))
902         image_id = create_glance_image(glance_client, name, path, format)
903         if not image_id:
904             logger.error("Failed to create a Glance image...")
905         else:
906             logger.debug("Image '%s' with ID=%s created successfully."
907                          % (name, image_id))
908
909     return image_exists, image_id
910
911
912 def delete_glance_image(nova_client, image_id):
913     try:
914         nova_client.images.delete(image_id)
915         return True
916     except Exception, e:
917         logger.error("Error [delete_glance_image(nova_client, '%s')]: %s"
918                      % (image_id, e))
919         return False
920
921
922 # *********************************************
923 #   CINDER
924 # *********************************************
925 def get_volumes(cinder_client):
926     try:
927         volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
928         return volumes
929     except Exception, e:
930         logger.error("Error [get_volumes(cinder_client)]: %s" % e)
931         return None
932
933
934 def list_volume_types(cinder_client, public=True, private=True):
935     try:
936         volume_types = cinder_client.volume_types.list()
937         if not public:
938             volume_types = [vt for vt in volume_types if not vt.is_public]
939         if not private:
940             volume_types = [vt for vt in volume_types if vt.is_public]
941         return volume_types
942     except Exception, e:
943         logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
944         return None
945
946
947 def create_volume_type(cinder_client, name):
948     try:
949         volume_type = cinder_client.volume_types.create(name)
950         return volume_type
951     except Exception, e:
952         logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
953                      % (name, e))
954         return None
955
956
957 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
958                         snapshots_quota, gigabytes_quota):
959     quotas_values = {"volumes": vols_quota,
960                      "snapshots": snapshots_quota,
961                      "gigabytes": gigabytes_quota}
962
963     try:
964         cinder_client.quotas.update(tenant_id, **quotas_values)
965         return True
966     except Exception, e:
967         logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
968                      "'%s' '%s')]: %s" % (tenant_id, vols_quota,
969                                           snapshots_quota, gigabytes_quota, e))
970         return False
971
972
973 def delete_volume(cinder_client, volume_id, forced=False):
974     try:
975         if forced:
976             try:
977                 cinder_client.volumes.detach(volume_id)
978             except:
979                 logger.error(sys.exc_info()[0])
980             cinder_client.volumes.force_delete(volume_id)
981         else:
982             cinder_client.volumes.delete(volume_id)
983         return True
984     except Exception, e:
985         logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
986                      % (volume_id, str(forced), e))
987         return False
988
989
990 def delete_volume_type(cinder_client, volume_type):
991     try:
992         cinder_client.volume_types.delete(volume_type)
993         return True
994     except Exception, e:
995         logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
996                      % (volume_type, e))
997         return False
998
999
1000 # *********************************************
1001 #   KEYSTONE
1002 # *********************************************
1003 def get_tenants(keystone_client):
1004     try:
1005         tenants = keystone_client.tenants.list()
1006         return tenants
1007     except Exception, e:
1008         logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1009         return None
1010
1011
1012 def get_users(keystone_client):
1013     try:
1014         users = keystone_client.users.list()
1015         return users
1016     except Exception, e:
1017         logger.error("Error [get_users(keystone_client)]: %s" % e)
1018         return None
1019
1020
1021 def get_tenant_id(keystone_client, tenant_name):
1022     tenants = keystone_client.tenants.list()
1023     id = ''
1024     for t in tenants:
1025         if t.name == tenant_name:
1026             id = t.id
1027             break
1028     return id
1029
1030
1031 def get_user_id(keystone_client, user_name):
1032     users = keystone_client.users.list()
1033     id = ''
1034     for u in users:
1035         if u.name == user_name:
1036             id = u.id
1037             break
1038     return id
1039
1040
1041 def get_role_id(keystone_client, role_name):
1042     roles = keystone_client.roles.list()
1043     id = ''
1044     for r in roles:
1045         if r.name == role_name:
1046             id = r.id
1047             break
1048     return id
1049
1050
1051 def create_tenant(keystone_client, tenant_name, tenant_description):
1052     try:
1053         tenant = keystone_client.tenants.create(tenant_name,
1054                                                 tenant_description,
1055                                                 enabled=True)
1056         return tenant.id
1057     except Exception, e:
1058         logger.error("Error [create_tenant(cinder_client, '%s', '%s')]: %s"
1059                      % (tenant_name, tenant_description, e))
1060         return None
1061
1062
1063 def create_user(keystone_client, user_name, user_password,
1064                 user_email, tenant_id):
1065     try:
1066         user = keystone_client.users.create(user_name, user_password,
1067                                             user_email, tenant_id,
1068                                             enabled=True)
1069         return user.id
1070     except Exception, e:
1071         logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1072                      "'%s')]: %s" % (user_name, user_password,
1073                                      user_email, tenant_id, e))
1074         return None
1075
1076
1077 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1078     try:
1079         keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1080         return True
1081     except Exception, e:
1082         logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1083                      "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1084         return False
1085
1086
1087 def delete_tenant(keystone_client, tenant_id):
1088     try:
1089         keystone_client.tenants.delete(tenant_id)
1090         return True
1091     except Exception, e:
1092         logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1093                      % (tenant_id, e))
1094         return False
1095
1096
1097 def delete_user(keystone_client, user_id):
1098     try:
1099         keystone_client.users.delete(user_id)
1100         return True
1101     except Exception, e:
1102         logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1103                      % (user_id, e))
1104         return False