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 from functest.utils.constants import CONST
27 import functest.utils.functest_utils as ft_utils
29 logger = logging.getLogger(__name__)
31 DEFAULT_API_VERSION = '2'
32 DEFAULT_HEAT_API_VERSION = '1'
35 # *********************************************
37 # *********************************************
38 class MissingEnvVar(Exception):
40 def __init__(self, var):
44 return str.format("Please set the mandatory env var: {}", self.var)
48 keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
49 if (keystone_api_version is None or
50 keystone_api_version == '2'):
56 def get_rc_env_vars():
57 env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD']
59 env_vars.extend(['OS_PROJECT_NAME',
60 'OS_USER_DOMAIN_NAME',
61 'OS_PROJECT_DOMAIN_NAME'])
63 env_vars.extend(['OS_TENANT_NAME'])
67 def check_credentials():
69 Check if the OpenStack credentials (openrc) are sourced
71 env_vars = get_rc_env_vars()
72 return all(map(lambda v: v in os.environ and os.environ[v], env_vars))
75 def get_env_cred_dict():
77 'OS_USERNAME': 'username',
78 'OS_PASSWORD': 'password',
79 'OS_AUTH_URL': 'auth_url',
80 'OS_TENANT_NAME': 'tenant_name',
81 'OS_USER_DOMAIN_NAME': 'user_domain_name',
82 'OS_PROJECT_DOMAIN_NAME': 'project_domain_name',
83 'OS_PROJECT_NAME': 'project_name',
84 'OS_ENDPOINT_TYPE': 'endpoint_type',
85 'OS_REGION_NAME': 'region_name',
86 'OS_CACERT': 'https_cacert',
87 'OS_INSECURE': 'https_insecure'
92 def get_credentials(other_creds={}):
93 """Returns a creds dictionary filled with parsed from env
96 env_vars = get_rc_env_vars()
97 env_cred_dict = get_env_cred_dict()
99 for envvar in env_vars:
100 if os.getenv(envvar) is None:
101 raise MissingEnvVar(envvar)
103 creds_key = env_cred_dict.get(envvar)
104 creds.update({creds_key: os.getenv(envvar)})
106 if 'tenant' in other_creds.keys():
108 tenant = 'project_name'
110 tenant = 'tenant_name'
111 other_creds[tenant] = other_creds.pop('tenant')
113 creds.update(other_creds)
118 def source_credentials(rc_file):
119 with open(rc_file, "r") as f:
121 var = (line.rstrip('"\n').replace('export ', '').split("=")
122 if re.search(r'(.*)=(.*)', line) else None)
123 # The two next lines should be modified as soon as rc_file
124 # conforms with common rules. Be aware that it could induce
125 # issues if value starts with '
127 key = re.sub(r'^["\' ]*|[ \'"]*$', '', var[0])
128 value = re.sub(r'^["\' ]*|[ \'"]*$', '', "".join(var[1:]))
129 os.environ[key] = value
132 def get_credentials_for_rally():
133 creds = get_credentials()
134 env_cred_dict = get_env_cred_dict()
135 rally_conf = {"type": "ExistingCloud", "admin": {}}
137 if key == 'auth_url':
138 rally_conf[key] = creds[key]
140 rally_conf['admin'][key] = creds[key]
142 endpoint_types = [('internalURL', 'internal'),
143 ('publicURL', 'public'), ('adminURL', 'admin')]
145 endpoint_type = get_endpoint_type_from_env()
146 if endpoint_type is not None:
147 cred_key = env_cred_dict.get('OS_ENDPOINT_TYPE')
148 for k, v in endpoint_types:
149 if endpoint_type == v:
150 rally_conf[cred_key] = v
152 region_name = os.getenv('OS_REGION_NAME')
153 if region_name is not None:
154 cred_key = env_cred_dict.get('OS_REGION_NAME')
155 rally_conf[cred_key] = region_name
157 cred_key = env_cred_dict.get('OS_CACERT')
158 rally_conf[cred_key] = os.getenv('OS_CACERT', '')
160 insecure_key = env_cred_dict.get('OS_INSECURE')
161 rally_conf[insecure_key] = os.getenv('OS_INSECURE', '').lower() == 'true'
166 def get_endpoint_type_from_env():
167 endpoint_type = os.environ.get("OS_ENDPOINT_TYPE",
168 os.environ.get("OS_INTERFACE"))
169 if endpoint_type and "URL" in endpoint_type:
170 endpoint_type = endpoint_type.replace("URL", "")
174 def get_session_auth(other_creds={}):
175 loader = loading.get_plugin_loader('password')
176 creds = get_credentials(other_creds)
177 auth = loader.load_from_options(**creds)
181 def get_endpoint(service_type, interface='public'):
182 auth = get_session_auth()
183 return get_session().get_endpoint(auth=auth,
184 service_type=service_type,
188 def get_session(other_creds={}):
189 auth = get_session_auth(other_creds)
190 https_cacert = os.getenv('OS_CACERT', '')
191 https_insecure = os.getenv('OS_INSECURE', '').lower() == 'true'
192 return session.Session(auth=auth,
193 verify=(https_cacert or not https_insecure))
196 # *********************************************
198 # *********************************************
199 def get_keystone_client_version():
200 api_version = os.getenv('OS_IDENTITY_API_VERSION')
201 if api_version is not None:
202 logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
205 return DEFAULT_API_VERSION
208 def get_keystone_client(other_creds={}):
209 sess = get_session(other_creds)
210 return keystoneclient.Client(get_keystone_client_version(),
212 interface=os.getenv('OS_INTERFACE', 'admin'))
215 def get_nova_client_version():
216 api_version = os.getenv('OS_COMPUTE_API_VERSION')
217 if api_version is not None:
218 logger.info("OS_COMPUTE_API_VERSION is set in env as '%s'",
221 return DEFAULT_API_VERSION
224 def get_nova_client(other_creds={}):
225 sess = get_session(other_creds)
226 return novaclient.Client(get_nova_client_version(), session=sess)
229 def get_cinder_client_version():
230 api_version = os.getenv('OS_VOLUME_API_VERSION')
231 if api_version is not None:
232 logger.info("OS_VOLUME_API_VERSION is set in env as '%s'",
235 return DEFAULT_API_VERSION
238 def get_cinder_client(other_creds={}):
239 sess = get_session(other_creds)
240 return cinderclient.Client(get_cinder_client_version(), session=sess)
243 def get_neutron_client_version():
244 api_version = os.getenv('OS_NETWORK_API_VERSION')
245 if api_version is not None:
246 logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
249 return DEFAULT_API_VERSION
252 def get_neutron_client(other_creds={}):
253 sess = get_session(other_creds)
254 return neutronclient.Client(get_neutron_client_version(), session=sess)
257 def get_glance_client_version():
258 api_version = os.getenv('OS_IMAGE_API_VERSION')
259 if api_version is not None:
260 logger.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version)
262 return DEFAULT_API_VERSION
265 def get_glance_client(other_creds={}):
266 sess = get_session(other_creds)
267 return glanceclient.Client(get_glance_client_version(), session=sess)
270 def get_heat_client_version():
271 api_version = os.getenv('OS_ORCHESTRATION_API_VERSION')
272 if api_version is not None:
273 logger.info("OS_ORCHESTRATION_API_VERSION is set in env as '%s'",
276 return DEFAULT_HEAT_API_VERSION
279 def get_heat_client(other_creds={}):
280 sess = get_session(other_creds)
281 return heatclient.Client(get_heat_client_version(), session=sess)
284 def download_and_add_image_on_glance(glance, image_name, image_url, data_dir):
287 if not os.path.exists(dest_path):
288 os.makedirs(dest_path)
289 file_name = image_url.rsplit('/')[-1]
290 if not ft_utils.download_url(image_url, dest_path):
293 raise Exception("Impossible to download image from {}".format(
297 image = create_glance_image(
298 glance, image_name, dest_path + file_name)
304 raise Exception("Impossible to put image {} in glance".format(
308 # *********************************************
310 # *********************************************
311 def get_instances(nova_client):
313 instances = nova_client.servers.list(search_opts={'all_tenants': 1})
315 except Exception as e:
316 logger.error("Error [get_instances(nova_client)]: %s" % e)
320 def get_instance_status(nova_client, instance):
322 instance = nova_client.servers.get(instance.id)
323 return instance.status
324 except Exception as e:
325 logger.error("Error [get_instance_status(nova_client)]: %s" % e)
329 def get_instance_by_name(nova_client, instance_name):
331 instance = nova_client.servers.find(name=instance_name)
333 except Exception as e:
334 logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
335 % (instance_name, e))
339 def get_flavor_id(nova_client, flavor_name):
340 flavors = nova_client.flavors.list(detailed=True)
343 if f.name == flavor_name:
349 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
350 flavors = nova_client.flavors.list(detailed=True)
353 if min_ram <= f.ram and f.ram <= max_ram:
359 def get_aggregates(nova_client):
361 aggregates = nova_client.aggregates.list()
363 except Exception as e:
364 logger.error("Error [get_aggregates(nova_client)]: %s" % e)
368 def get_aggregate_id(nova_client, aggregate_name):
370 aggregates = get_aggregates(nova_client)
371 _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
373 except Exception as e:
374 logger.error("Error [get_aggregate_id(nova_client, %s)]:"
375 " %s" % (aggregate_name, e))
379 def get_availability_zones(nova_client):
381 availability_zones = nova_client.availability_zones.list()
382 return availability_zones
383 except Exception as e:
384 logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
388 def get_availability_zone_names(nova_client):
390 az_names = [az.zoneName for az in get_availability_zones(nova_client)]
392 except Exception as e:
393 logger.error("Error [get_availability_zone_names(nova_client)]:"
398 def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
400 flavor = nova_client.flavors.create(
401 flavor_name, ram, vcpus, disk, is_public=public)
403 extra_specs = ft_utils.get_functest_config(
404 'general.flavor_extra_specs')
405 flavor.set_keys(extra_specs)
407 # flavor extra specs are not configured, therefore skip the update
410 except Exception as e:
411 logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
412 "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
417 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
418 flavor_exists = False
419 nova_client = get_nova_client()
421 flavor_id = get_flavor_id(nova_client, flavor_name)
423 logger.info("Using existing flavor '%s'..." % flavor_name)
426 logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
427 "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
428 flavor_id = create_flavor(
429 nova_client, flavor_name, ram, disk, vcpus, public=public)
431 raise Exception("Failed to create flavor '%s'..." % (flavor_name))
433 logger.debug("Flavor '%s' with ID=%s created successfully."
434 % (flavor_name, flavor_id))
436 return flavor_exists, flavor_id
439 def get_floating_ips(neutron_client):
441 floating_ips = neutron_client.list_floatingips()
442 return floating_ips['floatingips']
443 except Exception as e:
444 logger.error("Error [get_floating_ips(neutron_client)]: %s" % e)
448 def get_hypervisors(nova_client):
451 hypervisors = nova_client.hypervisors.list()
452 for hypervisor in hypervisors:
453 if hypervisor.state == "up":
454 nodes.append(hypervisor.hypervisor_hostname)
456 except Exception as e:
457 logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
461 def create_aggregate(nova_client, aggregate_name, av_zone):
463 nova_client.aggregates.create(aggregate_name, av_zone)
465 except Exception as e:
466 logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
467 % (aggregate_name, av_zone, e))
471 def add_host_to_aggregate(nova_client, aggregate_name, compute_host):
473 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
474 nova_client.aggregates.add_host(aggregate_id, compute_host)
476 except Exception as e:
477 logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
478 % (aggregate_name, compute_host, e))
482 def create_aggregate_with_host(
483 nova_client, aggregate_name, av_zone, compute_host):
485 create_aggregate(nova_client, aggregate_name, av_zone)
486 add_host_to_aggregate(nova_client, aggregate_name, compute_host)
488 except Exception as e:
489 logger.error("Error [create_aggregate_with_host("
490 "nova_client, %s, %s, %s)]: %s"
491 % (aggregate_name, av_zone, compute_host, e))
495 def create_instance(flavor_name,
498 instance_name="functest-vm",
504 nova_client = get_nova_client()
506 flavor = nova_client.flavors.find(name=flavor_name)
508 flavors = nova_client.flavors.list()
509 logger.error("Error: Flavor '%s' not found. Available flavors are: "
510 "\n%s" % (flavor_name, flavors))
512 if fixed_ip is not None:
513 nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
515 nics = {"net-id": network_id}
517 instance = nova_client.servers.create(
522 availability_zone=av_zone,
526 instance = nova_client.servers.create(
531 config_drive=confdrive,
533 availability_zone=av_zone,
539 def create_instance_and_wait_for_active(flavor_name,
549 VM_BOOT_TIMEOUT = 180
550 nova_client = get_nova_client()
551 instance = create_instance(flavor_name,
560 count = VM_BOOT_TIMEOUT / SLEEP
561 for n in range(count, -1, -1):
562 status = get_instance_status(nova_client, instance)
563 if status.lower() == "active":
565 elif status.lower() == "error":
566 logger.error("The instance %s went to ERROR status."
570 logger.error("Timeout booting the instance %s." % instance_name)
574 def create_floating_ip(neutron_client):
575 extnet_id = get_external_net_id(neutron_client)
576 props = {'floating_network_id': extnet_id}
578 ip_json = neutron_client.create_floatingip({'floatingip': props})
579 fip_addr = ip_json['floatingip']['floating_ip_address']
580 fip_id = ip_json['floatingip']['id']
581 except Exception as e:
582 logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
584 return {'fip_addr': fip_addr, 'fip_id': fip_id}
587 def add_floating_ip(nova_client, server_id, floatingip_addr):
589 nova_client.servers.add_floating_ip(server_id, floatingip_addr)
591 except Exception as e:
592 logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
593 % (server_id, floatingip_addr, e))
597 def delete_instance(nova_client, instance_id):
599 nova_client.servers.force_delete(instance_id)
601 except Exception as e:
602 logger.error("Error [delete_instance(nova_client, '%s')]: %s"
607 def delete_floating_ip(neutron_client, floatingip_id):
609 neutron_client.delete_floatingip(floatingip_id)
611 except Exception as e:
612 logger.error("Error [delete_floating_ip(neutron_client, '%s')]: %s"
613 % (floatingip_id, e))
617 def remove_host_from_aggregate(nova_client, aggregate_name, compute_host):
619 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
620 nova_client.aggregates.remove_host(aggregate_id, compute_host)
622 except Exception as e:
623 logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
624 " %s" % (aggregate_name, compute_host, e))
628 def remove_hosts_from_aggregate(nova_client, aggregate_name):
629 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
630 hosts = nova_client.aggregates.get(aggregate_id).hosts
632 all(remove_host_from_aggregate(nova_client, aggregate_name, host)
636 def delete_aggregate(nova_client, aggregate_name):
638 remove_hosts_from_aggregate(nova_client, aggregate_name)
639 nova_client.aggregates.delete(aggregate_name)
641 except Exception as e:
642 logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
643 % (aggregate_name, e))
647 # *********************************************
649 # *********************************************
650 def get_network_list(neutron_client):
651 network_list = neutron_client.list_networks()['networks']
652 if len(network_list) == 0:
658 def get_router_list(neutron_client):
659 router_list = neutron_client.list_routers()['routers']
660 if len(router_list) == 0:
666 def get_port_list(neutron_client):
667 port_list = neutron_client.list_ports()['ports']
668 if len(port_list) == 0:
674 def get_network_id(neutron_client, network_name):
675 networks = neutron_client.list_networks()['networks']
678 if n['name'] == network_name:
684 def get_subnet_id(neutron_client, subnet_name):
685 subnets = neutron_client.list_subnets()['subnets']
688 if s['name'] == subnet_name:
694 def get_router_id(neutron_client, router_name):
695 routers = neutron_client.list_routers()['routers']
698 if r['name'] == router_name:
704 def get_private_net(neutron_client):
705 # Checks if there is an existing shared private network
706 networks = neutron_client.list_networks()['networks']
707 if len(networks) == 0:
710 if (net['router:external'] is False) and (net['shared'] is True):
715 def get_external_net(neutron_client):
716 if (hasattr(CONST, 'EXTERNAL_NETWORK')):
717 return CONST.__getattribute__('EXTERNAL_NETWORK')
718 for network in neutron_client.list_networks()['networks']:
719 if network['router:external']:
720 return network['name']
724 def get_external_net_id(neutron_client):
725 if (hasattr(CONST, 'EXTERNAL_NETWORK')):
726 networks = neutron_client.list_networks(
727 name=CONST.__getattribute__('EXTERNAL_NETWORK'))
728 net_id = networks['networks'][0]['id']
730 for network in neutron_client.list_networks()['networks']:
731 if network['router:external']:
736 def check_neutron_net(neutron_client, net_name):
737 for network in neutron_client.list_networks()['networks']:
738 if network['name'] == net_name:
739 for subnet in network['subnets']:
744 def create_neutron_net(neutron_client, name):
745 json_body = {'network': {'name': name,
746 'admin_state_up': True}}
748 network = neutron_client.create_network(body=json_body)
749 network_dict = network['network']
750 return network_dict['id']
751 except Exception as e:
752 logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
757 def create_neutron_subnet(neutron_client, name, cidr, net_id,
758 dns=['8.8.8.8', '8.8.4.4']):
759 json_body = {'subnets': [{'name': name, 'cidr': cidr,
760 'ip_version': 4, 'network_id': net_id,
761 'dns_nameservers': dns}]}
764 subnet = neutron_client.create_subnet(body=json_body)
765 return subnet['subnets'][0]['id']
766 except Exception as e:
767 logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
768 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
772 def create_neutron_router(neutron_client, name):
773 json_body = {'router': {'name': name, 'admin_state_up': True}}
775 router = neutron_client.create_router(json_body)
776 return router['router']['id']
777 except Exception as e:
778 logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
783 def create_neutron_port(neutron_client, name, network_id, ip):
784 json_body = {'port': {
785 'admin_state_up': True,
787 'network_id': network_id,
788 'fixed_ips': [{"ip_address": ip}]
791 port = neutron_client.create_port(body=json_body)
792 return port['port']['id']
793 except Exception as e:
794 logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
795 "'%s')]: %s" % (name, network_id, ip, e))
799 def update_neutron_net(neutron_client, network_id, shared=False):
800 json_body = {'network': {'shared': shared}}
802 neutron_client.update_network(network_id, body=json_body)
804 except Exception as e:
805 logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
806 "%s" % (network_id, str(shared), e))
810 def update_neutron_port(neutron_client, port_id, device_owner):
811 json_body = {'port': {
812 'device_owner': device_owner,
815 port = neutron_client.update_port(port=port_id,
817 return port['port']['id']
818 except Exception as e:
819 logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
820 " %s" % (port_id, device_owner, e))
824 def add_interface_router(neutron_client, router_id, subnet_id):
825 json_body = {"subnet_id": subnet_id}
827 neutron_client.add_interface_router(router=router_id, body=json_body)
829 except Exception as e:
830 logger.error("Error [add_interface_router(neutron_client, '%s', "
831 "'%s')]: %s" % (router_id, subnet_id, e))
835 def add_gateway_router(neutron_client, router_id):
836 ext_net_id = get_external_net_id(neutron_client)
837 router_dict = {'network_id': ext_net_id}
839 neutron_client.add_gateway_router(router_id, router_dict)
841 except Exception as e:
842 logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
847 def delete_neutron_net(neutron_client, network_id):
849 neutron_client.delete_network(network_id)
851 except Exception as e:
852 logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
857 def delete_neutron_subnet(neutron_client, subnet_id):
859 neutron_client.delete_subnet(subnet_id)
861 except Exception as e:
862 logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
867 def delete_neutron_router(neutron_client, router_id):
869 neutron_client.delete_router(router=router_id)
871 except Exception as e:
872 logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
877 def delete_neutron_port(neutron_client, port_id):
879 neutron_client.delete_port(port_id)
881 except Exception as e:
882 logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
887 def remove_interface_router(neutron_client, router_id, subnet_id):
888 json_body = {"subnet_id": subnet_id}
890 neutron_client.remove_interface_router(router=router_id,
893 except Exception as e:
894 logger.error("Error [remove_interface_router(neutron_client, '%s', "
895 "'%s')]: %s" % (router_id, subnet_id, e))
899 def remove_gateway_router(neutron_client, router_id):
901 neutron_client.remove_gateway_router(router_id)
903 except Exception as e:
904 logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
909 def create_network_full(neutron_client,
914 dns=['8.8.8.8', '8.8.4.4']):
916 # Check if the network already exists
917 network_id = get_network_id(neutron_client, net_name)
918 subnet_id = get_subnet_id(neutron_client, subnet_name)
919 router_id = get_router_id(neutron_client, router_name)
921 if network_id != '' and subnet_id != '' and router_id != '':
922 logger.info("A network with name '%s' already exists..." % net_name)
924 neutron_client.format = 'json'
925 logger.info('Creating neutron network %s...' % net_name)
926 network_id = create_neutron_net(neutron_client, net_name)
931 logger.debug("Network '%s' created successfully" % network_id)
932 logger.debug('Creating Subnet....')
933 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
934 cidr, network_id, dns)
938 logger.debug("Subnet '%s' created successfully" % subnet_id)
939 logger.debug('Creating Router...')
940 router_id = create_neutron_router(neutron_client, router_name)
945 logger.debug("Router '%s' created successfully" % router_id)
946 logger.debug('Adding router to subnet...')
948 if not add_interface_router(neutron_client, router_id, subnet_id):
951 logger.debug("Interface added successfully.")
953 logger.debug('Adding gateway to router...')
954 if not add_gateway_router(neutron_client, router_id):
957 logger.debug("Gateway added successfully.")
959 network_dic = {'net_id': network_id,
960 'subnet_id': subnet_id,
961 'router_id': router_id}
965 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
966 neutron_client = get_neutron_client()
968 network_dic = create_network_full(neutron_client,
974 if not update_neutron_net(neutron_client,
975 network_dic['net_id'],
977 logger.error("Failed to update network %s..." % net_name)
980 logger.debug("Network '%s' is available..." % net_name)
982 logger.error("Network %s creation failed" % net_name)
987 # *********************************************
989 # *********************************************
992 def get_security_groups(neutron_client):
994 security_groups = neutron_client.list_security_groups()[
996 return security_groups
997 except Exception as e:
998 logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
1002 def get_security_group_id(neutron_client, sg_name):
1003 security_groups = get_security_groups(neutron_client)
1005 for sg in security_groups:
1006 if sg['name'] == sg_name:
1012 def create_security_group(neutron_client, sg_name, sg_description):
1013 json_body = {'security_group': {'name': sg_name,
1014 'description': sg_description}}
1016 secgroup = neutron_client.create_security_group(json_body)
1017 return secgroup['security_group']
1018 except Exception as e:
1019 logger.error("Error [create_security_group(neutron_client, '%s', "
1020 "'%s')]: %s" % (sg_name, sg_description, e))
1024 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
1025 port_range_min=None, port_range_max=None):
1026 # We create a security group in 2 steps
1027 # 1 - we check the format and set the json body accordingly
1028 # 2 - we call neturon client to create the security group
1031 json_body = {'security_group_rule': {'direction': direction,
1032 'security_group_id': sg_id,
1033 'protocol': protocol}}
1035 # - both None => we do nothing
1036 # - both Not None => we add them to the json description
1037 # but one cannot be None is the other is not None
1038 if (port_range_min is not None and port_range_max is not None):
1039 # add port_range in json description
1040 json_body['security_group_rule']['port_range_min'] = port_range_min
1041 json_body['security_group_rule']['port_range_max'] = port_range_max
1042 logger.debug("Security_group format set (port range included)")
1044 # either both port range are set to None => do nothing
1045 # or one is set but not the other => log it and return False
1046 if port_range_min is None and port_range_max is None:
1047 logger.debug("Security_group format set (no port range mentioned)")
1049 logger.error("Bad security group format."
1050 "One of the port range is not properly set:"
1052 "range max: {}".format(port_range_min,
1056 # Create security group using neutron client
1058 neutron_client.create_security_group_rule(json_body)
1061 logger.exception("Impossible to create_security_group_rule,"
1062 "security group rule probably already exists")
1066 def get_security_group_rules(neutron_client, sg_id):
1068 security_rules = neutron_client.list_security_group_rules()[
1069 'security_group_rules']
1070 security_rules = [rule for rule in security_rules
1071 if rule["security_group_id"] == sg_id]
1072 return security_rules
1073 except Exception as e:
1074 logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:"
1079 def check_security_group_rules(neutron_client, sg_id, direction, protocol,
1080 port_min=None, port_max=None):
1082 security_rules = get_security_group_rules(neutron_client, sg_id)
1083 security_rules = [rule for rule in security_rules
1084 if (rule["direction"].lower() == direction and
1085 rule["protocol"].lower() == protocol and
1086 rule["port_range_min"] == port_min and
1087 rule["port_range_max"] == port_max)]
1088 if len(security_rules) == 0:
1092 except Exception as e:
1093 logger.error("Error [check_security_group_rules("
1094 " neutron_client, sg_id, direction,"
1095 " protocol, port_min=None, port_max=None)]: "
1100 def create_security_group_full(neutron_client,
1101 sg_name, sg_description):
1102 sg_id = get_security_group_id(neutron_client, sg_name)
1104 logger.info("Using existing security group '%s'..." % sg_name)
1106 logger.info("Creating security group '%s'..." % sg_name)
1107 SECGROUP = create_security_group(neutron_client,
1111 logger.error("Failed to create the security group...")
1114 sg_id = SECGROUP['id']
1116 logger.debug("Security group '%s' with ID=%s created successfully."
1117 % (SECGROUP['name'], sg_id))
1119 logger.debug("Adding ICMP rules in security group '%s'..."
1121 if not create_secgroup_rule(neutron_client, sg_id,
1123 logger.error("Failed to create the security group rule...")
1126 logger.debug("Adding SSH rules in security group '%s'..."
1128 if not create_secgroup_rule(
1129 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1130 logger.error("Failed to create the security group rule...")
1133 if not create_secgroup_rule(
1134 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1135 logger.error("Failed to create the security group rule...")
1140 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
1142 nova_client.servers.add_security_group(instance_id, secgroup_id)
1144 except Exception as e:
1145 logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
1146 "'%s')]: %s" % (instance_id, secgroup_id, e))
1150 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1151 json_body = {"quota": {
1152 "security_group": sg_quota,
1153 "security_group_rule": sg_rule_quota
1157 neutron_client.update_quota(tenant_id=tenant_id,
1160 except Exception as e:
1161 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1162 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1166 def delete_security_group(neutron_client, secgroup_id):
1168 neutron_client.delete_security_group(secgroup_id)
1170 except Exception as e:
1171 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1176 # *********************************************
1178 # *********************************************
1179 def get_images(glance_client):
1181 images = glance_client.images.list()
1183 except Exception as e:
1184 logger.error("Error [get_images]: %s" % e)
1188 def get_image_id(glance_client, image_name):
1189 images = glance_client.images.list()
1192 if i.name == image_name:
1198 def create_glance_image(glance_client,
1202 extra_properties={},
1205 if not os.path.isfile(file_path):
1206 logger.error("Error: file %s does not exist." % file_path)
1209 image_id = get_image_id(glance_client, image_name)
1211 logger.info("Image %s already exists." % image_name)
1213 logger.info("Creating image '%s' from '%s'..." % (image_name,
1216 image = glance_client.images.create(name=image_name,
1219 container_format=container,
1222 with open(file_path) as image_data:
1223 glance_client.images.upload(image_id, image_data)
1225 except Exception as e:
1226 logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1227 "'%s')]: %s" % (image_name, file_path, public, e))
1231 def get_or_create_image(name, path, format, extra_properties):
1232 image_exists = False
1233 glance_client = get_glance_client()
1235 image_id = get_image_id(glance_client, name)
1237 logger.info("Using existing image '%s'..." % name)
1240 logger.info("Creating image '%s' from '%s'..." % (name, path))
1241 image_id = create_glance_image(glance_client,
1247 logger.error("Failed to create a Glance image...")
1249 logger.debug("Image '%s' with ID=%s created successfully."
1252 return image_exists, image_id
1255 def delete_glance_image(glance_client, image_id):
1257 glance_client.images.delete(image_id)
1259 except Exception as e:
1260 logger.error("Error [delete_glance_image(glance_client, '%s')]: %s"
1265 # *********************************************
1267 # *********************************************
1268 def get_volumes(cinder_client):
1270 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1272 except Exception as e:
1273 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1277 def list_volume_types(cinder_client, public=True, private=True):
1279 volume_types = cinder_client.volume_types.list()
1281 volume_types = [vt for vt in volume_types if not vt.is_public]
1283 volume_types = [vt for vt in volume_types if vt.is_public]
1285 except Exception as e:
1286 logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
1290 def create_volume_type(cinder_client, name):
1292 volume_type = cinder_client.volume_types.create(name)
1294 except Exception as e:
1295 logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
1300 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1301 snapshots_quota, gigabytes_quota):
1302 quotas_values = {"volumes": vols_quota,
1303 "snapshots": snapshots_quota,
1304 "gigabytes": gigabytes_quota}
1307 cinder_client.quotas.update(tenant_id, **quotas_values)
1309 except Exception as e:
1310 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1311 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1312 snapshots_quota, gigabytes_quota, e))
1316 def delete_volume(cinder_client, volume_id, forced=False):
1320 cinder_client.volumes.detach(volume_id)
1322 logger.error(sys.exc_info()[0])
1323 cinder_client.volumes.force_delete(volume_id)
1325 cinder_client.volumes.delete(volume_id)
1327 except Exception as e:
1328 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1329 % (volume_id, str(forced), e))
1333 def delete_volume_type(cinder_client, volume_type):
1335 cinder_client.volume_types.delete(volume_type)
1337 except Exception as e:
1338 logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
1343 # *********************************************
1345 # *********************************************
1346 def get_tenants(keystone_client):
1348 if is_keystone_v3():
1349 tenants = keystone_client.projects.list()
1351 tenants = keystone_client.tenants.list()
1353 except Exception as e:
1354 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1358 def get_users(keystone_client):
1360 users = keystone_client.users.list()
1362 except Exception as e:
1363 logger.error("Error [get_users(keystone_client)]: %s" % e)
1367 def get_tenant_id(keystone_client, tenant_name):
1368 tenants = get_tenants(keystone_client)
1371 if t.name == tenant_name:
1377 def get_user_id(keystone_client, user_name):
1378 users = get_users(keystone_client)
1381 if u.name == user_name:
1387 def get_role_id(keystone_client, role_name):
1388 roles = keystone_client.roles.list()
1391 if r.name == role_name:
1397 def get_domain_id(keystone_client, domain_name):
1398 domains = keystone_client.domains.list()
1401 if d.name == domain_name:
1407 def create_tenant(keystone_client, tenant_name, tenant_description):
1409 if is_keystone_v3():
1410 domain_name = CONST.__getattribute__('OS_PROJECT_DOMAIN_NAME')
1411 domain_id = get_domain_id(keystone_client, domain_name)
1412 tenant = keystone_client.projects.create(
1414 description=tenant_description,
1418 tenant = keystone_client.tenants.create(tenant_name,
1422 except Exception as e:
1423 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1424 % (tenant_name, tenant_description, e))
1428 def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
1429 tenant_id = get_tenant_id(keystone_client, tenant_name)
1431 tenant_id = create_tenant(keystone_client, tenant_name,
1437 def get_or_create_tenant_for_vnf(keystone_client, tenant_name,
1438 tenant_description):
1439 """Get or Create a Tenant
1442 keystone_client: keystone client reference
1443 tenant_name: the name of the tenant
1444 tenant_description: the description of the tenant
1446 return False if tenant retrieved though get
1447 return True if tenant created
1448 raise Exception if error during processing
1451 tenant_id = get_tenant_id(keystone_client, tenant_name)
1453 tenant_id = create_tenant(keystone_client, tenant_name,
1459 raise Exception("Impossible to create a Tenant for the VNF {}".format(
1463 def create_user(keystone_client, user_name, user_password,
1464 user_email, tenant_id):
1466 if is_keystone_v3():
1467 user = keystone_client.users.create(name=user_name,
1468 password=user_password,
1470 project_id=tenant_id,
1473 user = keystone_client.users.create(user_name,
1479 except Exception as e:
1480 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1481 "'%s')]: %s" % (user_name, user_password,
1482 user_email, tenant_id, e))
1486 def get_or_create_user(keystone_client, user_name, user_password,
1487 tenant_id, user_email=None):
1488 user_id = get_user_id(keystone_client, user_name)
1490 user_id = create_user(keystone_client, user_name, user_password,
1491 user_email, tenant_id)
1495 def get_or_create_user_for_vnf(keystone_client, vnf_ref):
1496 """Get or Create user for VNF
1499 keystone_client: keystone client reference
1500 vnf_ref: VNF reference used as user name & password, tenant name
1502 return False if user retrieved through get
1503 return True if user created
1504 raise Exception if error during processing
1507 user_id = get_user_id(keystone_client, vnf_ref)
1508 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1511 user_id = create_user(keystone_client, vnf_ref, vnf_ref,
1515 role_id = get_role_id(keystone_client, 'admin')
1516 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1517 add_role_user(keystone_client, user_id, role_id, tenant_id)
1519 logger.warn("Cannot associate user to role admin on tenant")
1522 raise Exception("Impossible to create a user for the VNF {}".format(
1526 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1528 if is_keystone_v3():
1529 keystone_client.roles.grant(role=role_id,
1533 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1535 except Exception as e:
1536 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1537 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1541 def delete_tenant(keystone_client, tenant_id):
1543 if is_keystone_v3():
1544 keystone_client.projects.delete(tenant_id)
1546 keystone_client.tenants.delete(tenant_id)
1548 except Exception as e:
1549 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1554 def delete_user(keystone_client, user_id):
1556 keystone_client.users.delete(user_id)
1558 except Exception as e:
1559 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1564 # *********************************************
1566 # *********************************************
1567 def get_resource(heat_client, stack_id, resource):
1569 resources = heat_client.resources.get(stack_id, resource)
1571 except Exception as e:
1572 logger.error("Error [get_resource]: %s" % e)