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 if re.search(r'(.*)=(.*)', line) else None)
122 # The two next lines should be modified as soon as rc_file
123 # conforms with common rules. Be aware that it could induce
124 # issues if value starts with '
126 key = re.sub(r'^["\' ]*|[ \'"]*$', '', var[0])
127 value = re.sub(r'^["\' ]*|[ \'"]*$', '', "".join(var[1:]))
128 os.environ[key] = value
131 def get_credentials_for_rally():
132 creds = get_credentials()
133 env_cred_dict = get_env_cred_dict()
134 rally_conf = {"type": "ExistingCloud", "admin": {}}
136 if key == 'auth_url':
137 rally_conf[key] = creds[key]
139 rally_conf['admin'][key] = creds[key]
141 endpoint_types = [('internalURL', 'internal'),
142 ('publicURL', 'public'), ('adminURL', 'admin')]
144 endpoint_type = get_endpoint_type_from_env()
145 if endpoint_type is not None:
146 cred_key = env_cred_dict.get('OS_ENDPOINT_TYPE')
147 for k, v in endpoint_types:
148 if endpoint_type == v:
149 rally_conf[cred_key] = v
151 region_name = os.getenv('OS_REGION_NAME')
152 if region_name is not None:
153 cred_key = env_cred_dict.get('OS_REGION_NAME')
154 rally_conf[cred_key] = region_name
156 cred_key = env_cred_dict.get('OS_CACERT')
157 rally_conf[cred_key] = os.getenv('OS_CACERT', '')
159 insecure_key = env_cred_dict.get('OS_INSECURE')
160 rally_conf[insecure_key] = os.getenv('OS_INSECURE', '').lower() == 'true'
165 def get_endpoint_type_from_env():
166 endpoint_type = os.environ.get("OS_ENDPOINT_TYPE",
167 os.environ.get("OS_INTERFACE"))
168 if endpoint_type and "URL" in endpoint_type:
169 endpoint_type = endpoint_type.replace("URL", "")
173 def get_session_auth(other_creds={}):
174 loader = loading.get_plugin_loader('password')
175 creds = get_credentials(other_creds)
176 auth = loader.load_from_options(**creds)
180 def get_endpoint(service_type, interface='public'):
181 auth = get_session_auth()
182 return get_session().get_endpoint(auth=auth,
183 service_type=service_type,
187 def get_session(other_creds={}):
188 auth = get_session_auth(other_creds)
189 https_cacert = os.getenv('OS_CACERT', '')
190 https_insecure = os.getenv('OS_INSECURE', '').lower() == 'true'
191 return session.Session(auth=auth,
192 verify=(https_cacert or not https_insecure))
195 # *********************************************
197 # *********************************************
198 def get_keystone_client_version():
199 api_version = os.getenv('OS_IDENTITY_API_VERSION')
200 if api_version is not None:
201 logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
204 return DEFAULT_API_VERSION
207 def get_keystone_client(other_creds={}):
208 sess = get_session(other_creds)
209 return keystoneclient.Client(get_keystone_client_version(),
211 interface=os.getenv('OS_INTERFACE', 'admin'))
214 def get_nova_client_version():
215 api_version = os.getenv('OS_COMPUTE_API_VERSION')
216 if api_version is not None:
217 logger.info("OS_COMPUTE_API_VERSION is set in env as '%s'",
220 return DEFAULT_API_VERSION
223 def get_nova_client(other_creds={}):
224 sess = get_session(other_creds)
225 return novaclient.Client(get_nova_client_version(), session=sess)
228 def get_cinder_client_version():
229 api_version = os.getenv('OS_VOLUME_API_VERSION')
230 if api_version is not None:
231 logger.info("OS_VOLUME_API_VERSION is set in env as '%s'",
234 return DEFAULT_API_VERSION
237 def get_cinder_client(other_creds={}):
238 sess = get_session(other_creds)
239 return cinderclient.Client(get_cinder_client_version(), session=sess)
242 def get_neutron_client_version():
243 api_version = os.getenv('OS_NETWORK_API_VERSION')
244 if api_version is not None:
245 logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
248 return DEFAULT_API_VERSION
251 def get_neutron_client(other_creds={}):
252 sess = get_session(other_creds)
253 return neutronclient.Client(get_neutron_client_version(), session=sess)
256 def get_glance_client_version():
257 api_version = os.getenv('OS_IMAGE_API_VERSION')
258 if api_version is not None:
259 logger.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version)
261 return DEFAULT_API_VERSION
264 def get_glance_client(other_creds={}):
265 sess = get_session(other_creds)
266 return glanceclient.Client(get_glance_client_version(), session=sess)
269 def get_heat_client_version():
270 api_version = os.getenv('OS_ORCHESTRATION_API_VERSION')
271 if api_version is not None:
272 logger.info("OS_ORCHESTRATION_API_VERSION is set in env as '%s'",
275 return DEFAULT_HEAT_API_VERSION
278 def get_heat_client(other_creds={}):
279 sess = get_session(other_creds)
280 return heatclient.Client(get_heat_client_version(), session=sess)
283 def download_and_add_image_on_glance(glance, image_name, image_url, data_dir):
286 if not os.path.exists(dest_path):
287 os.makedirs(dest_path)
288 file_name = image_url.rsplit('/')[-1]
289 if not ft_utils.download_url(image_url, dest_path):
292 raise Exception("Impossible to download image from {}".format(
296 image = create_glance_image(
297 glance, image_name, dest_path + file_name)
303 raise Exception("Impossible to put image {} in glance".format(
307 # *********************************************
309 # *********************************************
310 def get_instances(nova_client):
312 instances = nova_client.servers.list(search_opts={'all_tenants': 1})
314 except Exception as e:
315 logger.error("Error [get_instances(nova_client)]: %s" % e)
319 def get_instance_status(nova_client, instance):
321 instance = nova_client.servers.get(instance.id)
322 return instance.status
323 except Exception as e:
324 logger.error("Error [get_instance_status(nova_client)]: %s" % e)
328 def get_instance_by_name(nova_client, instance_name):
330 instance = nova_client.servers.find(name=instance_name)
332 except Exception as e:
333 logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
334 % (instance_name, e))
338 def get_flavor_id(nova_client, flavor_name):
339 flavors = nova_client.flavors.list(detailed=True)
342 if f.name == flavor_name:
348 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
349 flavors = nova_client.flavors.list(detailed=True)
352 if min_ram <= f.ram and f.ram <= max_ram:
358 def get_aggregates(nova_client):
360 aggregates = nova_client.aggregates.list()
362 except Exception as e:
363 logger.error("Error [get_aggregates(nova_client)]: %s" % e)
367 def get_aggregate_id(nova_client, aggregate_name):
369 aggregates = get_aggregates(nova_client)
370 _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
372 except Exception as e:
373 logger.error("Error [get_aggregate_id(nova_client, %s)]:"
374 " %s" % (aggregate_name, e))
378 def get_availability_zones(nova_client):
380 availability_zones = nova_client.availability_zones.list()
381 return availability_zones
382 except Exception as e:
383 logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
387 def get_availability_zone_names(nova_client):
389 az_names = [az.zoneName for az in get_availability_zones(nova_client)]
391 except Exception as e:
392 logger.error("Error [get_availability_zone_names(nova_client)]:"
397 def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
399 flavor = nova_client.flavors.create(
400 flavor_name, ram, vcpus, disk, is_public=public)
402 extra_specs = ft_utils.get_functest_config(
403 'general.flavor_extra_specs')
404 flavor.set_keys(extra_specs)
406 # flavor extra specs are not configured, therefore skip the update
409 except Exception as e:
410 logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
411 "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
416 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
417 flavor_exists = False
418 nova_client = get_nova_client()
420 flavor_id = get_flavor_id(nova_client, flavor_name)
422 logger.info("Using existing flavor '%s'..." % flavor_name)
425 logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
426 "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
427 flavor_id = create_flavor(
428 nova_client, flavor_name, ram, disk, vcpus, public=public)
430 raise Exception("Failed to create flavor '%s'..." % (flavor_name))
432 logger.debug("Flavor '%s' with ID=%s created successfully."
433 % (flavor_name, flavor_id))
435 return flavor_exists, flavor_id
438 def get_floating_ips(neutron_client):
440 floating_ips = neutron_client.list_floatingips()
441 return floating_ips['floatingips']
442 except Exception as e:
443 logger.error("Error [get_floating_ips(neutron_client)]: %s" % e)
447 def get_hypervisors(nova_client):
450 hypervisors = nova_client.hypervisors.list()
451 for hypervisor in hypervisors:
452 if hypervisor.state == "up":
453 nodes.append(hypervisor.hypervisor_hostname)
455 except Exception as e:
456 logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
460 def create_aggregate(nova_client, aggregate_name, av_zone):
462 nova_client.aggregates.create(aggregate_name, av_zone)
464 except Exception as e:
465 logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
466 % (aggregate_name, av_zone, e))
470 def add_host_to_aggregate(nova_client, aggregate_name, compute_host):
472 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
473 nova_client.aggregates.add_host(aggregate_id, compute_host)
475 except Exception as e:
476 logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
477 % (aggregate_name, compute_host, e))
481 def create_aggregate_with_host(
482 nova_client, aggregate_name, av_zone, compute_host):
484 create_aggregate(nova_client, aggregate_name, av_zone)
485 add_host_to_aggregate(nova_client, aggregate_name, compute_host)
487 except Exception as e:
488 logger.error("Error [create_aggregate_with_host("
489 "nova_client, %s, %s, %s)]: %s"
490 % (aggregate_name, av_zone, compute_host, e))
494 def create_instance(flavor_name,
497 instance_name="functest-vm",
503 nova_client = get_nova_client()
505 flavor = nova_client.flavors.find(name=flavor_name)
507 flavors = nova_client.flavors.list()
508 logger.error("Error: Flavor '%s' not found. Available flavors are: "
509 "\n%s" % (flavor_name, flavors))
511 if fixed_ip is not None:
512 nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
514 nics = {"net-id": network_id}
516 instance = nova_client.servers.create(
521 availability_zone=av_zone,
525 instance = nova_client.servers.create(
530 config_drive=confdrive,
532 availability_zone=av_zone,
538 def create_instance_and_wait_for_active(flavor_name,
548 VM_BOOT_TIMEOUT = 180
549 nova_client = get_nova_client()
550 instance = create_instance(flavor_name,
559 count = VM_BOOT_TIMEOUT / SLEEP
560 for n in range(count, -1, -1):
561 status = get_instance_status(nova_client, instance)
562 if status.lower() == "active":
564 elif status.lower() == "error":
565 logger.error("The instance %s went to ERROR status."
569 logger.error("Timeout booting the instance %s." % instance_name)
573 def create_floating_ip(neutron_client):
574 extnet_id = get_external_net_id(neutron_client)
575 props = {'floating_network_id': extnet_id}
577 ip_json = neutron_client.create_floatingip({'floatingip': props})
578 fip_addr = ip_json['floatingip']['floating_ip_address']
579 fip_id = ip_json['floatingip']['id']
580 except Exception as e:
581 logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
583 return {'fip_addr': fip_addr, 'fip_id': fip_id}
586 def add_floating_ip(nova_client, server_id, floatingip_addr):
588 nova_client.servers.add_floating_ip(server_id, floatingip_addr)
590 except Exception as e:
591 logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
592 % (server_id, floatingip_addr, e))
596 def delete_instance(nova_client, instance_id):
598 nova_client.servers.force_delete(instance_id)
600 except Exception as e:
601 logger.error("Error [delete_instance(nova_client, '%s')]: %s"
606 def delete_floating_ip(neutron_client, floatingip_id):
608 neutron_client.delete_floatingip(floatingip_id)
610 except Exception as e:
611 logger.error("Error [delete_floating_ip(neutron_client, '%s')]: %s"
612 % (floatingip_id, e))
616 def remove_host_from_aggregate(nova_client, aggregate_name, compute_host):
618 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
619 nova_client.aggregates.remove_host(aggregate_id, compute_host)
621 except Exception as e:
622 logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
623 " %s" % (aggregate_name, compute_host, e))
627 def remove_hosts_from_aggregate(nova_client, aggregate_name):
628 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
629 hosts = nova_client.aggregates.get(aggregate_id).hosts
631 all(remove_host_from_aggregate(nova_client, aggregate_name, host)
635 def delete_aggregate(nova_client, aggregate_name):
637 remove_hosts_from_aggregate(nova_client, aggregate_name)
638 nova_client.aggregates.delete(aggregate_name)
640 except Exception as e:
641 logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
642 % (aggregate_name, e))
646 # *********************************************
648 # *********************************************
649 def get_network_list(neutron_client):
650 network_list = neutron_client.list_networks()['networks']
651 if len(network_list) == 0:
657 def get_router_list(neutron_client):
658 router_list = neutron_client.list_routers()['routers']
659 if len(router_list) == 0:
665 def get_port_list(neutron_client):
666 port_list = neutron_client.list_ports()['ports']
667 if len(port_list) == 0:
673 def get_network_id(neutron_client, network_name):
674 networks = neutron_client.list_networks()['networks']
677 if n['name'] == network_name:
683 def get_subnet_id(neutron_client, subnet_name):
684 subnets = neutron_client.list_subnets()['subnets']
687 if s['name'] == subnet_name:
693 def get_router_id(neutron_client, router_name):
694 routers = neutron_client.list_routers()['routers']
697 if r['name'] == router_name:
703 def get_private_net(neutron_client):
704 # Checks if there is an existing shared private network
705 networks = neutron_client.list_networks()['networks']
706 if len(networks) == 0:
709 if (net['router:external'] is False) and (net['shared'] is True):
714 def get_external_net(neutron_client):
715 for network in neutron_client.list_networks()['networks']:
716 if network['router:external']:
717 return network['name']
721 def get_external_net_id(neutron_client):
722 for network in neutron_client.list_networks()['networks']:
723 if network['router:external']:
728 def check_neutron_net(neutron_client, net_name):
729 for network in neutron_client.list_networks()['networks']:
730 if network['name'] == net_name:
731 for subnet in network['subnets']:
736 def create_neutron_net(neutron_client, name):
737 json_body = {'network': {'name': name,
738 'admin_state_up': True}}
740 network = neutron_client.create_network(body=json_body)
741 network_dict = network['network']
742 return network_dict['id']
743 except Exception as e:
744 logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
749 def create_neutron_subnet(neutron_client, name, cidr, net_id,
750 dns=['8.8.8.8', '8.8.4.4']):
751 json_body = {'subnets': [{'name': name, 'cidr': cidr,
752 'ip_version': 4, 'network_id': net_id,
753 'dns_nameservers': dns}]}
756 subnet = neutron_client.create_subnet(body=json_body)
757 return subnet['subnets'][0]['id']
758 except Exception as e:
759 logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
760 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
764 def create_neutron_router(neutron_client, name):
765 json_body = {'router': {'name': name, 'admin_state_up': True}}
767 router = neutron_client.create_router(json_body)
768 return router['router']['id']
769 except Exception as e:
770 logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
775 def create_neutron_port(neutron_client, name, network_id, ip):
776 json_body = {'port': {
777 'admin_state_up': True,
779 'network_id': network_id,
780 'fixed_ips': [{"ip_address": ip}]
783 port = neutron_client.create_port(body=json_body)
784 return port['port']['id']
785 except Exception as e:
786 logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
787 "'%s')]: %s" % (name, network_id, ip, e))
791 def update_neutron_net(neutron_client, network_id, shared=False):
792 json_body = {'network': {'shared': shared}}
794 neutron_client.update_network(network_id, body=json_body)
796 except Exception as e:
797 logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
798 "%s" % (network_id, str(shared), e))
802 def update_neutron_port(neutron_client, port_id, device_owner):
803 json_body = {'port': {
804 'device_owner': device_owner,
807 port = neutron_client.update_port(port=port_id,
809 return port['port']['id']
810 except Exception as e:
811 logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
812 " %s" % (port_id, device_owner, e))
816 def add_interface_router(neutron_client, router_id, subnet_id):
817 json_body = {"subnet_id": subnet_id}
819 neutron_client.add_interface_router(router=router_id, body=json_body)
821 except Exception as e:
822 logger.error("Error [add_interface_router(neutron_client, '%s', "
823 "'%s')]: %s" % (router_id, subnet_id, e))
827 def add_gateway_router(neutron_client, router_id):
828 ext_net_id = get_external_net_id(neutron_client)
829 router_dict = {'network_id': ext_net_id}
831 neutron_client.add_gateway_router(router_id, router_dict)
833 except Exception as e:
834 logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
839 def delete_neutron_net(neutron_client, network_id):
841 neutron_client.delete_network(network_id)
843 except Exception as e:
844 logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
849 def delete_neutron_subnet(neutron_client, subnet_id):
851 neutron_client.delete_subnet(subnet_id)
853 except Exception as e:
854 logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
859 def delete_neutron_router(neutron_client, router_id):
861 neutron_client.delete_router(router=router_id)
863 except Exception as e:
864 logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
869 def delete_neutron_port(neutron_client, port_id):
871 neutron_client.delete_port(port_id)
873 except Exception as e:
874 logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
879 def remove_interface_router(neutron_client, router_id, subnet_id):
880 json_body = {"subnet_id": subnet_id}
882 neutron_client.remove_interface_router(router=router_id,
885 except Exception as e:
886 logger.error("Error [remove_interface_router(neutron_client, '%s', "
887 "'%s')]: %s" % (router_id, subnet_id, e))
891 def remove_gateway_router(neutron_client, router_id):
893 neutron_client.remove_gateway_router(router_id)
895 except Exception as e:
896 logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
901 def create_network_full(neutron_client,
906 dns=['8.8.8.8', '8.8.4.4']):
908 # Check if the network already exists
909 network_id = get_network_id(neutron_client, net_name)
910 subnet_id = get_subnet_id(neutron_client, subnet_name)
911 router_id = get_router_id(neutron_client, router_name)
913 if network_id != '' and subnet_id != '' and router_id != '':
914 logger.info("A network with name '%s' already exists..." % net_name)
916 neutron_client.format = 'json'
917 logger.info('Creating neutron network %s...' % net_name)
918 network_id = create_neutron_net(neutron_client, net_name)
923 logger.debug("Network '%s' created successfully" % network_id)
924 logger.debug('Creating Subnet....')
925 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
926 cidr, network_id, dns)
930 logger.debug("Subnet '%s' created successfully" % subnet_id)
931 logger.debug('Creating Router...')
932 router_id = create_neutron_router(neutron_client, router_name)
937 logger.debug("Router '%s' created successfully" % router_id)
938 logger.debug('Adding router to subnet...')
940 if not add_interface_router(neutron_client, router_id, subnet_id):
943 logger.debug("Interface added successfully.")
945 logger.debug('Adding gateway to router...')
946 if not add_gateway_router(neutron_client, router_id):
949 logger.debug("Gateway added successfully.")
951 network_dic = {'net_id': network_id,
952 'subnet_id': subnet_id,
953 'router_id': router_id}
957 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
958 neutron_client = get_neutron_client()
960 network_dic = create_network_full(neutron_client,
966 if not update_neutron_net(neutron_client,
967 network_dic['net_id'],
969 logger.error("Failed to update network %s..." % net_name)
972 logger.debug("Network '%s' is available..." % net_name)
974 logger.error("Network %s creation failed" % net_name)
979 # *********************************************
981 # *********************************************
984 def get_security_groups(neutron_client):
986 security_groups = neutron_client.list_security_groups()[
988 return security_groups
989 except Exception as e:
990 logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
994 def get_security_group_id(neutron_client, sg_name):
995 security_groups = get_security_groups(neutron_client)
997 for sg in security_groups:
998 if sg['name'] == sg_name:
1004 def create_security_group(neutron_client, sg_name, sg_description):
1005 json_body = {'security_group': {'name': sg_name,
1006 'description': sg_description}}
1008 secgroup = neutron_client.create_security_group(json_body)
1009 return secgroup['security_group']
1010 except Exception as e:
1011 logger.error("Error [create_security_group(neutron_client, '%s', "
1012 "'%s')]: %s" % (sg_name, sg_description, e))
1016 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
1017 port_range_min=None, port_range_max=None):
1018 # We create a security group in 2 steps
1019 # 1 - we check the format and set the json body accordingly
1020 # 2 - we call neturon client to create the security group
1023 json_body = {'security_group_rule': {'direction': direction,
1024 'security_group_id': sg_id,
1025 'protocol': protocol}}
1027 # - both None => we do nothing
1028 # - both Not None => we add them to the json description
1029 # but one cannot be None is the other is not None
1030 if (port_range_min is not None and port_range_max is not None):
1031 # add port_range in json description
1032 json_body['security_group_rule']['port_range_min'] = port_range_min
1033 json_body['security_group_rule']['port_range_max'] = port_range_max
1034 logger.debug("Security_group format set (port range included)")
1036 # either both port range are set to None => do nothing
1037 # or one is set but not the other => log it and return False
1038 if port_range_min is None and port_range_max is None:
1039 logger.debug("Security_group format set (no port range mentioned)")
1041 logger.error("Bad security group format."
1042 "One of the port range is not properly set:"
1044 "range max: {}".format(port_range_min,
1048 # Create security group using neutron client
1050 neutron_client.create_security_group_rule(json_body)
1053 logger.exception("Impossible to create_security_group_rule,"
1054 "security group rule probably already exists")
1058 def get_security_group_rules(neutron_client, sg_id):
1060 security_rules = neutron_client.list_security_group_rules()[
1061 'security_group_rules']
1062 security_rules = [rule for rule in security_rules
1063 if rule["security_group_id"] == sg_id]
1064 return security_rules
1065 except Exception as e:
1066 logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:"
1071 def check_security_group_rules(neutron_client, sg_id, direction, protocol,
1072 port_min=None, port_max=None):
1074 security_rules = get_security_group_rules(neutron_client, sg_id)
1075 security_rules = [rule for rule in security_rules
1076 if (rule["direction"].lower() == direction and
1077 rule["protocol"].lower() == protocol and
1078 rule["port_range_min"] == port_min and
1079 rule["port_range_max"] == port_max)]
1080 if len(security_rules) == 0:
1084 except Exception as e:
1085 logger.error("Error [check_security_group_rules("
1086 " neutron_client, sg_id, direction,"
1087 " protocol, port_min=None, port_max=None)]: "
1092 def create_security_group_full(neutron_client,
1093 sg_name, sg_description):
1094 sg_id = get_security_group_id(neutron_client, sg_name)
1096 logger.info("Using existing security group '%s'..." % sg_name)
1098 logger.info("Creating security group '%s'..." % sg_name)
1099 SECGROUP = create_security_group(neutron_client,
1103 logger.error("Failed to create the security group...")
1106 sg_id = SECGROUP['id']
1108 logger.debug("Security group '%s' with ID=%s created successfully."
1109 % (SECGROUP['name'], sg_id))
1111 logger.debug("Adding ICMP rules in security group '%s'..."
1113 if not create_secgroup_rule(neutron_client, sg_id,
1115 logger.error("Failed to create the security group rule...")
1118 logger.debug("Adding SSH rules in security group '%s'..."
1120 if not create_secgroup_rule(
1121 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1122 logger.error("Failed to create the security group rule...")
1125 if not create_secgroup_rule(
1126 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1127 logger.error("Failed to create the security group rule...")
1132 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
1134 nova_client.servers.add_security_group(instance_id, secgroup_id)
1136 except Exception as e:
1137 logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
1138 "'%s')]: %s" % (instance_id, secgroup_id, e))
1142 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1143 json_body = {"quota": {
1144 "security_group": sg_quota,
1145 "security_group_rule": sg_rule_quota
1149 neutron_client.update_quota(tenant_id=tenant_id,
1152 except Exception as e:
1153 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1154 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1158 def delete_security_group(neutron_client, secgroup_id):
1160 neutron_client.delete_security_group(secgroup_id)
1162 except Exception as e:
1163 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1168 # *********************************************
1170 # *********************************************
1171 def get_images(glance_client):
1173 images = glance_client.images.list()
1175 except Exception as e:
1176 logger.error("Error [get_images]: %s" % e)
1180 def get_image_id(glance_client, image_name):
1181 images = glance_client.images.list()
1184 if i.name == image_name:
1190 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
1191 container="bare", public="public"):
1192 if not os.path.isfile(file_path):
1193 logger.error("Error: file %s does not exist." % file_path)
1196 image_id = get_image_id(glance_client, image_name)
1198 logger.info("Image %s already exists." % image_name)
1200 logger.info("Creating image '%s' from '%s'..." % (image_name,
1203 image = glance_client.images.create(name=image_name,
1206 container_format=container)
1208 with open(file_path) as image_data:
1209 glance_client.images.upload(image_id, image_data)
1211 except Exception as e:
1212 logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1213 "'%s')]: %s" % (image_name, file_path, public, e))
1217 def get_or_create_image(name, path, format):
1218 image_exists = False
1219 glance_client = get_glance_client()
1221 image_id = get_image_id(glance_client, name)
1223 logger.info("Using existing image '%s'..." % name)
1226 logger.info("Creating image '%s' from '%s'..." % (name, path))
1227 image_id = create_glance_image(glance_client, name, path, format)
1229 logger.error("Failed to create a Glance image...")
1231 logger.debug("Image '%s' with ID=%s created successfully."
1234 return image_exists, image_id
1237 def delete_glance_image(glance_client, image_id):
1239 glance_client.images.delete(image_id)
1241 except Exception as e:
1242 logger.error("Error [delete_glance_image(glance_client, '%s')]: %s"
1247 # *********************************************
1249 # *********************************************
1250 def get_volumes(cinder_client):
1252 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1254 except Exception as e:
1255 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1259 def list_volume_types(cinder_client, public=True, private=True):
1261 volume_types = cinder_client.volume_types.list()
1263 volume_types = [vt for vt in volume_types if not vt.is_public]
1265 volume_types = [vt for vt in volume_types if vt.is_public]
1267 except Exception as e:
1268 logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
1272 def create_volume_type(cinder_client, name):
1274 volume_type = cinder_client.volume_types.create(name)
1276 except Exception as e:
1277 logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
1282 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1283 snapshots_quota, gigabytes_quota):
1284 quotas_values = {"volumes": vols_quota,
1285 "snapshots": snapshots_quota,
1286 "gigabytes": gigabytes_quota}
1289 cinder_client.quotas.update(tenant_id, **quotas_values)
1291 except Exception as e:
1292 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1293 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1294 snapshots_quota, gigabytes_quota, e))
1298 def delete_volume(cinder_client, volume_id, forced=False):
1302 cinder_client.volumes.detach(volume_id)
1304 logger.error(sys.exc_info()[0])
1305 cinder_client.volumes.force_delete(volume_id)
1307 cinder_client.volumes.delete(volume_id)
1309 except Exception as e:
1310 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1311 % (volume_id, str(forced), e))
1315 def delete_volume_type(cinder_client, volume_type):
1317 cinder_client.volume_types.delete(volume_type)
1319 except Exception as e:
1320 logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
1325 # *********************************************
1327 # *********************************************
1328 def get_tenants(keystone_client):
1330 if is_keystone_v3():
1331 tenants = keystone_client.projects.list()
1333 tenants = keystone_client.tenants.list()
1335 except Exception as e:
1336 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1340 def get_users(keystone_client):
1342 users = keystone_client.users.list()
1344 except Exception as e:
1345 logger.error("Error [get_users(keystone_client)]: %s" % e)
1349 def get_tenant_id(keystone_client, tenant_name):
1350 tenants = get_tenants(keystone_client)
1353 if t.name == tenant_name:
1359 def get_user_id(keystone_client, user_name):
1360 users = get_users(keystone_client)
1363 if u.name == user_name:
1369 def get_role_id(keystone_client, role_name):
1370 roles = keystone_client.roles.list()
1373 if r.name == role_name:
1379 def create_tenant(keystone_client, tenant_name, tenant_description):
1381 if is_keystone_v3():
1382 tenant = keystone_client.projects.create(
1384 description=tenant_description,
1388 tenant = keystone_client.tenants.create(tenant_name,
1392 except Exception as e:
1393 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1394 % (tenant_name, tenant_description, e))
1398 def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
1399 tenant_id = get_tenant_id(keystone_client, tenant_name)
1401 tenant_id = create_tenant(keystone_client, tenant_name,
1407 def get_or_create_tenant_for_vnf(keystone_client, tenant_name,
1408 tenant_description):
1409 """Get or Create a Tenant
1412 keystone_client: keystone client reference
1413 tenant_name: the name of the tenant
1414 tenant_description: the description of the tenant
1416 return False if tenant retrieved though get
1417 return True if tenant created
1418 raise Exception if error during processing
1421 tenant_id = get_tenant_id(keystone_client, tenant_name)
1423 tenant_id = create_tenant(keystone_client, tenant_name,
1429 raise Exception("Impossible to create a Tenant for the VNF {}".format(
1433 def create_user(keystone_client, user_name, user_password,
1434 user_email, tenant_id):
1436 if is_keystone_v3():
1437 user = keystone_client.users.create(name=user_name,
1438 password=user_password,
1440 project_id=tenant_id,
1443 user = keystone_client.users.create(user_name,
1449 except Exception as e:
1450 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1451 "'%s')]: %s" % (user_name, user_password,
1452 user_email, tenant_id, e))
1456 def get_or_create_user(keystone_client, user_name, user_password,
1457 tenant_id, user_email=None):
1458 user_id = get_user_id(keystone_client, user_name)
1460 user_id = create_user(keystone_client, user_name, user_password,
1461 user_email, tenant_id)
1465 def get_or_create_user_for_vnf(keystone_client, vnf_ref):
1466 """Get or Create user for VNF
1469 keystone_client: keystone client reference
1470 vnf_ref: VNF reference used as user name & password, tenant name
1472 return False if user retrieved through get
1473 return True if user created
1474 raise Exception if error during processing
1477 user_id = get_user_id(keystone_client, vnf_ref)
1478 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1481 user_id = create_user(keystone_client, vnf_ref, vnf_ref,
1485 role_id = get_role_id(keystone_client, 'admin')
1486 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1487 add_role_user(keystone_client, user_id, role_id, tenant_id)
1489 logger.warn("Cannot associate user to role admin on tenant")
1492 raise Exception("Impossible to create a user for the VNF {}".format(
1496 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1498 if is_keystone_v3():
1499 keystone_client.roles.grant(role=role_id,
1503 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1505 except Exception as e:
1506 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1507 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1511 def delete_tenant(keystone_client, tenant_id):
1513 if is_keystone_v3():
1514 keystone_client.projects.delete(tenant_id)
1516 keystone_client.tenants.delete(tenant_id)
1518 except Exception as e:
1519 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1524 def delete_user(keystone_client, user_id):
1526 keystone_client.users.delete(user_id)
1528 except Exception as e:
1529 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1534 # *********************************************
1536 # *********************************************
1537 def get_resource(heat_client, stack_id, resource):
1539 resources = heat_client.resources.get(stack_id, resource)
1541 except Exception as e:
1542 logger.error("Error [get_resource]: %s" % e)