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
18 from keystoneauth1 import loading
19 from keystoneauth1 import session
20 from cinderclient import client as cinderclient
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 openstack import connection
27 from functest.utils import env
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)
47 def get_os_connection():
48 return connection.from_config()
52 keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
53 if (keystone_api_version is None or
54 keystone_api_version == '2'):
60 def get_rc_env_vars():
61 env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD']
63 env_vars.extend(['OS_PROJECT_NAME',
64 'OS_USER_DOMAIN_NAME',
65 'OS_PROJECT_DOMAIN_NAME'])
67 env_vars.extend(['OS_TENANT_NAME'])
71 def check_credentials():
73 Check if the OpenStack credentials (openrc) are sourced
75 env_vars = get_rc_env_vars()
76 return all(map(lambda v: v in os.environ and os.environ[v], env_vars))
79 def get_env_cred_dict():
81 'OS_USERNAME': 'username',
82 'OS_PASSWORD': 'password',
83 'OS_AUTH_URL': 'auth_url',
84 'OS_TENANT_NAME': 'tenant_name',
85 'OS_USER_DOMAIN_NAME': 'user_domain_name',
86 'OS_PROJECT_DOMAIN_NAME': 'project_domain_name',
87 'OS_PROJECT_NAME': 'project_name',
88 'OS_ENDPOINT_TYPE': 'endpoint_type',
89 'OS_REGION_NAME': 'region_name',
90 'OS_CACERT': 'https_cacert',
91 'OS_INSECURE': 'https_insecure'
96 def get_credentials(other_creds={}):
97 """Returns a creds dictionary filled with parsed from env
100 env_vars = get_rc_env_vars()
101 env_cred_dict = get_env_cred_dict()
103 for envvar in env_vars:
104 if os.getenv(envvar) is None:
105 raise MissingEnvVar(envvar)
107 creds_key = env_cred_dict.get(envvar)
108 creds.update({creds_key: os.getenv(envvar)})
110 if 'tenant' in other_creds.keys():
112 tenant = 'project_name'
114 tenant = 'tenant_name'
115 other_creds[tenant] = other_creds.pop('tenant')
117 creds.update(other_creds)
122 def get_session_auth(other_creds={}):
123 loader = loading.get_plugin_loader('password')
124 creds = get_credentials(other_creds)
125 auth = loader.load_from_options(**creds)
129 def get_endpoint(service_type, interface='public'):
130 auth = get_session_auth()
131 return get_session().get_endpoint(auth=auth,
132 service_type=service_type,
136 def get_session(other_creds={}):
137 auth = get_session_auth(other_creds)
138 https_cacert = os.getenv('OS_CACERT', '')
139 https_insecure = os.getenv('OS_INSECURE', '').lower() == 'true'
140 return session.Session(auth=auth,
141 verify=(https_cacert or not https_insecure))
144 # *********************************************
146 # *********************************************
147 def get_keystone_client_version():
148 api_version = os.getenv('OS_IDENTITY_API_VERSION')
149 if api_version is not None:
150 logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
153 return DEFAULT_API_VERSION
156 def get_keystone_client(other_creds={}):
157 sess = get_session(other_creds)
158 return keystoneclient.Client(get_keystone_client_version(),
160 interface=os.getenv('OS_INTERFACE', 'admin'))
163 def get_nova_client_version():
164 api_version = os.getenv('OS_COMPUTE_API_VERSION')
165 if api_version is not None:
166 logger.info("OS_COMPUTE_API_VERSION is set in env as '%s'",
169 return DEFAULT_API_VERSION
172 def get_nova_client(other_creds={}):
173 sess = get_session(other_creds)
174 return novaclient.Client(get_nova_client_version(), session=sess)
177 def get_cinder_client_version():
178 api_version = os.getenv('OS_VOLUME_API_VERSION')
179 if api_version is not None:
180 logger.info("OS_VOLUME_API_VERSION is set in env as '%s'",
183 return DEFAULT_API_VERSION
186 def get_cinder_client(other_creds={}):
187 sess = get_session(other_creds)
188 return cinderclient.Client(get_cinder_client_version(), session=sess)
191 def get_neutron_client_version():
192 api_version = os.getenv('OS_NETWORK_API_VERSION')
193 if api_version is not None:
194 logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
197 return DEFAULT_API_VERSION
200 def get_neutron_client(other_creds={}):
201 sess = get_session(other_creds)
202 return neutronclient.Client(get_neutron_client_version(), session=sess)
205 def get_heat_client_version():
206 api_version = os.getenv('OS_ORCHESTRATION_API_VERSION')
207 if api_version is not None:
208 logger.info("OS_ORCHESTRATION_API_VERSION is set in env as '%s'",
211 return DEFAULT_HEAT_API_VERSION
214 def get_heat_client(other_creds={}):
215 sess = get_session(other_creds)
216 return heatclient.Client(get_heat_client_version(), session=sess)
219 def download_url(url, dest_path):
221 Download a file to a destination path given a URL
223 name = url.rsplit('/')[-1]
224 dest = dest_path + "/" + name
226 response = urllib.urlopen(url)
230 with open(dest, 'wb') as lfile:
231 shutil.copyfileobj(response, lfile)
235 def download_and_add_image_on_glance(conn, image_name, image_url, data_dir):
238 if not os.path.exists(dest_path):
239 os.makedirs(dest_path)
240 file_name = image_url.rsplit('/')[-1]
241 if not download_url(image_url, dest_path):
244 raise Exception("Impossible to download image from {}".format(
248 image = create_glance_image(
249 conn, image_name, dest_path + file_name)
255 raise Exception("Impossible to put image {} in glance".format(
259 # *********************************************
261 # *********************************************
262 def get_instances(nova_client):
264 instances = nova_client.servers.list(search_opts={'all_tenants': 1})
266 except Exception as e:
267 logger.error("Error [get_instances(nova_client)]: %s" % e)
271 def get_instance_status(nova_client, instance):
273 instance = nova_client.servers.get(instance.id)
274 return instance.status
275 except Exception as e:
276 logger.error("Error [get_instance_status(nova_client)]: %s" % e)
280 def get_instance_by_name(nova_client, instance_name):
282 instance = nova_client.servers.find(name=instance_name)
284 except Exception as e:
285 logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
286 % (instance_name, e))
290 def get_flavor_id(nova_client, flavor_name):
291 flavors = nova_client.flavors.list(detailed=True)
294 if f.name == flavor_name:
300 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
301 flavors = nova_client.flavors.list(detailed=True)
304 if min_ram <= f.ram and f.ram <= max_ram:
310 def get_aggregates(nova_client):
312 aggregates = nova_client.aggregates.list()
314 except Exception as e:
315 logger.error("Error [get_aggregates(nova_client)]: %s" % e)
319 def get_aggregate_id(nova_client, aggregate_name):
321 aggregates = get_aggregates(nova_client)
322 _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
324 except Exception as e:
325 logger.error("Error [get_aggregate_id(nova_client, %s)]:"
326 " %s" % (aggregate_name, e))
330 def get_availability_zones(nova_client):
332 availability_zones = nova_client.availability_zones.list()
333 return availability_zones
334 except Exception as e:
335 logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
339 def get_availability_zone_names(nova_client):
341 az_names = [az.zoneName for az in get_availability_zones(nova_client)]
343 except Exception as e:
344 logger.error("Error [get_availability_zone_names(nova_client)]:"
349 def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
351 flavor = nova_client.flavors.create(
352 flavor_name, ram, vcpus, disk, is_public=public)
353 except Exception as e:
354 logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
355 "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
360 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
361 flavor_exists = False
362 nova_client = get_nova_client()
364 flavor_id = get_flavor_id(nova_client, flavor_name)
366 logger.info("Using existing flavor '%s'..." % flavor_name)
369 logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
370 "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
371 flavor_id = create_flavor(
372 nova_client, flavor_name, ram, disk, vcpus, public=public)
374 raise Exception("Failed to create flavor '%s'..." % (flavor_name))
376 logger.debug("Flavor '%s' with ID=%s created successfully."
377 % (flavor_name, flavor_id))
379 return flavor_exists, flavor_id
382 def get_floating_ips(neutron_client):
384 floating_ips = neutron_client.list_floatingips()
385 return floating_ips['floatingips']
386 except Exception as e:
387 logger.error("Error [get_floating_ips(neutron_client)]: %s" % e)
391 def get_hypervisors(nova_client):
394 hypervisors = nova_client.hypervisors.list()
395 for hypervisor in hypervisors:
396 if hypervisor.state == "up":
397 nodes.append(hypervisor.hypervisor_hostname)
399 except Exception as e:
400 logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
404 def create_aggregate(nova_client, aggregate_name, av_zone):
406 nova_client.aggregates.create(aggregate_name, av_zone)
408 except Exception as e:
409 logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
410 % (aggregate_name, av_zone, e))
414 def add_host_to_aggregate(nova_client, aggregate_name, compute_host):
416 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
417 nova_client.aggregates.add_host(aggregate_id, compute_host)
419 except Exception as e:
420 logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
421 % (aggregate_name, compute_host, e))
425 def create_aggregate_with_host(
426 nova_client, aggregate_name, av_zone, compute_host):
428 create_aggregate(nova_client, aggregate_name, av_zone)
429 add_host_to_aggregate(nova_client, aggregate_name, compute_host)
431 except Exception as e:
432 logger.error("Error [create_aggregate_with_host("
433 "nova_client, %s, %s, %s)]: %s"
434 % (aggregate_name, av_zone, compute_host, e))
438 def create_instance(flavor_name,
441 instance_name="functest-vm",
447 nova_client = get_nova_client()
449 flavor = nova_client.flavors.find(name=flavor_name)
451 flavors = nova_client.flavors.list()
452 logger.error("Error: Flavor '%s' not found. Available flavors are: "
453 "\n%s" % (flavor_name, flavors))
455 if fixed_ip is not None:
456 nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
458 nics = {"net-id": network_id}
460 instance = nova_client.servers.create(
465 availability_zone=av_zone,
469 instance = nova_client.servers.create(
474 config_drive=confdrive,
476 availability_zone=av_zone,
482 def create_instance_and_wait_for_active(flavor_name,
492 VM_BOOT_TIMEOUT = 180
493 nova_client = get_nova_client()
494 instance = create_instance(flavor_name,
503 count = VM_BOOT_TIMEOUT / SLEEP
504 for n in range(count, -1, -1):
505 status = get_instance_status(nova_client, instance)
509 elif status.lower() == "active":
511 elif status.lower() == "error":
512 logger.error("The instance %s went to ERROR status."
516 logger.error("Timeout booting the instance %s." % instance_name)
520 def create_floating_ip(neutron_client):
521 extnet_id = get_external_net_id(neutron_client)
522 props = {'floating_network_id': extnet_id}
524 ip_json = neutron_client.create_floatingip({'floatingip': props})
525 fip_addr = ip_json['floatingip']['floating_ip_address']
526 fip_id = ip_json['floatingip']['id']
527 except Exception as e:
528 logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
530 return {'fip_addr': fip_addr, 'fip_id': fip_id}
533 def attach_floating_ip(neutron_client, port_id):
534 extnet_id = get_external_net_id(neutron_client)
535 props = {'floating_network_id': extnet_id,
538 return neutron_client.create_floatingip({'floatingip': props})
539 except Exception as e:
540 logger.error("Error [Attach_floating_ip(neutron_client), %s]: %s"
545 def add_floating_ip(nova_client, server_id, floatingip_addr):
547 nova_client.servers.add_floating_ip(server_id, floatingip_addr)
549 except Exception as e:
550 logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
551 % (server_id, floatingip_addr, e))
555 def delete_instance(nova_client, instance_id):
557 nova_client.servers.force_delete(instance_id)
559 except Exception as e:
560 logger.error("Error [delete_instance(nova_client, '%s')]: %s"
565 def delete_floating_ip(neutron_client, floatingip_id):
567 neutron_client.delete_floatingip(floatingip_id)
569 except Exception as e:
570 logger.error("Error [delete_floating_ip(neutron_client, '%s')]: %s"
571 % (floatingip_id, e))
575 def remove_host_from_aggregate(nova_client, aggregate_name, compute_host):
577 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
578 nova_client.aggregates.remove_host(aggregate_id, compute_host)
580 except Exception as e:
581 logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
582 " %s" % (aggregate_name, compute_host, e))
586 def remove_hosts_from_aggregate(nova_client, aggregate_name):
587 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
588 hosts = nova_client.aggregates.get(aggregate_id).hosts
590 all(remove_host_from_aggregate(nova_client, aggregate_name, host)
594 def delete_aggregate(nova_client, aggregate_name):
596 remove_hosts_from_aggregate(nova_client, aggregate_name)
597 nova_client.aggregates.delete(aggregate_name)
599 except Exception as e:
600 logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
601 % (aggregate_name, e))
605 # *********************************************
607 # *********************************************
608 def get_network_list(neutron_client):
609 network_list = neutron_client.list_networks()['networks']
610 if len(network_list) == 0:
616 def get_router_list(neutron_client):
617 router_list = neutron_client.list_routers()['routers']
618 if len(router_list) == 0:
624 def get_port_list(neutron_client):
625 port_list = neutron_client.list_ports()['ports']
626 if len(port_list) == 0:
632 def get_network_id(neutron_client, network_name):
633 networks = neutron_client.list_networks()['networks']
636 if n['name'] == network_name:
642 def get_subnet_id(neutron_client, subnet_name):
643 subnets = neutron_client.list_subnets()['subnets']
646 if s['name'] == subnet_name:
652 def get_router_id(neutron_client, router_name):
653 routers = neutron_client.list_routers()['routers']
656 if r['name'] == router_name:
662 def get_private_net(neutron_client):
663 # Checks if there is an existing shared private network
664 networks = neutron_client.list_networks()['networks']
665 if len(networks) == 0:
668 if (net['router:external'] is False) and (net['shared'] is True):
673 def get_external_net(neutron_client):
674 if (env.get('EXTERNAL_NETWORK')):
675 return env.get('EXTERNAL_NETWORK')
676 for network in neutron_client.list_networks()['networks']:
677 if network['router:external']:
678 return network['name']
682 def get_external_net_id(neutron_client):
683 if (env.get('EXTERNAL_NETWORK')):
684 networks = neutron_client.list_networks(
685 name=env.get('EXTERNAL_NETWORK'))
686 net_id = networks['networks'][0]['id']
688 for network in neutron_client.list_networks()['networks']:
689 if network['router:external']:
694 def check_neutron_net(neutron_client, net_name):
695 for network in neutron_client.list_networks()['networks']:
696 if network['name'] == net_name:
697 for subnet in network['subnets']:
702 def create_neutron_net(neutron_client, name):
703 json_body = {'network': {'name': name,
704 'admin_state_up': True}}
706 network = neutron_client.create_network(body=json_body)
707 network_dict = network['network']
708 return network_dict['id']
709 except Exception as e:
710 logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
715 def create_neutron_subnet(neutron_client, name, cidr, net_id,
716 dns=['8.8.8.8', '8.8.4.4']):
717 json_body = {'subnets': [{'name': name, 'cidr': cidr,
718 'ip_version': 4, 'network_id': net_id,
719 'dns_nameservers': dns}]}
722 subnet = neutron_client.create_subnet(body=json_body)
723 return subnet['subnets'][0]['id']
724 except Exception as e:
725 logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
726 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
730 def create_neutron_router(neutron_client, name):
731 json_body = {'router': {'name': name, 'admin_state_up': True}}
733 router = neutron_client.create_router(json_body)
734 return router['router']['id']
735 except Exception as e:
736 logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
741 def create_neutron_port(neutron_client, name, network_id, ip):
742 json_body = {'port': {
743 'admin_state_up': True,
745 'network_id': network_id,
746 'fixed_ips': [{"ip_address": ip}]
749 port = neutron_client.create_port(body=json_body)
750 return port['port']['id']
751 except Exception as e:
752 logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
753 "'%s')]: %s" % (name, network_id, ip, e))
757 def update_neutron_net(neutron_client, network_id, shared=False):
758 json_body = {'network': {'shared': shared}}
760 neutron_client.update_network(network_id, body=json_body)
762 except Exception as e:
763 logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
764 "%s" % (network_id, str(shared), e))
768 def update_neutron_port(neutron_client, port_id, device_owner):
769 json_body = {'port': {
770 'device_owner': device_owner,
773 port = neutron_client.update_port(port=port_id,
775 return port['port']['id']
776 except Exception as e:
777 logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
778 " %s" % (port_id, device_owner, e))
782 def add_interface_router(neutron_client, router_id, subnet_id):
783 json_body = {"subnet_id": subnet_id}
785 neutron_client.add_interface_router(router=router_id, body=json_body)
787 except Exception as e:
788 logger.error("Error [add_interface_router(neutron_client, '%s', "
789 "'%s')]: %s" % (router_id, subnet_id, e))
793 def add_gateway_router(neutron_client, router_id):
794 ext_net_id = get_external_net_id(neutron_client)
795 router_dict = {'network_id': ext_net_id}
797 neutron_client.add_gateway_router(router_id, router_dict)
799 except Exception as e:
800 logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
805 def delete_neutron_net(neutron_client, network_id):
807 neutron_client.delete_network(network_id)
809 except Exception as e:
810 logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
815 def delete_neutron_subnet(neutron_client, subnet_id):
817 neutron_client.delete_subnet(subnet_id)
819 except Exception as e:
820 logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
825 def delete_neutron_router(neutron_client, router_id):
827 neutron_client.delete_router(router=router_id)
829 except Exception as e:
830 logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
835 def delete_neutron_port(neutron_client, port_id):
837 neutron_client.delete_port(port_id)
839 except Exception as e:
840 logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
845 def remove_interface_router(neutron_client, router_id, subnet_id):
846 json_body = {"subnet_id": subnet_id}
848 neutron_client.remove_interface_router(router=router_id,
851 except Exception as e:
852 logger.error("Error [remove_interface_router(neutron_client, '%s', "
853 "'%s')]: %s" % (router_id, subnet_id, e))
857 def remove_gateway_router(neutron_client, router_id):
859 neutron_client.remove_gateway_router(router_id)
861 except Exception as e:
862 logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
867 def create_network_full(neutron_client,
872 dns=['8.8.8.8', '8.8.4.4']):
874 # Check if the network already exists
875 network_id = get_network_id(neutron_client, net_name)
876 subnet_id = get_subnet_id(neutron_client, subnet_name)
877 router_id = get_router_id(neutron_client, router_name)
879 if network_id != '' and subnet_id != '' and router_id != '':
880 logger.info("A network with name '%s' already exists..." % net_name)
882 neutron_client.format = 'json'
884 logger.info('Creating neutron network %s...' % net_name)
886 network_id = create_neutron_net(neutron_client, net_name)
889 logger.debug("Network '%s' created successfully" % network_id)
891 logger.debug('Creating Subnet....')
893 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
894 cidr, network_id, dns)
897 logger.debug("Subnet '%s' created successfully" % subnet_id)
899 logger.debug('Creating Router...')
901 router_id = create_neutron_router(neutron_client, router_name)
904 logger.debug("Router '%s' created successfully" % router_id)
906 logger.debug('Adding router to subnet...')
908 if not add_interface_router(neutron_client, router_id, subnet_id):
910 logger.debug("Interface added successfully.")
912 logger.debug('Adding gateway to router...')
913 if not add_gateway_router(neutron_client, router_id):
915 logger.debug("Gateway added successfully.")
917 network_dic = {'net_id': network_id,
918 'subnet_id': subnet_id,
919 'router_id': router_id}
923 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
924 neutron_client = get_neutron_client()
926 network_dic = create_network_full(neutron_client,
932 if not update_neutron_net(neutron_client,
933 network_dic['net_id'],
935 logger.error("Failed to update network %s..." % net_name)
938 logger.debug("Network '%s' is available..." % net_name)
940 logger.error("Network %s creation failed" % net_name)
945 # *********************************************
947 # *********************************************
950 def get_security_groups(neutron_client):
952 security_groups = neutron_client.list_security_groups()[
954 return security_groups
955 except Exception as e:
956 logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
960 def get_security_group_id(neutron_client, sg_name):
961 security_groups = get_security_groups(neutron_client)
963 for sg in security_groups:
964 if sg['name'] == sg_name:
970 def create_security_group(neutron_client, sg_name, sg_description):
971 json_body = {'security_group': {'name': sg_name,
972 'description': sg_description}}
974 secgroup = neutron_client.create_security_group(json_body)
975 return secgroup['security_group']
976 except Exception as e:
977 logger.error("Error [create_security_group(neutron_client, '%s', "
978 "'%s')]: %s" % (sg_name, sg_description, e))
982 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
983 port_range_min=None, port_range_max=None):
984 # We create a security group in 2 steps
985 # 1 - we check the format and set the json body accordingly
986 # 2 - we call neturon client to create the security group
989 json_body = {'security_group_rule': {'direction': direction,
990 'security_group_id': sg_id,
991 'protocol': protocol}}
993 # - both None => we do nothing
994 # - both Not None => we add them to the json description
995 # but one cannot be None is the other is not None
996 if (port_range_min is not None and port_range_max is not None):
997 # add port_range in json description
998 json_body['security_group_rule']['port_range_min'] = port_range_min
999 json_body['security_group_rule']['port_range_max'] = port_range_max
1000 logger.debug("Security_group format set (port range included)")
1002 # either both port range are set to None => do nothing
1003 # or one is set but not the other => log it and return False
1004 if port_range_min is None and port_range_max is None:
1005 logger.debug("Security_group format set (no port range mentioned)")
1007 logger.error("Bad security group format."
1008 "One of the port range is not properly set:"
1010 "range max: {}".format(port_range_min,
1014 # Create security group using neutron client
1016 neutron_client.create_security_group_rule(json_body)
1019 logger.exception("Impossible to create_security_group_rule,"
1020 "security group rule probably already exists")
1024 def get_security_group_rules(neutron_client, sg_id):
1026 security_rules = neutron_client.list_security_group_rules()[
1027 'security_group_rules']
1028 security_rules = [rule for rule in security_rules
1029 if rule["security_group_id"] == sg_id]
1030 return security_rules
1031 except Exception as e:
1032 logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:"
1037 def check_security_group_rules(neutron_client, sg_id, direction, protocol,
1038 port_min=None, port_max=None):
1040 security_rules = get_security_group_rules(neutron_client, sg_id)
1041 security_rules = [rule for rule in security_rules
1042 if (rule["direction"].lower() == direction and
1043 rule["protocol"].lower() == protocol and
1044 rule["port_range_min"] == port_min and
1045 rule["port_range_max"] == port_max)]
1046 if len(security_rules) == 0:
1050 except Exception as e:
1051 logger.error("Error [check_security_group_rules("
1052 " neutron_client, sg_id, direction,"
1053 " protocol, port_min=None, port_max=None)]: "
1058 def create_security_group_full(neutron_client,
1059 sg_name, sg_description):
1060 sg_id = get_security_group_id(neutron_client, sg_name)
1062 logger.info("Using existing security group '%s'..." % sg_name)
1064 logger.info("Creating security group '%s'..." % sg_name)
1065 SECGROUP = create_security_group(neutron_client,
1069 logger.error("Failed to create the security group...")
1072 sg_id = SECGROUP['id']
1074 logger.debug("Security group '%s' with ID=%s created successfully."
1075 % (SECGROUP['name'], sg_id))
1077 logger.debug("Adding ICMP rules in security group '%s'..."
1079 if not create_secgroup_rule(neutron_client, sg_id,
1081 logger.error("Failed to create the security group rule...")
1084 logger.debug("Adding SSH rules in security group '%s'..."
1086 if not create_secgroup_rule(
1087 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1088 logger.error("Failed to create the security group rule...")
1091 if not create_secgroup_rule(
1092 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1093 logger.error("Failed to create the security group rule...")
1098 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
1100 nova_client.servers.add_security_group(instance_id, secgroup_id)
1102 except Exception as e:
1103 logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
1104 "'%s')]: %s" % (instance_id, secgroup_id, e))
1108 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1109 json_body = {"quota": {
1110 "security_group": sg_quota,
1111 "security_group_rule": sg_rule_quota
1115 neutron_client.update_quota(tenant_id=tenant_id,
1118 except Exception as e:
1119 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1120 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1124 def delete_security_group(neutron_client, secgroup_id):
1126 neutron_client.delete_security_group(secgroup_id)
1128 except Exception as e:
1129 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1134 # *********************************************
1136 # *********************************************
1137 def get_images(conn):
1139 images = conn.image.images()
1141 except Exception as e:
1142 logger.error("Error [get_images]: %s" % e)
1146 def get_image_id(conn, image_name):
1147 images = conn.image.images()
1150 if i.name == image_name:
1156 def create_glance_image(conn,
1160 extra_properties={},
1163 if not os.path.isfile(file_path):
1164 logger.error("Error: file %s does not exist." % file_path)
1167 image_id = get_image_id(conn, image_name)
1169 logger.info("Image %s already exists." % image_name)
1171 logger.info("Creating image '%s' from '%s'..." % (image_name,
1173 with open(file_path) as image_data:
1174 image = conn.image.upload_image(name=image_name,
1177 container_format=container,
1182 except Exception as e:
1183 logger.error("Error [create_glance_image(image, '%s', '%s', "
1184 "'%s')]: %s" % (image_name, file_path, public, e))
1188 def get_or_create_image(name, path, format, extra_properties):
1189 image_exists = False
1190 conn = get_os_connection()
1192 image_id = get_image_id(conn, name)
1194 logger.info("Using existing image '%s'..." % name)
1197 logger.info("Creating image '%s' from '%s'..." % (name, path))
1198 image_id = create_glance_image(conn,
1204 logger.error("Failed to create a Glance image...")
1206 logger.debug("Image '%s' with ID=%s created successfully."
1209 return image_exists, image_id
1212 def delete_glance_image(conn, image_id):
1214 conn.image.delete_image(image_id)
1216 except Exception as e:
1217 logger.error("Error [delete_glance_image(image, '%s')]: %s"
1222 # *********************************************
1224 # *********************************************
1225 def get_volumes(cinder_client):
1227 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1229 except Exception as e:
1230 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1234 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1235 snapshots_quota, gigabytes_quota):
1236 quotas_values = {"volumes": vols_quota,
1237 "snapshots": snapshots_quota,
1238 "gigabytes": gigabytes_quota}
1241 cinder_client.quotas.update(tenant_id, **quotas_values)
1243 except Exception as e:
1244 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1245 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1246 snapshots_quota, gigabytes_quota, e))
1250 def delete_volume(cinder_client, volume_id, forced=False):
1254 cinder_client.volumes.detach(volume_id)
1256 logger.error(sys.exc_info()[0])
1257 cinder_client.volumes.force_delete(volume_id)
1259 cinder_client.volumes.delete(volume_id)
1261 except Exception as e:
1262 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1263 % (volume_id, str(forced), e))
1267 # *********************************************
1269 # *********************************************
1270 def get_tenants(keystone_client):
1272 if is_keystone_v3():
1273 tenants = keystone_client.projects.list()
1275 tenants = keystone_client.tenants.list()
1277 except Exception as e:
1278 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1282 def get_users(keystone_client):
1284 users = keystone_client.users.list()
1286 except Exception as e:
1287 logger.error("Error [get_users(keystone_client)]: %s" % e)
1291 def get_tenant_id(keystone_client, tenant_name):
1292 tenants = get_tenants(keystone_client)
1295 if t.name == tenant_name:
1301 def get_user_id(keystone_client, user_name):
1302 users = get_users(keystone_client)
1305 if u.name == user_name:
1311 def get_role_id(keystone_client, role_name):
1312 roles = keystone_client.roles.list()
1315 if r.name == role_name:
1321 def get_domain_id(keystone_client, domain_name):
1322 domains = keystone_client.domains.list()
1325 if d.name == domain_name:
1331 def create_tenant(keystone_client, tenant_name, tenant_description):
1333 if is_keystone_v3():
1334 domain_name = os.environ['OS_PROJECT_DOMAIN_NAME']
1335 domain_id = get_domain_id(keystone_client, domain_name)
1336 tenant = keystone_client.projects.create(
1338 description=tenant_description,
1342 tenant = keystone_client.tenants.create(tenant_name,
1346 except Exception as e:
1347 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1348 % (tenant_name, tenant_description, e))
1352 def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
1353 tenant_id = get_tenant_id(keystone_client, tenant_name)
1355 tenant_id = create_tenant(keystone_client, tenant_name,
1361 def get_or_create_tenant_for_vnf(keystone_client, tenant_name,
1362 tenant_description):
1363 """Get or Create a Tenant
1366 keystone_client: keystone client reference
1367 tenant_name: the name of the tenant
1368 tenant_description: the description of the tenant
1370 return False if tenant retrieved though get
1371 return True if tenant created
1372 raise Exception if error during processing
1375 tenant_id = get_tenant_id(keystone_client, tenant_name)
1377 tenant_id = create_tenant(keystone_client, tenant_name,
1383 raise Exception("Impossible to create a Tenant for the VNF {}".format(
1387 def create_user(keystone_client, user_name, user_password,
1388 user_email, tenant_id):
1390 if is_keystone_v3():
1391 user = keystone_client.users.create(name=user_name,
1392 password=user_password,
1394 project_id=tenant_id,
1397 user = keystone_client.users.create(user_name,
1403 except Exception as e:
1404 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1405 "'%s')]: %s" % (user_name, user_password,
1406 user_email, tenant_id, e))
1410 def get_or_create_user(keystone_client, user_name, user_password,
1411 tenant_id, user_email=None):
1412 user_id = get_user_id(keystone_client, user_name)
1414 user_id = create_user(keystone_client, user_name, user_password,
1415 user_email, tenant_id)
1419 def get_or_create_user_for_vnf(keystone_client, vnf_ref):
1420 """Get or Create user for VNF
1423 keystone_client: keystone client reference
1424 vnf_ref: VNF reference used as user name & password, tenant name
1426 return False if user retrieved through get
1427 return True if user created
1428 raise Exception if error during processing
1431 user_id = get_user_id(keystone_client, vnf_ref)
1432 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1435 user_id = create_user(keystone_client, vnf_ref, vnf_ref,
1439 role_id = get_role_id(keystone_client, 'admin')
1440 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1441 add_role_user(keystone_client, user_id, role_id, tenant_id)
1443 logger.warn("Cannot associate user to role admin on tenant")
1446 raise Exception("Impossible to create a user for the VNF {}".format(
1450 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1452 if is_keystone_v3():
1453 keystone_client.roles.grant(role=role_id,
1457 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1459 except Exception as e:
1460 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1461 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1465 def delete_tenant(keystone_client, tenant_id):
1467 if is_keystone_v3():
1468 keystone_client.projects.delete(tenant_id)
1470 keystone_client.tenants.delete(tenant_id)
1472 except Exception as e:
1473 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1478 def delete_user(keystone_client, user_id):
1480 keystone_client.users.delete(user_id)
1482 except Exception as e:
1483 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1488 # *********************************************
1490 # *********************************************
1491 def get_resource(heat_client, stack_id, resource):
1493 resources = heat_client.resources.get(stack_id, resource)
1495 except Exception as e:
1496 logger.error("Error [get_resource]: %s" % e)