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
16 from keystoneauth1 import loading
17 from keystoneauth1 import session
18 from cinderclient import client as cinderclient
19 from glanceclient import client as glanceclient
20 from heatclient import client as heatclient
21 from novaclient import client as novaclient
22 from keystoneclient import client as keystoneclient
23 from neutronclient.neutron import client as neutronclient
25 from functest.utils.constants import CONST
26 import functest.utils.functest_utils as ft_utils
28 logger = logging.getLogger(__name__)
30 DEFAULT_API_VERSION = '2'
31 DEFAULT_HEAT_API_VERSION = '1'
34 # *********************************************
36 # *********************************************
37 class MissingEnvVar(Exception):
39 def __init__(self, var):
43 return str.format("Please set the mandatory env var: {}", self.var)
47 keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
48 if (keystone_api_version is None or
49 keystone_api_version == '2'):
55 def get_rc_env_vars():
56 env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD']
58 env_vars.extend(['OS_PROJECT_NAME',
59 'OS_USER_DOMAIN_NAME',
60 'OS_PROJECT_DOMAIN_NAME'])
62 env_vars.extend(['OS_TENANT_NAME'])
66 def check_credentials():
68 Check if the OpenStack credentials (openrc) are sourced
70 env_vars = get_rc_env_vars()
71 return all(map(lambda v: v in os.environ and os.environ[v], env_vars))
74 def get_env_cred_dict():
76 'OS_USERNAME': 'username',
77 'OS_PASSWORD': 'password',
78 'OS_AUTH_URL': 'auth_url',
79 'OS_TENANT_NAME': 'tenant_name',
80 'OS_USER_DOMAIN_NAME': 'user_domain_name',
81 'OS_PROJECT_DOMAIN_NAME': 'project_domain_name',
82 'OS_PROJECT_NAME': 'project_name',
83 'OS_ENDPOINT_TYPE': 'endpoint_type',
84 'OS_REGION_NAME': 'region_name',
85 'OS_CACERT': 'https_cacert',
86 'OS_INSECURE': 'https_insecure'
91 def get_credentials(other_creds={}):
92 """Returns a creds dictionary filled with parsed from env
95 env_vars = get_rc_env_vars()
96 env_cred_dict = get_env_cred_dict()
98 for envvar in env_vars:
99 if os.getenv(envvar) is None:
100 raise MissingEnvVar(envvar)
102 creds_key = env_cred_dict.get(envvar)
103 creds.update({creds_key: os.getenv(envvar)})
105 if 'tenant' in other_creds.keys():
107 tenant = 'project_name'
109 tenant = 'tenant_name'
110 other_creds[tenant] = other_creds.pop('tenant')
112 creds.update(other_creds)
117 def get_session_auth(other_creds={}):
118 loader = loading.get_plugin_loader('password')
119 creds = get_credentials(other_creds)
120 auth = loader.load_from_options(**creds)
124 def get_endpoint(service_type, interface='public'):
125 auth = get_session_auth()
126 return get_session().get_endpoint(auth=auth,
127 service_type=service_type,
131 def get_session(other_creds={}):
132 auth = get_session_auth(other_creds)
133 https_cacert = os.getenv('OS_CACERT', '')
134 https_insecure = os.getenv('OS_INSECURE', '').lower() == 'true'
135 return session.Session(auth=auth,
136 verify=(https_cacert or not https_insecure))
139 # *********************************************
141 # *********************************************
142 def get_keystone_client_version():
143 api_version = os.getenv('OS_IDENTITY_API_VERSION')
144 if api_version is not None:
145 logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
148 return DEFAULT_API_VERSION
151 def get_keystone_client(other_creds={}):
152 sess = get_session(other_creds)
153 return keystoneclient.Client(get_keystone_client_version(),
155 interface=os.getenv('OS_INTERFACE', 'admin'))
158 def get_nova_client_version():
159 api_version = os.getenv('OS_COMPUTE_API_VERSION')
160 if api_version is not None:
161 logger.info("OS_COMPUTE_API_VERSION is set in env as '%s'",
164 return DEFAULT_API_VERSION
167 def get_nova_client(other_creds={}):
168 sess = get_session(other_creds)
169 return novaclient.Client(get_nova_client_version(), session=sess)
172 def get_cinder_client_version():
173 api_version = os.getenv('OS_VOLUME_API_VERSION')
174 if api_version is not None:
175 logger.info("OS_VOLUME_API_VERSION is set in env as '%s'",
178 return DEFAULT_API_VERSION
181 def get_cinder_client(other_creds={}):
182 sess = get_session(other_creds)
183 return cinderclient.Client(get_cinder_client_version(), session=sess)
186 def get_neutron_client_version():
187 api_version = os.getenv('OS_NETWORK_API_VERSION')
188 if api_version is not None:
189 logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
192 return DEFAULT_API_VERSION
195 def get_neutron_client(other_creds={}):
196 sess = get_session(other_creds)
197 return neutronclient.Client(get_neutron_client_version(), session=sess)
200 def get_glance_client_version():
201 api_version = os.getenv('OS_IMAGE_API_VERSION')
202 if api_version is not None:
203 logger.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version)
205 return DEFAULT_API_VERSION
208 def get_glance_client(other_creds={}):
209 sess = get_session(other_creds)
210 return glanceclient.Client(get_glance_client_version(), session=sess)
213 def get_heat_client_version():
214 api_version = os.getenv('OS_ORCHESTRATION_API_VERSION')
215 if api_version is not None:
216 logger.info("OS_ORCHESTRATION_API_VERSION is set in env as '%s'",
219 return DEFAULT_HEAT_API_VERSION
222 def get_heat_client(other_creds={}):
223 sess = get_session(other_creds)
224 return heatclient.Client(get_heat_client_version(), session=sess)
227 def download_and_add_image_on_glance(glance, image_name, image_url, data_dir):
230 if not os.path.exists(dest_path):
231 os.makedirs(dest_path)
232 file_name = image_url.rsplit('/')[-1]
233 if not ft_utils.download_url(image_url, dest_path):
236 raise Exception("Impossible to download image from {}".format(
240 image = create_glance_image(
241 glance, image_name, dest_path + file_name)
247 raise Exception("Impossible to put image {} in glance".format(
251 # *********************************************
253 # *********************************************
254 def get_instances(nova_client):
256 instances = nova_client.servers.list(search_opts={'all_tenants': 1})
258 except Exception as e:
259 logger.error("Error [get_instances(nova_client)]: %s" % e)
263 def get_instance_status(nova_client, instance):
265 instance = nova_client.servers.get(instance.id)
266 return instance.status
267 except Exception as e:
268 logger.error("Error [get_instance_status(nova_client)]: %s" % e)
272 def get_instance_by_name(nova_client, instance_name):
274 instance = nova_client.servers.find(name=instance_name)
276 except Exception as e:
277 logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
278 % (instance_name, e))
282 def get_flavor_id(nova_client, flavor_name):
283 flavors = nova_client.flavors.list(detailed=True)
286 if f.name == flavor_name:
292 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
293 flavors = nova_client.flavors.list(detailed=True)
296 if min_ram <= f.ram and f.ram <= max_ram:
302 def get_aggregates(nova_client):
304 aggregates = nova_client.aggregates.list()
306 except Exception as e:
307 logger.error("Error [get_aggregates(nova_client)]: %s" % e)
311 def get_aggregate_id(nova_client, aggregate_name):
313 aggregates = get_aggregates(nova_client)
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(nova_client, %s)]:"
318 " %s" % (aggregate_name, e))
322 def get_availability_zones(nova_client):
324 availability_zones = nova_client.availability_zones.list()
325 return availability_zones
326 except Exception as e:
327 logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
331 def get_availability_zone_names(nova_client):
333 az_names = [az.zoneName for az in get_availability_zones(nova_client)]
335 except Exception as e:
336 logger.error("Error [get_availability_zone_names(nova_client)]:"
341 def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
343 flavor = nova_client.flavors.create(
344 flavor_name, ram, vcpus, disk, is_public=public)
346 extra_specs = ft_utils.get_functest_config(
347 'general.flavor_extra_specs')
348 flavor.set_keys(extra_specs)
350 # flavor extra specs are not configured, therefore skip the update
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 add_floating_ip(nova_client, server_id, floatingip_addr):
535 nova_client.servers.add_floating_ip(server_id, floatingip_addr)
537 except Exception as e:
538 logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
539 % (server_id, floatingip_addr, e))
543 def delete_instance(nova_client, instance_id):
545 nova_client.servers.force_delete(instance_id)
547 except Exception as e:
548 logger.error("Error [delete_instance(nova_client, '%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(nova_client, aggregate_name, compute_host):
565 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
566 nova_client.aggregates.remove_host(aggregate_id, compute_host)
568 except Exception as e:
569 logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
570 " %s" % (aggregate_name, compute_host, e))
574 def remove_hosts_from_aggregate(nova_client, aggregate_name):
575 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
576 hosts = nova_client.aggregates.get(aggregate_id).hosts
578 all(remove_host_from_aggregate(nova_client, aggregate_name, host)
582 def delete_aggregate(nova_client, aggregate_name):
584 remove_hosts_from_aggregate(nova_client, aggregate_name)
585 nova_client.aggregates.delete(aggregate_name)
587 except Exception as e:
588 logger.error("Error [delete_aggregate(nova_client, %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 (hasattr(CONST, 'EXTERNAL_NETWORK')):
663 return CONST.__getattribute__('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 (hasattr(CONST, 'EXTERNAL_NETWORK')):
672 networks = neutron_client.list_networks(
673 name=CONST.__getattribute__('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'
871 logger.info('Creating neutron network %s...' % net_name)
872 network_id = create_neutron_net(neutron_client, net_name)
877 logger.debug("Network '%s' created successfully" % network_id)
878 logger.debug('Creating Subnet....')
879 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
880 cidr, network_id, dns)
884 logger.debug("Subnet '%s' created successfully" % subnet_id)
885 logger.debug('Creating Router...')
886 router_id = create_neutron_router(neutron_client, router_name)
891 logger.debug("Router '%s' created successfully" % router_id)
892 logger.debug('Adding router to subnet...')
894 if not add_interface_router(neutron_client, router_id, subnet_id):
897 logger.debug("Interface added successfully.")
899 logger.debug('Adding gateway to router...')
900 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(nova_client, instance_id, secgroup_id):
1088 nova_client.servers.add_security_group(instance_id, secgroup_id)
1090 except Exception as e:
1091 logger.error("Error [add_secgroup_to_instance(nova_client, '%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(glance_client):
1127 images = glance_client.images.list()
1129 except Exception as e:
1130 logger.error("Error [get_images]: %s" % e)
1134 def get_image_id(glance_client, image_name):
1135 images = glance_client.images.list()
1138 if i.name == image_name:
1144 def create_glance_image(glance_client,
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(glance_client, image_name)
1157 logger.info("Image %s already exists." % image_name)
1159 logger.info("Creating image '%s' from '%s'..." % (image_name,
1162 image = glance_client.images.create(name=image_name,
1165 container_format=container,
1168 with open(file_path) as image_data:
1169 glance_client.images.upload(image_id, image_data)
1171 except Exception as e:
1172 logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1173 "'%s')]: %s" % (image_name, file_path, public, e))
1177 def get_or_create_image(name, path, format, extra_properties):
1178 image_exists = False
1179 glance_client = get_glance_client()
1181 image_id = get_image_id(glance_client, name)
1183 logger.info("Using existing image '%s'..." % name)
1186 logger.info("Creating image '%s' from '%s'..." % (name, path))
1187 image_id = create_glance_image(glance_client,
1193 logger.error("Failed to create a Glance image...")
1195 logger.debug("Image '%s' with ID=%s created successfully."
1198 return image_exists, image_id
1201 def delete_glance_image(glance_client, image_id):
1203 glance_client.images.delete(image_id)
1205 except Exception as e:
1206 logger.error("Error [delete_glance_image(glance_client, '%s')]: %s"
1211 # *********************************************
1213 # *********************************************
1214 def get_volumes(cinder_client):
1216 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1218 except Exception as e:
1219 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1223 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1224 snapshots_quota, gigabytes_quota):
1225 quotas_values = {"volumes": vols_quota,
1226 "snapshots": snapshots_quota,
1227 "gigabytes": gigabytes_quota}
1230 cinder_client.quotas.update(tenant_id, **quotas_values)
1232 except Exception as e:
1233 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1234 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1235 snapshots_quota, gigabytes_quota, e))
1239 def delete_volume(cinder_client, volume_id, forced=False):
1243 cinder_client.volumes.detach(volume_id)
1245 logger.error(sys.exc_info()[0])
1246 cinder_client.volumes.force_delete(volume_id)
1248 cinder_client.volumes.delete(volume_id)
1250 except Exception as e:
1251 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1252 % (volume_id, str(forced), e))
1256 # *********************************************
1258 # *********************************************
1259 def get_tenants(keystone_client):
1261 if is_keystone_v3():
1262 tenants = keystone_client.projects.list()
1264 tenants = keystone_client.tenants.list()
1266 except Exception as e:
1267 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1271 def get_users(keystone_client):
1273 users = keystone_client.users.list()
1275 except Exception as e:
1276 logger.error("Error [get_users(keystone_client)]: %s" % e)
1280 def get_tenant_id(keystone_client, tenant_name):
1281 tenants = get_tenants(keystone_client)
1284 if t.name == tenant_name:
1290 def get_user_id(keystone_client, user_name):
1291 users = get_users(keystone_client)
1294 if u.name == user_name:
1300 def get_role_id(keystone_client, role_name):
1301 roles = keystone_client.roles.list()
1304 if r.name == role_name:
1310 def get_domain_id(keystone_client, domain_name):
1311 domains = keystone_client.domains.list()
1314 if d.name == domain_name:
1320 def create_tenant(keystone_client, tenant_name, tenant_description):
1322 if is_keystone_v3():
1323 domain_name = os.environ['OS_PROJECT_DOMAIN_NAME']
1324 domain_id = get_domain_id(keystone_client, domain_name)
1325 tenant = keystone_client.projects.create(
1327 description=tenant_description,
1331 tenant = keystone_client.tenants.create(tenant_name,
1335 except Exception as e:
1336 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1337 % (tenant_name, tenant_description, e))
1341 def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
1342 tenant_id = get_tenant_id(keystone_client, tenant_name)
1344 tenant_id = create_tenant(keystone_client, tenant_name,
1350 def get_or_create_tenant_for_vnf(keystone_client, tenant_name,
1351 tenant_description):
1352 """Get or Create a Tenant
1355 keystone_client: keystone client reference
1356 tenant_name: the name of the tenant
1357 tenant_description: the description of the tenant
1359 return False if tenant retrieved though get
1360 return True if tenant created
1361 raise Exception if error during processing
1364 tenant_id = get_tenant_id(keystone_client, tenant_name)
1366 tenant_id = create_tenant(keystone_client, tenant_name,
1372 raise Exception("Impossible to create a Tenant for the VNF {}".format(
1376 def create_user(keystone_client, user_name, user_password,
1377 user_email, tenant_id):
1379 if is_keystone_v3():
1380 user = keystone_client.users.create(name=user_name,
1381 password=user_password,
1383 project_id=tenant_id,
1386 user = keystone_client.users.create(user_name,
1392 except Exception as e:
1393 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1394 "'%s')]: %s" % (user_name, user_password,
1395 user_email, tenant_id, e))
1399 def get_or_create_user(keystone_client, user_name, user_password,
1400 tenant_id, user_email=None):
1401 user_id = get_user_id(keystone_client, user_name)
1403 user_id = create_user(keystone_client, user_name, user_password,
1404 user_email, tenant_id)
1408 def get_or_create_user_for_vnf(keystone_client, vnf_ref):
1409 """Get or Create user for VNF
1412 keystone_client: keystone client reference
1413 vnf_ref: VNF reference used as user name & password, tenant name
1415 return False if user retrieved through get
1416 return True if user created
1417 raise Exception if error during processing
1420 user_id = get_user_id(keystone_client, vnf_ref)
1421 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1424 user_id = create_user(keystone_client, vnf_ref, vnf_ref,
1428 role_id = get_role_id(keystone_client, 'admin')
1429 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1430 add_role_user(keystone_client, user_id, role_id, tenant_id)
1432 logger.warn("Cannot associate user to role admin on tenant")
1435 raise Exception("Impossible to create a user for the VNF {}".format(
1439 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1441 if is_keystone_v3():
1442 keystone_client.roles.grant(role=role_id,
1446 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1448 except Exception as e:
1449 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1450 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1454 def delete_tenant(keystone_client, tenant_id):
1456 if is_keystone_v3():
1457 keystone_client.projects.delete(tenant_id)
1459 keystone_client.tenants.delete(tenant_id)
1461 except Exception as e:
1462 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1467 def delete_user(keystone_client, user_id):
1469 keystone_client.users.delete(user_id)
1471 except Exception as e:
1472 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1477 # *********************************************
1479 # *********************************************
1480 def get_resource(heat_client, stack_id, resource):
1482 resources = heat_client.resources.get(stack_id, resource)
1484 except Exception as e:
1485 logger.error("Error [get_resource]: %s" % e)