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_utils as ft_utils
28 logger = logging.getLogger(__name__)
30 DEFAULT_API_VERSION = '2'
31 DEFAULT_HEAT_API_VERSION = '1'
34 # *********************************************
36 # *********************************************
37 class MissingEnvVar(Exception):
39 def __init__(self, var):
43 return str.format("Please set the mandatory env var: {}", self.var)
47 keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
48 if (keystone_api_version is None or
49 keystone_api_version == '2'):
55 def get_rc_env_vars():
56 env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD']
58 env_vars.extend(['OS_PROJECT_NAME',
59 'OS_USER_DOMAIN_NAME',
60 'OS_PROJECT_DOMAIN_NAME'])
62 env_vars.extend(['OS_TENANT_NAME'])
66 def check_credentials():
68 Check if the OpenStack credentials (openrc) are sourced
70 env_vars = get_rc_env_vars()
71 return all(map(lambda v: v in os.environ and os.environ[v], env_vars))
74 def get_env_cred_dict():
76 'OS_USERNAME': 'username',
77 'OS_PASSWORD': 'password',
78 'OS_AUTH_URL': 'auth_url',
79 'OS_TENANT_NAME': 'tenant_name',
80 'OS_USER_DOMAIN_NAME': 'user_domain_name',
81 'OS_PROJECT_DOMAIN_NAME': 'project_domain_name',
82 'OS_PROJECT_NAME': 'project_name',
83 'OS_ENDPOINT_TYPE': 'endpoint_type',
84 'OS_REGION_NAME': 'region_name',
85 'OS_CACERT': 'https_cacert',
86 'OS_INSECURE': 'https_insecure'
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 = get_endpoint_type_from_env()
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 == v:
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 cred_key = env_cred_dict.get('OS_CACERT')
155 rally_conf[cred_key] = os.getenv('OS_CACERT', '')
157 insecure_key = env_cred_dict.get('OS_INSECURE')
158 rally_conf[insecure_key] = os.getenv('OS_INSECURE', '').lower() == 'true'
163 def get_endpoint_type_from_env():
164 endpoint_type = os.environ.get("OS_ENDPOINT_TYPE",
165 os.environ.get("OS_INTERFACE"))
166 if endpoint_type and "URL" in endpoint_type:
167 endpoint_type = endpoint_type.replace("URL", "")
171 def get_session_auth(other_creds={}):
172 loader = loading.get_plugin_loader('password')
173 creds = get_credentials(other_creds)
174 auth = loader.load_from_options(**creds)
178 def get_endpoint(service_type, endpoint_type='publicURL'):
179 auth = get_session_auth()
180 return get_session().get_endpoint(auth=auth,
181 service_type=service_type,
182 endpoint_type=endpoint_type)
185 def get_session(other_creds={}):
186 auth = get_session_auth(other_creds)
187 https_cacert = os.getenv('OS_CACERT', '')
188 https_insecure = os.getenv('OS_INSECURE', '').lower() == 'true'
189 return session.Session(auth=auth,
190 verify=(https_cacert or not https_insecure))
193 # *********************************************
195 # *********************************************
196 def get_keystone_client_version():
197 api_version = os.getenv('OS_IDENTITY_API_VERSION')
198 if api_version is not None:
199 logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
202 return DEFAULT_API_VERSION
205 def get_keystone_client(other_creds={}):
206 sess = get_session(other_creds)
207 return keystoneclient.Client(get_keystone_client_version(),
209 interface=os.getenv('OS_INTERFACE', 'admin'))
212 def get_nova_client_version():
213 api_version = os.getenv('OS_COMPUTE_API_VERSION')
214 if api_version is not None:
215 logger.info("OS_COMPUTE_API_VERSION is set in env as '%s'",
218 return DEFAULT_API_VERSION
221 def get_nova_client(other_creds={}):
222 sess = get_session(other_creds)
223 return novaclient.Client(get_nova_client_version(), session=sess)
226 def get_cinder_client_version():
227 api_version = os.getenv('OS_VOLUME_API_VERSION')
228 if api_version is not None:
229 logger.info("OS_VOLUME_API_VERSION is set in env as '%s'",
232 return DEFAULT_API_VERSION
235 def get_cinder_client(other_creds={}):
236 sess = get_session(other_creds)
237 return cinderclient.Client(get_cinder_client_version(), session=sess)
240 def get_neutron_client_version():
241 api_version = os.getenv('OS_NETWORK_API_VERSION')
242 if api_version is not None:
243 logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
246 return DEFAULT_API_VERSION
249 def get_neutron_client(other_creds={}):
250 sess = get_session(other_creds)
251 return neutronclient.Client(get_neutron_client_version(), session=sess)
254 def get_glance_client_version():
255 api_version = os.getenv('OS_IMAGE_API_VERSION')
256 if api_version is not None:
257 logger.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version)
259 return DEFAULT_API_VERSION
262 def get_glance_client(other_creds={}):
263 sess = get_session(other_creds)
264 return glanceclient.Client(get_glance_client_version(), session=sess)
267 def get_heat_client_version():
268 api_version = os.getenv('OS_ORCHESTRATION_API_VERSION')
269 if api_version is not None:
270 logger.info("OS_ORCHESTRATION_API_VERSION is set in env as '%s'",
273 return DEFAULT_HEAT_API_VERSION
276 def get_heat_client(other_creds={}):
277 sess = get_session(other_creds)
278 return heatclient.Client(get_heat_client_version(), session=sess)
281 def download_and_add_image_on_glance(glance, image_name, image_url, data_dir):
283 if not os.path.exists(dest_path):
284 os.makedirs(dest_path)
285 file_name = image_url.rsplit('/')[-1]
286 if not ft_utils.download_url(image_url, dest_path):
289 image = create_glance_image(
290 glance, image_name, dest_path + file_name)
297 # *********************************************
299 # *********************************************
300 def get_instances(nova_client):
302 instances = nova_client.servers.list(search_opts={'all_tenants': 1})
304 except Exception as e:
305 logger.error("Error [get_instances(nova_client)]: %s" % e)
309 def get_instance_status(nova_client, instance):
311 instance = nova_client.servers.get(instance.id)
312 return instance.status
313 except Exception as e:
314 logger.error("Error [get_instance_status(nova_client)]: %s" % e)
318 def get_instance_by_name(nova_client, instance_name):
320 instance = nova_client.servers.find(name=instance_name)
322 except Exception as e:
323 logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
324 % (instance_name, e))
328 def get_flavor_id(nova_client, flavor_name):
329 flavors = nova_client.flavors.list(detailed=True)
332 if f.name == flavor_name:
338 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
339 flavors = nova_client.flavors.list(detailed=True)
342 if min_ram <= f.ram and f.ram <= max_ram:
348 def get_aggregates(nova_client):
350 aggregates = nova_client.aggregates.list()
352 except Exception as e:
353 logger.error("Error [get_aggregates(nova_client)]: %s" % e)
357 def get_aggregate_id(nova_client, aggregate_name):
359 aggregates = get_aggregates(nova_client)
360 _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
362 except Exception as e:
363 logger.error("Error [get_aggregate_id(nova_client, %s)]:"
364 " %s" % (aggregate_name, e))
368 def get_availability_zones(nova_client):
370 availability_zones = nova_client.availability_zones.list()
371 return availability_zones
372 except Exception as e:
373 logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
377 def get_availability_zone_names(nova_client):
379 az_names = [az.zoneName for az in get_availability_zones(nova_client)]
381 except Exception as e:
382 logger.error("Error [get_availability_zone_names(nova_client)]:"
387 def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
389 flavor = nova_client.flavors.create(
390 flavor_name, ram, vcpus, disk, is_public=public)
392 extra_specs = ft_utils.get_functest_config(
393 'general.flavor_extra_specs')
394 flavor.set_keys(extra_specs)
396 # flavor extra specs are not configured, therefore skip the update
399 except Exception as e:
400 logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
401 "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
406 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
407 flavor_exists = False
408 nova_client = get_nova_client()
410 flavor_id = get_flavor_id(nova_client, flavor_name)
412 logger.info("Using existing flavor '%s'..." % flavor_name)
415 logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
416 "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
417 flavor_id = create_flavor(
418 nova_client, flavor_name, ram, disk, vcpus, public=public)
420 logger.error("Failed to create flavor '%s'..." % (flavor_name))
422 logger.debug("Flavor '%s' with ID=%s created successfully."
423 % (flavor_name, flavor_id))
425 return flavor_exists, flavor_id
428 def get_floating_ips(neutron_client):
430 floating_ips = neutron_client.list_floatingips()
431 return floating_ips['floatingips']
432 except Exception as e:
433 logger.error("Error [get_floating_ips(neutron_client)]: %s" % e)
437 def get_hypervisors(nova_client):
440 hypervisors = nova_client.hypervisors.list()
441 for hypervisor in hypervisors:
442 if hypervisor.state == "up":
443 nodes.append(hypervisor.hypervisor_hostname)
445 except Exception as e:
446 logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
450 def create_aggregate(nova_client, aggregate_name, av_zone):
452 nova_client.aggregates.create(aggregate_name, av_zone)
454 except Exception as e:
455 logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
456 % (aggregate_name, av_zone, e))
460 def add_host_to_aggregate(nova_client, aggregate_name, compute_host):
462 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
463 nova_client.aggregates.add_host(aggregate_id, compute_host)
465 except Exception as e:
466 logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
467 % (aggregate_name, compute_host, e))
471 def create_aggregate_with_host(
472 nova_client, aggregate_name, av_zone, compute_host):
474 create_aggregate(nova_client, aggregate_name, av_zone)
475 add_host_to_aggregate(nova_client, aggregate_name, compute_host)
477 except Exception as e:
478 logger.error("Error [create_aggregate_with_host("
479 "nova_client, %s, %s, %s)]: %s"
480 % (aggregate_name, av_zone, compute_host, e))
484 def create_instance(flavor_name,
487 instance_name="functest-vm",
493 nova_client = get_nova_client()
495 flavor = nova_client.flavors.find(name=flavor_name)
497 flavors = nova_client.flavors.list()
498 logger.error("Error: Flavor '%s' not found. Available flavors are: "
499 "\n%s" % (flavor_name, flavors))
501 if fixed_ip is not None:
502 nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
504 nics = {"net-id": network_id}
506 instance = nova_client.servers.create(
511 availability_zone=av_zone,
515 instance = nova_client.servers.create(
520 config_drive=confdrive,
522 availability_zone=av_zone,
528 def create_instance_and_wait_for_active(flavor_name,
538 VM_BOOT_TIMEOUT = 180
539 nova_client = get_nova_client()
540 instance = create_instance(flavor_name,
549 count = VM_BOOT_TIMEOUT / SLEEP
550 for n in range(count, -1, -1):
551 status = get_instance_status(nova_client, instance)
552 if status.lower() == "active":
554 elif status.lower() == "error":
555 logger.error("The instance %s went to ERROR status."
559 logger.error("Timeout booting the instance %s." % instance_name)
563 def create_floating_ip(neutron_client):
564 extnet_id = get_external_net_id(neutron_client)
565 props = {'floating_network_id': extnet_id}
567 ip_json = neutron_client.create_floatingip({'floatingip': props})
568 fip_addr = ip_json['floatingip']['floating_ip_address']
569 fip_id = ip_json['floatingip']['id']
570 except Exception as e:
571 logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
573 return {'fip_addr': fip_addr, 'fip_id': fip_id}
576 def add_floating_ip(nova_client, server_id, floatingip_addr):
578 nova_client.servers.add_floating_ip(server_id, floatingip_addr)
580 except Exception as e:
581 logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
582 % (server_id, floatingip_addr, e))
586 def delete_instance(nova_client, instance_id):
588 nova_client.servers.force_delete(instance_id)
590 except Exception as e:
591 logger.error("Error [delete_instance(nova_client, '%s')]: %s"
596 def delete_floating_ip(neutron_client, floatingip_id):
598 neutron_client.delete_floatingip(floatingip_id)
600 except Exception as e:
601 logger.error("Error [delete_floating_ip(neutron_client, '%s')]: %s"
602 % (floatingip_id, e))
606 def remove_host_from_aggregate(nova_client, aggregate_name, compute_host):
608 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
609 nova_client.aggregates.remove_host(aggregate_id, compute_host)
611 except Exception as e:
612 logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
613 " %s" % (aggregate_name, compute_host, e))
617 def remove_hosts_from_aggregate(nova_client, aggregate_name):
618 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
619 hosts = nova_client.aggregates.get(aggregate_id).hosts
621 all(remove_host_from_aggregate(nova_client, aggregate_name, host)
625 def delete_aggregate(nova_client, aggregate_name):
627 remove_hosts_from_aggregate(nova_client, aggregate_name)
628 nova_client.aggregates.delete(aggregate_name)
630 except Exception as e:
631 logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
632 % (aggregate_name, e))
636 # *********************************************
638 # *********************************************
639 def get_network_list(neutron_client):
640 network_list = neutron_client.list_networks()['networks']
641 if len(network_list) == 0:
647 def get_router_list(neutron_client):
648 router_list = neutron_client.list_routers()['routers']
649 if len(router_list) == 0:
655 def get_port_list(neutron_client):
656 port_list = neutron_client.list_ports()['ports']
657 if len(port_list) == 0:
663 def get_network_id(neutron_client, network_name):
664 networks = neutron_client.list_networks()['networks']
667 if n['name'] == network_name:
673 def get_subnet_id(neutron_client, subnet_name):
674 subnets = neutron_client.list_subnets()['subnets']
677 if s['name'] == subnet_name:
683 def get_router_id(neutron_client, router_name):
684 routers = neutron_client.list_routers()['routers']
687 if r['name'] == router_name:
693 def get_private_net(neutron_client):
694 # Checks if there is an existing shared private network
695 networks = neutron_client.list_networks()['networks']
696 if len(networks) == 0:
699 if (net['router:external'] is False) and (net['shared'] is True):
704 def get_external_net(neutron_client):
705 for network in neutron_client.list_networks()['networks']:
706 if network['router:external']:
707 return network['name']
711 def get_external_net_id(neutron_client):
712 for network in neutron_client.list_networks()['networks']:
713 if network['router:external']:
718 def check_neutron_net(neutron_client, net_name):
719 for network in neutron_client.list_networks()['networks']:
720 if network['name'] == net_name:
721 for subnet in network['subnets']:
726 def create_neutron_net(neutron_client, name):
727 json_body = {'network': {'name': name,
728 'admin_state_up': True}}
730 network = neutron_client.create_network(body=json_body)
731 network_dict = network['network']
732 return network_dict['id']
733 except Exception as e:
734 logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
739 def create_neutron_subnet(neutron_client, name, cidr, net_id):
740 json_body = {'subnets': [{'name': name, 'cidr': cidr,
741 'ip_version': 4, 'network_id': net_id}]}
743 subnet = neutron_client.create_subnet(body=json_body)
744 return subnet['subnets'][0]['id']
745 except Exception as e:
746 logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
747 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
751 def create_neutron_router(neutron_client, name):
752 json_body = {'router': {'name': name, 'admin_state_up': True}}
754 router = neutron_client.create_router(json_body)
755 return router['router']['id']
756 except Exception as e:
757 logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
762 def create_neutron_port(neutron_client, name, network_id, ip):
763 json_body = {'port': {
764 'admin_state_up': True,
766 'network_id': network_id,
767 'fixed_ips': [{"ip_address": ip}]
770 port = neutron_client.create_port(body=json_body)
771 return port['port']['id']
772 except Exception as e:
773 logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
774 "'%s')]: %s" % (name, network_id, ip, e))
778 def update_neutron_net(neutron_client, network_id, shared=False):
779 json_body = {'network': {'shared': shared}}
781 neutron_client.update_network(network_id, body=json_body)
783 except Exception as e:
784 logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
785 "%s" % (network_id, str(shared), e))
789 def update_neutron_port(neutron_client, port_id, device_owner):
790 json_body = {'port': {
791 'device_owner': device_owner,
794 port = neutron_client.update_port(port=port_id,
796 return port['port']['id']
797 except Exception as e:
798 logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
799 " %s" % (port_id, device_owner, e))
803 def add_interface_router(neutron_client, router_id, subnet_id):
804 json_body = {"subnet_id": subnet_id}
806 neutron_client.add_interface_router(router=router_id, body=json_body)
808 except Exception as e:
809 logger.error("Error [add_interface_router(neutron_client, '%s', "
810 "'%s')]: %s" % (router_id, subnet_id, e))
814 def add_gateway_router(neutron_client, router_id):
815 ext_net_id = get_external_net_id(neutron_client)
816 router_dict = {'network_id': ext_net_id}
818 neutron_client.add_gateway_router(router_id, router_dict)
820 except Exception as e:
821 logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
826 def delete_neutron_net(neutron_client, network_id):
828 neutron_client.delete_network(network_id)
830 except Exception as e:
831 logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
836 def delete_neutron_subnet(neutron_client, subnet_id):
838 neutron_client.delete_subnet(subnet_id)
840 except Exception as e:
841 logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
846 def delete_neutron_router(neutron_client, router_id):
848 neutron_client.delete_router(router=router_id)
850 except Exception as e:
851 logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
856 def delete_neutron_port(neutron_client, port_id):
858 neutron_client.delete_port(port_id)
860 except Exception as e:
861 logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
866 def remove_interface_router(neutron_client, router_id, subnet_id):
867 json_body = {"subnet_id": subnet_id}
869 neutron_client.remove_interface_router(router=router_id,
872 except Exception as e:
873 logger.error("Error [remove_interface_router(neutron_client, '%s', "
874 "'%s')]: %s" % (router_id, subnet_id, e))
878 def remove_gateway_router(neutron_client, router_id):
880 neutron_client.remove_gateway_router(router_id)
882 except Exception as e:
883 logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
888 def create_network_full(neutron_client,
894 # Check if the network already exists
895 network_id = get_network_id(neutron_client, net_name)
896 subnet_id = get_subnet_id(neutron_client, subnet_name)
897 router_id = get_router_id(neutron_client, router_name)
899 if network_id != '' and subnet_id != '' and router_id != '':
900 logger.info("A network with name '%s' already exists..." % net_name)
902 neutron_client.format = 'json'
903 logger.info('Creating neutron network %s...' % net_name)
904 network_id = create_neutron_net(neutron_client, net_name)
909 logger.debug("Network '%s' created successfully" % network_id)
910 logger.debug('Creating Subnet....')
911 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
916 logger.debug("Subnet '%s' created successfully" % subnet_id)
917 logger.debug('Creating Router...')
918 router_id = create_neutron_router(neutron_client, router_name)
923 logger.debug("Router '%s' created successfully" % router_id)
924 logger.debug('Adding router to subnet...')
926 if not add_interface_router(neutron_client, router_id, subnet_id):
929 logger.debug("Interface added successfully.")
931 logger.debug('Adding gateway to router...')
932 if not add_gateway_router(neutron_client, router_id):
935 logger.debug("Gateway added successfully.")
937 network_dic = {'net_id': network_id,
938 'subnet_id': subnet_id,
939 'router_id': router_id}
943 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
944 neutron_client = get_neutron_client()
946 network_dic = create_network_full(neutron_client,
952 if not update_neutron_net(neutron_client,
953 network_dic['net_id'],
955 logger.error("Failed to update network %s..." % net_name)
958 logger.debug("Network '%s' is available..." % net_name)
960 logger.error("Network %s creation failed" % net_name)
965 def create_bgpvpn(neutron_client, **kwargs):
966 # route_distinguishers
968 json_body = {"bgpvpn": kwargs}
969 return neutron_client.create_bgpvpn(json_body)
972 def create_network_association(neutron_client, bgpvpn_id, neutron_network_id):
973 json_body = {"network_association": {"network_id": neutron_network_id}}
974 return neutron_client.create_network_association(bgpvpn_id, json_body)
977 def create_router_association(neutron_client, bgpvpn_id, router_id):
978 json_body = {"router_association": {"router_id": router_id}}
979 return neutron_client.create_router_association(bgpvpn_id, json_body)
982 def update_bgpvpn(neutron_client, bgpvpn_id, **kwargs):
983 json_body = {"bgpvpn": kwargs}
984 return neutron_client.update_bgpvpn(bgpvpn_id, json_body)
987 def delete_bgpvpn(neutron_client, bgpvpn_id):
988 return neutron_client.delete_bgpvpn(bgpvpn_id)
991 def get_bgpvpn(neutron_client, bgpvpn_id):
992 return neutron_client.show_bgpvpn(bgpvpn_id)
995 def get_bgpvpn_routers(neutron_client, bgpvpn_id):
996 return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['routers']
999 def get_bgpvpn_networks(neutron_client, bgpvpn_id):
1000 return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['networks']
1002 # *********************************************
1004 # *********************************************
1007 def get_security_groups(neutron_client):
1009 security_groups = neutron_client.list_security_groups()[
1011 return security_groups
1012 except Exception as e:
1013 logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
1017 def get_security_group_id(neutron_client, sg_name):
1018 security_groups = get_security_groups(neutron_client)
1020 for sg in security_groups:
1021 if sg['name'] == sg_name:
1027 def create_security_group(neutron_client, sg_name, sg_description):
1028 json_body = {'security_group': {'name': sg_name,
1029 'description': sg_description}}
1031 secgroup = neutron_client.create_security_group(json_body)
1032 return secgroup['security_group']
1033 except Exception as e:
1034 logger.error("Error [create_security_group(neutron_client, '%s', "
1035 "'%s')]: %s" % (sg_name, sg_description, e))
1039 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
1040 port_range_min=None, port_range_max=None):
1041 # We create a security group in 2 steps
1042 # 1 - we check the format and set the json body accordingly
1043 # 2 - we call neturon client to create the security group
1046 json_body = {'security_group_rule': {'direction': direction,
1047 'security_group_id': sg_id,
1048 'protocol': protocol}}
1050 # - both None => we do nothing
1051 # - both Not None => we add them to the json description
1052 # but one cannot be None is the other is not None
1053 if (port_range_min is not None and port_range_max is not None):
1054 # add port_range in json description
1055 json_body['security_group_rule']['port_range_min'] = port_range_min
1056 json_body['security_group_rule']['port_range_max'] = port_range_max
1057 logger.debug("Security_group format set (port range included)")
1059 # either both port range are set to None => do nothing
1060 # or one is set but not the other => log it and return False
1061 if port_range_min is None and port_range_max is None:
1062 logger.debug("Security_group format set (no port range mentioned)")
1064 logger.error("Bad security group format."
1065 "One of the port range is not properly set:"
1067 "range max: {}".format(port_range_min,
1071 # Create security group using neutron client
1073 neutron_client.create_security_group_rule(json_body)
1076 logger.exception("Impossible to create_security_group_rule,"
1077 "security group rule probably already exists")
1081 def get_security_group_rules(neutron_client, sg_id):
1083 security_rules = neutron_client.list_security_group_rules()[
1084 'security_group_rules']
1085 security_rules = [rule for rule in security_rules
1086 if rule["security_group_id"] == sg_id]
1087 return security_rules
1088 except Exception as e:
1089 logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:"
1094 def check_security_group_rules(neutron_client, sg_id, direction, protocol,
1095 port_min=None, port_max=None):
1097 security_rules = get_security_group_rules(neutron_client, sg_id)
1098 security_rules = [rule for rule in security_rules
1099 if (rule["direction"].lower() == direction and
1100 rule["protocol"].lower() == protocol and
1101 rule["port_range_min"] == port_min and
1102 rule["port_range_max"] == port_max)]
1103 if len(security_rules) == 0:
1107 except Exception as e:
1108 logger.error("Error [check_security_group_rules("
1109 " neutron_client, sg_id, direction,"
1110 " protocol, port_min=None, port_max=None)]: "
1115 def create_security_group_full(neutron_client,
1116 sg_name, sg_description):
1117 sg_id = get_security_group_id(neutron_client, sg_name)
1119 logger.info("Using existing security group '%s'..." % sg_name)
1121 logger.info("Creating security group '%s'..." % sg_name)
1122 SECGROUP = create_security_group(neutron_client,
1126 logger.error("Failed to create the security group...")
1129 sg_id = SECGROUP['id']
1131 logger.debug("Security group '%s' with ID=%s created successfully."
1132 % (SECGROUP['name'], sg_id))
1134 logger.debug("Adding ICMP rules in security group '%s'..."
1136 if not create_secgroup_rule(neutron_client, sg_id,
1138 logger.error("Failed to create the security group rule...")
1141 logger.debug("Adding SSH rules in security group '%s'..."
1143 if not create_secgroup_rule(
1144 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1145 logger.error("Failed to create the security group rule...")
1148 if not create_secgroup_rule(
1149 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1150 logger.error("Failed to create the security group rule...")
1155 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
1157 nova_client.servers.add_security_group(instance_id, secgroup_id)
1159 except Exception as e:
1160 logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
1161 "'%s')]: %s" % (instance_id, secgroup_id, e))
1165 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1166 json_body = {"quota": {
1167 "security_group": sg_quota,
1168 "security_group_rule": sg_rule_quota
1172 neutron_client.update_quota(tenant_id=tenant_id,
1175 except Exception as e:
1176 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1177 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1181 def delete_security_group(neutron_client, secgroup_id):
1183 neutron_client.delete_security_group(secgroup_id)
1185 except Exception as e:
1186 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1191 # *********************************************
1193 # *********************************************
1194 def get_images(glance_client):
1196 images = glance_client.images.list()
1198 except Exception as e:
1199 logger.error("Error [get_images]: %s" % e)
1203 def get_image_id(glance_client, image_name):
1204 images = glance_client.images.list()
1207 if i.name == image_name:
1213 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
1214 container="bare", public="public"):
1215 if not os.path.isfile(file_path):
1216 logger.error("Error: file %s does not exist." % file_path)
1219 image_id = get_image_id(glance_client, image_name)
1221 logger.info("Image %s already exists." % image_name)
1223 logger.info("Creating image '%s' from '%s'..." % (image_name,
1226 image = glance_client.images.create(name=image_name,
1229 container_format=container)
1231 with open(file_path) as image_data:
1232 glance_client.images.upload(image_id, image_data)
1234 except Exception as e:
1235 logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1236 "'%s')]: %s" % (image_name, file_path, public, e))
1240 def get_or_create_image(name, path, format):
1241 image_exists = False
1242 glance_client = get_glance_client()
1244 image_id = get_image_id(glance_client, name)
1246 logger.info("Using existing image '%s'..." % name)
1249 logger.info("Creating image '%s' from '%s'..." % (name, path))
1250 image_id = create_glance_image(glance_client, name, path, format)
1252 logger.error("Failed to create a Glance image...")
1254 logger.debug("Image '%s' with ID=%s created successfully."
1257 return image_exists, image_id
1260 def delete_glance_image(glance_client, image_id):
1262 glance_client.images.delete(image_id)
1264 except Exception as e:
1265 logger.error("Error [delete_glance_image(glance_client, '%s')]: %s"
1270 # *********************************************
1272 # *********************************************
1273 def get_volumes(cinder_client):
1275 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1277 except Exception as e:
1278 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1282 def list_volume_types(cinder_client, public=True, private=True):
1284 volume_types = cinder_client.volume_types.list()
1286 volume_types = [vt for vt in volume_types if not vt.is_public]
1288 volume_types = [vt for vt in volume_types if vt.is_public]
1290 except Exception as e:
1291 logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
1295 def create_volume_type(cinder_client, name):
1297 volume_type = cinder_client.volume_types.create(name)
1299 except Exception as e:
1300 logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
1305 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1306 snapshots_quota, gigabytes_quota):
1307 quotas_values = {"volumes": vols_quota,
1308 "snapshots": snapshots_quota,
1309 "gigabytes": gigabytes_quota}
1312 cinder_client.quotas.update(tenant_id, **quotas_values)
1314 except Exception as e:
1315 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1316 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1317 snapshots_quota, gigabytes_quota, e))
1321 def delete_volume(cinder_client, volume_id, forced=False):
1325 cinder_client.volumes.detach(volume_id)
1327 logger.error(sys.exc_info()[0])
1328 cinder_client.volumes.force_delete(volume_id)
1330 cinder_client.volumes.delete(volume_id)
1332 except Exception as e:
1333 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1334 % (volume_id, str(forced), e))
1338 def delete_volume_type(cinder_client, volume_type):
1340 cinder_client.volume_types.delete(volume_type)
1342 except Exception as e:
1343 logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
1348 # *********************************************
1350 # *********************************************
1351 def get_tenants(keystone_client):
1353 if is_keystone_v3():
1354 tenants = keystone_client.projects.list()
1356 tenants = keystone_client.tenants.list()
1358 except Exception as e:
1359 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1363 def get_users(keystone_client):
1365 users = keystone_client.users.list()
1367 except Exception as e:
1368 logger.error("Error [get_users(keystone_client)]: %s" % e)
1372 def get_tenant_id(keystone_client, tenant_name):
1373 tenants = get_tenants(keystone_client)
1376 if t.name == tenant_name:
1382 def get_user_id(keystone_client, user_name):
1383 users = get_users(keystone_client)
1386 if u.name == user_name:
1392 def get_role_id(keystone_client, role_name):
1393 roles = keystone_client.roles.list()
1396 if r.name == role_name:
1402 def create_tenant(keystone_client, tenant_name, tenant_description):
1404 if is_keystone_v3():
1405 tenant = keystone_client.projects.create(
1407 description=tenant_description,
1411 tenant = keystone_client.tenants.create(tenant_name,
1415 except Exception as e:
1416 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1417 % (tenant_name, tenant_description, e))
1421 def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
1422 tenant_id = get_tenant_id(keystone_client, tenant_name)
1424 tenant_id = create_tenant(keystone_client, tenant_name,
1430 def get_or_create_tenant_for_vnf(keystone_client, tenant_name,
1431 tenant_description):
1432 """Get or Create a Tenant
1435 keystone_client: keystone client reference
1436 tenant_name: the name of the tenant
1437 tenant_description: the description of the tenant
1439 return False if tenant retrieved though get
1440 return True if tenant created
1441 raise Exception if error during processing
1444 tenant_id = get_tenant_id(keystone_client, tenant_name)
1446 tenant_id = create_tenant(keystone_client, tenant_name,
1452 raise Exception("Impossible to create a Tenant for the VNF {}".format(
1456 def create_user(keystone_client, user_name, user_password,
1457 user_email, tenant_id):
1459 if is_keystone_v3():
1460 user = keystone_client.users.create(name=user_name,
1461 password=user_password,
1463 project_id=tenant_id,
1466 user = keystone_client.users.create(user_name,
1472 except Exception as e:
1473 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1474 "'%s')]: %s" % (user_name, user_password,
1475 user_email, tenant_id, e))
1479 def get_or_create_user(keystone_client, user_name, user_password,
1480 tenant_id, user_email=None):
1481 user_id = get_user_id(keystone_client, user_name)
1483 user_id = create_user(keystone_client, user_name, user_password,
1484 user_email, tenant_id)
1488 def get_or_create_user_for_vnf(keystone_client, vnf_ref):
1489 """Get or Create user for VNF
1492 keystone_client: keystone client reference
1493 vnf_ref: VNF reference used as user name & password, tenant name
1495 return False if user retrieved through get
1496 return True if user created
1497 raise Exception if error during processing
1500 user_id = get_user_id(keystone_client, vnf_ref)
1501 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1503 user_id = create_user(keystone_client, vnf_ref, vnf_ref,
1508 add_role_user(keystone_client, user_id, 'admin', vnf_ref)
1510 raise Exception("Impossible to create a user for the VNF {}".format(
1514 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1516 if is_keystone_v3():
1517 keystone_client.roles.grant(role=role_id,
1521 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1523 except Exception as e:
1524 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1525 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1529 def delete_tenant(keystone_client, tenant_id):
1531 if is_keystone_v3():
1532 keystone_client.projects.delete(tenant_id)
1534 keystone_client.tenants.delete(tenant_id)
1536 except Exception as e:
1537 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1542 def delete_user(keystone_client, user_id):
1544 keystone_client.users.delete(user_id)
1546 except Exception as e:
1547 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1552 # *********************************************
1554 # *********************************************
1555 def get_resource(heat_client, stack_id, resource):
1557 resources = heat_client.resources.get(stack_id, resource)
1559 except Exception as e:
1560 logger.error("Error [get_resource]: %s" % e)