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 keystoneclient import client as keystoneclient
22 from neutronclient.neutron import client as neutronclient
23 from openstack import connection
24 from openstack import cloud as os_cloud
25 from openstack.exceptions import ResourceNotFound
27 from functest.utils import env
29 logger = logging.getLogger(__name__)
31 DEFAULT_API_VERSION = '2'
34 # *********************************************
36 # *********************************************
37 class MissingEnvVar(Exception):
39 def __init__(self, var):
43 return str.format("Please set the mandatory env var: {}", self.var)
46 def get_os_connection():
47 return connection.from_config()
51 return os_cloud.openstack_cloud()
55 keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
56 if (keystone_api_version is None or
57 keystone_api_version == '2'):
63 def get_rc_env_vars():
64 env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD']
66 env_vars.extend(['OS_PROJECT_NAME',
67 'OS_USER_DOMAIN_NAME',
68 'OS_PROJECT_DOMAIN_NAME'])
70 env_vars.extend(['OS_TENANT_NAME'])
74 def check_credentials():
76 Check if the OpenStack credentials (openrc) are sourced
78 env_vars = get_rc_env_vars()
79 return all(map(lambda v: v in os.environ and os.environ[v], env_vars))
82 def get_env_cred_dict():
84 'OS_USERNAME': 'username',
85 'OS_PASSWORD': 'password',
86 'OS_AUTH_URL': 'auth_url',
87 'OS_TENANT_NAME': 'tenant_name',
88 'OS_USER_DOMAIN_NAME': 'user_domain_name',
89 'OS_PROJECT_DOMAIN_NAME': 'project_domain_name',
90 'OS_PROJECT_NAME': 'project_name',
91 'OS_ENDPOINT_TYPE': 'endpoint_type',
92 'OS_REGION_NAME': 'region_name',
93 'OS_CACERT': 'https_cacert',
94 'OS_INSECURE': 'https_insecure'
99 def get_credentials(other_creds={}):
100 """Returns a creds dictionary filled with parsed from env
103 env_vars = get_rc_env_vars()
104 env_cred_dict = get_env_cred_dict()
106 for envvar in env_vars:
107 if os.getenv(envvar) is None:
108 raise MissingEnvVar(envvar)
110 creds_key = env_cred_dict.get(envvar)
111 creds.update({creds_key: os.getenv(envvar)})
113 if 'tenant' in other_creds.keys():
115 tenant = 'project_name'
117 tenant = 'tenant_name'
118 other_creds[tenant] = other_creds.pop('tenant')
120 creds.update(other_creds)
125 def get_session_auth(other_creds={}):
126 loader = loading.get_plugin_loader('password')
127 creds = get_credentials(other_creds)
128 auth = loader.load_from_options(**creds)
132 def get_endpoint(service_type, interface='public'):
133 auth = get_session_auth()
134 return get_session().get_endpoint(auth=auth,
135 service_type=service_type,
139 def get_session(other_creds={}):
140 auth = get_session_auth(other_creds)
141 https_cacert = os.getenv('OS_CACERT', '')
142 https_insecure = os.getenv('OS_INSECURE', '').lower() == 'true'
143 return session.Session(auth=auth,
144 verify=(https_cacert or not https_insecure))
147 # *********************************************
149 # *********************************************
150 def get_keystone_client_version():
151 api_version = os.getenv('OS_IDENTITY_API_VERSION')
152 if api_version is not None:
153 logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
156 return DEFAULT_API_VERSION
159 def get_keystone_client(other_creds={}):
160 sess = get_session(other_creds)
161 return keystoneclient.Client(get_keystone_client_version(),
163 interface=os.getenv('OS_INTERFACE', 'admin'))
166 def get_neutron_client_version():
167 api_version = os.getenv('OS_NETWORK_API_VERSION')
168 if api_version is not None:
169 logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
172 return DEFAULT_API_VERSION
175 def get_neutron_client(other_creds={}):
176 sess = get_session(other_creds)
177 return neutronclient.Client(get_neutron_client_version(), session=sess)
180 def download_url(url, dest_path):
182 Download a file to a destination path given a URL
184 name = url.rsplit('/')[-1]
185 dest = dest_path + "/" + name
187 response = urllib.urlopen(url)
191 with open(dest, 'wb') as lfile:
192 shutil.copyfileobj(response, lfile)
196 def download_and_add_image_on_glance(conn, image_name, image_url, data_dir):
199 if not os.path.exists(dest_path):
200 os.makedirs(dest_path)
201 file_name = image_url.rsplit('/')[-1]
202 if not download_url(image_url, dest_path):
205 raise Exception("Impossible to download image from {}".format(
209 image = create_glance_image(
210 conn, image_name, dest_path + file_name)
216 raise Exception("Impossible to put image {} in glance".format(
220 # *********************************************
222 # *********************************************
223 def get_instances(conn):
225 instances = conn.compute.servers(all_tenants=1)
227 except Exception as e:
228 logger.error("Error [get_instances(compute)]: %s" % e)
232 def get_instance_status(conn, instance):
234 instance = conn.compute.get_server(instance.id)
235 return instance.status
236 except Exception as e:
237 logger.error("Error [get_instance_status(compute)]: %s" % e)
241 def get_instance_by_name(conn, instance_name):
243 instance = conn.compute.find_server(instance_name,
244 ignore_missing=False)
246 except Exception as e:
247 logger.error("Error [get_instance_by_name(compute, '%s')]: %s"
248 % (instance_name, e))
252 def get_flavor_id(conn, flavor_name):
253 flavors = conn.compute.flavors()
256 if f.name == flavor_name:
262 def get_flavor_id_by_ram_range(conn, min_ram, max_ram):
263 flavors = conn.compute.flavors()
266 if min_ram <= f.ram and f.ram <= max_ram:
272 def get_aggregates(cloud):
274 aggregates = cloud.list_aggregates()
276 except Exception as e:
277 logger.error("Error [get_aggregates(compute)]: %s" % e)
281 def get_aggregate_id(cloud, aggregate_name):
283 aggregates = get_aggregates(cloud)
284 _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
286 except Exception as e:
287 logger.error("Error [get_aggregate_id(compute, %s)]:"
288 " %s" % (aggregate_name, e))
292 def get_availability_zones(conn):
294 availability_zones = conn.compute.availability_zones()
295 return availability_zones
296 except Exception as e:
297 logger.error("Error [get_availability_zones(compute)]: %s" % e)
301 def get_availability_zone_names(conn):
303 az_names = [az.zoneName for az in get_availability_zones(conn)]
305 except Exception as e:
306 logger.error("Error [get_availability_zone_names(compute)]:"
311 def create_flavor(conn, flavor_name, ram, disk, vcpus, public=True):
313 flavor = conn.compute.create_flavor(
314 name=flavor_name, ram=ram, disk=disk, vcpus=vcpus,
316 except Exception as e:
317 logger.error("Error [create_flavor(compute, '%s', '%s', '%s', "
318 "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
323 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
324 flavor_exists = False
325 conn = get_os_connection()
327 flavor_id = get_flavor_id(conn, flavor_name)
329 logger.info("Using existing flavor '%s'..." % flavor_name)
332 logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
333 "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
334 flavor_id = create_flavor(
335 conn, flavor_name, ram, disk, vcpus, public=public)
337 raise Exception("Failed to create flavor '%s'..." % (flavor_name))
339 logger.debug("Flavor '%s' with ID=%s created successfully."
340 % (flavor_name, flavor_id))
342 return flavor_exists, flavor_id
345 def get_floating_ips(conn):
347 floating_ips = conn.network.ips()
349 except Exception as e:
350 logger.error("Error [get_floating_ips(network)]: %s" % e)
354 def get_hypervisors(conn):
357 hypervisors = conn.compute.hypervisors()
358 for hypervisor in hypervisors:
359 if hypervisor.state == "up":
360 nodes.append(hypervisor.name)
362 except Exception as e:
363 logger.error("Error [get_hypervisors(compute)]: %s" % e)
367 def create_aggregate(cloud, aggregate_name, av_zone):
369 cloud.create_aggregate(aggregate_name, av_zone)
371 except Exception as e:
372 logger.error("Error [create_aggregate(compute, %s, %s)]: %s"
373 % (aggregate_name, av_zone, e))
377 def add_host_to_aggregate(cloud, aggregate_name, compute_host):
379 aggregate_id = get_aggregate_id(cloud, aggregate_name)
380 cloud.add_host_to_aggregate(aggregate_id, compute_host)
382 except Exception as e:
383 logger.error("Error [add_host_to_aggregate(compute, %s, %s)]: %s"
384 % (aggregate_name, compute_host, e))
388 def create_aggregate_with_host(
389 cloud, aggregate_name, av_zone, compute_host):
391 create_aggregate(cloud, aggregate_name, av_zone)
392 add_host_to_aggregate(cloud, aggregate_name, compute_host)
394 except Exception as e:
395 logger.error("Error [create_aggregate_with_host("
396 "compute, %s, %s, %s)]: %s"
397 % (aggregate_name, av_zone, compute_host, e))
401 def create_instance(flavor_name,
404 instance_name="functest-vm",
410 conn = get_os_connection()
412 flavor = conn.compute.find_flavor(flavor_name, ignore_missing=False)
414 flavors = [flavor.name for flavor in conn.compute.flavors()]
415 logger.error("Error: Flavor '%s' not found. Available flavors are: "
416 "\n%s" % (flavor_name, flavors))
418 if fixed_ip is not None:
419 networks = {"uuid": network_id, "fixed_ip": fixed_ip}
421 networks = {"uuid": network_id}
424 'name': instance_name,
425 'flavor_id': flavor.id,
426 'image_id': image_id,
427 'networks': [networks],
430 if userdata is not None:
431 server_attrs['config_drive'] = confdrive
432 server_attrs['user_data'] = base64.b64encode(userdata.encode())
433 if av_zone is not None:
434 server_attrs['availability_zone'] = av_zone
436 instance = conn.compute.create_server(**server_attrs)
440 def create_instance_and_wait_for_active(flavor_name,
450 VM_BOOT_TIMEOUT = 180
451 conn = get_os_connection()
452 instance = create_instance(flavor_name,
461 count = VM_BOOT_TIMEOUT / SLEEP
462 for n in range(count, -1, -1):
463 status = get_instance_status(conn, instance)
467 elif status.lower() == "active":
469 elif status.lower() == "error":
470 logger.error("The instance %s went to ERROR status."
474 logger.error("Timeout booting the instance %s." % instance_name)
478 def create_floating_ip(conn):
479 extnet_id = get_external_net_id(conn)
481 fip = conn.network.create_ip(floating_network_id=extnet_id)
482 fip_addr = fip.floating_ip_address
484 except Exception as e:
485 logger.error("Error [create_floating_ip(network)]: %s" % e)
487 return {'fip_addr': fip_addr, 'fip_id': fip_id}
490 def attach_floating_ip(conn, port_id):
491 extnet_id = get_external_net_id(conn)
493 return conn.network.create_ip(floating_network_id=extnet_id,
495 except Exception as e:
496 logger.error("Error [Attach_floating_ip(network), %s]: %s"
501 def add_floating_ip(conn, server_id, floatingip_addr):
503 conn.compute.add_floating_ip_to_server(server_id, floatingip_addr)
505 except Exception as e:
506 logger.error("Error [add_floating_ip(compute, '%s', '%s')]: %s"
507 % (server_id, floatingip_addr, e))
511 def delete_instance(conn, instance_id):
513 conn.compute.delete_server(instance_id, force=True)
515 except Exception as e:
516 logger.error("Error [delete_instance(compute, '%s')]: %s"
521 def delete_floating_ip(conn, floatingip_id):
523 conn.network.delete_ip(floatingip_id)
525 except Exception as e:
526 logger.error("Error [delete_floating_ip(network, '%s')]: %s"
527 % (floatingip_id, e))
531 def remove_host_from_aggregate(cloud, aggregate_name, compute_host):
533 aggregate_id = get_aggregate_id(cloud, aggregate_name)
534 cloud.remove_host_from_aggregate(aggregate_id, compute_host)
536 except Exception as e:
537 logger.error("Error [remove_host_from_aggregate(compute, %s, %s)]:"
538 " %s" % (aggregate_name, compute_host, e))
542 def remove_hosts_from_aggregate(cloud, aggregate_name):
543 aggregate_id = get_aggregate_id(cloud, aggregate_name)
544 hosts = cloud.get_aggregate(aggregate_id).hosts
546 all(remove_host_from_aggregate(cloud, aggregate_name, host)
550 def delete_aggregate(cloud, aggregate_name):
552 remove_hosts_from_aggregate(cloud, aggregate_name)
553 cloud.delete_aggregate(aggregate_name)
555 except Exception as e:
556 logger.error("Error [delete_aggregate(compute, %s)]: %s"
557 % (aggregate_name, e))
561 # *********************************************
563 # *********************************************
564 def get_network_list(conn):
565 return conn.network.networks()
568 def get_router_list(conn):
569 return conn.network.routers()
572 def get_port_list(conn):
573 return conn.network.ports()
576 def get_network_id(conn, network_name):
577 networks = conn.network.networks()
580 if n.name == network_name:
586 def get_subnet_id(conn, subnet_name):
587 subnets = conn.network.subnets()
590 if s.name == subnet_name:
596 def get_router_id(conn, router_name):
597 routers = conn.network.routers()
600 if r.name == router_name:
606 def get_private_net(conn):
607 # Checks if there is an existing shared private network
608 networks = conn.network.networks()
610 if (net.is_router_external is False) and (net.is_shared is True):
615 def get_external_net(conn):
616 if (env.get('EXTERNAL_NETWORK')):
617 return env.get('EXTERNAL_NETWORK')
618 for network in conn.network.networks():
619 if network.is_router_external:
624 def get_external_net_id(conn):
625 if (env.get('EXTERNAL_NETWORK')):
626 networks = conn.network.networks(name=env.get('EXTERNAL_NETWORK'))
627 net_id = networks.next().id
629 for network in conn.network.networks():
630 if network.is_router_external:
635 def check_neutron_net(conn, net_name):
636 for network in conn.network.networks():
637 if network.name == net_name:
638 for subnet in network.subnet_ids:
643 def create_neutron_net(conn, name):
645 network = conn.network.create_network(name=name)
647 except Exception as e:
648 logger.error("Error [create_neutron_net(network, '%s')]: %s"
653 def create_neutron_subnet(conn, name, cidr, net_id,
654 dns=['8.8.8.8', '8.8.4.4']):
656 subnet = conn.network.create_subnet(name=name,
662 except Exception as e:
663 logger.error("Error [create_neutron_subnet(network, '%s', "
664 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
668 def create_neutron_router(conn, name):
670 router = conn.network.create_router(name=name)
672 except Exception as e:
673 logger.error("Error [create_neutron_router(network, '%s')]: %s"
678 def create_neutron_port(conn, name, network_id, ip):
680 port = conn.network.create_port(name=name,
681 network_id=network_id,
682 fixed_ips=[{'ip_address': ip}])
684 except Exception as e:
685 logger.error("Error [create_neutron_port(network, '%s', '%s', "
686 "'%s')]: %s" % (name, network_id, ip, e))
690 def update_neutron_net(conn, network_id, shared=False):
692 conn.network.update_network(network_id, is_shared=shared)
694 except Exception as e:
695 logger.error("Error [update_neutron_net(network, '%s', '%s')]: "
696 "%s" % (network_id, str(shared), e))
700 def update_neutron_port(conn, port_id, device_owner):
702 port = conn.network.update_port(port_id, device_owner=device_owner)
704 except Exception as e:
705 logger.error("Error [update_neutron_port(network, '%s', '%s')]:"
706 " %s" % (port_id, device_owner, e))
710 def add_interface_router(conn, router_id, subnet_id):
712 conn.network.add_interface_to_router(router_id, subnet_id=subnet_id)
714 except Exception as e:
715 logger.error("Error [add_interface_router(network, '%s', "
716 "'%s')]: %s" % (router_id, subnet_id, e))
720 def add_gateway_router(conn, router_id):
721 ext_net_id = get_external_net_id(conn)
722 router_dict = {'network_id': ext_net_id}
724 conn.network.update_router(router_id,
725 external_gateway_info=router_dict)
727 except Exception as e:
728 logger.error("Error [add_gateway_router(network, '%s')]: %s"
733 def delete_neutron_net(conn, network_id):
735 conn.network.delete_network(network_id, ignore_missing=False)
737 except Exception as e:
738 logger.error("Error [delete_neutron_net(network, '%s')]: %s"
743 def delete_neutron_subnet(conn, subnet_id):
745 conn.network.delete_subnet(subnet_id, ignore_missing=False)
747 except Exception as e:
748 logger.error("Error [delete_neutron_subnet(network, '%s')]: %s"
753 def delete_neutron_router(conn, router_id):
755 conn.network.delete_router(router_id, ignore_missing=False)
757 except Exception as e:
758 logger.error("Error [delete_neutron_router(network, '%s')]: %s"
763 def delete_neutron_port(conn, port_id):
765 conn.network.delete_port(port_id, ignore_missing=False)
767 except Exception as e:
768 logger.error("Error [delete_neutron_port(network, '%s')]: %s"
773 def remove_interface_router(conn, router_id, subnet_id):
775 conn.network.remove_interface_from_router(router_id,
778 except Exception as e:
779 logger.error("Error [remove_interface_router(network, '%s', "
780 "'%s')]: %s" % (router_id, subnet_id, e))
784 def remove_gateway_router(conn, router_id):
786 conn.network.update_router(router_id, external_gateway_info=None)
788 except Exception as e:
789 logger.error("Error [remove_gateway_router(network, '%s')]: %s"
794 def create_network_full(conn,
799 dns=['8.8.8.8', '8.8.4.4']):
801 # Check if the network already exists
802 network_id = get_network_id(conn, net_name)
803 subnet_id = get_subnet_id(conn, subnet_name)
804 router_id = get_router_id(conn, router_name)
806 if network_id != '' and subnet_id != '' and router_id != '':
807 logger.info("A network with name '%s' already exists..." % net_name)
809 logger.info('Creating neutron network %s...' % net_name)
811 network_id = create_neutron_net(conn, net_name)
814 logger.debug("Network '%s' created successfully" % network_id)
816 logger.debug('Creating Subnet....')
818 subnet_id = create_neutron_subnet(conn, subnet_name, cidr,
822 logger.debug("Subnet '%s' created successfully" % subnet_id)
824 logger.debug('Creating Router...')
826 router_id = create_neutron_router(conn, router_name)
829 logger.debug("Router '%s' created successfully" % router_id)
831 logger.debug('Adding router to subnet...')
833 if not add_interface_router(conn, router_id, subnet_id):
835 logger.debug("Interface added successfully.")
837 logger.debug('Adding gateway to router...')
838 if not add_gateway_router(conn, router_id):
840 logger.debug("Gateway added successfully.")
842 network_dic = {'net_id': network_id,
843 'subnet_id': subnet_id,
844 'router_id': router_id}
848 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
849 conn = get_os_connection()
851 network_dic = create_network_full(conn,
857 if not update_neutron_net(conn,
858 network_dic['net_id'],
860 logger.error("Failed to update network %s..." % net_name)
863 logger.debug("Network '%s' is available..." % net_name)
865 logger.error("Network %s creation failed" % net_name)
870 # *********************************************
872 # *********************************************
875 def get_security_groups(conn):
876 return conn.network.security_groups()
879 def get_security_group_id(conn, sg_name):
880 security_groups = get_security_groups(conn)
882 for sg in security_groups:
883 if sg.name == sg_name:
889 def create_security_group(conn, sg_name, sg_description):
891 secgroup = conn.network.\
892 create_security_group(name=sg_name, description=sg_description)
894 except Exception as e:
895 logger.error("Error [create_security_group(network, '%s', "
896 "'%s')]: %s" % (sg_name, sg_description, e))
900 def create_secgroup_rule(conn, sg_id, direction, protocol,
901 port_range_min=None, port_range_max=None):
902 # We create a security group in 2 steps
903 # 1 - we check the format and set the secgroup rule attributes accordingly
904 # 2 - we call openstacksdk to create the security group
907 secgroup_rule_attrs = {'direction': direction,
908 'security_group_id': sg_id,
909 'protocol': protocol}
911 # - both None => we do nothing
912 # - both Not None => we add them to the secgroup rule attributes
913 # but one cannot be None is the other is not None
914 if (port_range_min is not None and port_range_max is not None):
915 # add port_range in secgroup rule attributes
916 secgroup_rule_attrs['port_range_min'] = port_range_min
917 secgroup_rule_attrs['port_range_max'] = port_range_max
918 logger.debug("Security_group format set (port range included)")
920 # either both port range are set to None => do nothing
921 # or one is set but not the other => log it and return False
922 if port_range_min is None and port_range_max is None:
923 logger.debug("Security_group format set (no port range mentioned)")
925 logger.error("Bad security group format."
926 "One of the port range is not properly set:"
928 "range max: {}".format(port_range_min,
932 # Create security group using neutron client
934 conn.network.create_security_group_rule(**secgroup_rule_attrs)
937 logger.exception("Impossible to create_security_group_rule,"
938 "security group rule probably already exists")
942 def get_security_group_rules(conn, sg_id):
944 security_rules = conn.network.security_group_rules()
945 security_rules = [rule for rule in security_rules
946 if rule.security_group_id == sg_id]
947 return security_rules
948 except Exception as e:
949 logger.error("Error [get_security_group_rules(network, sg_id)]:"
954 def check_security_group_rules(conn, sg_id, direction, protocol,
955 port_min=None, port_max=None):
957 security_rules = get_security_group_rules(conn, sg_id)
958 security_rules = [rule for rule in security_rules
959 if (rule.direction.lower() == direction and
960 rule.protocol.lower() == protocol and
961 rule.port_range_min == port_min and
962 rule.port_range_max == port_max)]
963 if len(security_rules) == 0:
967 except Exception as e:
968 logger.error("Error [check_security_group_rules("
969 " network, sg_id, direction,"
970 " protocol, port_min=None, port_max=None)]: "
975 def create_security_group_full(conn,
976 sg_name, sg_description):
977 sg_id = get_security_group_id(conn, sg_name)
979 logger.info("Using existing security group '%s'..." % sg_name)
981 logger.info("Creating security group '%s'..." % sg_name)
982 SECGROUP = create_security_group(conn,
986 logger.error("Failed to create the security group...")
991 logger.debug("Security group '%s' with ID=%s created successfully."
992 % (SECGROUP.name, sg_id))
994 logger.debug("Adding ICMP rules in security group '%s'..."
996 if not create_secgroup_rule(conn, sg_id,
998 logger.error("Failed to create the security group rule...")
1001 logger.debug("Adding SSH rules in security group '%s'..."
1003 if not create_secgroup_rule(
1004 conn, sg_id, 'ingress', 'tcp', '22', '22'):
1005 logger.error("Failed to create the security group rule...")
1008 if not create_secgroup_rule(
1009 conn, sg_id, 'egress', 'tcp', '22', '22'):
1010 logger.error("Failed to create the security group rule...")
1015 def add_secgroup_to_instance(conn, instance_id, secgroup_id):
1017 conn.compute.add_security_group_to_server(instance_id, secgroup_id)
1019 except Exception as e:
1020 logger.error("Error [add_secgroup_to_instance(compute, '%s', "
1021 "'%s')]: %s" % (instance_id, secgroup_id, e))
1025 def update_sg_quota(conn, tenant_id, sg_quota, sg_rule_quota):
1027 conn.network.update_quota(tenant_id,
1028 security_group_rules=sg_rule_quota,
1029 security_groups=sg_quota)
1031 except Exception as e:
1032 logger.error("Error [update_sg_quota(network, '%s', '%s', "
1033 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1037 def delete_security_group(conn, secgroup_id):
1039 conn.network.delete_security_group(secgroup_id, ignore_missing=False)
1041 except Exception as e:
1042 logger.error("Error [delete_security_group(network, '%s')]: %s"
1047 # *********************************************
1049 # *********************************************
1050 def get_images(conn):
1052 images = conn.image.images()
1054 except Exception as e:
1055 logger.error("Error [get_images]: %s" % e)
1059 def get_image_id(conn, image_name):
1060 images = conn.image.images()
1063 if i.name == image_name:
1069 def create_glance_image(conn,
1073 extra_properties={},
1076 if not os.path.isfile(file_path):
1077 logger.error("Error: file %s does not exist." % file_path)
1080 image_id = get_image_id(conn, image_name)
1082 logger.info("Image %s already exists." % image_name)
1084 logger.info("Creating image '%s' from '%s'..." % (image_name,
1086 with open(file_path) as image_data:
1087 image = conn.image.upload_image(name=image_name,
1090 container_format=container,
1095 except Exception as e:
1096 logger.error("Error [create_glance_image(image, '%s', '%s', "
1097 "'%s')]: %s" % (image_name, file_path, public, e))
1101 def get_or_create_image(name, path, format, extra_properties):
1102 image_exists = False
1103 conn = get_os_connection()
1105 image_id = get_image_id(conn, name)
1107 logger.info("Using existing image '%s'..." % name)
1110 logger.info("Creating image '%s' from '%s'..." % (name, path))
1111 image_id = create_glance_image(conn,
1117 logger.error("Failed to create a Glance image...")
1119 logger.debug("Image '%s' with ID=%s created successfully."
1122 return image_exists, image_id
1125 def delete_glance_image(conn, image_id):
1127 conn.image.delete_image(image_id)
1129 except Exception as e:
1130 logger.error("Error [delete_glance_image(image, '%s')]: %s"
1135 # *********************************************
1137 # *********************************************
1138 def get_volumes(conn):
1140 volumes = conn.block_store.volumes(all_tenants=1)
1142 except Exception as e:
1143 logger.error("Error [get_volumes(volume)]: %s" % e)
1147 def update_cinder_quota(cloud, tenant_id, vols_quota,
1148 snapshots_quota, gigabytes_quota):
1149 quotas_values = {"volumes": vols_quota,
1150 "snapshots": snapshots_quota,
1151 "gigabytes": gigabytes_quota}
1154 cloud.set_volume_quotas(tenant_id, **quotas_values)
1156 except Exception as e:
1157 logger.error("Error [update_cinder_quota(volume, '%s', '%s', "
1158 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1159 snapshots_quota, gigabytes_quota, e))
1163 def delete_volume(cloud, volume_id, forced=False):
1167 volume = cloud.get_volume(volume_id)
1168 for attachment in volume.attachments:
1169 server = cloud.get_server(attachment.server_id)
1170 cloud.detach_volume(server, volume)
1172 logger.error(sys.exc_info()[0])
1173 cloud.delete_volume(volume_id, force=True)
1175 cloud.delete_volume(volume_id)
1177 except Exception as e:
1178 logger.error("Error [delete_volume(volume, '%s', '%s')]: %s"
1179 % (volume_id, str(forced), e))
1183 # *********************************************
1185 # *********************************************
1186 def get_tenants(keystone_client):
1188 if is_keystone_v3():
1189 tenants = keystone_client.projects.list()
1191 tenants = keystone_client.tenants.list()
1193 except Exception as e:
1194 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1198 def get_users(keystone_client):
1200 users = keystone_client.users.list()
1202 except Exception as e:
1203 logger.error("Error [get_users(keystone_client)]: %s" % e)
1207 def get_tenant_id(keystone_client, tenant_name):
1208 tenants = get_tenants(keystone_client)
1211 if t.name == tenant_name:
1217 def get_user_id(keystone_client, user_name):
1218 users = get_users(keystone_client)
1221 if u.name == user_name:
1227 def get_role_id(keystone_client, role_name):
1228 roles = keystone_client.roles.list()
1231 if r.name == role_name:
1237 def get_domain_id(keystone_client, domain_name):
1238 domains = keystone_client.domains.list()
1241 if d.name == domain_name:
1247 def create_tenant(keystone_client, tenant_name, tenant_description):
1249 if is_keystone_v3():
1250 domain_name = os.environ['OS_PROJECT_DOMAIN_NAME']
1251 domain_id = get_domain_id(keystone_client, domain_name)
1252 tenant = keystone_client.projects.create(
1254 description=tenant_description,
1258 tenant = keystone_client.tenants.create(tenant_name,
1262 except Exception as e:
1263 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1264 % (tenant_name, tenant_description, e))
1268 def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
1269 tenant_id = get_tenant_id(keystone_client, tenant_name)
1271 tenant_id = create_tenant(keystone_client, tenant_name,
1277 def get_or_create_tenant_for_vnf(keystone_client, tenant_name,
1278 tenant_description):
1279 """Get or Create a Tenant
1282 keystone_client: keystone client reference
1283 tenant_name: the name of the tenant
1284 tenant_description: the description of the tenant
1286 return False if tenant retrieved though get
1287 return True if tenant created
1288 raise Exception if error during processing
1291 tenant_id = get_tenant_id(keystone_client, tenant_name)
1293 tenant_id = create_tenant(keystone_client, tenant_name,
1299 raise Exception("Impossible to create a Tenant for the VNF {}".format(
1303 def create_user(keystone_client, user_name, user_password,
1304 user_email, tenant_id):
1306 if is_keystone_v3():
1307 user = keystone_client.users.create(name=user_name,
1308 password=user_password,
1310 project_id=tenant_id,
1313 user = keystone_client.users.create(user_name,
1319 except Exception as e:
1320 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1321 "'%s')]: %s" % (user_name, user_password,
1322 user_email, tenant_id, e))
1326 def get_or_create_user(keystone_client, user_name, user_password,
1327 tenant_id, user_email=None):
1328 user_id = get_user_id(keystone_client, user_name)
1330 user_id = create_user(keystone_client, user_name, user_password,
1331 user_email, tenant_id)
1335 def get_or_create_user_for_vnf(keystone_client, vnf_ref):
1336 """Get or Create user for VNF
1339 keystone_client: keystone client reference
1340 vnf_ref: VNF reference used as user name & password, tenant name
1342 return False if user retrieved through get
1343 return True if user created
1344 raise Exception if error during processing
1347 user_id = get_user_id(keystone_client, vnf_ref)
1348 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1351 user_id = create_user(keystone_client, vnf_ref, vnf_ref,
1355 role_id = get_role_id(keystone_client, 'admin')
1356 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1357 add_role_user(keystone_client, user_id, role_id, tenant_id)
1359 logger.warn("Cannot associate user to role admin on tenant")
1362 raise Exception("Impossible to create a user for the VNF {}".format(
1366 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1368 if is_keystone_v3():
1369 keystone_client.roles.grant(role=role_id,
1373 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1375 except Exception as e:
1376 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1377 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1381 def delete_tenant(keystone_client, tenant_id):
1383 if is_keystone_v3():
1384 keystone_client.projects.delete(tenant_id)
1386 keystone_client.tenants.delete(tenant_id)
1388 except Exception as e:
1389 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1394 def delete_user(keystone_client, user_id):
1396 keystone_client.users.delete(user_id)
1398 except Exception as e:
1399 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1404 # *********************************************
1406 # *********************************************
1407 def get_resource(conn, stack_id, resource):
1409 resource = conn.orchestration.resources(stack_id, id=resource).next()
1411 except Exception as e:
1412 logger.error("Error [get_resource(orchestration)]: %s" % e)
1416 def create_stack(conn, **kwargs):
1418 stack = conn.orchestration.create_stack(**kwargs)
1420 if stack_id is None:
1421 logger.error("Stack create start failed")
1422 raise SystemError("Stack create start failed")
1424 except Exception as e:
1425 logger.error("Error [create_stack(orchestration)]: %s" % e)
1429 def delete_stack(conn, stack_id):
1431 conn.orchestration.delete_stack(stack_id)
1433 except Exception as e:
1434 logger.error("Error [delete_stack(orchestration)]: %s" % e)
1438 def list_stacks(conn, **kwargs):
1440 result = conn.orchestration.stacks(**kwargs)
1442 except Exception as e:
1443 logger.error("Error [list_stack(orchestration)]: %s" % e)
1447 def get_output(conn, stack_id, output_key):
1449 stack = conn.orchestration.get_stack(stack_id)
1450 for output in stack.outputs:
1451 if output['output_key'] == output_key:
1453 except ResourceNotFound as e:
1454 logger.error("Error [get_output(orchestration)]: %s" % e)