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, interface='public'):
179 auth = get_session_auth()
180 return get_session().get_endpoint(auth=auth,
181 service_type=service_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):
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 raise Exception("Impossible to download image from {}".format(
294 image = create_glance_image(
295 glance, image_name, dest_path + file_name)
301 raise Exception("Impossible to put image {} in glance".format(
305 # *********************************************
307 # *********************************************
308 def get_instances(nova_client):
310 instances = nova_client.servers.list(search_opts={'all_tenants': 1})
312 except Exception as e:
313 logger.error("Error [get_instances(nova_client)]: %s" % e)
317 def get_instance_status(nova_client, instance):
319 instance = nova_client.servers.get(instance.id)
320 return instance.status
321 except Exception as e:
322 logger.error("Error [get_instance_status(nova_client)]: %s" % e)
326 def get_instance_by_name(nova_client, instance_name):
328 instance = nova_client.servers.find(name=instance_name)
330 except Exception as e:
331 logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
332 % (instance_name, e))
336 def get_flavor_id(nova_client, flavor_name):
337 flavors = nova_client.flavors.list(detailed=True)
340 if f.name == flavor_name:
346 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
347 flavors = nova_client.flavors.list(detailed=True)
350 if min_ram <= f.ram and f.ram <= max_ram:
356 def get_aggregates(nova_client):
358 aggregates = nova_client.aggregates.list()
360 except Exception as e:
361 logger.error("Error [get_aggregates(nova_client)]: %s" % e)
365 def get_aggregate_id(nova_client, aggregate_name):
367 aggregates = get_aggregates(nova_client)
368 _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
370 except Exception as e:
371 logger.error("Error [get_aggregate_id(nova_client, %s)]:"
372 " %s" % (aggregate_name, e))
376 def get_availability_zones(nova_client):
378 availability_zones = nova_client.availability_zones.list()
379 return availability_zones
380 except Exception as e:
381 logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
385 def get_availability_zone_names(nova_client):
387 az_names = [az.zoneName for az in get_availability_zones(nova_client)]
389 except Exception as e:
390 logger.error("Error [get_availability_zone_names(nova_client)]:"
395 def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
397 flavor = nova_client.flavors.create(
398 flavor_name, ram, vcpus, disk, is_public=public)
400 extra_specs = ft_utils.get_functest_config(
401 'general.flavor_extra_specs')
402 flavor.set_keys(extra_specs)
404 # flavor extra specs are not configured, therefore skip the update
407 except Exception as e:
408 logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
409 "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
414 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
415 flavor_exists = False
416 nova_client = get_nova_client()
418 flavor_id = get_flavor_id(nova_client, flavor_name)
420 logger.info("Using existing flavor '%s'..." % flavor_name)
423 logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
424 "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
425 flavor_id = create_flavor(
426 nova_client, flavor_name, ram, disk, vcpus, public=public)
428 raise Exception("Failed to create flavor '%s'..." % (flavor_name))
430 logger.debug("Flavor '%s' with ID=%s created successfully."
431 % (flavor_name, flavor_id))
433 return flavor_exists, flavor_id
436 def get_floating_ips(neutron_client):
438 floating_ips = neutron_client.list_floatingips()
439 return floating_ips['floatingips']
440 except Exception as e:
441 logger.error("Error [get_floating_ips(neutron_client)]: %s" % e)
445 def get_hypervisors(nova_client):
448 hypervisors = nova_client.hypervisors.list()
449 for hypervisor in hypervisors:
450 if hypervisor.state == "up":
451 nodes.append(hypervisor.hypervisor_hostname)
453 except Exception as e:
454 logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
458 def create_aggregate(nova_client, aggregate_name, av_zone):
460 nova_client.aggregates.create(aggregate_name, av_zone)
462 except Exception as e:
463 logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
464 % (aggregate_name, av_zone, e))
468 def add_host_to_aggregate(nova_client, aggregate_name, compute_host):
470 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
471 nova_client.aggregates.add_host(aggregate_id, compute_host)
473 except Exception as e:
474 logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
475 % (aggregate_name, compute_host, e))
479 def create_aggregate_with_host(
480 nova_client, aggregate_name, av_zone, compute_host):
482 create_aggregate(nova_client, aggregate_name, av_zone)
483 add_host_to_aggregate(nova_client, aggregate_name, compute_host)
485 except Exception as e:
486 logger.error("Error [create_aggregate_with_host("
487 "nova_client, %s, %s, %s)]: %s"
488 % (aggregate_name, av_zone, compute_host, e))
492 def create_instance(flavor_name,
495 instance_name="functest-vm",
501 nova_client = get_nova_client()
503 flavor = nova_client.flavors.find(name=flavor_name)
505 flavors = nova_client.flavors.list()
506 logger.error("Error: Flavor '%s' not found. Available flavors are: "
507 "\n%s" % (flavor_name, flavors))
509 if fixed_ip is not None:
510 nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
512 nics = {"net-id": network_id}
514 instance = nova_client.servers.create(
519 availability_zone=av_zone,
523 instance = nova_client.servers.create(
528 config_drive=confdrive,
530 availability_zone=av_zone,
536 def create_instance_and_wait_for_active(flavor_name,
546 VM_BOOT_TIMEOUT = 180
547 nova_client = get_nova_client()
548 instance = create_instance(flavor_name,
557 count = VM_BOOT_TIMEOUT / SLEEP
558 for n in range(count, -1, -1):
559 status = get_instance_status(nova_client, instance)
560 if status.lower() == "active":
562 elif status.lower() == "error":
563 logger.error("The instance %s went to ERROR status."
567 logger.error("Timeout booting the instance %s." % instance_name)
571 def create_floating_ip(neutron_client):
572 extnet_id = get_external_net_id(neutron_client)
573 props = {'floating_network_id': extnet_id}
575 ip_json = neutron_client.create_floatingip({'floatingip': props})
576 fip_addr = ip_json['floatingip']['floating_ip_address']
577 fip_id = ip_json['floatingip']['id']
578 except Exception as e:
579 logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
581 return {'fip_addr': fip_addr, 'fip_id': fip_id}
584 def add_floating_ip(nova_client, server_id, floatingip_addr):
586 nova_client.servers.add_floating_ip(server_id, floatingip_addr)
588 except Exception as e:
589 logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
590 % (server_id, floatingip_addr, e))
594 def delete_instance(nova_client, instance_id):
596 nova_client.servers.force_delete(instance_id)
598 except Exception as e:
599 logger.error("Error [delete_instance(nova_client, '%s')]: %s"
604 def delete_floating_ip(neutron_client, floatingip_id):
606 neutron_client.delete_floatingip(floatingip_id)
608 except Exception as e:
609 logger.error("Error [delete_floating_ip(neutron_client, '%s')]: %s"
610 % (floatingip_id, e))
614 def remove_host_from_aggregate(nova_client, aggregate_name, compute_host):
616 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
617 nova_client.aggregates.remove_host(aggregate_id, compute_host)
619 except Exception as e:
620 logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
621 " %s" % (aggregate_name, compute_host, e))
625 def remove_hosts_from_aggregate(nova_client, aggregate_name):
626 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
627 hosts = nova_client.aggregates.get(aggregate_id).hosts
629 all(remove_host_from_aggregate(nova_client, aggregate_name, host)
633 def delete_aggregate(nova_client, aggregate_name):
635 remove_hosts_from_aggregate(nova_client, aggregate_name)
636 nova_client.aggregates.delete(aggregate_name)
638 except Exception as e:
639 logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
640 % (aggregate_name, e))
644 # *********************************************
646 # *********************************************
647 def get_network_list(neutron_client):
648 network_list = neutron_client.list_networks()['networks']
649 if len(network_list) == 0:
655 def get_router_list(neutron_client):
656 router_list = neutron_client.list_routers()['routers']
657 if len(router_list) == 0:
663 def get_port_list(neutron_client):
664 port_list = neutron_client.list_ports()['ports']
665 if len(port_list) == 0:
671 def get_network_id(neutron_client, network_name):
672 networks = neutron_client.list_networks()['networks']
675 if n['name'] == network_name:
681 def get_subnet_id(neutron_client, subnet_name):
682 subnets = neutron_client.list_subnets()['subnets']
685 if s['name'] == subnet_name:
691 def get_router_id(neutron_client, router_name):
692 routers = neutron_client.list_routers()['routers']
695 if r['name'] == router_name:
701 def get_private_net(neutron_client):
702 # Checks if there is an existing shared private network
703 networks = neutron_client.list_networks()['networks']
704 if len(networks) == 0:
707 if (net['router:external'] is False) and (net['shared'] is True):
712 def get_external_net(neutron_client):
713 for network in neutron_client.list_networks()['networks']:
714 if network['router:external']:
715 return network['name']
719 def get_external_net_id(neutron_client):
720 for network in neutron_client.list_networks()['networks']:
721 if network['router:external']:
726 def check_neutron_net(neutron_client, net_name):
727 for network in neutron_client.list_networks()['networks']:
728 if network['name'] == net_name:
729 for subnet in network['subnets']:
734 def create_neutron_net(neutron_client, name):
735 json_body = {'network': {'name': name,
736 'admin_state_up': True}}
738 network = neutron_client.create_network(body=json_body)
739 network_dict = network['network']
740 return network_dict['id']
741 except Exception as e:
742 logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
747 def create_neutron_subnet(neutron_client, name, cidr, net_id,
748 dns=['8.8.8.8', '8.8.4.4']):
749 json_body = {'subnets': [{'name': name, 'cidr': cidr,
750 'ip_version': 4, 'network_id': net_id,
751 'dns_nameservers': dns}]}
754 subnet = neutron_client.create_subnet(body=json_body)
755 return subnet['subnets'][0]['id']
756 except Exception as e:
757 logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
758 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
762 def create_neutron_router(neutron_client, name):
763 json_body = {'router': {'name': name, 'admin_state_up': True}}
765 router = neutron_client.create_router(json_body)
766 return router['router']['id']
767 except Exception as e:
768 logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
773 def create_neutron_port(neutron_client, name, network_id, ip):
774 json_body = {'port': {
775 'admin_state_up': True,
777 'network_id': network_id,
778 'fixed_ips': [{"ip_address": ip}]
781 port = neutron_client.create_port(body=json_body)
782 return port['port']['id']
783 except Exception as e:
784 logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
785 "'%s')]: %s" % (name, network_id, ip, e))
789 def update_neutron_net(neutron_client, network_id, shared=False):
790 json_body = {'network': {'shared': shared}}
792 neutron_client.update_network(network_id, body=json_body)
794 except Exception as e:
795 logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
796 "%s" % (network_id, str(shared), e))
800 def update_neutron_port(neutron_client, port_id, device_owner):
801 json_body = {'port': {
802 'device_owner': device_owner,
805 port = neutron_client.update_port(port=port_id,
807 return port['port']['id']
808 except Exception as e:
809 logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
810 " %s" % (port_id, device_owner, e))
814 def add_interface_router(neutron_client, router_id, subnet_id):
815 json_body = {"subnet_id": subnet_id}
817 neutron_client.add_interface_router(router=router_id, body=json_body)
819 except Exception as e:
820 logger.error("Error [add_interface_router(neutron_client, '%s', "
821 "'%s')]: %s" % (router_id, subnet_id, e))
825 def add_gateway_router(neutron_client, router_id):
826 ext_net_id = get_external_net_id(neutron_client)
827 router_dict = {'network_id': ext_net_id}
829 neutron_client.add_gateway_router(router_id, router_dict)
831 except Exception as e:
832 logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
837 def delete_neutron_net(neutron_client, network_id):
839 neutron_client.delete_network(network_id)
841 except Exception as e:
842 logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
847 def delete_neutron_subnet(neutron_client, subnet_id):
849 neutron_client.delete_subnet(subnet_id)
851 except Exception as e:
852 logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
857 def delete_neutron_router(neutron_client, router_id):
859 neutron_client.delete_router(router=router_id)
861 except Exception as e:
862 logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
867 def delete_neutron_port(neutron_client, port_id):
869 neutron_client.delete_port(port_id)
871 except Exception as e:
872 logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
877 def remove_interface_router(neutron_client, router_id, subnet_id):
878 json_body = {"subnet_id": subnet_id}
880 neutron_client.remove_interface_router(router=router_id,
883 except Exception as e:
884 logger.error("Error [remove_interface_router(neutron_client, '%s', "
885 "'%s')]: %s" % (router_id, subnet_id, e))
889 def remove_gateway_router(neutron_client, router_id):
891 neutron_client.remove_gateway_router(router_id)
893 except Exception as e:
894 logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
899 def create_network_full(neutron_client,
904 dns=['8.8.8.8', '8.8.4.4']):
906 # Check if the network already exists
907 network_id = get_network_id(neutron_client, net_name)
908 subnet_id = get_subnet_id(neutron_client, subnet_name)
909 router_id = get_router_id(neutron_client, router_name)
911 if network_id != '' and subnet_id != '' and router_id != '':
912 logger.info("A network with name '%s' already exists..." % net_name)
914 neutron_client.format = 'json'
915 logger.info('Creating neutron network %s...' % net_name)
916 network_id = create_neutron_net(neutron_client, net_name)
921 logger.debug("Network '%s' created successfully" % network_id)
922 logger.debug('Creating Subnet....')
923 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
924 cidr, network_id, dns)
928 logger.debug("Subnet '%s' created successfully" % subnet_id)
929 logger.debug('Creating Router...')
930 router_id = create_neutron_router(neutron_client, router_name)
935 logger.debug("Router '%s' created successfully" % router_id)
936 logger.debug('Adding router to subnet...')
938 if not add_interface_router(neutron_client, router_id, subnet_id):
941 logger.debug("Interface added successfully.")
943 logger.debug('Adding gateway to router...')
944 if not add_gateway_router(neutron_client, router_id):
947 logger.debug("Gateway added successfully.")
949 network_dic = {'net_id': network_id,
950 'subnet_id': subnet_id,
951 'router_id': router_id}
955 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
956 neutron_client = get_neutron_client()
958 network_dic = create_network_full(neutron_client,
964 if not update_neutron_net(neutron_client,
965 network_dic['net_id'],
967 logger.error("Failed to update network %s..." % net_name)
970 logger.debug("Network '%s' is available..." % net_name)
972 logger.error("Network %s creation failed" % net_name)
977 # *********************************************
979 # *********************************************
982 def get_security_groups(neutron_client):
984 security_groups = neutron_client.list_security_groups()[
986 return security_groups
987 except Exception as e:
988 logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
992 def get_security_group_id(neutron_client, sg_name):
993 security_groups = get_security_groups(neutron_client)
995 for sg in security_groups:
996 if sg['name'] == sg_name:
1002 def create_security_group(neutron_client, sg_name, sg_description):
1003 json_body = {'security_group': {'name': sg_name,
1004 'description': sg_description}}
1006 secgroup = neutron_client.create_security_group(json_body)
1007 return secgroup['security_group']
1008 except Exception as e:
1009 logger.error("Error [create_security_group(neutron_client, '%s', "
1010 "'%s')]: %s" % (sg_name, sg_description, e))
1014 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
1015 port_range_min=None, port_range_max=None):
1016 # We create a security group in 2 steps
1017 # 1 - we check the format and set the json body accordingly
1018 # 2 - we call neturon client to create the security group
1021 json_body = {'security_group_rule': {'direction': direction,
1022 'security_group_id': sg_id,
1023 'protocol': protocol}}
1025 # - both None => we do nothing
1026 # - both Not None => we add them to the json description
1027 # but one cannot be None is the other is not None
1028 if (port_range_min is not None and port_range_max is not None):
1029 # add port_range in json description
1030 json_body['security_group_rule']['port_range_min'] = port_range_min
1031 json_body['security_group_rule']['port_range_max'] = port_range_max
1032 logger.debug("Security_group format set (port range included)")
1034 # either both port range are set to None => do nothing
1035 # or one is set but not the other => log it and return False
1036 if port_range_min is None and port_range_max is None:
1037 logger.debug("Security_group format set (no port range mentioned)")
1039 logger.error("Bad security group format."
1040 "One of the port range is not properly set:"
1042 "range max: {}".format(port_range_min,
1046 # Create security group using neutron client
1048 neutron_client.create_security_group_rule(json_body)
1051 logger.exception("Impossible to create_security_group_rule,"
1052 "security group rule probably already exists")
1056 def get_security_group_rules(neutron_client, sg_id):
1058 security_rules = neutron_client.list_security_group_rules()[
1059 'security_group_rules']
1060 security_rules = [rule for rule in security_rules
1061 if rule["security_group_id"] == sg_id]
1062 return security_rules
1063 except Exception as e:
1064 logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:"
1069 def check_security_group_rules(neutron_client, sg_id, direction, protocol,
1070 port_min=None, port_max=None):
1072 security_rules = get_security_group_rules(neutron_client, sg_id)
1073 security_rules = [rule for rule in security_rules
1074 if (rule["direction"].lower() == direction and
1075 rule["protocol"].lower() == protocol and
1076 rule["port_range_min"] == port_min and
1077 rule["port_range_max"] == port_max)]
1078 if len(security_rules) == 0:
1082 except Exception as e:
1083 logger.error("Error [check_security_group_rules("
1084 " neutron_client, sg_id, direction,"
1085 " protocol, port_min=None, port_max=None)]: "
1090 def create_security_group_full(neutron_client,
1091 sg_name, sg_description):
1092 sg_id = get_security_group_id(neutron_client, sg_name)
1094 logger.info("Using existing security group '%s'..." % sg_name)
1096 logger.info("Creating security group '%s'..." % sg_name)
1097 SECGROUP = create_security_group(neutron_client,
1101 logger.error("Failed to create the security group...")
1104 sg_id = SECGROUP['id']
1106 logger.debug("Security group '%s' with ID=%s created successfully."
1107 % (SECGROUP['name'], sg_id))
1109 logger.debug("Adding ICMP rules in security group '%s'..."
1111 if not create_secgroup_rule(neutron_client, sg_id,
1113 logger.error("Failed to create the security group rule...")
1116 logger.debug("Adding SSH rules in security group '%s'..."
1118 if not create_secgroup_rule(
1119 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1120 logger.error("Failed to create the security group rule...")
1123 if not create_secgroup_rule(
1124 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1125 logger.error("Failed to create the security group rule...")
1130 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
1132 nova_client.servers.add_security_group(instance_id, secgroup_id)
1134 except Exception as e:
1135 logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
1136 "'%s')]: %s" % (instance_id, secgroup_id, e))
1140 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1141 json_body = {"quota": {
1142 "security_group": sg_quota,
1143 "security_group_rule": sg_rule_quota
1147 neutron_client.update_quota(tenant_id=tenant_id,
1150 except Exception as e:
1151 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1152 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1156 def delete_security_group(neutron_client, secgroup_id):
1158 neutron_client.delete_security_group(secgroup_id)
1160 except Exception as e:
1161 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1166 # *********************************************
1168 # *********************************************
1169 def get_images(glance_client):
1171 images = glance_client.images.list()
1173 except Exception as e:
1174 logger.error("Error [get_images]: %s" % e)
1178 def get_image_id(glance_client, image_name):
1179 images = glance_client.images.list()
1182 if i.name == image_name:
1188 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
1189 container="bare", public="public"):
1190 if not os.path.isfile(file_path):
1191 logger.error("Error: file %s does not exist." % file_path)
1194 image_id = get_image_id(glance_client, image_name)
1196 logger.info("Image %s already exists." % image_name)
1198 logger.info("Creating image '%s' from '%s'..." % (image_name,
1201 image = glance_client.images.create(name=image_name,
1204 container_format=container)
1206 with open(file_path) as image_data:
1207 glance_client.images.upload(image_id, image_data)
1209 except Exception as e:
1210 logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1211 "'%s')]: %s" % (image_name, file_path, public, e))
1215 def get_or_create_image(name, path, format):
1216 image_exists = False
1217 glance_client = get_glance_client()
1219 image_id = get_image_id(glance_client, name)
1221 logger.info("Using existing image '%s'..." % name)
1224 logger.info("Creating image '%s' from '%s'..." % (name, path))
1225 image_id = create_glance_image(glance_client, name, path, format)
1227 logger.error("Failed to create a Glance image...")
1229 logger.debug("Image '%s' with ID=%s created successfully."
1232 return image_exists, image_id
1235 def delete_glance_image(glance_client, image_id):
1237 glance_client.images.delete(image_id)
1239 except Exception as e:
1240 logger.error("Error [delete_glance_image(glance_client, '%s')]: %s"
1245 # *********************************************
1247 # *********************************************
1248 def get_volumes(cinder_client):
1250 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1252 except Exception as e:
1253 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1257 def list_volume_types(cinder_client, public=True, private=True):
1259 volume_types = cinder_client.volume_types.list()
1261 volume_types = [vt for vt in volume_types if not vt.is_public]
1263 volume_types = [vt for vt in volume_types if vt.is_public]
1265 except Exception as e:
1266 logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
1270 def create_volume_type(cinder_client, name):
1272 volume_type = cinder_client.volume_types.create(name)
1274 except Exception as e:
1275 logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
1280 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1281 snapshots_quota, gigabytes_quota):
1282 quotas_values = {"volumes": vols_quota,
1283 "snapshots": snapshots_quota,
1284 "gigabytes": gigabytes_quota}
1287 cinder_client.quotas.update(tenant_id, **quotas_values)
1289 except Exception as e:
1290 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1291 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1292 snapshots_quota, gigabytes_quota, e))
1296 def delete_volume(cinder_client, volume_id, forced=False):
1300 cinder_client.volumes.detach(volume_id)
1302 logger.error(sys.exc_info()[0])
1303 cinder_client.volumes.force_delete(volume_id)
1305 cinder_client.volumes.delete(volume_id)
1307 except Exception as e:
1308 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1309 % (volume_id, str(forced), e))
1313 def delete_volume_type(cinder_client, volume_type):
1315 cinder_client.volume_types.delete(volume_type)
1317 except Exception as e:
1318 logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
1323 # *********************************************
1325 # *********************************************
1326 def get_tenants(keystone_client):
1328 if is_keystone_v3():
1329 tenants = keystone_client.projects.list()
1331 tenants = keystone_client.tenants.list()
1333 except Exception as e:
1334 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1338 def get_users(keystone_client):
1340 users = keystone_client.users.list()
1342 except Exception as e:
1343 logger.error("Error [get_users(keystone_client)]: %s" % e)
1347 def get_tenant_id(keystone_client, tenant_name):
1348 tenants = get_tenants(keystone_client)
1351 if t.name == tenant_name:
1357 def get_user_id(keystone_client, user_name):
1358 users = get_users(keystone_client)
1361 if u.name == user_name:
1367 def get_role_id(keystone_client, role_name):
1368 roles = keystone_client.roles.list()
1371 if r.name == role_name:
1377 def create_tenant(keystone_client, tenant_name, tenant_description):
1379 if is_keystone_v3():
1380 tenant = keystone_client.projects.create(
1382 description=tenant_description,
1386 tenant = keystone_client.tenants.create(tenant_name,
1390 except Exception as e:
1391 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1392 % (tenant_name, tenant_description, e))
1396 def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
1397 tenant_id = get_tenant_id(keystone_client, tenant_name)
1399 tenant_id = create_tenant(keystone_client, tenant_name,
1405 def get_or_create_tenant_for_vnf(keystone_client, tenant_name,
1406 tenant_description):
1407 """Get or Create a Tenant
1410 keystone_client: keystone client reference
1411 tenant_name: the name of the tenant
1412 tenant_description: the description of the tenant
1414 return False if tenant retrieved though get
1415 return True if tenant created
1416 raise Exception if error during processing
1419 tenant_id = get_tenant_id(keystone_client, tenant_name)
1421 tenant_id = create_tenant(keystone_client, tenant_name,
1427 raise Exception("Impossible to create a Tenant for the VNF {}".format(
1431 def create_user(keystone_client, user_name, user_password,
1432 user_email, tenant_id):
1434 if is_keystone_v3():
1435 user = keystone_client.users.create(name=user_name,
1436 password=user_password,
1438 project_id=tenant_id,
1441 user = keystone_client.users.create(user_name,
1447 except Exception as e:
1448 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1449 "'%s')]: %s" % (user_name, user_password,
1450 user_email, tenant_id, e))
1454 def get_or_create_user(keystone_client, user_name, user_password,
1455 tenant_id, user_email=None):
1456 user_id = get_user_id(keystone_client, user_name)
1458 user_id = create_user(keystone_client, user_name, user_password,
1459 user_email, tenant_id)
1463 def get_or_create_user_for_vnf(keystone_client, vnf_ref):
1464 """Get or Create user for VNF
1467 keystone_client: keystone client reference
1468 vnf_ref: VNF reference used as user name & password, tenant name
1470 return False if user retrieved through get
1471 return True if user created
1472 raise Exception if error during processing
1475 user_id = get_user_id(keystone_client, vnf_ref)
1476 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1479 user_id = create_user(keystone_client, vnf_ref, vnf_ref,
1483 role_id = get_role_id(keystone_client, 'admin')
1484 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1485 add_role_user(keystone_client, user_id, role_id, tenant_id)
1487 logger.warn("Cannot associate user to role admin on tenant")
1490 raise Exception("Impossible to create a user for the VNF {}".format(
1494 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1496 if is_keystone_v3():
1497 keystone_client.roles.grant(role=role_id,
1501 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1503 except Exception as e:
1504 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1505 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1509 def delete_tenant(keystone_client, tenant_id):
1511 if is_keystone_v3():
1512 keystone_client.projects.delete(tenant_id)
1514 keystone_client.tenants.delete(tenant_id)
1516 except Exception as e:
1517 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1522 def delete_user(keystone_client, user_id):
1524 keystone_client.users.delete(user_id)
1526 except Exception as e:
1527 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1532 # *********************************************
1534 # *********************************************
1535 def get_resource(heat_client, stack_id, resource):
1537 resources = heat_client.resources.get(stack_id, resource)
1539 except Exception as e:
1540 logger.error("Error [get_resource]: %s" % e)