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
17 from keystoneauth1 import loading
18 from keystoneauth1 import session
19 from cinderclient import client as cinderclient
20 from glanceclient import client as glanceclient
21 from heatclient import client as heatclient
22 from novaclient import client as novaclient
23 from keystoneclient import client as keystoneclient
24 from neutronclient.neutron import client as neutronclient
26 import functest.utils.functest_logger as ft_logger
27 import functest.utils.functest_utils as ft_utils
29 logger = ft_logger.Logger("openstack_utils").getLogger()
31 DEFAULT_API_VERSION = '2'
32 DEFAULT_HEAT_API_VERSION = '1'
35 # *********************************************
37 # *********************************************
38 class MissingEnvVar(Exception):
40 def __init__(self, var):
44 return str.format("Please set the mandatory env var: {}", self.var)
48 keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
49 if (keystone_api_version is None or
50 keystone_api_version == '2'):
56 def get_rc_env_vars():
57 env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD']
59 env_vars.extend(['OS_PROJECT_NAME',
60 'OS_USER_DOMAIN_NAME',
61 'OS_PROJECT_DOMAIN_NAME'])
63 env_vars.extend(['OS_TENANT_NAME'])
67 def check_credentials():
69 Check if the OpenStack credentials (openrc) are sourced
71 env_vars = get_rc_env_vars()
72 return all(map(lambda v: v in os.environ and os.environ[v], env_vars))
75 def get_env_cred_dict():
77 'OS_USERNAME': 'username',
78 'OS_PASSWORD': 'password',
79 'OS_AUTH_URL': 'auth_url',
80 'OS_TENANT_NAME': 'tenant_name',
81 'OS_USER_DOMAIN_NAME': 'user_domain_name',
82 'OS_PROJECT_DOMAIN_NAME': 'project_domain_name',
83 'OS_PROJECT_NAME': 'project_name',
84 'OS_ENDPOINT_TYPE': 'endpoint_type',
85 'OS_REGION_NAME': 'region_name',
86 'OS_CACERT': 'https_cacert'
91 def get_credentials(other_creds={}):
92 """Returns a creds dictionary filled with parsed from env
95 env_vars = get_rc_env_vars()
96 env_cred_dict = get_env_cred_dict()
98 for envvar in env_vars:
99 if os.getenv(envvar) is None:
100 raise MissingEnvVar(envvar)
102 creds_key = env_cred_dict.get(envvar)
103 creds.update({creds_key: os.getenv(envvar)})
105 if 'tenant' in other_creds.keys():
107 tenant = 'project_name'
109 tenant = 'tenant_name'
110 other_creds[tenant] = other_creds.pop('tenant')
112 creds.update(other_creds)
117 def source_credentials(rc_file):
118 with open(rc_file, "r") as f:
120 var = line.rstrip('"\n').replace('export ', '').split("=")
121 # The two next lines should be modified as soon as rc_file
122 # conforms with common rules. Be aware that it could induce
123 # issues if value starts with '
124 key = re.sub(r'^["\' ]*|[ \'"]*$', '', var[0])
125 value = re.sub(r'^["\' ]*|[ \'"]*$', '', "".join(var[1:]))
126 os.environ[key] = value
129 def get_credentials_for_rally():
130 creds = get_credentials()
131 env_cred_dict = get_env_cred_dict()
132 rally_conf = {"type": "ExistingCloud", "admin": {}}
134 if key == 'auth_url':
135 rally_conf[key] = creds[key]
137 rally_conf['admin'][key] = creds[key]
139 endpoint_types = [('internalURL', 'internal'),
140 ('publicURL', 'public'), ('adminURL', 'admin')]
142 endpoint_type = os.getenv('OS_ENDPOINT_TYPE')
143 if endpoint_type is not None:
144 cred_key = env_cred_dict.get('OS_ENDPOINT_TYPE')
145 for k, v in endpoint_types:
146 if endpoint_type == k:
147 rally_conf[cred_key] = v
149 region_name = os.getenv('OS_REGION_NAME')
150 if region_name is not None:
151 cred_key = env_cred_dict.get('OS_REGION_NAME')
152 rally_conf[cred_key] = region_name
154 cacert = os.getenv('OS_CACERT')
155 if cacert is not None:
156 cred_key = env_cred_dict.get('OS_CACERT')
157 rally_conf[cred_key] = cacert
161 def get_session_auth(other_creds={}):
162 loader = loading.get_plugin_loader('password')
163 creds = get_credentials(other_creds)
164 auth = loader.load_from_options(**creds)
168 def get_endpoint(service_type, endpoint_type='publicURL'):
169 auth = get_session_auth()
170 return get_session().get_endpoint(auth=auth,
171 service_type=service_type,
172 endpoint_type=endpoint_type)
175 def get_session(other_creds={}):
176 auth = get_session_auth(other_creds)
177 cacert = os.getenv('OS_CACERT')
178 if cacert is not None:
179 if not os.path.isfile(cacert):
180 raise Exception("The 'OS_CACERT' environment"
181 "variable is set to %s but the file"
182 "does not exist.", cacert)
184 return session.Session(auth=auth, verify=cacert)
187 # *********************************************
189 # *********************************************
190 def get_keystone_client_version():
191 api_version = os.getenv('OS_IDENTITY_API_VERSION')
192 if api_version is not None:
193 logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
196 return DEFAULT_API_VERSION
199 def get_keystone_client(other_creds={}):
200 sess = get_session(other_creds)
201 return keystoneclient.Client(get_keystone_client_version(), session=sess)
204 def get_nova_client_version():
205 api_version = os.getenv('OS_COMPUTE_API_VERSION')
206 if api_version is not None:
207 logger.info("OS_COMPUTE_API_VERSION is set in env as '%s'",
210 return DEFAULT_API_VERSION
213 def get_nova_client(other_creds={}):
214 sess = get_session(other_creds)
215 return novaclient.Client(get_nova_client_version(), session=sess)
218 def get_cinder_client_version():
219 api_version = os.getenv('OS_VOLUME_API_VERSION')
220 if api_version is not None:
221 logger.info("OS_VOLUME_API_VERSION is set in env as '%s'",
224 return DEFAULT_API_VERSION
227 def get_cinder_client(other_creds={}):
228 sess = get_session(other_creds)
229 return cinderclient.Client(get_cinder_client_version(), session=sess)
232 def get_neutron_client_version():
233 api_version = os.getenv('OS_NETWORK_API_VERSION')
234 if api_version is not None:
235 logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
238 return DEFAULT_API_VERSION
241 def get_neutron_client(other_creds={}):
242 sess = get_session(other_creds)
243 return neutronclient.Client(get_neutron_client_version(), session=sess)
246 def get_glance_client_version():
247 api_version = os.getenv('OS_IMAGE_API_VERSION')
248 if api_version is not None:
249 logger.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version)
251 return DEFAULT_API_VERSION
254 def get_glance_client(other_creds={}):
255 sess = get_session(other_creds)
256 return glanceclient.Client(get_glance_client_version(), session=sess)
259 def get_heat_client_version():
260 api_version = os.getenv('OS_ORCHESTRATION_API_VERSION')
261 if api_version is not None:
262 logger.info("OS_ORCHESTRATION_API_VERSION is set in env as '%s'",
265 return DEFAULT_HEAT_API_VERSION
268 def get_heat_client(other_creds={}):
269 sess = get_session(other_creds)
270 return heatclient.Client(get_heat_client_version(), session=sess)
273 # *********************************************
275 # *********************************************
276 def get_instances(nova_client):
278 instances = nova_client.servers.list(search_opts={'all_tenants': 1})
281 logger.error("Error [get_instances(nova_client)]: %s" % e)
285 def get_instance_status(nova_client, instance):
287 instance = nova_client.servers.get(instance.id)
288 return instance.status
290 logger.error("Error [get_instance_status(nova_client)]: %s" % e)
294 def get_instance_by_name(nova_client, instance_name):
296 instance = nova_client.servers.find(name=instance_name)
299 logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
300 % (instance_name, e))
304 def get_flavor_id(nova_client, flavor_name):
305 flavors = nova_client.flavors.list(detailed=True)
308 if f.name == flavor_name:
314 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
315 flavors = nova_client.flavors.list(detailed=True)
318 if min_ram <= f.ram and f.ram <= max_ram:
324 def get_aggregates(nova_client):
326 aggregates = nova_client.aggregates.list()
329 logger.error("Error [get_aggregates(nova_client)]: %s" % e)
333 def get_aggregate_id(nova_client, aggregate_name):
335 aggregates = get_aggregates(nova_client)
336 _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
339 logger.error("Error [get_aggregate_id(nova_client, %s)]:"
340 " %s" % (aggregate_name, e))
344 def get_availability_zones(nova_client):
346 availability_zones = nova_client.availability_zones.list()
347 return availability_zones
349 logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
353 def get_availability_zone_names(nova_client):
355 az_names = [az.zoneName for az in get_availability_zones(nova_client)]
358 logger.error("Error [get_availability_zone_names(nova_client)]:"
363 def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
365 flavor = nova_client.flavors.create(
366 flavor_name, ram, vcpus, disk, is_public=public)
368 extra_specs = ft_utils.get_functest_config(
369 'general.flavor_extra_specs')
370 flavor.set_keys(extra_specs)
372 # flavor extra specs are not configured, therefore skip the update
376 logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
377 "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
382 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
383 flavor_exists = False
384 nova_client = get_nova_client()
386 flavor_id = get_flavor_id(nova_client, flavor_name)
388 logger.info("Using existing flavor '%s'..." % flavor_name)
391 logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
392 "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
393 flavor_id = create_flavor(
394 nova_client, flavor_name, ram, disk, vcpus, public=public)
396 logger.error("Failed to create flavor '%s'..." % (flavor_name))
398 logger.debug("Flavor '%s' with ID=%s created successfully."
399 % (flavor_name, flavor_id))
401 return flavor_exists, flavor_id
404 def get_floating_ips(nova_client):
406 floating_ips = nova_client.floating_ips.list()
409 logger.error("Error [get_floating_ips(nova_client)]: %s" % e)
413 def get_hypervisors(nova_client):
416 hypervisors = nova_client.hypervisors.list()
417 for hypervisor in hypervisors:
418 if hypervisor.state == "up":
419 nodes.append(hypervisor.hypervisor_hostname)
422 logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
426 def create_aggregate(nova_client, aggregate_name, av_zone):
428 nova_client.aggregates.create(aggregate_name, av_zone)
431 logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
432 % (aggregate_name, av_zone, e))
436 def add_host_to_aggregate(nova_client, aggregate_name, compute_host):
438 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
439 nova_client.aggregates.add_host(aggregate_id, compute_host)
442 logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
443 % (aggregate_name, compute_host, e))
447 def create_aggregate_with_host(
448 nova_client, aggregate_name, av_zone, compute_host):
450 create_aggregate(nova_client, aggregate_name, av_zone)
451 add_host_to_aggregate(nova_client, aggregate_name, compute_host)
454 logger.error("Error [create_aggregate_with_host("
455 "nova_client, %s, %s, %s)]: %s"
456 % (aggregate_name, av_zone, compute_host, e))
460 def create_instance(flavor_name,
463 instance_name="functest-vm",
469 nova_client = get_nova_client()
471 flavor = nova_client.flavors.find(name=flavor_name)
473 flavors = nova_client.flavors.list()
474 logger.error("Error: Flavor '%s' not found. Available flavors are: "
475 "\n%s" % (flavor_name, flavors))
477 if fixed_ip is not None:
478 nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
480 nics = {"net-id": network_id}
482 instance = nova_client.servers.create(
487 availability_zone=av_zone,
491 instance = nova_client.servers.create(
496 config_drive=confdrive,
498 availability_zone=av_zone,
504 def create_instance_and_wait_for_active(flavor_name,
514 VM_BOOT_TIMEOUT = 180
515 nova_client = get_nova_client()
516 instance = create_instance(flavor_name,
525 count = VM_BOOT_TIMEOUT / SLEEP
526 for n in range(count, -1, -1):
527 status = get_instance_status(nova_client, instance)
528 if status.lower() == "active":
530 elif status.lower() == "error":
531 logger.error("The instance %s went to ERROR status."
535 logger.error("Timeout booting the instance %s." % instance_name)
539 def create_floating_ip(neutron_client):
540 extnet_id = get_external_net_id(neutron_client)
541 props = {'floating_network_id': extnet_id}
543 ip_json = neutron_client.create_floatingip({'floatingip': props})
544 fip_addr = ip_json['floatingip']['floating_ip_address']
545 fip_id = ip_json['floatingip']['id']
547 logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
549 return {'fip_addr': fip_addr, 'fip_id': fip_id}
552 def add_floating_ip(nova_client, server_id, floatingip_addr):
554 nova_client.servers.add_floating_ip(server_id, floatingip_addr)
557 logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
558 % (server_id, floatingip_addr, e))
562 def delete_instance(nova_client, instance_id):
564 nova_client.servers.force_delete(instance_id)
567 logger.error("Error [delete_instance(nova_client, '%s')]: %s"
572 def delete_floating_ip(nova_client, floatingip_id):
574 nova_client.floating_ips.delete(floatingip_id)
577 logger.error("Error [delete_floating_ip(nova_client, '%s')]: %s"
578 % (floatingip_id, e))
582 def remove_host_from_aggregate(nova_client, aggregate_name, compute_host):
584 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
585 nova_client.aggregates.remove_host(aggregate_id, compute_host)
588 logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
589 " %s" % (aggregate_name, compute_host, e))
593 def remove_hosts_from_aggregate(nova_client, aggregate_name):
594 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
595 hosts = nova_client.aggregates.get(aggregate_id).hosts
597 all(remove_host_from_aggregate(nova_client, aggregate_name, host)
601 def delete_aggregate(nova_client, aggregate_name):
603 remove_hosts_from_aggregate(nova_client, aggregate_name)
604 nova_client.aggregates.delete(aggregate_name)
607 logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
608 % (aggregate_name, e))
612 # *********************************************
614 # *********************************************
615 def get_network_list(neutron_client):
616 network_list = neutron_client.list_networks()['networks']
617 if len(network_list) == 0:
623 def get_router_list(neutron_client):
624 router_list = neutron_client.list_routers()['routers']
625 if len(router_list) == 0:
631 def get_port_list(neutron_client):
632 port_list = neutron_client.list_ports()['ports']
633 if len(port_list) == 0:
639 def get_network_id(neutron_client, network_name):
640 networks = neutron_client.list_networks()['networks']
643 if n['name'] == network_name:
649 def get_subnet_id(neutron_client, subnet_name):
650 subnets = neutron_client.list_subnets()['subnets']
653 if s['name'] == subnet_name:
659 def get_router_id(neutron_client, router_name):
660 routers = neutron_client.list_routers()['routers']
663 if r['name'] == router_name:
669 def get_private_net(neutron_client):
670 # Checks if there is an existing shared private network
671 networks = neutron_client.list_networks()['networks']
672 if len(networks) == 0:
675 if (net['router:external'] is False) and (net['shared'] is True):
680 def get_external_net(neutron_client):
681 for network in neutron_client.list_networks()['networks']:
682 if network['router:external']:
683 return network['name']
687 def get_external_net_id(neutron_client):
688 for network in neutron_client.list_networks()['networks']:
689 if network['router:external']:
694 def check_neutron_net(neutron_client, net_name):
695 for network in neutron_client.list_networks()['networks']:
696 if network['name'] == net_name:
697 for subnet in network['subnets']:
702 def create_neutron_net(neutron_client, name):
703 json_body = {'network': {'name': name,
704 'admin_state_up': True}}
706 network = neutron_client.create_network(body=json_body)
707 network_dict = network['network']
708 return network_dict['id']
710 logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
715 def create_neutron_subnet(neutron_client, name, cidr, net_id):
716 json_body = {'subnets': [{'name': name, 'cidr': cidr,
717 'ip_version': 4, 'network_id': net_id}]}
719 subnet = neutron_client.create_subnet(body=json_body)
720 return subnet['subnets'][0]['id']
722 logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
723 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
727 def create_neutron_router(neutron_client, name):
728 json_body = {'router': {'name': name, 'admin_state_up': True}}
730 router = neutron_client.create_router(json_body)
731 return router['router']['id']
733 logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
738 def create_neutron_port(neutron_client, name, network_id, ip):
739 json_body = {'port': {
740 'admin_state_up': True,
742 'network_id': network_id,
743 'fixed_ips': [{"ip_address": ip}]
746 port = neutron_client.create_port(body=json_body)
747 return port['port']['id']
749 logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
750 "'%s')]: %s" % (name, network_id, ip, e))
754 def update_neutron_net(neutron_client, network_id, shared=False):
755 json_body = {'network': {'shared': shared}}
757 neutron_client.update_network(network_id, body=json_body)
760 logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
761 "%s" % (network_id, str(shared), e))
765 def update_neutron_port(neutron_client, port_id, device_owner):
766 json_body = {'port': {
767 'device_owner': device_owner,
770 port = neutron_client.update_port(port=port_id,
772 return port['port']['id']
774 logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
775 " %s" % (port_id, device_owner, e))
779 def add_interface_router(neutron_client, router_id, subnet_id):
780 json_body = {"subnet_id": subnet_id}
782 neutron_client.add_interface_router(router=router_id, body=json_body)
785 logger.error("Error [add_interface_router(neutron_client, '%s', "
786 "'%s')]: %s" % (router_id, subnet_id, e))
790 def add_gateway_router(neutron_client, router_id):
791 ext_net_id = get_external_net_id(neutron_client)
792 router_dict = {'network_id': ext_net_id}
794 neutron_client.add_gateway_router(router_id, router_dict)
797 logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
802 def delete_neutron_net(neutron_client, network_id):
804 neutron_client.delete_network(network_id)
807 logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
812 def delete_neutron_subnet(neutron_client, subnet_id):
814 neutron_client.delete_subnet(subnet_id)
817 logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
822 def delete_neutron_router(neutron_client, router_id):
824 neutron_client.delete_router(router=router_id)
827 logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
832 def delete_neutron_port(neutron_client, port_id):
834 neutron_client.delete_port(port_id)
837 logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
842 def remove_interface_router(neutron_client, router_id, subnet_id):
843 json_body = {"subnet_id": subnet_id}
845 neutron_client.remove_interface_router(router=router_id,
849 logger.error("Error [remove_interface_router(neutron_client, '%s', "
850 "'%s')]: %s" % (router_id, subnet_id, e))
854 def remove_gateway_router(neutron_client, router_id):
856 neutron_client.remove_gateway_router(router_id)
859 logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
864 def create_network_full(neutron_client,
870 # Check if the network already exists
871 network_id = get_network_id(neutron_client, net_name)
872 subnet_id = get_subnet_id(neutron_client, subnet_name)
873 router_id = get_router_id(neutron_client, router_name)
875 if network_id != '' and subnet_id != '' and router_id != '':
876 logger.info("A network with name '%s' already exists..." % net_name)
878 neutron_client.format = 'json'
879 logger.info('Creating neutron network %s...' % net_name)
880 network_id = create_neutron_net(neutron_client, net_name)
885 logger.debug("Network '%s' created successfully" % network_id)
886 logger.debug('Creating Subnet....')
887 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
892 logger.debug("Subnet '%s' created successfully" % subnet_id)
893 logger.debug('Creating Router...')
894 router_id = create_neutron_router(neutron_client, router_name)
899 logger.debug("Router '%s' created successfully" % router_id)
900 logger.debug('Adding router to subnet...')
902 if not add_interface_router(neutron_client, router_id, subnet_id):
905 logger.debug("Interface added successfully.")
907 logger.debug('Adding gateway to router...')
908 if not add_gateway_router(neutron_client, router_id):
911 logger.debug("Gateway added successfully.")
913 network_dic = {'net_id': network_id,
914 'subnet_id': subnet_id,
915 'router_id': router_id}
919 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
920 neutron_client = get_neutron_client()
922 network_dic = create_network_full(neutron_client,
928 if not update_neutron_net(neutron_client,
929 network_dic['net_id'],
931 logger.error("Failed to update network %s..." % net_name)
934 logger.debug("Network '%s' is available..." % net_name)
936 logger.error("Network %s creation failed" % net_name)
941 def create_bgpvpn(neutron_client, **kwargs):
942 # route_distinguishers
944 json_body = {"bgpvpn": kwargs}
945 return neutron_client.create_bgpvpn(json_body)
948 def create_network_association(neutron_client, bgpvpn_id, neutron_network_id):
949 json_body = {"network_association": {"network_id": neutron_network_id}}
950 return neutron_client.create_network_association(bgpvpn_id, json_body)
953 def create_router_association(neutron_client, bgpvpn_id, router_id):
954 json_body = {"router_association": {"router_id": router_id}}
955 return neutron_client.create_router_association(bgpvpn_id, json_body)
958 def update_bgpvpn(neutron_client, bgpvpn_id, **kwargs):
959 json_body = {"bgpvpn": kwargs}
960 return neutron_client.update_bgpvpn(bgpvpn_id, json_body)
963 def delete_bgpvpn(neutron_client, bgpvpn_id):
964 return neutron_client.delete_bgpvpn(bgpvpn_id)
967 def get_bgpvpn(neutron_client, bgpvpn_id):
968 return neutron_client.show_bgpvpn(bgpvpn_id)
971 def get_bgpvpn_routers(neutron_client, bgpvpn_id):
972 return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['routers']
975 def get_bgpvpn_networks(neutron_client, bgpvpn_id):
976 return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['networks']
978 # *********************************************
980 # *********************************************
983 def get_security_groups(neutron_client):
985 security_groups = neutron_client.list_security_groups()[
987 return security_groups
989 logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
993 def get_security_group_id(neutron_client, sg_name):
994 security_groups = get_security_groups(neutron_client)
996 for sg in security_groups:
997 if sg['name'] == sg_name:
1003 def create_security_group(neutron_client, sg_name, sg_description):
1004 json_body = {'security_group': {'name': sg_name,
1005 'description': sg_description}}
1007 secgroup = neutron_client.create_security_group(json_body)
1008 return secgroup['security_group']
1009 except Exception, e:
1010 logger.error("Error [create_security_group(neutron_client, '%s', "
1011 "'%s')]: %s" % (sg_name, sg_description, e))
1015 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
1016 port_range_min=None, port_range_max=None):
1017 # We create a security group in 2 steps
1018 # 1 - we check the format and set the json body accordingly
1019 # 2 - we call neturon client to create the security group
1022 json_body = {'security_group_rule': {'direction': direction,
1023 'security_group_id': sg_id,
1024 'protocol': protocol}}
1026 # - both None => we do nothing
1027 # - both Not None => we add them to the json description
1028 # but one cannot be None is the other is not None
1029 if (port_range_min is not None and port_range_max is not None):
1030 # add port_range in json description
1031 json_body['security_group_rule']['port_range_min'] = port_range_min
1032 json_body['security_group_rule']['port_range_max'] = port_range_max
1033 logger.debug("Security_group format set (port range included)")
1035 # either both port range are set to None => do nothing
1036 # or one is set but not the other => log it and return False
1037 if port_range_min is None and port_range_max is None:
1038 logger.debug("Security_group format set (no port range mentioned)")
1040 logger.error("Bad security group format."
1041 "One of the port range is not properly set:"
1043 "range max: {}".format(port_range_min,
1047 # Create security group using neutron client
1049 neutron_client.create_security_group_rule(json_body)
1052 logger.exception("Impossible to create_security_group_rule,"
1053 "security group rule probably already exists")
1057 def get_security_group_rules(neutron_client, sg_id):
1059 security_rules = neutron_client.list_security_group_rules()[
1060 'security_group_rules']
1061 security_rules = [rule for rule in security_rules
1062 if rule["security_group_id"] == sg_id]
1063 return security_rules
1064 except Exception, e:
1065 logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:"
1070 def check_security_group_rules(neutron_client, sg_id, direction, protocol,
1071 port_min=None, port_max=None):
1073 security_rules = get_security_group_rules(neutron_client, sg_id)
1074 security_rules = [rule for rule in security_rules
1075 if (rule["direction"].lower() == direction
1076 and rule["protocol"].lower() == protocol
1077 and rule["port_range_min"] == port_min
1078 and rule["port_range_max"] == port_max)]
1079 if len(security_rules) == 0:
1083 except Exception, e:
1084 logger.error("Error [check_security_group_rules("
1085 " neutron_client, sg_id, direction,"
1086 " protocol, port_min=None, port_max=None)]: "
1091 def create_security_group_full(neutron_client,
1092 sg_name, sg_description):
1093 sg_id = get_security_group_id(neutron_client, sg_name)
1095 logger.info("Using existing security group '%s'..." % sg_name)
1097 logger.info("Creating security group '%s'..." % sg_name)
1098 SECGROUP = create_security_group(neutron_client,
1102 logger.error("Failed to create the security group...")
1105 sg_id = SECGROUP['id']
1107 logger.debug("Security group '%s' with ID=%s created successfully."
1108 % (SECGROUP['name'], sg_id))
1110 logger.debug("Adding ICMP rules in security group '%s'..."
1112 if not create_secgroup_rule(neutron_client, sg_id,
1114 logger.error("Failed to create the security group rule...")
1117 logger.debug("Adding SSH rules in security group '%s'..."
1119 if not create_secgroup_rule(
1120 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1121 logger.error("Failed to create the security group rule...")
1124 if not create_secgroup_rule(
1125 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1126 logger.error("Failed to create the security group rule...")
1131 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
1133 nova_client.servers.add_security_group(instance_id, secgroup_id)
1135 except Exception, e:
1136 logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
1137 "'%s')]: %s" % (instance_id, secgroup_id, e))
1141 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1142 json_body = {"quota": {
1143 "security_group": sg_quota,
1144 "security_group_rule": sg_rule_quota
1148 neutron_client.update_quota(tenant_id=tenant_id,
1151 except Exception, e:
1152 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1153 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1157 def delete_security_group(neutron_client, secgroup_id):
1159 neutron_client.delete_security_group(secgroup_id)
1161 except Exception, e:
1162 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1167 # *********************************************
1169 # *********************************************
1170 def get_images(nova_client):
1172 images = nova_client.images.list()
1174 except Exception, e:
1175 logger.error("Error [get_images]: %s" % e)
1179 def get_image_id(glance_client, image_name):
1180 images = glance_client.images.list()
1183 if i.name == image_name:
1189 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
1190 container="bare", public="public"):
1191 if not os.path.isfile(file_path):
1192 logger.error("Error: file %s does not exist." % file_path)
1195 image_id = get_image_id(glance_client, image_name)
1197 logger.info("Image %s already exists." % image_name)
1199 logger.info("Creating image '%s' from '%s'..." % (image_name,
1202 image = glance_client.images.create(name=image_name,
1205 container_format=container)
1207 with open(file_path) as image_data:
1208 glance_client.images.upload(image_id, image_data)
1210 except Exception, e:
1211 logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1212 "'%s')]: %s" % (image_name, file_path, public, e))
1216 def get_or_create_image(name, path, format):
1217 image_exists = False
1218 glance_client = get_glance_client()
1220 image_id = get_image_id(glance_client, name)
1222 logger.info("Using existing image '%s'..." % name)
1225 logger.info("Creating image '%s' from '%s'..." % (name, path))
1226 image_id = create_glance_image(glance_client, name, path, format)
1228 logger.error("Failed to create a Glance image...")
1230 logger.debug("Image '%s' with ID=%s created successfully."
1233 return image_exists, image_id
1236 def delete_glance_image(nova_client, image_id):
1238 nova_client.images.delete(image_id)
1240 except Exception, e:
1241 logger.error("Error [delete_glance_image(nova_client, '%s')]: %s"
1246 # *********************************************
1248 # *********************************************
1249 def get_volumes(cinder_client):
1251 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1253 except Exception, e:
1254 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1258 def list_volume_types(cinder_client, public=True, private=True):
1260 volume_types = cinder_client.volume_types.list()
1262 volume_types = [vt for vt in volume_types if not vt.is_public]
1264 volume_types = [vt for vt in volume_types if vt.is_public]
1266 except Exception, e:
1267 logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
1271 def create_volume_type(cinder_client, name):
1273 volume_type = cinder_client.volume_types.create(name)
1275 except Exception, e:
1276 logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
1281 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1282 snapshots_quota, gigabytes_quota):
1283 quotas_values = {"volumes": vols_quota,
1284 "snapshots": snapshots_quota,
1285 "gigabytes": gigabytes_quota}
1288 cinder_client.quotas.update(tenant_id, **quotas_values)
1290 except Exception, e:
1291 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1292 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1293 snapshots_quota, gigabytes_quota, e))
1297 def delete_volume(cinder_client, volume_id, forced=False):
1301 cinder_client.volumes.detach(volume_id)
1303 logger.error(sys.exc_info()[0])
1304 cinder_client.volumes.force_delete(volume_id)
1306 cinder_client.volumes.delete(volume_id)
1308 except Exception, e:
1309 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1310 % (volume_id, str(forced), e))
1314 def delete_volume_type(cinder_client, volume_type):
1316 cinder_client.volume_types.delete(volume_type)
1318 except Exception, e:
1319 logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
1324 # *********************************************
1326 # *********************************************
1327 def get_tenants(keystone_client):
1329 if is_keystone_v3():
1330 tenants = keystone_client.projects.list()
1332 tenants = keystone_client.tenants.list()
1334 except Exception, e:
1335 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1339 def get_users(keystone_client):
1341 users = keystone_client.users.list()
1343 except Exception, e:
1344 logger.error("Error [get_users(keystone_client)]: %s" % e)
1348 def get_tenant_id(keystone_client, tenant_name):
1349 tenants = get_tenants(keystone_client)
1352 if t.name == tenant_name:
1358 def get_user_id(keystone_client, user_name):
1359 users = get_users(keystone_client)
1362 if u.name == user_name:
1368 def get_role_id(keystone_client, role_name):
1369 roles = keystone_client.roles.list()
1372 if r.name == role_name:
1378 def create_tenant(keystone_client, tenant_name, tenant_description):
1380 if is_keystone_v3():
1381 tenant = keystone_client.projects.create(
1383 description=tenant_description,
1387 tenant = keystone_client.tenants.create(tenant_name,
1391 except Exception, e:
1392 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1393 % (tenant_name, tenant_description, e))
1397 def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
1398 tenant_id = get_tenant_id(keystone_client, tenant_name)
1400 tenant_id = create_tenant(keystone_client, tenant_name,
1406 def create_user(keystone_client, user_name, user_password,
1407 user_email, tenant_id):
1409 if is_keystone_v3():
1410 user = keystone_client.users.create(name=user_name,
1411 password=user_password,
1413 project_id=tenant_id,
1416 user = keystone_client.users.create(user_name,
1422 except Exception, e:
1423 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1424 "'%s')]: %s" % (user_name, user_password,
1425 user_email, tenant_id, e))
1429 def get_or_create_user(keystone_client, user_name, user_password,
1430 tenant_id, user_email=None):
1431 user_id = get_user_id(keystone_client, user_name)
1433 user_id = create_user(keystone_client, user_name, user_password,
1434 user_email, tenant_id)
1438 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1440 if is_keystone_v3():
1441 keystone_client.roles.grant(role=role_id,
1445 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1447 except Exception, e:
1448 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1449 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1453 def delete_tenant(keystone_client, tenant_id):
1455 if is_keystone_v3():
1456 keystone_client.projects.delete(tenant_id)
1458 keystone_client.tenants.delete(tenant_id)
1460 except Exception, e:
1461 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1466 def delete_user(keystone_client, user_id):
1468 keystone_client.users.delete(user_id)
1470 except Exception, e:
1471 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1476 # *********************************************
1478 # *********************************************
1479 def get_resource(heat_client, stack_id, resource):
1481 resources = heat_client.resources.get(stack_id, resource)
1483 except Exception, e:
1484 logger.error("Error [get_resource]: %s" % e)