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
19 from keystoneauth1 import loading
20 from keystoneauth1 import session
21 from cinderclient import client as cinderclient
22 from heatclient import client as heatclient
23 from keystoneclient import client as keystoneclient
24 from neutronclient.neutron import client as neutronclient
25 from openstack import connection
26 from openstack import cloud as os_cloud
28 from functest.utils import env
30 logger = logging.getLogger(__name__)
32 DEFAULT_API_VERSION = '2'
33 DEFAULT_HEAT_API_VERSION = '1'
36 # *********************************************
38 # *********************************************
39 class MissingEnvVar(Exception):
41 def __init__(self, var):
45 return str.format("Please set the mandatory env var: {}", self.var)
48 def get_os_connection():
49 return connection.from_config()
53 return os_cloud.openstack_cloud()
57 keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
58 if (keystone_api_version is None or
59 keystone_api_version == '2'):
65 def get_rc_env_vars():
66 env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD']
68 env_vars.extend(['OS_PROJECT_NAME',
69 'OS_USER_DOMAIN_NAME',
70 'OS_PROJECT_DOMAIN_NAME'])
72 env_vars.extend(['OS_TENANT_NAME'])
76 def check_credentials():
78 Check if the OpenStack credentials (openrc) are sourced
80 env_vars = get_rc_env_vars()
81 return all(map(lambda v: v in os.environ and os.environ[v], env_vars))
84 def get_env_cred_dict():
86 'OS_USERNAME': 'username',
87 'OS_PASSWORD': 'password',
88 'OS_AUTH_URL': 'auth_url',
89 'OS_TENANT_NAME': 'tenant_name',
90 'OS_USER_DOMAIN_NAME': 'user_domain_name',
91 'OS_PROJECT_DOMAIN_NAME': 'project_domain_name',
92 'OS_PROJECT_NAME': 'project_name',
93 'OS_ENDPOINT_TYPE': 'endpoint_type',
94 'OS_REGION_NAME': 'region_name',
95 'OS_CACERT': 'https_cacert',
96 'OS_INSECURE': 'https_insecure'
101 def get_credentials(other_creds={}):
102 """Returns a creds dictionary filled with parsed from env
105 env_vars = get_rc_env_vars()
106 env_cred_dict = get_env_cred_dict()
108 for envvar in env_vars:
109 if os.getenv(envvar) is None:
110 raise MissingEnvVar(envvar)
112 creds_key = env_cred_dict.get(envvar)
113 creds.update({creds_key: os.getenv(envvar)})
115 if 'tenant' in other_creds.keys():
117 tenant = 'project_name'
119 tenant = 'tenant_name'
120 other_creds[tenant] = other_creds.pop('tenant')
122 creds.update(other_creds)
127 def get_session_auth(other_creds={}):
128 loader = loading.get_plugin_loader('password')
129 creds = get_credentials(other_creds)
130 auth = loader.load_from_options(**creds)
134 def get_endpoint(service_type, interface='public'):
135 auth = get_session_auth()
136 return get_session().get_endpoint(auth=auth,
137 service_type=service_type,
141 def get_session(other_creds={}):
142 auth = get_session_auth(other_creds)
143 https_cacert = os.getenv('OS_CACERT', '')
144 https_insecure = os.getenv('OS_INSECURE', '').lower() == 'true'
145 return session.Session(auth=auth,
146 verify=(https_cacert or not https_insecure))
149 # *********************************************
151 # *********************************************
152 def get_keystone_client_version():
153 api_version = os.getenv('OS_IDENTITY_API_VERSION')
154 if api_version is not None:
155 logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
158 return DEFAULT_API_VERSION
161 def get_keystone_client(other_creds={}):
162 sess = get_session(other_creds)
163 return keystoneclient.Client(get_keystone_client_version(),
165 interface=os.getenv('OS_INTERFACE', 'admin'))
168 def get_cinder_client_version():
169 api_version = os.getenv('OS_VOLUME_API_VERSION')
170 if api_version is not None:
171 logger.info("OS_VOLUME_API_VERSION is set in env as '%s'",
174 return DEFAULT_API_VERSION
177 def get_cinder_client(other_creds={}):
178 sess = get_session(other_creds)
179 return cinderclient.Client(get_cinder_client_version(), session=sess)
182 def get_neutron_client_version():
183 api_version = os.getenv('OS_NETWORK_API_VERSION')
184 if api_version is not None:
185 logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
188 return DEFAULT_API_VERSION
191 def get_neutron_client(other_creds={}):
192 sess = get_session(other_creds)
193 return neutronclient.Client(get_neutron_client_version(), session=sess)
196 def get_heat_client_version():
197 api_version = os.getenv('OS_ORCHESTRATION_API_VERSION')
198 if api_version is not None:
199 logger.info("OS_ORCHESTRATION_API_VERSION is set in env as '%s'",
202 return DEFAULT_HEAT_API_VERSION
205 def get_heat_client(other_creds={}):
206 sess = get_session(other_creds)
207 return heatclient.Client(get_heat_client_version(), session=sess)
210 def download_url(url, dest_path):
212 Download a file to a destination path given a URL
214 name = url.rsplit('/')[-1]
215 dest = dest_path + "/" + name
217 response = urllib.urlopen(url)
221 with open(dest, 'wb') as lfile:
222 shutil.copyfileobj(response, lfile)
226 def download_and_add_image_on_glance(conn, image_name, image_url, data_dir):
229 if not os.path.exists(dest_path):
230 os.makedirs(dest_path)
231 file_name = image_url.rsplit('/')[-1]
232 if not download_url(image_url, dest_path):
235 raise Exception("Impossible to download image from {}".format(
239 image = create_glance_image(
240 conn, image_name, dest_path + file_name)
246 raise Exception("Impossible to put image {} in glance".format(
250 # *********************************************
252 # *********************************************
253 def get_instances(conn):
255 instances = conn.compute.servers(all_tenants=1)
257 except Exception as e:
258 logger.error("Error [get_instances(compute)]: %s" % e)
262 def get_instance_status(conn, instance):
264 instance = conn.compute.get_server(instance.id)
265 return instance.status
266 except Exception as e:
267 logger.error("Error [get_instance_status(compute)]: %s" % e)
271 def get_instance_by_name(conn, instance_name):
273 instance = conn.compute.find_server(instance_name,
274 ignore_missing=False)
276 except Exception as e:
277 logger.error("Error [get_instance_by_name(compute, '%s')]: %s"
278 % (instance_name, e))
282 def get_flavor_id(conn, flavor_name):
283 flavors = conn.compute.flavors()
286 if f.name == flavor_name:
292 def get_flavor_id_by_ram_range(conn, min_ram, max_ram):
293 flavors = conn.compute.flavors()
296 if min_ram <= f.ram and f.ram <= max_ram:
302 def get_aggregates(cloud):
304 aggregates = cloud.list_aggregates()
306 except Exception as e:
307 logger.error("Error [get_aggregates(compute)]: %s" % e)
311 def get_aggregate_id(cloud, aggregate_name):
313 aggregates = get_aggregates(cloud)
314 _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
316 except Exception as e:
317 logger.error("Error [get_aggregate_id(compute, %s)]:"
318 " %s" % (aggregate_name, e))
322 def get_availability_zones(conn):
324 availability_zones = conn.compute.availability_zones()
325 return availability_zones
326 except Exception as e:
327 logger.error("Error [get_availability_zones(compute)]: %s" % e)
331 def get_availability_zone_names(conn):
333 az_names = [az.zoneName for az in get_availability_zones(conn)]
335 except Exception as e:
336 logger.error("Error [get_availability_zone_names(compute)]:"
341 def create_flavor(conn, flavor_name, ram, disk, vcpus, public=True):
343 flavor = conn.compute.create_flavor(
344 name=flavor_name, ram=ram, disk=disk, vcpus=vcpus,
346 except Exception as e:
347 logger.error("Error [create_flavor(compute, '%s', '%s', '%s', "
348 "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
353 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
354 flavor_exists = False
355 conn = get_os_connection()
357 flavor_id = get_flavor_id(conn, flavor_name)
359 logger.info("Using existing flavor '%s'..." % flavor_name)
362 logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
363 "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
364 flavor_id = create_flavor(
365 conn, flavor_name, ram, disk, vcpus, public=public)
367 raise Exception("Failed to create flavor '%s'..." % (flavor_name))
369 logger.debug("Flavor '%s' with ID=%s created successfully."
370 % (flavor_name, flavor_id))
372 return flavor_exists, flavor_id
375 def get_floating_ips(neutron_client):
377 floating_ips = neutron_client.list_floatingips()
378 return floating_ips['floatingips']
379 except Exception as e:
380 logger.error("Error [get_floating_ips(neutron_client)]: %s" % e)
384 def get_hypervisors(conn):
387 hypervisors = conn.compute.hypervisors()
388 for hypervisor in hypervisors:
389 if hypervisor.state == "up":
390 nodes.append(hypervisor.name)
392 except Exception as e:
393 logger.error("Error [get_hypervisors(compute)]: %s" % e)
397 def create_aggregate(cloud, aggregate_name, av_zone):
399 cloud.create_aggregate(aggregate_name, av_zone)
401 except Exception as e:
402 logger.error("Error [create_aggregate(compute, %s, %s)]: %s"
403 % (aggregate_name, av_zone, e))
407 def add_host_to_aggregate(cloud, aggregate_name, compute_host):
409 aggregate_id = get_aggregate_id(cloud, aggregate_name)
410 cloud.add_host_to_aggregate(aggregate_id, compute_host)
412 except Exception as e:
413 logger.error("Error [add_host_to_aggregate(compute, %s, %s)]: %s"
414 % (aggregate_name, compute_host, e))
418 def create_aggregate_with_host(
419 cloud, aggregate_name, av_zone, compute_host):
421 create_aggregate(cloud, aggregate_name, av_zone)
422 add_host_to_aggregate(cloud, aggregate_name, compute_host)
424 except Exception as e:
425 logger.error("Error [create_aggregate_with_host("
426 "compute, %s, %s, %s)]: %s"
427 % (aggregate_name, av_zone, compute_host, e))
431 def create_instance(flavor_name,
434 instance_name="functest-vm",
440 conn = get_os_connection()
442 flavor = conn.compute.find_flavor(flavor_name, ignore_missing=False)
444 flavors = [flavor.name for flavor in conn.compute.flavors()]
445 logger.error("Error: Flavor '%s' not found. Available flavors are: "
446 "\n%s" % (flavor_name, flavors))
448 if fixed_ip is not None:
449 networks = {"uuid": network_id, "fixed_ip": fixed_ip}
451 networks = {"uuid": network_id}
454 'name': instance_name,
455 'flavor_id': flavor.id,
456 'image_id': image_id,
457 'networks': [networks],
460 if userdata is not None:
461 server_attrs['config_drive'] = confdrive
462 server_attrs['user_data'] = base64.b64encode(userdata.encode())
463 if av_zone is not None:
464 server_attrs['availability_zone'] = av_zone
466 instance = conn.compute.create_server(**server_attrs)
470 def create_instance_and_wait_for_active(flavor_name,
480 VM_BOOT_TIMEOUT = 180
481 conn = get_os_connection()
482 instance = create_instance(flavor_name,
491 count = VM_BOOT_TIMEOUT / SLEEP
492 for n in range(count, -1, -1):
493 status = get_instance_status(conn, instance)
497 elif status.lower() == "active":
499 elif status.lower() == "error":
500 logger.error("The instance %s went to ERROR status."
504 logger.error("Timeout booting the instance %s." % instance_name)
508 def create_floating_ip(neutron_client):
509 extnet_id = get_external_net_id(neutron_client)
510 props = {'floating_network_id': extnet_id}
512 ip_json = neutron_client.create_floatingip({'floatingip': props})
513 fip_addr = ip_json['floatingip']['floating_ip_address']
514 fip_id = ip_json['floatingip']['id']
515 except Exception as e:
516 logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
518 return {'fip_addr': fip_addr, 'fip_id': fip_id}
521 def attach_floating_ip(neutron_client, port_id):
522 extnet_id = get_external_net_id(neutron_client)
523 props = {'floating_network_id': extnet_id,
526 return neutron_client.create_floatingip({'floatingip': props})
527 except Exception as e:
528 logger.error("Error [Attach_floating_ip(neutron_client), %s]: %s"
533 def add_floating_ip(conn, server_id, floatingip_addr):
535 conn.compute.add_floating_ip_to_server(server_id, floatingip_addr)
537 except Exception as e:
538 logger.error("Error [add_floating_ip(compute, '%s', '%s')]: %s"
539 % (server_id, floatingip_addr, e))
543 def delete_instance(conn, instance_id):
545 conn.compute.delete_server(instance_id, force=True)
547 except Exception as e:
548 logger.error("Error [delete_instance(compute, '%s')]: %s"
553 def delete_floating_ip(neutron_client, floatingip_id):
555 neutron_client.delete_floatingip(floatingip_id)
557 except Exception as e:
558 logger.error("Error [delete_floating_ip(neutron_client, '%s')]: %s"
559 % (floatingip_id, e))
563 def remove_host_from_aggregate(cloud, aggregate_name, compute_host):
565 aggregate_id = get_aggregate_id(cloud, aggregate_name)
566 cloud.remove_host_from_aggregate(aggregate_id, compute_host)
568 except Exception as e:
569 logger.error("Error [remove_host_from_aggregate(compute, %s, %s)]:"
570 " %s" % (aggregate_name, compute_host, e))
574 def remove_hosts_from_aggregate(cloud, aggregate_name):
575 aggregate_id = get_aggregate_id(cloud, aggregate_name)
576 hosts = cloud.get_aggregate(aggregate_id).hosts
578 all(remove_host_from_aggregate(cloud, aggregate_name, host)
582 def delete_aggregate(cloud, aggregate_name):
584 remove_hosts_from_aggregate(cloud, aggregate_name)
585 cloud.delete_aggregate(aggregate_name)
587 except Exception as e:
588 logger.error("Error [delete_aggregate(compute, %s)]: %s"
589 % (aggregate_name, e))
593 # *********************************************
595 # *********************************************
596 def get_network_list(neutron_client):
597 network_list = neutron_client.list_networks()['networks']
598 if len(network_list) == 0:
604 def get_router_list(neutron_client):
605 router_list = neutron_client.list_routers()['routers']
606 if len(router_list) == 0:
612 def get_port_list(neutron_client):
613 port_list = neutron_client.list_ports()['ports']
614 if len(port_list) == 0:
620 def get_network_id(neutron_client, network_name):
621 networks = neutron_client.list_networks()['networks']
624 if n['name'] == network_name:
630 def get_subnet_id(neutron_client, subnet_name):
631 subnets = neutron_client.list_subnets()['subnets']
634 if s['name'] == subnet_name:
640 def get_router_id(neutron_client, router_name):
641 routers = neutron_client.list_routers()['routers']
644 if r['name'] == router_name:
650 def get_private_net(neutron_client):
651 # Checks if there is an existing shared private network
652 networks = neutron_client.list_networks()['networks']
653 if len(networks) == 0:
656 if (net['router:external'] is False) and (net['shared'] is True):
661 def get_external_net(neutron_client):
662 if (env.get('EXTERNAL_NETWORK')):
663 return env.get('EXTERNAL_NETWORK')
664 for network in neutron_client.list_networks()['networks']:
665 if network['router:external']:
666 return network['name']
670 def get_external_net_id(neutron_client):
671 if (env.get('EXTERNAL_NETWORK')):
672 networks = neutron_client.list_networks(
673 name=env.get('EXTERNAL_NETWORK'))
674 net_id = networks['networks'][0]['id']
676 for network in neutron_client.list_networks()['networks']:
677 if network['router:external']:
682 def check_neutron_net(neutron_client, net_name):
683 for network in neutron_client.list_networks()['networks']:
684 if network['name'] == net_name:
685 for subnet in network['subnets']:
690 def create_neutron_net(neutron_client, name):
691 json_body = {'network': {'name': name,
692 'admin_state_up': True}}
694 network = neutron_client.create_network(body=json_body)
695 network_dict = network['network']
696 return network_dict['id']
697 except Exception as e:
698 logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
703 def create_neutron_subnet(neutron_client, name, cidr, net_id,
704 dns=['8.8.8.8', '8.8.4.4']):
705 json_body = {'subnets': [{'name': name, 'cidr': cidr,
706 'ip_version': 4, 'network_id': net_id,
707 'dns_nameservers': dns}]}
710 subnet = neutron_client.create_subnet(body=json_body)
711 return subnet['subnets'][0]['id']
712 except Exception as e:
713 logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
714 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
718 def create_neutron_router(neutron_client, name):
719 json_body = {'router': {'name': name, 'admin_state_up': True}}
721 router = neutron_client.create_router(json_body)
722 return router['router']['id']
723 except Exception as e:
724 logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
729 def create_neutron_port(neutron_client, name, network_id, ip):
730 json_body = {'port': {
731 'admin_state_up': True,
733 'network_id': network_id,
734 'fixed_ips': [{"ip_address": ip}]
737 port = neutron_client.create_port(body=json_body)
738 return port['port']['id']
739 except Exception as e:
740 logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
741 "'%s')]: %s" % (name, network_id, ip, e))
745 def update_neutron_net(neutron_client, network_id, shared=False):
746 json_body = {'network': {'shared': shared}}
748 neutron_client.update_network(network_id, body=json_body)
750 except Exception as e:
751 logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
752 "%s" % (network_id, str(shared), e))
756 def update_neutron_port(neutron_client, port_id, device_owner):
757 json_body = {'port': {
758 'device_owner': device_owner,
761 port = neutron_client.update_port(port=port_id,
763 return port['port']['id']
764 except Exception as e:
765 logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
766 " %s" % (port_id, device_owner, e))
770 def add_interface_router(neutron_client, router_id, subnet_id):
771 json_body = {"subnet_id": subnet_id}
773 neutron_client.add_interface_router(router=router_id, body=json_body)
775 except Exception as e:
776 logger.error("Error [add_interface_router(neutron_client, '%s', "
777 "'%s')]: %s" % (router_id, subnet_id, e))
781 def add_gateway_router(neutron_client, router_id):
782 ext_net_id = get_external_net_id(neutron_client)
783 router_dict = {'network_id': ext_net_id}
785 neutron_client.add_gateway_router(router_id, router_dict)
787 except Exception as e:
788 logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
793 def delete_neutron_net(neutron_client, network_id):
795 neutron_client.delete_network(network_id)
797 except Exception as e:
798 logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
803 def delete_neutron_subnet(neutron_client, subnet_id):
805 neutron_client.delete_subnet(subnet_id)
807 except Exception as e:
808 logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
813 def delete_neutron_router(neutron_client, router_id):
815 neutron_client.delete_router(router=router_id)
817 except Exception as e:
818 logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
823 def delete_neutron_port(neutron_client, port_id):
825 neutron_client.delete_port(port_id)
827 except Exception as e:
828 logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
833 def remove_interface_router(neutron_client, router_id, subnet_id):
834 json_body = {"subnet_id": subnet_id}
836 neutron_client.remove_interface_router(router=router_id,
839 except Exception as e:
840 logger.error("Error [remove_interface_router(neutron_client, '%s', "
841 "'%s')]: %s" % (router_id, subnet_id, e))
845 def remove_gateway_router(neutron_client, router_id):
847 neutron_client.remove_gateway_router(router_id)
849 except Exception as e:
850 logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
855 def create_network_full(neutron_client,
860 dns=['8.8.8.8', '8.8.4.4']):
862 # Check if the network already exists
863 network_id = get_network_id(neutron_client, net_name)
864 subnet_id = get_subnet_id(neutron_client, subnet_name)
865 router_id = get_router_id(neutron_client, router_name)
867 if network_id != '' and subnet_id != '' and router_id != '':
868 logger.info("A network with name '%s' already exists..." % net_name)
870 neutron_client.format = 'json'
872 logger.info('Creating neutron network %s...' % net_name)
874 network_id = create_neutron_net(neutron_client, net_name)
877 logger.debug("Network '%s' created successfully" % network_id)
879 logger.debug('Creating Subnet....')
881 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
882 cidr, network_id, dns)
885 logger.debug("Subnet '%s' created successfully" % subnet_id)
887 logger.debug('Creating Router...')
889 router_id = create_neutron_router(neutron_client, router_name)
892 logger.debug("Router '%s' created successfully" % router_id)
894 logger.debug('Adding router to subnet...')
896 if not add_interface_router(neutron_client, router_id, subnet_id):
898 logger.debug("Interface added successfully.")
900 logger.debug('Adding gateway to router...')
901 if not add_gateway_router(neutron_client, router_id):
903 logger.debug("Gateway added successfully.")
905 network_dic = {'net_id': network_id,
906 'subnet_id': subnet_id,
907 'router_id': router_id}
911 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
912 neutron_client = get_neutron_client()
914 network_dic = create_network_full(neutron_client,
920 if not update_neutron_net(neutron_client,
921 network_dic['net_id'],
923 logger.error("Failed to update network %s..." % net_name)
926 logger.debug("Network '%s' is available..." % net_name)
928 logger.error("Network %s creation failed" % net_name)
933 # *********************************************
935 # *********************************************
938 def get_security_groups(neutron_client):
940 security_groups = neutron_client.list_security_groups()[
942 return security_groups
943 except Exception as e:
944 logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
948 def get_security_group_id(neutron_client, sg_name):
949 security_groups = get_security_groups(neutron_client)
951 for sg in security_groups:
952 if sg['name'] == sg_name:
958 def create_security_group(neutron_client, sg_name, sg_description):
959 json_body = {'security_group': {'name': sg_name,
960 'description': sg_description}}
962 secgroup = neutron_client.create_security_group(json_body)
963 return secgroup['security_group']
964 except Exception as e:
965 logger.error("Error [create_security_group(neutron_client, '%s', "
966 "'%s')]: %s" % (sg_name, sg_description, e))
970 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
971 port_range_min=None, port_range_max=None):
972 # We create a security group in 2 steps
973 # 1 - we check the format and set the json body accordingly
974 # 2 - we call neturon client to create the security group
977 json_body = {'security_group_rule': {'direction': direction,
978 'security_group_id': sg_id,
979 'protocol': protocol}}
981 # - both None => we do nothing
982 # - both Not None => we add them to the json description
983 # but one cannot be None is the other is not None
984 if (port_range_min is not None and port_range_max is not None):
985 # add port_range in json description
986 json_body['security_group_rule']['port_range_min'] = port_range_min
987 json_body['security_group_rule']['port_range_max'] = port_range_max
988 logger.debug("Security_group format set (port range included)")
990 # either both port range are set to None => do nothing
991 # or one is set but not the other => log it and return False
992 if port_range_min is None and port_range_max is None:
993 logger.debug("Security_group format set (no port range mentioned)")
995 logger.error("Bad security group format."
996 "One of the port range is not properly set:"
998 "range max: {}".format(port_range_min,
1002 # Create security group using neutron client
1004 neutron_client.create_security_group_rule(json_body)
1007 logger.exception("Impossible to create_security_group_rule,"
1008 "security group rule probably already exists")
1012 def get_security_group_rules(neutron_client, sg_id):
1014 security_rules = neutron_client.list_security_group_rules()[
1015 'security_group_rules']
1016 security_rules = [rule for rule in security_rules
1017 if rule["security_group_id"] == sg_id]
1018 return security_rules
1019 except Exception as e:
1020 logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:"
1025 def check_security_group_rules(neutron_client, sg_id, direction, protocol,
1026 port_min=None, port_max=None):
1028 security_rules = get_security_group_rules(neutron_client, sg_id)
1029 security_rules = [rule for rule in security_rules
1030 if (rule["direction"].lower() == direction and
1031 rule["protocol"].lower() == protocol and
1032 rule["port_range_min"] == port_min and
1033 rule["port_range_max"] == port_max)]
1034 if len(security_rules) == 0:
1038 except Exception as e:
1039 logger.error("Error [check_security_group_rules("
1040 " neutron_client, sg_id, direction,"
1041 " protocol, port_min=None, port_max=None)]: "
1046 def create_security_group_full(neutron_client,
1047 sg_name, sg_description):
1048 sg_id = get_security_group_id(neutron_client, sg_name)
1050 logger.info("Using existing security group '%s'..." % sg_name)
1052 logger.info("Creating security group '%s'..." % sg_name)
1053 SECGROUP = create_security_group(neutron_client,
1057 logger.error("Failed to create the security group...")
1060 sg_id = SECGROUP['id']
1062 logger.debug("Security group '%s' with ID=%s created successfully."
1063 % (SECGROUP['name'], sg_id))
1065 logger.debug("Adding ICMP rules in security group '%s'..."
1067 if not create_secgroup_rule(neutron_client, sg_id,
1069 logger.error("Failed to create the security group rule...")
1072 logger.debug("Adding SSH rules in security group '%s'..."
1074 if not create_secgroup_rule(
1075 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1076 logger.error("Failed to create the security group rule...")
1079 if not create_secgroup_rule(
1080 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1081 logger.error("Failed to create the security group rule...")
1086 def add_secgroup_to_instance(conn, instance_id, secgroup_id):
1088 conn.compute.add_security_group_to_server(instance_id, secgroup_id)
1090 except Exception as e:
1091 logger.error("Error [add_secgroup_to_instance(compute, '%s', "
1092 "'%s')]: %s" % (instance_id, secgroup_id, e))
1096 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1097 json_body = {"quota": {
1098 "security_group": sg_quota,
1099 "security_group_rule": sg_rule_quota
1103 neutron_client.update_quota(tenant_id=tenant_id,
1106 except Exception as e:
1107 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1108 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1112 def delete_security_group(neutron_client, secgroup_id):
1114 neutron_client.delete_security_group(secgroup_id)
1116 except Exception as e:
1117 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1122 # *********************************************
1124 # *********************************************
1125 def get_images(conn):
1127 images = conn.image.images()
1129 except Exception as e:
1130 logger.error("Error [get_images]: %s" % e)
1134 def get_image_id(conn, image_name):
1135 images = conn.image.images()
1138 if i.name == image_name:
1144 def create_glance_image(conn,
1148 extra_properties={},
1151 if not os.path.isfile(file_path):
1152 logger.error("Error: file %s does not exist." % file_path)
1155 image_id = get_image_id(conn, image_name)
1157 logger.info("Image %s already exists." % image_name)
1159 logger.info("Creating image '%s' from '%s'..." % (image_name,
1161 with open(file_path) as image_data:
1162 image = conn.image.upload_image(name=image_name,
1165 container_format=container,
1170 except Exception as e:
1171 logger.error("Error [create_glance_image(image, '%s', '%s', "
1172 "'%s')]: %s" % (image_name, file_path, public, e))
1176 def get_or_create_image(name, path, format, extra_properties):
1177 image_exists = False
1178 conn = get_os_connection()
1180 image_id = get_image_id(conn, name)
1182 logger.info("Using existing image '%s'..." % name)
1185 logger.info("Creating image '%s' from '%s'..." % (name, path))
1186 image_id = create_glance_image(conn,
1192 logger.error("Failed to create a Glance image...")
1194 logger.debug("Image '%s' with ID=%s created successfully."
1197 return image_exists, image_id
1200 def delete_glance_image(conn, image_id):
1202 conn.image.delete_image(image_id)
1204 except Exception as e:
1205 logger.error("Error [delete_glance_image(image, '%s')]: %s"
1210 # *********************************************
1212 # *********************************************
1213 def get_volumes(cinder_client):
1215 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1217 except Exception as e:
1218 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1222 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1223 snapshots_quota, gigabytes_quota):
1224 quotas_values = {"volumes": vols_quota,
1225 "snapshots": snapshots_quota,
1226 "gigabytes": gigabytes_quota}
1229 cinder_client.quotas.update(tenant_id, **quotas_values)
1231 except Exception as e:
1232 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1233 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1234 snapshots_quota, gigabytes_quota, e))
1238 def delete_volume(cinder_client, volume_id, forced=False):
1242 cinder_client.volumes.detach(volume_id)
1244 logger.error(sys.exc_info()[0])
1245 cinder_client.volumes.force_delete(volume_id)
1247 cinder_client.volumes.delete(volume_id)
1249 except Exception as e:
1250 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1251 % (volume_id, str(forced), e))
1255 # *********************************************
1257 # *********************************************
1258 def get_tenants(keystone_client):
1260 if is_keystone_v3():
1261 tenants = keystone_client.projects.list()
1263 tenants = keystone_client.tenants.list()
1265 except Exception as e:
1266 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1270 def get_users(keystone_client):
1272 users = keystone_client.users.list()
1274 except Exception as e:
1275 logger.error("Error [get_users(keystone_client)]: %s" % e)
1279 def get_tenant_id(keystone_client, tenant_name):
1280 tenants = get_tenants(keystone_client)
1283 if t.name == tenant_name:
1289 def get_user_id(keystone_client, user_name):
1290 users = get_users(keystone_client)
1293 if u.name == user_name:
1299 def get_role_id(keystone_client, role_name):
1300 roles = keystone_client.roles.list()
1303 if r.name == role_name:
1309 def get_domain_id(keystone_client, domain_name):
1310 domains = keystone_client.domains.list()
1313 if d.name == domain_name:
1319 def create_tenant(keystone_client, tenant_name, tenant_description):
1321 if is_keystone_v3():
1322 domain_name = os.environ['OS_PROJECT_DOMAIN_NAME']
1323 domain_id = get_domain_id(keystone_client, domain_name)
1324 tenant = keystone_client.projects.create(
1326 description=tenant_description,
1330 tenant = keystone_client.tenants.create(tenant_name,
1334 except Exception as e:
1335 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1336 % (tenant_name, tenant_description, e))
1340 def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
1341 tenant_id = get_tenant_id(keystone_client, tenant_name)
1343 tenant_id = create_tenant(keystone_client, tenant_name,
1349 def get_or_create_tenant_for_vnf(keystone_client, tenant_name,
1350 tenant_description):
1351 """Get or Create a Tenant
1354 keystone_client: keystone client reference
1355 tenant_name: the name of the tenant
1356 tenant_description: the description of the tenant
1358 return False if tenant retrieved though get
1359 return True if tenant created
1360 raise Exception if error during processing
1363 tenant_id = get_tenant_id(keystone_client, tenant_name)
1365 tenant_id = create_tenant(keystone_client, tenant_name,
1371 raise Exception("Impossible to create a Tenant for the VNF {}".format(
1375 def create_user(keystone_client, user_name, user_password,
1376 user_email, tenant_id):
1378 if is_keystone_v3():
1379 user = keystone_client.users.create(name=user_name,
1380 password=user_password,
1382 project_id=tenant_id,
1385 user = keystone_client.users.create(user_name,
1391 except Exception as e:
1392 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1393 "'%s')]: %s" % (user_name, user_password,
1394 user_email, tenant_id, e))
1398 def get_or_create_user(keystone_client, user_name, user_password,
1399 tenant_id, user_email=None):
1400 user_id = get_user_id(keystone_client, user_name)
1402 user_id = create_user(keystone_client, user_name, user_password,
1403 user_email, tenant_id)
1407 def get_or_create_user_for_vnf(keystone_client, vnf_ref):
1408 """Get or Create user for VNF
1411 keystone_client: keystone client reference
1412 vnf_ref: VNF reference used as user name & password, tenant name
1414 return False if user retrieved through get
1415 return True if user created
1416 raise Exception if error during processing
1419 user_id = get_user_id(keystone_client, vnf_ref)
1420 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1423 user_id = create_user(keystone_client, vnf_ref, vnf_ref,
1427 role_id = get_role_id(keystone_client, 'admin')
1428 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1429 add_role_user(keystone_client, user_id, role_id, tenant_id)
1431 logger.warn("Cannot associate user to role admin on tenant")
1434 raise Exception("Impossible to create a user for the VNF {}".format(
1438 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1440 if is_keystone_v3():
1441 keystone_client.roles.grant(role=role_id,
1445 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1447 except Exception as e:
1448 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1449 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1453 def delete_tenant(keystone_client, tenant_id):
1455 if is_keystone_v3():
1456 keystone_client.projects.delete(tenant_id)
1458 keystone_client.tenants.delete(tenant_id)
1460 except Exception as e:
1461 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1466 def delete_user(keystone_client, user_id):
1468 keystone_client.users.delete(user_id)
1470 except Exception as e:
1471 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1476 # *********************************************
1478 # *********************************************
1479 def get_resource(heat_client, stack_id, resource):
1481 resources = heat_client.resources.get(stack_id, resource)
1483 except Exception as e:
1484 logger.error("Error [get_resource]: %s" % e)