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 cacert = os.getenv('OS_CACERT')
185 if cacert is not None:
186 if not os.path.isfile(cacert):
187 raise Exception("The 'OS_CACERT' environment"
188 "variable is set to %s but the file"
189 "does not exist.", cacert)
191 return session.Session(auth=auth, verify=cacert)
194 # *********************************************
196 # *********************************************
197 def get_keystone_client_version():
198 api_version = os.getenv('OS_IDENTITY_API_VERSION')
199 if api_version is not None:
200 logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
203 return DEFAULT_API_VERSION
206 def get_keystone_client(other_creds={}):
207 sess = get_session(other_creds)
208 return keystoneclient.Client(get_keystone_client_version(),
210 interface=os.getenv('OS_INTERFACE', 'admin'))
213 def get_nova_client_version():
214 api_version = os.getenv('OS_COMPUTE_API_VERSION')
215 if api_version is not None:
216 logger.info("OS_COMPUTE_API_VERSION is set in env as '%s'",
219 return DEFAULT_API_VERSION
222 def get_nova_client(other_creds={}):
223 sess = get_session(other_creds)
224 return novaclient.Client(get_nova_client_version(), session=sess)
227 def get_cinder_client_version():
228 api_version = os.getenv('OS_VOLUME_API_VERSION')
229 if api_version is not None:
230 logger.info("OS_VOLUME_API_VERSION is set in env as '%s'",
233 return DEFAULT_API_VERSION
236 def get_cinder_client(other_creds={}):
237 sess = get_session(other_creds)
238 return cinderclient.Client(get_cinder_client_version(), session=sess)
241 def get_neutron_client_version():
242 api_version = os.getenv('OS_NETWORK_API_VERSION')
243 if api_version is not None:
244 logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
247 return DEFAULT_API_VERSION
250 def get_neutron_client(other_creds={}):
251 sess = get_session(other_creds)
252 return neutronclient.Client(get_neutron_client_version(), session=sess)
255 def get_glance_client_version():
256 api_version = os.getenv('OS_IMAGE_API_VERSION')
257 if api_version is not None:
258 logger.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version)
260 return DEFAULT_API_VERSION
263 def get_glance_client(other_creds={}):
264 sess = get_session(other_creds)
265 return glanceclient.Client(get_glance_client_version(), session=sess)
268 def get_heat_client_version():
269 api_version = os.getenv('OS_ORCHESTRATION_API_VERSION')
270 if api_version is not None:
271 logger.info("OS_ORCHESTRATION_API_VERSION is set in env as '%s'",
274 return DEFAULT_HEAT_API_VERSION
277 def get_heat_client(other_creds={}):
278 sess = get_session(other_creds)
279 return heatclient.Client(get_heat_client_version(), session=sess)
282 def download_and_add_image_on_glance(glance, image_name, image_url, data_dir):
284 if not os.path.exists(dest_path):
285 os.makedirs(dest_path)
286 file_name = image_url.rsplit('/')[-1]
287 if not ft_utils.download_url(image_url, dest_path):
290 image = create_glance_image(
291 glance, image_name, dest_path + file_name)
298 # *********************************************
300 # *********************************************
301 def get_instances(nova_client):
303 instances = nova_client.servers.list(search_opts={'all_tenants': 1})
305 except Exception as e:
306 logger.error("Error [get_instances(nova_client)]: %s" % e)
310 def get_instance_status(nova_client, instance):
312 instance = nova_client.servers.get(instance.id)
313 return instance.status
314 except Exception as e:
315 logger.error("Error [get_instance_status(nova_client)]: %s" % e)
319 def get_instance_by_name(nova_client, instance_name):
321 instance = nova_client.servers.find(name=instance_name)
323 except Exception as e:
324 logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
325 % (instance_name, e))
329 def get_flavor_id(nova_client, flavor_name):
330 flavors = nova_client.flavors.list(detailed=True)
333 if f.name == flavor_name:
339 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
340 flavors = nova_client.flavors.list(detailed=True)
343 if min_ram <= f.ram and f.ram <= max_ram:
349 def get_aggregates(nova_client):
351 aggregates = nova_client.aggregates.list()
353 except Exception as e:
354 logger.error("Error [get_aggregates(nova_client)]: %s" % e)
358 def get_aggregate_id(nova_client, aggregate_name):
360 aggregates = get_aggregates(nova_client)
361 _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
363 except Exception as e:
364 logger.error("Error [get_aggregate_id(nova_client, %s)]:"
365 " %s" % (aggregate_name, e))
369 def get_availability_zones(nova_client):
371 availability_zones = nova_client.availability_zones.list()
372 return availability_zones
373 except Exception as e:
374 logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
378 def get_availability_zone_names(nova_client):
380 az_names = [az.zoneName for az in get_availability_zones(nova_client)]
382 except Exception as e:
383 logger.error("Error [get_availability_zone_names(nova_client)]:"
388 def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
390 flavor = nova_client.flavors.create(
391 flavor_name, ram, vcpus, disk, is_public=public)
393 extra_specs = ft_utils.get_functest_config(
394 'general.flavor_extra_specs')
395 flavor.set_keys(extra_specs)
397 # flavor extra specs are not configured, therefore skip the update
400 except Exception as e:
401 logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
402 "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
407 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
408 flavor_exists = False
409 nova_client = get_nova_client()
411 flavor_id = get_flavor_id(nova_client, flavor_name)
413 logger.info("Using existing flavor '%s'..." % flavor_name)
416 logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
417 "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
418 flavor_id = create_flavor(
419 nova_client, flavor_name, ram, disk, vcpus, public=public)
421 logger.error("Failed to create flavor '%s'..." % (flavor_name))
423 logger.debug("Flavor '%s' with ID=%s created successfully."
424 % (flavor_name, flavor_id))
426 return flavor_exists, flavor_id
429 def get_floating_ips(nova_client):
431 floating_ips = nova_client.floating_ips.list()
433 except Exception as e:
434 logger.error("Error [get_floating_ips(nova_client)]: %s" % e)
438 def get_hypervisors(nova_client):
441 hypervisors = nova_client.hypervisors.list()
442 for hypervisor in hypervisors:
443 if hypervisor.state == "up":
444 nodes.append(hypervisor.hypervisor_hostname)
446 except Exception as e:
447 logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
451 def create_aggregate(nova_client, aggregate_name, av_zone):
453 nova_client.aggregates.create(aggregate_name, av_zone)
455 except Exception as e:
456 logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
457 % (aggregate_name, av_zone, e))
461 def add_host_to_aggregate(nova_client, aggregate_name, compute_host):
463 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
464 nova_client.aggregates.add_host(aggregate_id, compute_host)
466 except Exception as e:
467 logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
468 % (aggregate_name, compute_host, e))
472 def create_aggregate_with_host(
473 nova_client, aggregate_name, av_zone, compute_host):
475 create_aggregate(nova_client, aggregate_name, av_zone)
476 add_host_to_aggregate(nova_client, aggregate_name, compute_host)
478 except Exception as e:
479 logger.error("Error [create_aggregate_with_host("
480 "nova_client, %s, %s, %s)]: %s"
481 % (aggregate_name, av_zone, compute_host, e))
485 def create_instance(flavor_name,
488 instance_name="functest-vm",
494 nova_client = get_nova_client()
496 flavor = nova_client.flavors.find(name=flavor_name)
498 flavors = nova_client.flavors.list()
499 logger.error("Error: Flavor '%s' not found. Available flavors are: "
500 "\n%s" % (flavor_name, flavors))
502 if fixed_ip is not None:
503 nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
505 nics = {"net-id": network_id}
507 instance = nova_client.servers.create(
512 availability_zone=av_zone,
516 instance = nova_client.servers.create(
521 config_drive=confdrive,
523 availability_zone=av_zone,
529 def create_instance_and_wait_for_active(flavor_name,
539 VM_BOOT_TIMEOUT = 180
540 nova_client = get_nova_client()
541 instance = create_instance(flavor_name,
550 count = VM_BOOT_TIMEOUT / SLEEP
551 for n in range(count, -1, -1):
552 status = get_instance_status(nova_client, instance)
553 if status.lower() == "active":
555 elif status.lower() == "error":
556 logger.error("The instance %s went to ERROR status."
560 logger.error("Timeout booting the instance %s." % instance_name)
564 def create_floating_ip(neutron_client):
565 extnet_id = get_external_net_id(neutron_client)
566 props = {'floating_network_id': extnet_id}
568 ip_json = neutron_client.create_floatingip({'floatingip': props})
569 fip_addr = ip_json['floatingip']['floating_ip_address']
570 fip_id = ip_json['floatingip']['id']
571 except Exception as e:
572 logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
574 return {'fip_addr': fip_addr, 'fip_id': fip_id}
577 def add_floating_ip(nova_client, server_id, floatingip_addr):
579 nova_client.servers.add_floating_ip(server_id, floatingip_addr)
581 except Exception as e:
582 logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
583 % (server_id, floatingip_addr, e))
587 def delete_instance(nova_client, instance_id):
589 nova_client.servers.force_delete(instance_id)
591 except Exception as e:
592 logger.error("Error [delete_instance(nova_client, '%s')]: %s"
597 def delete_floating_ip(nova_client, floatingip_id):
599 nova_client.floating_ips.delete(floatingip_id)
601 except Exception as e:
602 logger.error("Error [delete_floating_ip(nova_client, '%s')]: %s"
603 % (floatingip_id, e))
607 def remove_host_from_aggregate(nova_client, aggregate_name, compute_host):
609 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
610 nova_client.aggregates.remove_host(aggregate_id, compute_host)
612 except Exception as e:
613 logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
614 " %s" % (aggregate_name, compute_host, e))
618 def remove_hosts_from_aggregate(nova_client, aggregate_name):
619 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
620 hosts = nova_client.aggregates.get(aggregate_id).hosts
622 all(remove_host_from_aggregate(nova_client, aggregate_name, host)
626 def delete_aggregate(nova_client, aggregate_name):
628 remove_hosts_from_aggregate(nova_client, aggregate_name)
629 nova_client.aggregates.delete(aggregate_name)
631 except Exception as e:
632 logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
633 % (aggregate_name, e))
637 # *********************************************
639 # *********************************************
640 def get_network_list(neutron_client):
641 network_list = neutron_client.list_networks()['networks']
642 if len(network_list) == 0:
648 def get_router_list(neutron_client):
649 router_list = neutron_client.list_routers()['routers']
650 if len(router_list) == 0:
656 def get_port_list(neutron_client):
657 port_list = neutron_client.list_ports()['ports']
658 if len(port_list) == 0:
664 def get_network_id(neutron_client, network_name):
665 networks = neutron_client.list_networks()['networks']
668 if n['name'] == network_name:
674 def get_subnet_id(neutron_client, subnet_name):
675 subnets = neutron_client.list_subnets()['subnets']
678 if s['name'] == subnet_name:
684 def get_router_id(neutron_client, router_name):
685 routers = neutron_client.list_routers()['routers']
688 if r['name'] == router_name:
694 def get_private_net(neutron_client):
695 # Checks if there is an existing shared private network
696 networks = neutron_client.list_networks()['networks']
697 if len(networks) == 0:
700 if (net['router:external'] is False) and (net['shared'] is True):
705 def get_external_net(neutron_client):
706 for network in neutron_client.list_networks()['networks']:
707 if network['router:external']:
708 return network['name']
712 def get_external_net_id(neutron_client):
713 for network in neutron_client.list_networks()['networks']:
714 if network['router:external']:
719 def check_neutron_net(neutron_client, net_name):
720 for network in neutron_client.list_networks()['networks']:
721 if network['name'] == net_name:
722 for subnet in network['subnets']:
727 def create_neutron_net(neutron_client, name):
728 json_body = {'network': {'name': name,
729 'admin_state_up': True}}
731 network = neutron_client.create_network(body=json_body)
732 network_dict = network['network']
733 return network_dict['id']
734 except Exception as e:
735 logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
740 def create_neutron_subnet(neutron_client, name, cidr, net_id):
741 json_body = {'subnets': [{'name': name, 'cidr': cidr,
742 'ip_version': 4, 'network_id': net_id}]}
744 subnet = neutron_client.create_subnet(body=json_body)
745 return subnet['subnets'][0]['id']
746 except Exception as e:
747 logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
748 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
752 def create_neutron_router(neutron_client, name):
753 json_body = {'router': {'name': name, 'admin_state_up': True}}
755 router = neutron_client.create_router(json_body)
756 return router['router']['id']
757 except Exception as e:
758 logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
763 def create_neutron_port(neutron_client, name, network_id, ip):
764 json_body = {'port': {
765 'admin_state_up': True,
767 'network_id': network_id,
768 'fixed_ips': [{"ip_address": ip}]
771 port = neutron_client.create_port(body=json_body)
772 return port['port']['id']
773 except Exception as e:
774 logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
775 "'%s')]: %s" % (name, network_id, ip, e))
779 def update_neutron_net(neutron_client, network_id, shared=False):
780 json_body = {'network': {'shared': shared}}
782 neutron_client.update_network(network_id, body=json_body)
784 except Exception as e:
785 logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
786 "%s" % (network_id, str(shared), e))
790 def update_neutron_port(neutron_client, port_id, device_owner):
791 json_body = {'port': {
792 'device_owner': device_owner,
795 port = neutron_client.update_port(port=port_id,
797 return port['port']['id']
798 except Exception as e:
799 logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
800 " %s" % (port_id, device_owner, e))
804 def add_interface_router(neutron_client, router_id, subnet_id):
805 json_body = {"subnet_id": subnet_id}
807 neutron_client.add_interface_router(router=router_id, body=json_body)
809 except Exception as e:
810 logger.error("Error [add_interface_router(neutron_client, '%s', "
811 "'%s')]: %s" % (router_id, subnet_id, e))
815 def add_gateway_router(neutron_client, router_id):
816 ext_net_id = get_external_net_id(neutron_client)
817 router_dict = {'network_id': ext_net_id}
819 neutron_client.add_gateway_router(router_id, router_dict)
821 except Exception as e:
822 logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
827 def delete_neutron_net(neutron_client, network_id):
829 neutron_client.delete_network(network_id)
831 except Exception as e:
832 logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
837 def delete_neutron_subnet(neutron_client, subnet_id):
839 neutron_client.delete_subnet(subnet_id)
841 except Exception as e:
842 logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
847 def delete_neutron_router(neutron_client, router_id):
849 neutron_client.delete_router(router=router_id)
851 except Exception as e:
852 logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
857 def delete_neutron_port(neutron_client, port_id):
859 neutron_client.delete_port(port_id)
861 except Exception as e:
862 logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
867 def remove_interface_router(neutron_client, router_id, subnet_id):
868 json_body = {"subnet_id": subnet_id}
870 neutron_client.remove_interface_router(router=router_id,
873 except Exception as e:
874 logger.error("Error [remove_interface_router(neutron_client, '%s', "
875 "'%s')]: %s" % (router_id, subnet_id, e))
879 def remove_gateway_router(neutron_client, router_id):
881 neutron_client.remove_gateway_router(router_id)
883 except Exception as e:
884 logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
889 def create_network_full(neutron_client,
895 # Check if the network already exists
896 network_id = get_network_id(neutron_client, net_name)
897 subnet_id = get_subnet_id(neutron_client, subnet_name)
898 router_id = get_router_id(neutron_client, router_name)
900 if network_id != '' and subnet_id != '' and router_id != '':
901 logger.info("A network with name '%s' already exists..." % net_name)
903 neutron_client.format = 'json'
904 logger.info('Creating neutron network %s...' % net_name)
905 network_id = create_neutron_net(neutron_client, net_name)
910 logger.debug("Network '%s' created successfully" % network_id)
911 logger.debug('Creating Subnet....')
912 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
917 logger.debug("Subnet '%s' created successfully" % subnet_id)
918 logger.debug('Creating Router...')
919 router_id = create_neutron_router(neutron_client, router_name)
924 logger.debug("Router '%s' created successfully" % router_id)
925 logger.debug('Adding router to subnet...')
927 if not add_interface_router(neutron_client, router_id, subnet_id):
930 logger.debug("Interface added successfully.")
932 logger.debug('Adding gateway to router...')
933 if not add_gateway_router(neutron_client, router_id):
936 logger.debug("Gateway added successfully.")
938 network_dic = {'net_id': network_id,
939 'subnet_id': subnet_id,
940 'router_id': router_id}
944 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
945 neutron_client = get_neutron_client()
947 network_dic = create_network_full(neutron_client,
953 if not update_neutron_net(neutron_client,
954 network_dic['net_id'],
956 logger.error("Failed to update network %s..." % net_name)
959 logger.debug("Network '%s' is available..." % net_name)
961 logger.error("Network %s creation failed" % net_name)
966 def create_bgpvpn(neutron_client, **kwargs):
967 # route_distinguishers
969 json_body = {"bgpvpn": kwargs}
970 return neutron_client.create_bgpvpn(json_body)
973 def create_network_association(neutron_client, bgpvpn_id, neutron_network_id):
974 json_body = {"network_association": {"network_id": neutron_network_id}}
975 return neutron_client.create_network_association(bgpvpn_id, json_body)
978 def create_router_association(neutron_client, bgpvpn_id, router_id):
979 json_body = {"router_association": {"router_id": router_id}}
980 return neutron_client.create_router_association(bgpvpn_id, json_body)
983 def update_bgpvpn(neutron_client, bgpvpn_id, **kwargs):
984 json_body = {"bgpvpn": kwargs}
985 return neutron_client.update_bgpvpn(bgpvpn_id, json_body)
988 def delete_bgpvpn(neutron_client, bgpvpn_id):
989 return neutron_client.delete_bgpvpn(bgpvpn_id)
992 def get_bgpvpn(neutron_client, bgpvpn_id):
993 return neutron_client.show_bgpvpn(bgpvpn_id)
996 def get_bgpvpn_routers(neutron_client, bgpvpn_id):
997 return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['routers']
1000 def get_bgpvpn_networks(neutron_client, bgpvpn_id):
1001 return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['networks']
1003 # *********************************************
1005 # *********************************************
1008 def get_security_groups(neutron_client):
1010 security_groups = neutron_client.list_security_groups()[
1012 return security_groups
1013 except Exception as e:
1014 logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
1018 def get_security_group_id(neutron_client, sg_name):
1019 security_groups = get_security_groups(neutron_client)
1021 for sg in security_groups:
1022 if sg['name'] == sg_name:
1028 def create_security_group(neutron_client, sg_name, sg_description):
1029 json_body = {'security_group': {'name': sg_name,
1030 'description': sg_description}}
1032 secgroup = neutron_client.create_security_group(json_body)
1033 return secgroup['security_group']
1034 except Exception as e:
1035 logger.error("Error [create_security_group(neutron_client, '%s', "
1036 "'%s')]: %s" % (sg_name, sg_description, e))
1040 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
1041 port_range_min=None, port_range_max=None):
1042 # We create a security group in 2 steps
1043 # 1 - we check the format and set the json body accordingly
1044 # 2 - we call neturon client to create the security group
1047 json_body = {'security_group_rule': {'direction': direction,
1048 'security_group_id': sg_id,
1049 'protocol': protocol}}
1051 # - both None => we do nothing
1052 # - both Not None => we add them to the json description
1053 # but one cannot be None is the other is not None
1054 if (port_range_min is not None and port_range_max is not None):
1055 # add port_range in json description
1056 json_body['security_group_rule']['port_range_min'] = port_range_min
1057 json_body['security_group_rule']['port_range_max'] = port_range_max
1058 logger.debug("Security_group format set (port range included)")
1060 # either both port range are set to None => do nothing
1061 # or one is set but not the other => log it and return False
1062 if port_range_min is None and port_range_max is None:
1063 logger.debug("Security_group format set (no port range mentioned)")
1065 logger.error("Bad security group format."
1066 "One of the port range is not properly set:"
1068 "range max: {}".format(port_range_min,
1072 # Create security group using neutron client
1074 neutron_client.create_security_group_rule(json_body)
1077 logger.exception("Impossible to create_security_group_rule,"
1078 "security group rule probably already exists")
1082 def get_security_group_rules(neutron_client, sg_id):
1084 security_rules = neutron_client.list_security_group_rules()[
1085 'security_group_rules']
1086 security_rules = [rule for rule in security_rules
1087 if rule["security_group_id"] == sg_id]
1088 return security_rules
1089 except Exception as e:
1090 logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:"
1095 def check_security_group_rules(neutron_client, sg_id, direction, protocol,
1096 port_min=None, port_max=None):
1098 security_rules = get_security_group_rules(neutron_client, sg_id)
1099 security_rules = [rule for rule in security_rules
1100 if (rule["direction"].lower() == direction and
1101 rule["protocol"].lower() == protocol and
1102 rule["port_range_min"] == port_min and
1103 rule["port_range_max"] == port_max)]
1104 if len(security_rules) == 0:
1108 except Exception as e:
1109 logger.error("Error [check_security_group_rules("
1110 " neutron_client, sg_id, direction,"
1111 " protocol, port_min=None, port_max=None)]: "
1116 def create_security_group_full(neutron_client,
1117 sg_name, sg_description):
1118 sg_id = get_security_group_id(neutron_client, sg_name)
1120 logger.info("Using existing security group '%s'..." % sg_name)
1122 logger.info("Creating security group '%s'..." % sg_name)
1123 SECGROUP = create_security_group(neutron_client,
1127 logger.error("Failed to create the security group...")
1130 sg_id = SECGROUP['id']
1132 logger.debug("Security group '%s' with ID=%s created successfully."
1133 % (SECGROUP['name'], sg_id))
1135 logger.debug("Adding ICMP rules in security group '%s'..."
1137 if not create_secgroup_rule(neutron_client, sg_id,
1139 logger.error("Failed to create the security group rule...")
1142 logger.debug("Adding SSH rules in security group '%s'..."
1144 if not create_secgroup_rule(
1145 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1146 logger.error("Failed to create the security group rule...")
1149 if not create_secgroup_rule(
1150 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1151 logger.error("Failed to create the security group rule...")
1156 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
1158 nova_client.servers.add_security_group(instance_id, secgroup_id)
1160 except Exception as e:
1161 logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
1162 "'%s')]: %s" % (instance_id, secgroup_id, e))
1166 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1167 json_body = {"quota": {
1168 "security_group": sg_quota,
1169 "security_group_rule": sg_rule_quota
1173 neutron_client.update_quota(tenant_id=tenant_id,
1176 except Exception as e:
1177 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1178 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1182 def delete_security_group(neutron_client, secgroup_id):
1184 neutron_client.delete_security_group(secgroup_id)
1186 except Exception as e:
1187 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1192 # *********************************************
1194 # *********************************************
1195 def get_images(nova_client):
1197 images = nova_client.images.list()
1199 except Exception as e:
1200 logger.error("Error [get_images]: %s" % e)
1204 def get_image_id(glance_client, image_name):
1205 images = glance_client.images.list()
1208 if i.name == image_name:
1214 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
1215 container="bare", public="public"):
1216 if not os.path.isfile(file_path):
1217 logger.error("Error: file %s does not exist." % file_path)
1220 image_id = get_image_id(glance_client, image_name)
1222 logger.info("Image %s already exists." % image_name)
1224 logger.info("Creating image '%s' from '%s'..." % (image_name,
1227 image = glance_client.images.create(name=image_name,
1230 container_format=container)
1232 with open(file_path) as image_data:
1233 glance_client.images.upload(image_id, image_data)
1235 except Exception as e:
1236 logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1237 "'%s')]: %s" % (image_name, file_path, public, e))
1241 def get_or_create_image(name, path, format):
1242 image_exists = False
1243 glance_client = get_glance_client()
1245 image_id = get_image_id(glance_client, name)
1247 logger.info("Using existing image '%s'..." % name)
1250 logger.info("Creating image '%s' from '%s'..." % (name, path))
1251 image_id = create_glance_image(glance_client, name, path, format)
1253 logger.error("Failed to create a Glance image...")
1255 logger.debug("Image '%s' with ID=%s created successfully."
1258 return image_exists, image_id
1261 def delete_glance_image(nova_client, image_id):
1263 nova_client.images.delete(image_id)
1265 except Exception as e:
1266 logger.error("Error [delete_glance_image(nova_client, '%s')]: %s"
1271 # *********************************************
1273 # *********************************************
1274 def get_volumes(cinder_client):
1276 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1278 except Exception as e:
1279 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1283 def list_volume_types(cinder_client, public=True, private=True):
1285 volume_types = cinder_client.volume_types.list()
1287 volume_types = [vt for vt in volume_types if not vt.is_public]
1289 volume_types = [vt for vt in volume_types if vt.is_public]
1291 except Exception as e:
1292 logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
1296 def create_volume_type(cinder_client, name):
1298 volume_type = cinder_client.volume_types.create(name)
1300 except Exception as e:
1301 logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
1306 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1307 snapshots_quota, gigabytes_quota):
1308 quotas_values = {"volumes": vols_quota,
1309 "snapshots": snapshots_quota,
1310 "gigabytes": gigabytes_quota}
1313 cinder_client.quotas.update(tenant_id, **quotas_values)
1315 except Exception as e:
1316 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1317 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1318 snapshots_quota, gigabytes_quota, e))
1322 def delete_volume(cinder_client, volume_id, forced=False):
1326 cinder_client.volumes.detach(volume_id)
1328 logger.error(sys.exc_info()[0])
1329 cinder_client.volumes.force_delete(volume_id)
1331 cinder_client.volumes.delete(volume_id)
1333 except Exception as e:
1334 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1335 % (volume_id, str(forced), e))
1339 def delete_volume_type(cinder_client, volume_type):
1341 cinder_client.volume_types.delete(volume_type)
1343 except Exception as e:
1344 logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
1349 # *********************************************
1351 # *********************************************
1352 def get_tenants(keystone_client):
1354 if is_keystone_v3():
1355 tenants = keystone_client.projects.list()
1357 tenants = keystone_client.tenants.list()
1359 except Exception as e:
1360 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1364 def get_users(keystone_client):
1366 users = keystone_client.users.list()
1368 except Exception as e:
1369 logger.error("Error [get_users(keystone_client)]: %s" % e)
1373 def get_tenant_id(keystone_client, tenant_name):
1374 tenants = get_tenants(keystone_client)
1377 if t.name == tenant_name:
1383 def get_user_id(keystone_client, user_name):
1384 users = get_users(keystone_client)
1387 if u.name == user_name:
1393 def get_role_id(keystone_client, role_name):
1394 roles = keystone_client.roles.list()
1397 if r.name == role_name:
1403 def create_tenant(keystone_client, tenant_name, tenant_description):
1405 if is_keystone_v3():
1406 tenant = keystone_client.projects.create(
1408 description=tenant_description,
1412 tenant = keystone_client.tenants.create(tenant_name,
1416 except Exception as e:
1417 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1418 % (tenant_name, tenant_description, e))
1422 def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
1423 tenant_id = get_tenant_id(keystone_client, tenant_name)
1425 tenant_id = create_tenant(keystone_client, tenant_name,
1431 def get_or_create_tenant_for_vnf(keystone_client, tenant_name,
1432 tenant_description):
1433 """Get or Create a Tenant
1436 keystone_client: keystone client reference
1437 tenant_name: the name of the tenant
1438 tenant_description: the description of the tenant
1440 return False if tenant retrieved though get
1441 return True if tenant created
1442 raise Exception if error during processing
1445 tenant_id = get_tenant_id(keystone_client, tenant_name)
1447 tenant_id = create_tenant(keystone_client, tenant_name,
1453 raise Exception("Impossible to create a Tenant for the VNF {}".format(
1457 def create_user(keystone_client, user_name, user_password,
1458 user_email, tenant_id):
1460 if is_keystone_v3():
1461 user = keystone_client.users.create(name=user_name,
1462 password=user_password,
1464 project_id=tenant_id,
1467 user = keystone_client.users.create(user_name,
1473 except Exception as e:
1474 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1475 "'%s')]: %s" % (user_name, user_password,
1476 user_email, tenant_id, e))
1480 def get_or_create_user(keystone_client, user_name, user_password,
1481 tenant_id, user_email=None):
1482 user_id = get_user_id(keystone_client, user_name)
1484 user_id = create_user(keystone_client, user_name, user_password,
1485 user_email, tenant_id)
1489 def get_or_create_user_for_vnf(keystone_client, vnf_ref):
1490 """Get or Create user for VNF
1493 keystone_client: keystone client reference
1494 vnf_ref: VNF reference used as user name & password, tenant name
1496 return False if user retrieved through get
1497 return True if user created
1498 raise Exception if error during processing
1501 user_id = get_user_id(keystone_client, vnf_ref)
1502 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1504 user_id = create_user(keystone_client, vnf_ref, vnf_ref,
1509 add_role_user(keystone_client, user_id, 'admin', vnf_ref)
1511 raise Exception("Impossible to create a user for the VNF {}".format(
1515 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1517 if is_keystone_v3():
1518 keystone_client.roles.grant(role=role_id,
1522 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1524 except Exception as e:
1525 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1526 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1530 def delete_tenant(keystone_client, tenant_id):
1532 if is_keystone_v3():
1533 keystone_client.projects.delete(tenant_id)
1535 keystone_client.tenants.delete(tenant_id)
1537 except Exception as e:
1538 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1543 def delete_user(keystone_client, user_id):
1545 keystone_client.users.delete(user_id)
1547 except Exception as e:
1548 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1553 # *********************************************
1555 # *********************************************
1556 def get_resource(heat_client, stack_id, resource):
1558 resources = heat_client.resources.get(stack_id, resource)
1560 except Exception as e:
1561 logger.error("Error [get_resource]: %s" % e)