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'
90 def get_credentials(other_creds={}):
91 """Returns a creds dictionary filled with parsed from env
94 env_vars = get_rc_env_vars()
95 env_cred_dict = get_env_cred_dict()
97 for envvar in env_vars:
98 if os.getenv(envvar) is None:
99 raise MissingEnvVar(envvar)
101 creds_key = env_cred_dict.get(envvar)
102 creds.update({creds_key: os.getenv(envvar)})
104 if 'tenant' in other_creds.keys():
106 tenant = 'project_name'
108 tenant = 'tenant_name'
109 other_creds[tenant] = other_creds.pop('tenant')
111 creds.update(other_creds)
116 def source_credentials(rc_file):
117 with open(rc_file, "r") as f:
119 var = line.rstrip('"\n').replace('export ', '').split("=")
120 # The two next lines should be modified as soon as rc_file
121 # conforms with common rules. Be aware that it could induce
122 # issues if value starts with '
123 key = re.sub(r'^["\' ]*|[ \'"]*$', '', var[0])
124 value = re.sub(r'^["\' ]*|[ \'"]*$', '', "".join(var[1:]))
125 os.environ[key] = value
128 def get_credentials_for_rally():
129 creds = get_credentials()
130 env_cred_dict = get_env_cred_dict()
131 rally_conf = {"type": "ExistingCloud", "admin": {}}
133 if key == 'auth_url':
134 rally_conf[key] = creds[key]
136 rally_conf['admin'][key] = creds[key]
138 endpoint_types = [('internalURL', 'internal'),
139 ('publicURL', 'public'), ('adminURL', 'admin')]
141 endpoint_type = get_endpoint_type_from_env()
142 if endpoint_type is not None:
143 cred_key = env_cred_dict.get('OS_ENDPOINT_TYPE')
144 for k, v in endpoint_types:
145 if endpoint_type == v:
146 rally_conf[cred_key] = v
148 region_name = os.getenv('OS_REGION_NAME')
149 if region_name is not None:
150 cred_key = env_cred_dict.get('OS_REGION_NAME')
151 rally_conf[cred_key] = region_name
153 cacert = os.getenv('OS_CACERT')
154 if cacert is not None:
155 cred_key = env_cred_dict.get('OS_CACERT')
156 rally_conf[cred_key] = cacert
160 def get_endpoint_type_from_env():
161 endpoint_type = os.environ.get("OS_ENDPOINT_TYPE",
162 os.environ.get("OS_INTERFACE"))
163 if endpoint_type and "URL" in endpoint_type:
164 endpoint_type = endpoint_type.replace("URL", "")
168 def get_session_auth(other_creds={}):
169 loader = loading.get_plugin_loader('password')
170 creds = get_credentials(other_creds)
171 auth = loader.load_from_options(**creds)
175 def get_endpoint(service_type, endpoint_type='publicURL'):
176 auth = get_session_auth()
177 return get_session().get_endpoint(auth=auth,
178 service_type=service_type,
179 endpoint_type=endpoint_type)
182 def get_session(other_creds={}):
183 auth = get_session_auth(other_creds)
184 https_cacert = os.getenv('OS_CACERT', '')
185 https_insecure = os.getenv('OS_INSECURE', '').lower() == 'true'
186 return session.Session(auth=auth,
187 verify=(https_cacert or not https_insecure))
190 # *********************************************
192 # *********************************************
193 def get_keystone_client_version():
194 api_version = os.getenv('OS_IDENTITY_API_VERSION')
195 if api_version is not None:
196 logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
199 return DEFAULT_API_VERSION
202 def get_keystone_client(other_creds={}):
203 sess = get_session(other_creds)
204 return keystoneclient.Client(get_keystone_client_version(),
206 interface=os.getenv('OS_INTERFACE', 'admin'))
209 def get_nova_client_version():
210 api_version = os.getenv('OS_COMPUTE_API_VERSION')
211 if api_version is not None:
212 logger.info("OS_COMPUTE_API_VERSION is set in env as '%s'",
215 return DEFAULT_API_VERSION
218 def get_nova_client(other_creds={}):
219 sess = get_session(other_creds)
220 return novaclient.Client(get_nova_client_version(), session=sess)
223 def get_cinder_client_version():
224 api_version = os.getenv('OS_VOLUME_API_VERSION')
225 if api_version is not None:
226 logger.info("OS_VOLUME_API_VERSION is set in env as '%s'",
229 return DEFAULT_API_VERSION
232 def get_cinder_client(other_creds={}):
233 sess = get_session(other_creds)
234 return cinderclient.Client(get_cinder_client_version(), session=sess)
237 def get_neutron_client_version():
238 api_version = os.getenv('OS_NETWORK_API_VERSION')
239 if api_version is not None:
240 logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
243 return DEFAULT_API_VERSION
246 def get_neutron_client(other_creds={}):
247 sess = get_session(other_creds)
248 return neutronclient.Client(get_neutron_client_version(), session=sess)
251 def get_glance_client_version():
252 api_version = os.getenv('OS_IMAGE_API_VERSION')
253 if api_version is not None:
254 logger.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version)
256 return DEFAULT_API_VERSION
259 def get_glance_client(other_creds={}):
260 sess = get_session(other_creds)
261 return glanceclient.Client(get_glance_client_version(), session=sess)
264 def get_heat_client_version():
265 api_version = os.getenv('OS_ORCHESTRATION_API_VERSION')
266 if api_version is not None:
267 logger.info("OS_ORCHESTRATION_API_VERSION is set in env as '%s'",
270 return DEFAULT_HEAT_API_VERSION
273 def get_heat_client(other_creds={}):
274 sess = get_session(other_creds)
275 return heatclient.Client(get_heat_client_version(), session=sess)
278 def download_and_add_image_on_glance(glance, image_name, image_url, data_dir):
280 if not os.path.exists(dest_path):
281 os.makedirs(dest_path)
282 file_name = image_url.rsplit('/')[-1]
283 if not ft_utils.download_url(image_url, dest_path):
286 image = create_glance_image(
287 glance, image_name, dest_path + file_name)
294 # *********************************************
296 # *********************************************
297 def get_instances(nova_client):
299 instances = nova_client.servers.list(search_opts={'all_tenants': 1})
301 except Exception as e:
302 logger.error("Error [get_instances(nova_client)]: %s" % e)
306 def get_instance_status(nova_client, instance):
308 instance = nova_client.servers.get(instance.id)
309 return instance.status
310 except Exception as e:
311 logger.error("Error [get_instance_status(nova_client)]: %s" % e)
315 def get_instance_by_name(nova_client, instance_name):
317 instance = nova_client.servers.find(name=instance_name)
319 except Exception as e:
320 logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
321 % (instance_name, e))
325 def get_flavor_id(nova_client, flavor_name):
326 flavors = nova_client.flavors.list(detailed=True)
329 if f.name == flavor_name:
335 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
336 flavors = nova_client.flavors.list(detailed=True)
339 if min_ram <= f.ram and f.ram <= max_ram:
345 def get_aggregates(nova_client):
347 aggregates = nova_client.aggregates.list()
349 except Exception as e:
350 logger.error("Error [get_aggregates(nova_client)]: %s" % e)
354 def get_aggregate_id(nova_client, aggregate_name):
356 aggregates = get_aggregates(nova_client)
357 _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
359 except Exception as e:
360 logger.error("Error [get_aggregate_id(nova_client, %s)]:"
361 " %s" % (aggregate_name, e))
365 def get_availability_zones(nova_client):
367 availability_zones = nova_client.availability_zones.list()
368 return availability_zones
369 except Exception as e:
370 logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
374 def get_availability_zone_names(nova_client):
376 az_names = [az.zoneName for az in get_availability_zones(nova_client)]
378 except Exception as e:
379 logger.error("Error [get_availability_zone_names(nova_client)]:"
384 def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
386 flavor = nova_client.flavors.create(
387 flavor_name, ram, vcpus, disk, is_public=public)
389 extra_specs = ft_utils.get_functest_config(
390 'general.flavor_extra_specs')
391 flavor.set_keys(extra_specs)
393 # flavor extra specs are not configured, therefore skip the update
396 except Exception as e:
397 logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
398 "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
403 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
404 flavor_exists = False
405 nova_client = get_nova_client()
407 flavor_id = get_flavor_id(nova_client, flavor_name)
409 logger.info("Using existing flavor '%s'..." % flavor_name)
412 logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
413 "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
414 flavor_id = create_flavor(
415 nova_client, flavor_name, ram, disk, vcpus, public=public)
417 logger.error("Failed to create flavor '%s'..." % (flavor_name))
419 logger.debug("Flavor '%s' with ID=%s created successfully."
420 % (flavor_name, flavor_id))
422 return flavor_exists, flavor_id
425 def get_floating_ips(neutron_client):
427 floating_ips = neutron_client.list_floatingips()
428 return floating_ips['floatingips']
429 except Exception as e:
430 logger.error("Error [get_floating_ips(neutron_client)]: %s" % e)
434 def get_hypervisors(nova_client):
437 hypervisors = nova_client.hypervisors.list()
438 for hypervisor in hypervisors:
439 if hypervisor.state == "up":
440 nodes.append(hypervisor.hypervisor_hostname)
442 except Exception as e:
443 logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
447 def create_aggregate(nova_client, aggregate_name, av_zone):
449 nova_client.aggregates.create(aggregate_name, av_zone)
451 except Exception as e:
452 logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
453 % (aggregate_name, av_zone, e))
457 def add_host_to_aggregate(nova_client, aggregate_name, compute_host):
459 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
460 nova_client.aggregates.add_host(aggregate_id, compute_host)
462 except Exception as e:
463 logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
464 % (aggregate_name, compute_host, e))
468 def create_aggregate_with_host(
469 nova_client, aggregate_name, av_zone, compute_host):
471 create_aggregate(nova_client, aggregate_name, av_zone)
472 add_host_to_aggregate(nova_client, aggregate_name, compute_host)
474 except Exception as e:
475 logger.error("Error [create_aggregate_with_host("
476 "nova_client, %s, %s, %s)]: %s"
477 % (aggregate_name, av_zone, compute_host, e))
481 def create_instance(flavor_name,
484 instance_name="functest-vm",
490 nova_client = get_nova_client()
492 flavor = nova_client.flavors.find(name=flavor_name)
494 flavors = nova_client.flavors.list()
495 logger.error("Error: Flavor '%s' not found. Available flavors are: "
496 "\n%s" % (flavor_name, flavors))
498 if fixed_ip is not None:
499 nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
501 nics = {"net-id": network_id}
503 instance = nova_client.servers.create(
508 availability_zone=av_zone,
512 instance = nova_client.servers.create(
517 config_drive=confdrive,
519 availability_zone=av_zone,
525 def create_instance_and_wait_for_active(flavor_name,
535 VM_BOOT_TIMEOUT = 180
536 nova_client = get_nova_client()
537 instance = create_instance(flavor_name,
546 count = VM_BOOT_TIMEOUT / SLEEP
547 for n in range(count, -1, -1):
548 status = get_instance_status(nova_client, instance)
549 if status.lower() == "active":
551 elif status.lower() == "error":
552 logger.error("The instance %s went to ERROR status."
556 logger.error("Timeout booting the instance %s." % instance_name)
560 def create_floating_ip(neutron_client):
561 extnet_id = get_external_net_id(neutron_client)
562 props = {'floating_network_id': extnet_id}
564 ip_json = neutron_client.create_floatingip({'floatingip': props})
565 fip_addr = ip_json['floatingip']['floating_ip_address']
566 fip_id = ip_json['floatingip']['id']
567 except Exception as e:
568 logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
570 return {'fip_addr': fip_addr, 'fip_id': fip_id}
573 def add_floating_ip(nova_client, server_id, floatingip_addr):
575 nova_client.servers.add_floating_ip(server_id, floatingip_addr)
577 except Exception as e:
578 logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
579 % (server_id, floatingip_addr, e))
583 def delete_instance(nova_client, instance_id):
585 nova_client.servers.force_delete(instance_id)
587 except Exception as e:
588 logger.error("Error [delete_instance(nova_client, '%s')]: %s"
593 def delete_floating_ip(neutron_client, floatingip_id):
595 neutron_client.delete_floatingip(floatingip_id)
597 except Exception as e:
598 logger.error("Error [delete_floating_ip(neutron_client, '%s')]: %s"
599 % (floatingip_id, e))
603 def remove_host_from_aggregate(nova_client, aggregate_name, compute_host):
605 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
606 nova_client.aggregates.remove_host(aggregate_id, compute_host)
608 except Exception as e:
609 logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
610 " %s" % (aggregate_name, compute_host, e))
614 def remove_hosts_from_aggregate(nova_client, aggregate_name):
615 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
616 hosts = nova_client.aggregates.get(aggregate_id).hosts
618 all(remove_host_from_aggregate(nova_client, aggregate_name, host)
622 def delete_aggregate(nova_client, aggregate_name):
624 remove_hosts_from_aggregate(nova_client, aggregate_name)
625 nova_client.aggregates.delete(aggregate_name)
627 except Exception as e:
628 logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
629 % (aggregate_name, e))
633 # *********************************************
635 # *********************************************
636 def get_network_list(neutron_client):
637 network_list = neutron_client.list_networks()['networks']
638 if len(network_list) == 0:
644 def get_router_list(neutron_client):
645 router_list = neutron_client.list_routers()['routers']
646 if len(router_list) == 0:
652 def get_port_list(neutron_client):
653 port_list = neutron_client.list_ports()['ports']
654 if len(port_list) == 0:
660 def get_network_id(neutron_client, network_name):
661 networks = neutron_client.list_networks()['networks']
664 if n['name'] == network_name:
670 def get_subnet_id(neutron_client, subnet_name):
671 subnets = neutron_client.list_subnets()['subnets']
674 if s['name'] == subnet_name:
680 def get_router_id(neutron_client, router_name):
681 routers = neutron_client.list_routers()['routers']
684 if r['name'] == router_name:
690 def get_private_net(neutron_client):
691 # Checks if there is an existing shared private network
692 networks = neutron_client.list_networks()['networks']
693 if len(networks) == 0:
696 if (net['router:external'] is False) and (net['shared'] is True):
701 def get_external_net(neutron_client):
702 for network in neutron_client.list_networks()['networks']:
703 if network['router:external']:
704 return network['name']
708 def get_external_net_id(neutron_client):
709 for network in neutron_client.list_networks()['networks']:
710 if network['router:external']:
715 def check_neutron_net(neutron_client, net_name):
716 for network in neutron_client.list_networks()['networks']:
717 if network['name'] == net_name:
718 for subnet in network['subnets']:
723 def create_neutron_net(neutron_client, name):
724 json_body = {'network': {'name': name,
725 'admin_state_up': True}}
727 network = neutron_client.create_network(body=json_body)
728 network_dict = network['network']
729 return network_dict['id']
730 except Exception as e:
731 logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
736 def create_neutron_subnet(neutron_client, name, cidr, net_id):
737 json_body = {'subnets': [{'name': name, 'cidr': cidr,
738 'ip_version': 4, 'network_id': net_id}]}
740 subnet = neutron_client.create_subnet(body=json_body)
741 return subnet['subnets'][0]['id']
742 except Exception as e:
743 logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
744 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
748 def create_neutron_router(neutron_client, name):
749 json_body = {'router': {'name': name, 'admin_state_up': True}}
751 router = neutron_client.create_router(json_body)
752 return router['router']['id']
753 except Exception as e:
754 logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
759 def create_neutron_port(neutron_client, name, network_id, ip):
760 json_body = {'port': {
761 'admin_state_up': True,
763 'network_id': network_id,
764 'fixed_ips': [{"ip_address": ip}]
767 port = neutron_client.create_port(body=json_body)
768 return port['port']['id']
769 except Exception as e:
770 logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
771 "'%s')]: %s" % (name, network_id, ip, e))
775 def update_neutron_net(neutron_client, network_id, shared=False):
776 json_body = {'network': {'shared': shared}}
778 neutron_client.update_network(network_id, body=json_body)
780 except Exception as e:
781 logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
782 "%s" % (network_id, str(shared), e))
786 def update_neutron_port(neutron_client, port_id, device_owner):
787 json_body = {'port': {
788 'device_owner': device_owner,
791 port = neutron_client.update_port(port=port_id,
793 return port['port']['id']
794 except Exception as e:
795 logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
796 " %s" % (port_id, device_owner, e))
800 def add_interface_router(neutron_client, router_id, subnet_id):
801 json_body = {"subnet_id": subnet_id}
803 neutron_client.add_interface_router(router=router_id, body=json_body)
805 except Exception as e:
806 logger.error("Error [add_interface_router(neutron_client, '%s', "
807 "'%s')]: %s" % (router_id, subnet_id, e))
811 def add_gateway_router(neutron_client, router_id):
812 ext_net_id = get_external_net_id(neutron_client)
813 router_dict = {'network_id': ext_net_id}
815 neutron_client.add_gateway_router(router_id, router_dict)
817 except Exception as e:
818 logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
823 def delete_neutron_net(neutron_client, network_id):
825 neutron_client.delete_network(network_id)
827 except Exception as e:
828 logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
833 def delete_neutron_subnet(neutron_client, subnet_id):
835 neutron_client.delete_subnet(subnet_id)
837 except Exception as e:
838 logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
843 def delete_neutron_router(neutron_client, router_id):
845 neutron_client.delete_router(router=router_id)
847 except Exception as e:
848 logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
853 def delete_neutron_port(neutron_client, port_id):
855 neutron_client.delete_port(port_id)
857 except Exception as e:
858 logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
863 def remove_interface_router(neutron_client, router_id, subnet_id):
864 json_body = {"subnet_id": subnet_id}
866 neutron_client.remove_interface_router(router=router_id,
869 except Exception as e:
870 logger.error("Error [remove_interface_router(neutron_client, '%s', "
871 "'%s')]: %s" % (router_id, subnet_id, e))
875 def remove_gateway_router(neutron_client, router_id):
877 neutron_client.remove_gateway_router(router_id)
879 except Exception as e:
880 logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
885 def create_network_full(neutron_client,
891 # Check if the network already exists
892 network_id = get_network_id(neutron_client, net_name)
893 subnet_id = get_subnet_id(neutron_client, subnet_name)
894 router_id = get_router_id(neutron_client, router_name)
896 if network_id != '' and subnet_id != '' and router_id != '':
897 logger.info("A network with name '%s' already exists..." % net_name)
899 neutron_client.format = 'json'
900 logger.info('Creating neutron network %s...' % net_name)
901 network_id = create_neutron_net(neutron_client, net_name)
906 logger.debug("Network '%s' created successfully" % network_id)
907 logger.debug('Creating Subnet....')
908 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
913 logger.debug("Subnet '%s' created successfully" % subnet_id)
914 logger.debug('Creating Router...')
915 router_id = create_neutron_router(neutron_client, router_name)
920 logger.debug("Router '%s' created successfully" % router_id)
921 logger.debug('Adding router to subnet...')
923 if not add_interface_router(neutron_client, router_id, subnet_id):
926 logger.debug("Interface added successfully.")
928 logger.debug('Adding gateway to router...')
929 if not add_gateway_router(neutron_client, router_id):
932 logger.debug("Gateway added successfully.")
934 network_dic = {'net_id': network_id,
935 'subnet_id': subnet_id,
936 'router_id': router_id}
940 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
941 neutron_client = get_neutron_client()
943 network_dic = create_network_full(neutron_client,
949 if not update_neutron_net(neutron_client,
950 network_dic['net_id'],
952 logger.error("Failed to update network %s..." % net_name)
955 logger.debug("Network '%s' is available..." % net_name)
957 logger.error("Network %s creation failed" % net_name)
962 def create_bgpvpn(neutron_client, **kwargs):
963 # route_distinguishers
965 json_body = {"bgpvpn": kwargs}
966 return neutron_client.create_bgpvpn(json_body)
969 def create_network_association(neutron_client, bgpvpn_id, neutron_network_id):
970 json_body = {"network_association": {"network_id": neutron_network_id}}
971 return neutron_client.create_network_association(bgpvpn_id, json_body)
974 def create_router_association(neutron_client, bgpvpn_id, router_id):
975 json_body = {"router_association": {"router_id": router_id}}
976 return neutron_client.create_router_association(bgpvpn_id, json_body)
979 def update_bgpvpn(neutron_client, bgpvpn_id, **kwargs):
980 json_body = {"bgpvpn": kwargs}
981 return neutron_client.update_bgpvpn(bgpvpn_id, json_body)
984 def delete_bgpvpn(neutron_client, bgpvpn_id):
985 return neutron_client.delete_bgpvpn(bgpvpn_id)
988 def get_bgpvpn(neutron_client, bgpvpn_id):
989 return neutron_client.show_bgpvpn(bgpvpn_id)
992 def get_bgpvpn_routers(neutron_client, bgpvpn_id):
993 return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['routers']
996 def get_bgpvpn_networks(neutron_client, bgpvpn_id):
997 return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['networks']
999 # *********************************************
1001 # *********************************************
1004 def get_security_groups(neutron_client):
1006 security_groups = neutron_client.list_security_groups()[
1008 return security_groups
1009 except Exception as e:
1010 logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
1014 def get_security_group_id(neutron_client, sg_name):
1015 security_groups = get_security_groups(neutron_client)
1017 for sg in security_groups:
1018 if sg['name'] == sg_name:
1024 def create_security_group(neutron_client, sg_name, sg_description):
1025 json_body = {'security_group': {'name': sg_name,
1026 'description': sg_description}}
1028 secgroup = neutron_client.create_security_group(json_body)
1029 return secgroup['security_group']
1030 except Exception as e:
1031 logger.error("Error [create_security_group(neutron_client, '%s', "
1032 "'%s')]: %s" % (sg_name, sg_description, e))
1036 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
1037 port_range_min=None, port_range_max=None):
1038 # We create a security group in 2 steps
1039 # 1 - we check the format and set the json body accordingly
1040 # 2 - we call neturon client to create the security group
1043 json_body = {'security_group_rule': {'direction': direction,
1044 'security_group_id': sg_id,
1045 'protocol': protocol}}
1047 # - both None => we do nothing
1048 # - both Not None => we add them to the json description
1049 # but one cannot be None is the other is not None
1050 if (port_range_min is not None and port_range_max is not None):
1051 # add port_range in json description
1052 json_body['security_group_rule']['port_range_min'] = port_range_min
1053 json_body['security_group_rule']['port_range_max'] = port_range_max
1054 logger.debug("Security_group format set (port range included)")
1056 # either both port range are set to None => do nothing
1057 # or one is set but not the other => log it and return False
1058 if port_range_min is None and port_range_max is None:
1059 logger.debug("Security_group format set (no port range mentioned)")
1061 logger.error("Bad security group format."
1062 "One of the port range is not properly set:"
1064 "range max: {}".format(port_range_min,
1068 # Create security group using neutron client
1070 neutron_client.create_security_group_rule(json_body)
1073 logger.exception("Impossible to create_security_group_rule,"
1074 "security group rule probably already exists")
1078 def get_security_group_rules(neutron_client, sg_id):
1080 security_rules = neutron_client.list_security_group_rules()[
1081 'security_group_rules']
1082 security_rules = [rule for rule in security_rules
1083 if rule["security_group_id"] == sg_id]
1084 return security_rules
1085 except Exception as e:
1086 logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:"
1091 def check_security_group_rules(neutron_client, sg_id, direction, protocol,
1092 port_min=None, port_max=None):
1094 security_rules = get_security_group_rules(neutron_client, sg_id)
1095 security_rules = [rule for rule in security_rules
1096 if (rule["direction"].lower() == direction and
1097 rule["protocol"].lower() == protocol and
1098 rule["port_range_min"] == port_min and
1099 rule["port_range_max"] == port_max)]
1100 if len(security_rules) == 0:
1104 except Exception as e:
1105 logger.error("Error [check_security_group_rules("
1106 " neutron_client, sg_id, direction,"
1107 " protocol, port_min=None, port_max=None)]: "
1112 def create_security_group_full(neutron_client,
1113 sg_name, sg_description):
1114 sg_id = get_security_group_id(neutron_client, sg_name)
1116 logger.info("Using existing security group '%s'..." % sg_name)
1118 logger.info("Creating security group '%s'..." % sg_name)
1119 SECGROUP = create_security_group(neutron_client,
1123 logger.error("Failed to create the security group...")
1126 sg_id = SECGROUP['id']
1128 logger.debug("Security group '%s' with ID=%s created successfully."
1129 % (SECGROUP['name'], sg_id))
1131 logger.debug("Adding ICMP rules in security group '%s'..."
1133 if not create_secgroup_rule(neutron_client, sg_id,
1135 logger.error("Failed to create the security group rule...")
1138 logger.debug("Adding SSH rules in security group '%s'..."
1140 if not create_secgroup_rule(
1141 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1142 logger.error("Failed to create the security group rule...")
1145 if not create_secgroup_rule(
1146 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1147 logger.error("Failed to create the security group rule...")
1152 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
1154 nova_client.servers.add_security_group(instance_id, secgroup_id)
1156 except Exception as e:
1157 logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
1158 "'%s')]: %s" % (instance_id, secgroup_id, e))
1162 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1163 json_body = {"quota": {
1164 "security_group": sg_quota,
1165 "security_group_rule": sg_rule_quota
1169 neutron_client.update_quota(tenant_id=tenant_id,
1172 except Exception as e:
1173 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1174 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1178 def delete_security_group(neutron_client, secgroup_id):
1180 neutron_client.delete_security_group(secgroup_id)
1182 except Exception as e:
1183 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1188 # *********************************************
1190 # *********************************************
1191 def get_images(nova_client):
1193 images = nova_client.images.list()
1195 except Exception as e:
1196 logger.error("Error [get_images]: %s" % e)
1200 def get_image_id(glance_client, image_name):
1201 images = glance_client.images.list()
1204 if i.name == image_name:
1210 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
1211 container="bare", public="public"):
1212 if not os.path.isfile(file_path):
1213 logger.error("Error: file %s does not exist." % file_path)
1216 image_id = get_image_id(glance_client, image_name)
1218 logger.info("Image %s already exists." % image_name)
1220 logger.info("Creating image '%s' from '%s'..." % (image_name,
1223 image = glance_client.images.create(name=image_name,
1226 container_format=container)
1228 with open(file_path) as image_data:
1229 glance_client.images.upload(image_id, image_data)
1231 except Exception as e:
1232 logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1233 "'%s')]: %s" % (image_name, file_path, public, e))
1237 def get_or_create_image(name, path, format):
1238 image_exists = False
1239 glance_client = get_glance_client()
1241 image_id = get_image_id(glance_client, name)
1243 logger.info("Using existing image '%s'..." % name)
1246 logger.info("Creating image '%s' from '%s'..." % (name, path))
1247 image_id = create_glance_image(glance_client, name, path, format)
1249 logger.error("Failed to create a Glance image...")
1251 logger.debug("Image '%s' with ID=%s created successfully."
1254 return image_exists, image_id
1257 def delete_glance_image(nova_client, image_id):
1259 nova_client.images.delete(image_id)
1261 except Exception as e:
1262 logger.error("Error [delete_glance_image(nova_client, '%s')]: %s"
1267 # *********************************************
1269 # *********************************************
1270 def get_volumes(cinder_client):
1272 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1274 except Exception as e:
1275 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1279 def list_volume_types(cinder_client, public=True, private=True):
1281 volume_types = cinder_client.volume_types.list()
1283 volume_types = [vt for vt in volume_types if not vt.is_public]
1285 volume_types = [vt for vt in volume_types if vt.is_public]
1287 except Exception as e:
1288 logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
1292 def create_volume_type(cinder_client, name):
1294 volume_type = cinder_client.volume_types.create(name)
1296 except Exception as e:
1297 logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
1302 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1303 snapshots_quota, gigabytes_quota):
1304 quotas_values = {"volumes": vols_quota,
1305 "snapshots": snapshots_quota,
1306 "gigabytes": gigabytes_quota}
1309 cinder_client.quotas.update(tenant_id, **quotas_values)
1311 except Exception as e:
1312 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1313 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1314 snapshots_quota, gigabytes_quota, e))
1318 def delete_volume(cinder_client, volume_id, forced=False):
1322 cinder_client.volumes.detach(volume_id)
1324 logger.error(sys.exc_info()[0])
1325 cinder_client.volumes.force_delete(volume_id)
1327 cinder_client.volumes.delete(volume_id)
1329 except Exception as e:
1330 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1331 % (volume_id, str(forced), e))
1335 def delete_volume_type(cinder_client, volume_type):
1337 cinder_client.volume_types.delete(volume_type)
1339 except Exception as e:
1340 logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
1345 # *********************************************
1347 # *********************************************
1348 def get_tenants(keystone_client):
1350 if is_keystone_v3():
1351 tenants = keystone_client.projects.list()
1353 tenants = keystone_client.tenants.list()
1355 except Exception as e:
1356 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1360 def get_users(keystone_client):
1362 users = keystone_client.users.list()
1364 except Exception as e:
1365 logger.error("Error [get_users(keystone_client)]: %s" % e)
1369 def get_tenant_id(keystone_client, tenant_name):
1370 tenants = get_tenants(keystone_client)
1373 if t.name == tenant_name:
1379 def get_user_id(keystone_client, user_name):
1380 users = get_users(keystone_client)
1383 if u.name == user_name:
1389 def get_role_id(keystone_client, role_name):
1390 roles = keystone_client.roles.list()
1393 if r.name == role_name:
1399 def create_tenant(keystone_client, tenant_name, tenant_description):
1401 if is_keystone_v3():
1402 tenant = keystone_client.projects.create(
1404 description=tenant_description,
1408 tenant = keystone_client.tenants.create(tenant_name,
1412 except Exception as e:
1413 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1414 % (tenant_name, tenant_description, e))
1418 def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
1419 tenant_id = get_tenant_id(keystone_client, tenant_name)
1421 tenant_id = create_tenant(keystone_client, tenant_name,
1427 def get_or_create_tenant_for_vnf(keystone_client, tenant_name,
1428 tenant_description):
1429 """Get or Create a Tenant
1432 keystone_client: keystone client reference
1433 tenant_name: the name of the tenant
1434 tenant_description: the description of the tenant
1436 return False if tenant retrieved though get
1437 return True if tenant created
1438 raise Exception if error during processing
1441 tenant_id = get_tenant_id(keystone_client, tenant_name)
1443 tenant_id = create_tenant(keystone_client, tenant_name,
1449 raise Exception("Impossible to create a Tenant for the VNF {}".format(
1453 def create_user(keystone_client, user_name, user_password,
1454 user_email, tenant_id):
1456 if is_keystone_v3():
1457 user = keystone_client.users.create(name=user_name,
1458 password=user_password,
1460 project_id=tenant_id,
1463 user = keystone_client.users.create(user_name,
1469 except Exception as e:
1470 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1471 "'%s')]: %s" % (user_name, user_password,
1472 user_email, tenant_id, e))
1476 def get_or_create_user(keystone_client, user_name, user_password,
1477 tenant_id, user_email=None):
1478 user_id = get_user_id(keystone_client, user_name)
1480 user_id = create_user(keystone_client, user_name, user_password,
1481 user_email, tenant_id)
1485 def get_or_create_user_for_vnf(keystone_client, vnf_ref):
1486 """Get or Create user for VNF
1489 keystone_client: keystone client reference
1490 vnf_ref: VNF reference used as user name & password, tenant name
1492 return False if user retrieved through get
1493 return True if user created
1494 raise Exception if error during processing
1497 user_id = get_user_id(keystone_client, vnf_ref)
1498 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1500 user_id = create_user(keystone_client, vnf_ref, vnf_ref,
1505 add_role_user(keystone_client, user_id, 'admin', vnf_ref)
1507 raise Exception("Impossible to create a user for the VNF {}".format(
1511 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1513 if is_keystone_v3():
1514 keystone_client.roles.grant(role=role_id,
1518 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1520 except Exception as e:
1521 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1522 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1526 def delete_tenant(keystone_client, tenant_id):
1528 if is_keystone_v3():
1529 keystone_client.projects.delete(tenant_id)
1531 keystone_client.tenants.delete(tenant_id)
1533 except Exception as e:
1534 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1539 def delete_user(keystone_client, user_id):
1541 keystone_client.users.delete(user_id)
1543 except Exception as e:
1544 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1549 # *********************************************
1551 # *********************************************
1552 def get_resource(heat_client, stack_id, resource):
1554 resources = heat_client.resources.get(stack_id, resource)
1556 except Exception as e:
1557 logger.error("Error [get_resource]: %s" % e)