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
25 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 for network in neutron_client.list_networks()['networks']:
717 if network['router:external']:
718 return network['name']
722 def get_external_net_id(neutron_client):
723 for network in neutron_client.list_networks()['networks']:
724 if network['router:external']:
729 def check_neutron_net(neutron_client, net_name):
730 for network in neutron_client.list_networks()['networks']:
731 if network['name'] == net_name:
732 for subnet in network['subnets']:
737 def create_neutron_net(neutron_client, name):
738 json_body = {'network': {'name': name,
739 'admin_state_up': True}}
741 network = neutron_client.create_network(body=json_body)
742 network_dict = network['network']
743 return network_dict['id']
744 except Exception as e:
745 logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
750 def create_neutron_subnet(neutron_client, name, cidr, net_id,
751 dns=['8.8.8.8', '8.8.4.4']):
752 json_body = {'subnets': [{'name': name, 'cidr': cidr,
753 'ip_version': 4, 'network_id': net_id,
754 'dns_nameservers': dns}]}
757 subnet = neutron_client.create_subnet(body=json_body)
758 return subnet['subnets'][0]['id']
759 except Exception as e:
760 logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
761 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
765 def create_neutron_router(neutron_client, name):
766 json_body = {'router': {'name': name, 'admin_state_up': True}}
768 router = neutron_client.create_router(json_body)
769 return router['router']['id']
770 except Exception as e:
771 logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
776 def create_neutron_port(neutron_client, name, network_id, ip):
777 json_body = {'port': {
778 'admin_state_up': True,
780 'network_id': network_id,
781 'fixed_ips': [{"ip_address": ip}]
784 port = neutron_client.create_port(body=json_body)
785 return port['port']['id']
786 except Exception as e:
787 logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
788 "'%s')]: %s" % (name, network_id, ip, e))
792 def update_neutron_net(neutron_client, network_id, shared=False):
793 json_body = {'network': {'shared': shared}}
795 neutron_client.update_network(network_id, body=json_body)
797 except Exception as e:
798 logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
799 "%s" % (network_id, str(shared), e))
803 def update_neutron_port(neutron_client, port_id, device_owner):
804 json_body = {'port': {
805 'device_owner': device_owner,
808 port = neutron_client.update_port(port=port_id,
810 return port['port']['id']
811 except Exception as e:
812 logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
813 " %s" % (port_id, device_owner, e))
817 def add_interface_router(neutron_client, router_id, subnet_id):
818 json_body = {"subnet_id": subnet_id}
820 neutron_client.add_interface_router(router=router_id, body=json_body)
822 except Exception as e:
823 logger.error("Error [add_interface_router(neutron_client, '%s', "
824 "'%s')]: %s" % (router_id, subnet_id, e))
828 def add_gateway_router(neutron_client, router_id):
829 ext_net_id = get_external_net_id(neutron_client)
830 router_dict = {'network_id': ext_net_id}
832 neutron_client.add_gateway_router(router_id, router_dict)
834 except Exception as e:
835 logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
840 def delete_neutron_net(neutron_client, network_id):
842 neutron_client.delete_network(network_id)
844 except Exception as e:
845 logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
850 def delete_neutron_subnet(neutron_client, subnet_id):
852 neutron_client.delete_subnet(subnet_id)
854 except Exception as e:
855 logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
860 def delete_neutron_router(neutron_client, router_id):
862 neutron_client.delete_router(router=router_id)
864 except Exception as e:
865 logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
870 def delete_neutron_port(neutron_client, port_id):
872 neutron_client.delete_port(port_id)
874 except Exception as e:
875 logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
880 def remove_interface_router(neutron_client, router_id, subnet_id):
881 json_body = {"subnet_id": subnet_id}
883 neutron_client.remove_interface_router(router=router_id,
886 except Exception as e:
887 logger.error("Error [remove_interface_router(neutron_client, '%s', "
888 "'%s')]: %s" % (router_id, subnet_id, e))
892 def remove_gateway_router(neutron_client, router_id):
894 neutron_client.remove_gateway_router(router_id)
896 except Exception as e:
897 logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
902 def create_network_full(neutron_client,
907 dns=['8.8.8.8', '8.8.4.4']):
909 # Check if the network already exists
910 network_id = get_network_id(neutron_client, net_name)
911 subnet_id = get_subnet_id(neutron_client, subnet_name)
912 router_id = get_router_id(neutron_client, router_name)
914 if network_id != '' and subnet_id != '' and router_id != '':
915 logger.info("A network with name '%s' already exists..." % net_name)
917 neutron_client.format = 'json'
918 logger.info('Creating neutron network %s...' % net_name)
919 network_id = create_neutron_net(neutron_client, net_name)
924 logger.debug("Network '%s' created successfully" % network_id)
925 logger.debug('Creating Subnet....')
926 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
927 cidr, network_id, dns)
931 logger.debug("Subnet '%s' created successfully" % subnet_id)
932 logger.debug('Creating Router...')
933 router_id = create_neutron_router(neutron_client, router_name)
938 logger.debug("Router '%s' created successfully" % router_id)
939 logger.debug('Adding router to subnet...')
941 if not add_interface_router(neutron_client, router_id, subnet_id):
944 logger.debug("Interface added successfully.")
946 logger.debug('Adding gateway to router...')
947 if not add_gateway_router(neutron_client, router_id):
950 logger.debug("Gateway added successfully.")
952 network_dic = {'net_id': network_id,
953 'subnet_id': subnet_id,
954 'router_id': router_id}
958 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
959 neutron_client = get_neutron_client()
961 network_dic = create_network_full(neutron_client,
967 if not update_neutron_net(neutron_client,
968 network_dic['net_id'],
970 logger.error("Failed to update network %s..." % net_name)
973 logger.debug("Network '%s' is available..." % net_name)
975 logger.error("Network %s creation failed" % net_name)
980 # *********************************************
982 # *********************************************
985 def get_security_groups(neutron_client):
987 security_groups = neutron_client.list_security_groups()[
989 return security_groups
990 except Exception as e:
991 logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
995 def get_security_group_id(neutron_client, sg_name):
996 security_groups = get_security_groups(neutron_client)
998 for sg in security_groups:
999 if sg['name'] == sg_name:
1005 def create_security_group(neutron_client, sg_name, sg_description):
1006 json_body = {'security_group': {'name': sg_name,
1007 'description': sg_description}}
1009 secgroup = neutron_client.create_security_group(json_body)
1010 return secgroup['security_group']
1011 except Exception as e:
1012 logger.error("Error [create_security_group(neutron_client, '%s', "
1013 "'%s')]: %s" % (sg_name, sg_description, e))
1017 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
1018 port_range_min=None, port_range_max=None):
1019 # We create a security group in 2 steps
1020 # 1 - we check the format and set the json body accordingly
1021 # 2 - we call neturon client to create the security group
1024 json_body = {'security_group_rule': {'direction': direction,
1025 'security_group_id': sg_id,
1026 'protocol': protocol}}
1028 # - both None => we do nothing
1029 # - both Not None => we add them to the json description
1030 # but one cannot be None is the other is not None
1031 if (port_range_min is not None and port_range_max is not None):
1032 # add port_range in json description
1033 json_body['security_group_rule']['port_range_min'] = port_range_min
1034 json_body['security_group_rule']['port_range_max'] = port_range_max
1035 logger.debug("Security_group format set (port range included)")
1037 # either both port range are set to None => do nothing
1038 # or one is set but not the other => log it and return False
1039 if port_range_min is None and port_range_max is None:
1040 logger.debug("Security_group format set (no port range mentioned)")
1042 logger.error("Bad security group format."
1043 "One of the port range is not properly set:"
1045 "range max: {}".format(port_range_min,
1049 # Create security group using neutron client
1051 neutron_client.create_security_group_rule(json_body)
1054 logger.exception("Impossible to create_security_group_rule,"
1055 "security group rule probably already exists")
1059 def get_security_group_rules(neutron_client, sg_id):
1061 security_rules = neutron_client.list_security_group_rules()[
1062 'security_group_rules']
1063 security_rules = [rule for rule in security_rules
1064 if rule["security_group_id"] == sg_id]
1065 return security_rules
1066 except Exception as e:
1067 logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:"
1072 def check_security_group_rules(neutron_client, sg_id, direction, protocol,
1073 port_min=None, port_max=None):
1075 security_rules = get_security_group_rules(neutron_client, sg_id)
1076 security_rules = [rule for rule in security_rules
1077 if (rule["direction"].lower() == direction and
1078 rule["protocol"].lower() == protocol and
1079 rule["port_range_min"] == port_min and
1080 rule["port_range_max"] == port_max)]
1081 if len(security_rules) == 0:
1085 except Exception as e:
1086 logger.error("Error [check_security_group_rules("
1087 " neutron_client, sg_id, direction,"
1088 " protocol, port_min=None, port_max=None)]: "
1093 def create_security_group_full(neutron_client,
1094 sg_name, sg_description):
1095 sg_id = get_security_group_id(neutron_client, sg_name)
1097 logger.info("Using existing security group '%s'..." % sg_name)
1099 logger.info("Creating security group '%s'..." % sg_name)
1100 SECGROUP = create_security_group(neutron_client,
1104 logger.error("Failed to create the security group...")
1107 sg_id = SECGROUP['id']
1109 logger.debug("Security group '%s' with ID=%s created successfully."
1110 % (SECGROUP['name'], sg_id))
1112 logger.debug("Adding ICMP rules in security group '%s'..."
1114 if not create_secgroup_rule(neutron_client, sg_id,
1116 logger.error("Failed to create the security group rule...")
1119 logger.debug("Adding SSH rules in security group '%s'..."
1121 if not create_secgroup_rule(
1122 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1123 logger.error("Failed to create the security group rule...")
1126 if not create_secgroup_rule(
1127 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1128 logger.error("Failed to create the security group rule...")
1133 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
1135 nova_client.servers.add_security_group(instance_id, secgroup_id)
1137 except Exception as e:
1138 logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
1139 "'%s')]: %s" % (instance_id, secgroup_id, e))
1143 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1144 json_body = {"quota": {
1145 "security_group": sg_quota,
1146 "security_group_rule": sg_rule_quota
1150 neutron_client.update_quota(tenant_id=tenant_id,
1153 except Exception as e:
1154 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1155 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1159 def delete_security_group(neutron_client, secgroup_id):
1161 neutron_client.delete_security_group(secgroup_id)
1163 except Exception as e:
1164 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1169 # *********************************************
1171 # *********************************************
1172 def get_images(glance_client):
1174 images = glance_client.images.list()
1176 except Exception as e:
1177 logger.error("Error [get_images]: %s" % e)
1181 def get_image_id(glance_client, image_name):
1182 images = glance_client.images.list()
1185 if i.name == image_name:
1191 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
1192 container="bare", public="public"):
1193 if not os.path.isfile(file_path):
1194 logger.error("Error: file %s does not exist." % file_path)
1197 image_id = get_image_id(glance_client, image_name)
1199 logger.info("Image %s already exists." % image_name)
1201 logger.info("Creating image '%s' from '%s'..." % (image_name,
1204 image = glance_client.images.create(name=image_name,
1207 container_format=container)
1209 with open(file_path) as image_data:
1210 glance_client.images.upload(image_id, image_data)
1212 except Exception as e:
1213 logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1214 "'%s')]: %s" % (image_name, file_path, public, e))
1218 def get_or_create_image(name, path, format):
1219 image_exists = False
1220 glance_client = get_glance_client()
1222 image_id = get_image_id(glance_client, name)
1224 logger.info("Using existing image '%s'..." % name)
1227 logger.info("Creating image '%s' from '%s'..." % (name, path))
1228 image_id = create_glance_image(glance_client, name, path, format)
1230 logger.error("Failed to create a Glance image...")
1232 logger.debug("Image '%s' with ID=%s created successfully."
1235 return image_exists, image_id
1238 def delete_glance_image(glance_client, image_id):
1240 glance_client.images.delete(image_id)
1242 except Exception as e:
1243 logger.error("Error [delete_glance_image(glance_client, '%s')]: %s"
1248 # *********************************************
1250 # *********************************************
1251 def get_volumes(cinder_client):
1253 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1255 except Exception as e:
1256 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1260 def list_volume_types(cinder_client, public=True, private=True):
1262 volume_types = cinder_client.volume_types.list()
1264 volume_types = [vt for vt in volume_types if not vt.is_public]
1266 volume_types = [vt for vt in volume_types if vt.is_public]
1268 except Exception as e:
1269 logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
1273 def create_volume_type(cinder_client, name):
1275 volume_type = cinder_client.volume_types.create(name)
1277 except Exception as e:
1278 logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
1283 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1284 snapshots_quota, gigabytes_quota):
1285 quotas_values = {"volumes": vols_quota,
1286 "snapshots": snapshots_quota,
1287 "gigabytes": gigabytes_quota}
1290 cinder_client.quotas.update(tenant_id, **quotas_values)
1292 except Exception as e:
1293 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1294 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1295 snapshots_quota, gigabytes_quota, e))
1299 def delete_volume(cinder_client, volume_id, forced=False):
1303 cinder_client.volumes.detach(volume_id)
1305 logger.error(sys.exc_info()[0])
1306 cinder_client.volumes.force_delete(volume_id)
1308 cinder_client.volumes.delete(volume_id)
1310 except Exception as e:
1311 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1312 % (volume_id, str(forced), e))
1316 def delete_volume_type(cinder_client, volume_type):
1318 cinder_client.volume_types.delete(volume_type)
1320 except Exception as e:
1321 logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
1326 # *********************************************
1328 # *********************************************
1329 def get_tenants(keystone_client):
1331 if is_keystone_v3():
1332 tenants = keystone_client.projects.list()
1334 tenants = keystone_client.tenants.list()
1336 except Exception as e:
1337 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1341 def get_users(keystone_client):
1343 users = keystone_client.users.list()
1345 except Exception as e:
1346 logger.error("Error [get_users(keystone_client)]: %s" % e)
1350 def get_tenant_id(keystone_client, tenant_name):
1351 tenants = get_tenants(keystone_client)
1354 if t.name == tenant_name:
1360 def get_user_id(keystone_client, user_name):
1361 users = get_users(keystone_client)
1364 if u.name == user_name:
1370 def get_role_id(keystone_client, role_name):
1371 roles = keystone_client.roles.list()
1374 if r.name == role_name:
1380 def get_domain_id(keystone_client, domain_name):
1381 domains = keystone_client.domains.list()
1384 if d.name == domain_name:
1390 def create_tenant(keystone_client, tenant_name, tenant_description):
1392 if is_keystone_v3():
1393 domain_name = CONST.__getattribute__('OS_PROJECT_DOMAIN_NAME')
1394 domain_id = get_domain_id(keystone_client, domain_name)
1395 tenant = keystone_client.projects.create(
1397 description=tenant_description,
1401 tenant = keystone_client.tenants.create(tenant_name,
1405 except Exception as e:
1406 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1407 % (tenant_name, tenant_description, e))
1411 def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
1412 tenant_id = get_tenant_id(keystone_client, tenant_name)
1414 tenant_id = create_tenant(keystone_client, tenant_name,
1420 def get_or_create_tenant_for_vnf(keystone_client, tenant_name,
1421 tenant_description):
1422 """Get or Create a Tenant
1425 keystone_client: keystone client reference
1426 tenant_name: the name of the tenant
1427 tenant_description: the description of the tenant
1429 return False if tenant retrieved though get
1430 return True if tenant created
1431 raise Exception if error during processing
1434 tenant_id = get_tenant_id(keystone_client, tenant_name)
1436 tenant_id = create_tenant(keystone_client, tenant_name,
1442 raise Exception("Impossible to create a Tenant for the VNF {}".format(
1446 def create_user(keystone_client, user_name, user_password,
1447 user_email, tenant_id):
1449 if is_keystone_v3():
1450 user = keystone_client.users.create(name=user_name,
1451 password=user_password,
1453 project_id=tenant_id,
1456 user = keystone_client.users.create(user_name,
1462 except Exception as e:
1463 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1464 "'%s')]: %s" % (user_name, user_password,
1465 user_email, tenant_id, e))
1469 def get_or_create_user(keystone_client, user_name, user_password,
1470 tenant_id, user_email=None):
1471 user_id = get_user_id(keystone_client, user_name)
1473 user_id = create_user(keystone_client, user_name, user_password,
1474 user_email, tenant_id)
1478 def get_or_create_user_for_vnf(keystone_client, vnf_ref):
1479 """Get or Create user for VNF
1482 keystone_client: keystone client reference
1483 vnf_ref: VNF reference used as user name & password, tenant name
1485 return False if user retrieved through get
1486 return True if user created
1487 raise Exception if error during processing
1490 user_id = get_user_id(keystone_client, vnf_ref)
1491 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1494 user_id = create_user(keystone_client, vnf_ref, vnf_ref,
1498 role_id = get_role_id(keystone_client, 'admin')
1499 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1500 add_role_user(keystone_client, user_id, role_id, tenant_id)
1502 logger.warn("Cannot associate user to role admin on tenant")
1505 raise Exception("Impossible to create a user for the VNF {}".format(
1509 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1511 if is_keystone_v3():
1512 keystone_client.roles.grant(role=role_id,
1516 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1518 except Exception as e:
1519 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1520 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1524 def delete_tenant(keystone_client, tenant_id):
1526 if is_keystone_v3():
1527 keystone_client.projects.delete(tenant_id)
1529 keystone_client.tenants.delete(tenant_id)
1531 except Exception as e:
1532 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1537 def delete_user(keystone_client, user_id):
1539 keystone_client.users.delete(user_id)
1541 except Exception as e:
1542 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1547 # *********************************************
1549 # *********************************************
1550 def get_resource(heat_client, stack_id, resource):
1552 resources = heat_client.resources.get(stack_id, resource)
1554 except Exception as e:
1555 logger.error("Error [get_resource]: %s" % e)