3 # jose.lausuch@ericsson.com
4 # valentin.boucher@orange.com
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
17 from keystoneauth1 import loading
18 from keystoneauth1 import session
19 from cinderclient import client as cinderclient
20 from glanceclient import client as glanceclient
21 from heatclient import client as heatclient
22 from novaclient import client as novaclient
23 from keystoneclient import client as keystoneclient
24 from neutronclient.neutron import client as neutronclient
26 from functest.utils.constants import CONST
27 import functest.utils.functest_utils as ft_utils
29 logger = logging.getLogger(__name__)
31 DEFAULT_API_VERSION = '2'
32 DEFAULT_HEAT_API_VERSION = '1'
35 # *********************************************
37 # *********************************************
38 class MissingEnvVar(Exception):
40 def __init__(self, var):
44 return str.format("Please set the mandatory env var: {}", self.var)
48 keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
49 if (keystone_api_version is None or
50 keystone_api_version == '2'):
56 def get_rc_env_vars():
57 env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD']
59 env_vars.extend(['OS_PROJECT_NAME',
60 'OS_USER_DOMAIN_NAME',
61 'OS_PROJECT_DOMAIN_NAME'])
63 env_vars.extend(['OS_TENANT_NAME'])
67 def check_credentials():
69 Check if the OpenStack credentials (openrc) are sourced
71 env_vars = get_rc_env_vars()
72 return all(map(lambda v: v in os.environ and os.environ[v], env_vars))
75 def get_env_cred_dict():
77 'OS_USERNAME': 'username',
78 'OS_PASSWORD': 'password',
79 'OS_AUTH_URL': 'auth_url',
80 'OS_TENANT_NAME': 'tenant_name',
81 'OS_USER_DOMAIN_NAME': 'user_domain_name',
82 'OS_PROJECT_DOMAIN_NAME': 'project_domain_name',
83 'OS_PROJECT_NAME': 'project_name',
84 'OS_ENDPOINT_TYPE': 'endpoint_type',
85 'OS_REGION_NAME': 'region_name',
86 'OS_CACERT': 'https_cacert',
87 'OS_INSECURE': 'https_insecure'
92 def get_credentials(other_creds={}):
93 """Returns a creds dictionary filled with parsed from env
96 env_vars = get_rc_env_vars()
97 env_cred_dict = get_env_cred_dict()
99 for envvar in env_vars:
100 if os.getenv(envvar) is None:
101 raise MissingEnvVar(envvar)
103 creds_key = env_cred_dict.get(envvar)
104 creds.update({creds_key: os.getenv(envvar)})
106 if 'tenant' in other_creds.keys():
108 tenant = 'project_name'
110 tenant = 'tenant_name'
111 other_creds[tenant] = other_creds.pop('tenant')
113 creds.update(other_creds)
118 def source_credentials(rc_file):
119 with open(rc_file, "r") as f:
121 var = (line.rstrip('"\n').replace('export ', '').split("=")
122 if re.search(r'(.*)=(.*)', line) else None)
123 # The two next lines should be modified as soon as rc_file
124 # conforms with common rules. Be aware that it could induce
125 # issues if value starts with '
127 key = re.sub(r'^["\' ]*|[ \'"]*$', '', var[0])
128 value = re.sub(r'^["\' ]*|[ \'"]*$', '', "".join(var[1:]))
129 os.environ[key] = value
132 def get_credentials_for_rally():
133 creds = get_credentials()
134 env_cred_dict = get_env_cred_dict()
135 rally_conf = {"admin": {}}
137 if key == 'auth_url':
138 rally_conf[key] = creds[key]
140 rally_conf['admin'][key] = creds[key]
142 endpoint_types = [('internalURL', 'internal'),
143 ('publicURL', 'public'), ('adminURL', 'admin')]
145 endpoint_type = get_endpoint_type_from_env()
146 if endpoint_type is not None:
147 cred_key = env_cred_dict.get('OS_ENDPOINT_TYPE')
148 for k, v in endpoint_types:
149 if endpoint_type == v:
150 rally_conf[cred_key] = v
152 region_name = os.getenv('OS_REGION_NAME')
153 if region_name is not None:
154 cred_key = env_cred_dict.get('OS_REGION_NAME')
155 rally_conf[cred_key] = region_name
157 cred_key = env_cred_dict.get('OS_CACERT')
158 rally_conf[cred_key] = os.getenv('OS_CACERT', '')
160 insecure_key = env_cred_dict.get('OS_INSECURE')
161 rally_conf[insecure_key] = os.getenv('OS_INSECURE', '').lower() == 'true'
162 rally_conf = {"openstack": rally_conf}
167 def get_endpoint_type_from_env():
168 endpoint_type = os.environ.get("OS_ENDPOINT_TYPE",
169 os.environ.get("OS_INTERFACE"))
170 if endpoint_type and "URL" in endpoint_type:
171 endpoint_type = endpoint_type.replace("URL", "")
175 def get_session_auth(other_creds={}):
176 loader = loading.get_plugin_loader('password')
177 creds = get_credentials(other_creds)
178 auth = loader.load_from_options(**creds)
182 def get_endpoint(service_type, interface='public'):
183 auth = get_session_auth()
184 return get_session().get_endpoint(auth=auth,
185 service_type=service_type,
189 def get_session(other_creds={}):
190 auth = get_session_auth(other_creds)
191 https_cacert = os.getenv('OS_CACERT', '')
192 https_insecure = os.getenv('OS_INSECURE', '').lower() == 'true'
193 return session.Session(auth=auth,
194 verify=(https_cacert or not https_insecure))
197 # *********************************************
199 # *********************************************
200 def get_keystone_client_version():
201 api_version = os.getenv('OS_IDENTITY_API_VERSION')
202 if api_version is not None:
203 logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
206 return DEFAULT_API_VERSION
209 def get_keystone_client(other_creds={}):
210 sess = get_session(other_creds)
211 return keystoneclient.Client(get_keystone_client_version(),
213 interface=os.getenv('OS_INTERFACE', 'admin'))
216 def get_nova_client_version():
217 api_version = os.getenv('OS_COMPUTE_API_VERSION')
218 if api_version is not None:
219 logger.info("OS_COMPUTE_API_VERSION is set in env as '%s'",
222 return DEFAULT_API_VERSION
225 def get_nova_client(other_creds={}):
226 sess = get_session(other_creds)
227 return novaclient.Client(get_nova_client_version(), session=sess)
230 def get_cinder_client_version():
231 api_version = os.getenv('OS_VOLUME_API_VERSION')
232 if api_version is not None:
233 logger.info("OS_VOLUME_API_VERSION is set in env as '%s'",
236 return DEFAULT_API_VERSION
239 def get_cinder_client(other_creds={}):
240 sess = get_session(other_creds)
241 return cinderclient.Client(get_cinder_client_version(), session=sess)
244 def get_neutron_client_version():
245 api_version = os.getenv('OS_NETWORK_API_VERSION')
246 if api_version is not None:
247 logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
250 return DEFAULT_API_VERSION
253 def get_neutron_client(other_creds={}):
254 sess = get_session(other_creds)
255 return neutronclient.Client(get_neutron_client_version(), session=sess)
258 def get_glance_client_version():
259 api_version = os.getenv('OS_IMAGE_API_VERSION')
260 if api_version is not None:
261 logger.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version)
263 return DEFAULT_API_VERSION
266 def get_glance_client(other_creds={}):
267 sess = get_session(other_creds)
268 return glanceclient.Client(get_glance_client_version(), session=sess)
271 def get_heat_client_version():
272 api_version = os.getenv('OS_ORCHESTRATION_API_VERSION')
273 if api_version is not None:
274 logger.info("OS_ORCHESTRATION_API_VERSION is set in env as '%s'",
277 return DEFAULT_HEAT_API_VERSION
280 def get_heat_client(other_creds={}):
281 sess = get_session(other_creds)
282 return heatclient.Client(get_heat_client_version(), session=sess)
285 def download_and_add_image_on_glance(glance, image_name, image_url, data_dir):
288 if not os.path.exists(dest_path):
289 os.makedirs(dest_path)
290 file_name = image_url.rsplit('/')[-1]
291 if not ft_utils.download_url(image_url, dest_path):
294 raise Exception("Impossible to download image from {}".format(
298 image = create_glance_image(
299 glance, image_name, dest_path + file_name)
305 raise Exception("Impossible to put image {} in glance".format(
309 # *********************************************
311 # *********************************************
312 def get_instances(nova_client):
314 instances = nova_client.servers.list(search_opts={'all_tenants': 1})
316 except Exception as e:
317 logger.error("Error [get_instances(nova_client)]: %s" % e)
321 def get_instance_status(nova_client, instance):
323 instance = nova_client.servers.get(instance.id)
324 return instance.status
325 except Exception as e:
326 logger.error("Error [get_instance_status(nova_client)]: %s" % e)
330 def get_instance_by_name(nova_client, instance_name):
332 instance = nova_client.servers.find(name=instance_name)
334 except Exception as e:
335 logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
336 % (instance_name, e))
340 def get_flavor_id(nova_client, flavor_name):
341 flavors = nova_client.flavors.list(detailed=True)
344 if f.name == flavor_name:
350 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
351 flavors = nova_client.flavors.list(detailed=True)
354 if min_ram <= f.ram and f.ram <= max_ram:
360 def get_aggregates(nova_client):
362 aggregates = nova_client.aggregates.list()
364 except Exception as e:
365 logger.error("Error [get_aggregates(nova_client)]: %s" % e)
369 def get_aggregate_id(nova_client, aggregate_name):
371 aggregates = get_aggregates(nova_client)
372 _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
374 except Exception as e:
375 logger.error("Error [get_aggregate_id(nova_client, %s)]:"
376 " %s" % (aggregate_name, e))
380 def get_availability_zones(nova_client):
382 availability_zones = nova_client.availability_zones.list()
383 return availability_zones
384 except Exception as e:
385 logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
389 def get_availability_zone_names(nova_client):
391 az_names = [az.zoneName for az in get_availability_zones(nova_client)]
393 except Exception as e:
394 logger.error("Error [get_availability_zone_names(nova_client)]:"
399 def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
401 flavor = nova_client.flavors.create(
402 flavor_name, ram, vcpus, disk, is_public=public)
404 extra_specs = ft_utils.get_functest_config(
405 'general.flavor_extra_specs')
406 flavor.set_keys(extra_specs)
408 # flavor extra specs are not configured, therefore skip the update
411 except Exception as e:
412 logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
413 "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
418 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
419 flavor_exists = False
420 nova_client = get_nova_client()
422 flavor_id = get_flavor_id(nova_client, flavor_name)
424 logger.info("Using existing flavor '%s'..." % flavor_name)
427 logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
428 "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
429 flavor_id = create_flavor(
430 nova_client, flavor_name, ram, disk, vcpus, public=public)
432 raise Exception("Failed to create flavor '%s'..." % (flavor_name))
434 logger.debug("Flavor '%s' with ID=%s created successfully."
435 % (flavor_name, flavor_id))
437 return flavor_exists, flavor_id
440 def get_floating_ips(neutron_client):
442 floating_ips = neutron_client.list_floatingips()
443 return floating_ips['floatingips']
444 except Exception as e:
445 logger.error("Error [get_floating_ips(neutron_client)]: %s" % e)
449 def get_hypervisors(nova_client):
452 hypervisors = nova_client.hypervisors.list()
453 for hypervisor in hypervisors:
454 if hypervisor.state == "up":
455 nodes.append(hypervisor.hypervisor_hostname)
457 except Exception as e:
458 logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
462 def create_aggregate(nova_client, aggregate_name, av_zone):
464 nova_client.aggregates.create(aggregate_name, av_zone)
466 except Exception as e:
467 logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
468 % (aggregate_name, av_zone, e))
472 def add_host_to_aggregate(nova_client, aggregate_name, compute_host):
474 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
475 nova_client.aggregates.add_host(aggregate_id, compute_host)
477 except Exception as e:
478 logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
479 % (aggregate_name, compute_host, e))
483 def create_aggregate_with_host(
484 nova_client, aggregate_name, av_zone, compute_host):
486 create_aggregate(nova_client, aggregate_name, av_zone)
487 add_host_to_aggregate(nova_client, aggregate_name, compute_host)
489 except Exception as e:
490 logger.error("Error [create_aggregate_with_host("
491 "nova_client, %s, %s, %s)]: %s"
492 % (aggregate_name, av_zone, compute_host, e))
496 def create_instance(flavor_name,
499 instance_name="functest-vm",
505 nova_client = get_nova_client()
507 flavor = nova_client.flavors.find(name=flavor_name)
509 flavors = nova_client.flavors.list()
510 logger.error("Error: Flavor '%s' not found. Available flavors are: "
511 "\n%s" % (flavor_name, flavors))
513 if fixed_ip is not None:
514 nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
516 nics = {"net-id": network_id}
518 instance = nova_client.servers.create(
523 availability_zone=av_zone,
527 instance = nova_client.servers.create(
532 config_drive=confdrive,
534 availability_zone=av_zone,
540 def create_instance_and_wait_for_active(flavor_name,
550 VM_BOOT_TIMEOUT = 180
551 nova_client = get_nova_client()
552 instance = create_instance(flavor_name,
561 count = VM_BOOT_TIMEOUT / SLEEP
562 for n in range(count, -1, -1):
563 status = get_instance_status(nova_client, instance)
564 if status.lower() == "active":
566 elif status.lower() == "error":
567 logger.error("The instance %s went to ERROR status."
571 logger.error("Timeout booting the instance %s." % instance_name)
575 def create_floating_ip(neutron_client):
576 extnet_id = get_external_net_id(neutron_client)
577 props = {'floating_network_id': extnet_id}
579 ip_json = neutron_client.create_floatingip({'floatingip': props})
580 fip_addr = ip_json['floatingip']['floating_ip_address']
581 fip_id = ip_json['floatingip']['id']
582 except Exception as e:
583 logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
585 return {'fip_addr': fip_addr, 'fip_id': fip_id}
588 def add_floating_ip(nova_client, server_id, floatingip_addr):
590 nova_client.servers.add_floating_ip(server_id, floatingip_addr)
592 except Exception as e:
593 logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
594 % (server_id, floatingip_addr, e))
598 def delete_instance(nova_client, instance_id):
600 nova_client.servers.force_delete(instance_id)
602 except Exception as e:
603 logger.error("Error [delete_instance(nova_client, '%s')]: %s"
608 def delete_floating_ip(neutron_client, floatingip_id):
610 neutron_client.delete_floatingip(floatingip_id)
612 except Exception as e:
613 logger.error("Error [delete_floating_ip(neutron_client, '%s')]: %s"
614 % (floatingip_id, e))
618 def remove_host_from_aggregate(nova_client, aggregate_name, compute_host):
620 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
621 nova_client.aggregates.remove_host(aggregate_id, compute_host)
623 except Exception as e:
624 logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
625 " %s" % (aggregate_name, compute_host, e))
629 def remove_hosts_from_aggregate(nova_client, aggregate_name):
630 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
631 hosts = nova_client.aggregates.get(aggregate_id).hosts
633 all(remove_host_from_aggregate(nova_client, aggregate_name, host)
637 def delete_aggregate(nova_client, aggregate_name):
639 remove_hosts_from_aggregate(nova_client, aggregate_name)
640 nova_client.aggregates.delete(aggregate_name)
642 except Exception as e:
643 logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
644 % (aggregate_name, e))
648 # *********************************************
650 # *********************************************
651 def get_network_list(neutron_client):
652 network_list = neutron_client.list_networks()['networks']
653 if len(network_list) == 0:
659 def get_router_list(neutron_client):
660 router_list = neutron_client.list_routers()['routers']
661 if len(router_list) == 0:
667 def get_port_list(neutron_client):
668 port_list = neutron_client.list_ports()['ports']
669 if len(port_list) == 0:
675 def get_network_id(neutron_client, network_name):
676 networks = neutron_client.list_networks()['networks']
679 if n['name'] == network_name:
685 def get_subnet_id(neutron_client, subnet_name):
686 subnets = neutron_client.list_subnets()['subnets']
689 if s['name'] == subnet_name:
695 def get_router_id(neutron_client, router_name):
696 routers = neutron_client.list_routers()['routers']
699 if r['name'] == router_name:
705 def get_private_net(neutron_client):
706 # Checks if there is an existing shared private network
707 networks = neutron_client.list_networks()['networks']
708 if len(networks) == 0:
711 if (net['router:external'] is False) and (net['shared'] is True):
716 def get_external_net(neutron_client):
717 if (hasattr(CONST, 'EXTERNAL_NETWORK')):
718 return CONST.__getattribute__('EXTERNAL_NETWORK')
719 for network in neutron_client.list_networks()['networks']:
720 if network['router:external']:
721 return network['name']
725 def get_external_net_id(neutron_client):
726 if (hasattr(CONST, 'EXTERNAL_NETWORK')):
727 networks = neutron_client.list_networks(
728 name=CONST.__getattribute__('EXTERNAL_NETWORK'))
729 net_id = networks['networks'][0]['id']
731 for network in neutron_client.list_networks()['networks']:
732 if network['router:external']:
737 def check_neutron_net(neutron_client, net_name):
738 for network in neutron_client.list_networks()['networks']:
739 if network['name'] == net_name:
740 for subnet in network['subnets']:
745 def create_neutron_net(neutron_client, name):
746 json_body = {'network': {'name': name,
747 'admin_state_up': True}}
749 network = neutron_client.create_network(body=json_body)
750 network_dict = network['network']
751 return network_dict['id']
752 except Exception as e:
753 logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
758 def create_neutron_subnet(neutron_client, name, cidr, net_id,
759 dns=['8.8.8.8', '8.8.4.4']):
760 json_body = {'subnets': [{'name': name, 'cidr': cidr,
761 'ip_version': 4, 'network_id': net_id,
762 'dns_nameservers': dns}]}
765 subnet = neutron_client.create_subnet(body=json_body)
766 return subnet['subnets'][0]['id']
767 except Exception as e:
768 logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
769 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
773 def create_neutron_router(neutron_client, name):
774 json_body = {'router': {'name': name, 'admin_state_up': True}}
776 router = neutron_client.create_router(json_body)
777 return router['router']['id']
778 except Exception as e:
779 logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
784 def create_neutron_port(neutron_client, name, network_id, ip):
785 json_body = {'port': {
786 'admin_state_up': True,
788 'network_id': network_id,
789 'fixed_ips': [{"ip_address": ip}]
792 port = neutron_client.create_port(body=json_body)
793 return port['port']['id']
794 except Exception as e:
795 logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
796 "'%s')]: %s" % (name, network_id, ip, e))
800 def update_neutron_net(neutron_client, network_id, shared=False):
801 json_body = {'network': {'shared': shared}}
803 neutron_client.update_network(network_id, body=json_body)
805 except Exception as e:
806 logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
807 "%s" % (network_id, str(shared), e))
811 def update_neutron_port(neutron_client, port_id, device_owner):
812 json_body = {'port': {
813 'device_owner': device_owner,
816 port = neutron_client.update_port(port=port_id,
818 return port['port']['id']
819 except Exception as e:
820 logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
821 " %s" % (port_id, device_owner, e))
825 def add_interface_router(neutron_client, router_id, subnet_id):
826 json_body = {"subnet_id": subnet_id}
828 neutron_client.add_interface_router(router=router_id, body=json_body)
830 except Exception as e:
831 logger.error("Error [add_interface_router(neutron_client, '%s', "
832 "'%s')]: %s" % (router_id, subnet_id, e))
836 def add_gateway_router(neutron_client, router_id):
837 ext_net_id = get_external_net_id(neutron_client)
838 router_dict = {'network_id': ext_net_id}
840 neutron_client.add_gateway_router(router_id, router_dict)
842 except Exception as e:
843 logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
848 def delete_neutron_net(neutron_client, network_id):
850 neutron_client.delete_network(network_id)
852 except Exception as e:
853 logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
858 def delete_neutron_subnet(neutron_client, subnet_id):
860 neutron_client.delete_subnet(subnet_id)
862 except Exception as e:
863 logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
868 def delete_neutron_router(neutron_client, router_id):
870 neutron_client.delete_router(router=router_id)
872 except Exception as e:
873 logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
878 def delete_neutron_port(neutron_client, port_id):
880 neutron_client.delete_port(port_id)
882 except Exception as e:
883 logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
888 def remove_interface_router(neutron_client, router_id, subnet_id):
889 json_body = {"subnet_id": subnet_id}
891 neutron_client.remove_interface_router(router=router_id,
894 except Exception as e:
895 logger.error("Error [remove_interface_router(neutron_client, '%s', "
896 "'%s')]: %s" % (router_id, subnet_id, e))
900 def remove_gateway_router(neutron_client, router_id):
902 neutron_client.remove_gateway_router(router_id)
904 except Exception as e:
905 logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
910 def create_network_full(neutron_client,
915 dns=['8.8.8.8', '8.8.4.4']):
917 # Check if the network already exists
918 network_id = get_network_id(neutron_client, net_name)
919 subnet_id = get_subnet_id(neutron_client, subnet_name)
920 router_id = get_router_id(neutron_client, router_name)
922 if network_id != '' and subnet_id != '' and router_id != '':
923 logger.info("A network with name '%s' already exists..." % net_name)
925 neutron_client.format = 'json'
926 logger.info('Creating neutron network %s...' % net_name)
927 network_id = create_neutron_net(neutron_client, net_name)
932 logger.debug("Network '%s' created successfully" % network_id)
933 logger.debug('Creating Subnet....')
934 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
935 cidr, network_id, dns)
939 logger.debug("Subnet '%s' created successfully" % subnet_id)
940 logger.debug('Creating Router...')
941 router_id = create_neutron_router(neutron_client, router_name)
946 logger.debug("Router '%s' created successfully" % router_id)
947 logger.debug('Adding router to subnet...')
949 if not add_interface_router(neutron_client, router_id, subnet_id):
952 logger.debug("Interface added successfully.")
954 logger.debug('Adding gateway to router...')
955 if not add_gateway_router(neutron_client, router_id):
958 logger.debug("Gateway added successfully.")
960 network_dic = {'net_id': network_id,
961 'subnet_id': subnet_id,
962 'router_id': router_id}
966 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
967 neutron_client = get_neutron_client()
969 network_dic = create_network_full(neutron_client,
975 if not update_neutron_net(neutron_client,
976 network_dic['net_id'],
978 logger.error("Failed to update network %s..." % net_name)
981 logger.debug("Network '%s' is available..." % net_name)
983 logger.error("Network %s creation failed" % net_name)
988 # *********************************************
990 # *********************************************
993 def get_security_groups(neutron_client):
995 security_groups = neutron_client.list_security_groups()[
997 return security_groups
998 except Exception as e:
999 logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
1003 def get_security_group_id(neutron_client, sg_name):
1004 security_groups = get_security_groups(neutron_client)
1006 for sg in security_groups:
1007 if sg['name'] == sg_name:
1013 def create_security_group(neutron_client, sg_name, sg_description):
1014 json_body = {'security_group': {'name': sg_name,
1015 'description': sg_description}}
1017 secgroup = neutron_client.create_security_group(json_body)
1018 return secgroup['security_group']
1019 except Exception as e:
1020 logger.error("Error [create_security_group(neutron_client, '%s', "
1021 "'%s')]: %s" % (sg_name, sg_description, e))
1025 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
1026 port_range_min=None, port_range_max=None):
1027 # We create a security group in 2 steps
1028 # 1 - we check the format and set the json body accordingly
1029 # 2 - we call neturon client to create the security group
1032 json_body = {'security_group_rule': {'direction': direction,
1033 'security_group_id': sg_id,
1034 'protocol': protocol}}
1036 # - both None => we do nothing
1037 # - both Not None => we add them to the json description
1038 # but one cannot be None is the other is not None
1039 if (port_range_min is not None and port_range_max is not None):
1040 # add port_range in json description
1041 json_body['security_group_rule']['port_range_min'] = port_range_min
1042 json_body['security_group_rule']['port_range_max'] = port_range_max
1043 logger.debug("Security_group format set (port range included)")
1045 # either both port range are set to None => do nothing
1046 # or one is set but not the other => log it and return False
1047 if port_range_min is None and port_range_max is None:
1048 logger.debug("Security_group format set (no port range mentioned)")
1050 logger.error("Bad security group format."
1051 "One of the port range is not properly set:"
1053 "range max: {}".format(port_range_min,
1057 # Create security group using neutron client
1059 neutron_client.create_security_group_rule(json_body)
1062 logger.exception("Impossible to create_security_group_rule,"
1063 "security group rule probably already exists")
1067 def get_security_group_rules(neutron_client, sg_id):
1069 security_rules = neutron_client.list_security_group_rules()[
1070 'security_group_rules']
1071 security_rules = [rule for rule in security_rules
1072 if rule["security_group_id"] == sg_id]
1073 return security_rules
1074 except Exception as e:
1075 logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:"
1080 def check_security_group_rules(neutron_client, sg_id, direction, protocol,
1081 port_min=None, port_max=None):
1083 security_rules = get_security_group_rules(neutron_client, sg_id)
1084 security_rules = [rule for rule in security_rules
1085 if (rule["direction"].lower() == direction and
1086 rule["protocol"].lower() == protocol and
1087 rule["port_range_min"] == port_min and
1088 rule["port_range_max"] == port_max)]
1089 if len(security_rules) == 0:
1093 except Exception as e:
1094 logger.error("Error [check_security_group_rules("
1095 " neutron_client, sg_id, direction,"
1096 " protocol, port_min=None, port_max=None)]: "
1101 def create_security_group_full(neutron_client,
1102 sg_name, sg_description):
1103 sg_id = get_security_group_id(neutron_client, sg_name)
1105 logger.info("Using existing security group '%s'..." % sg_name)
1107 logger.info("Creating security group '%s'..." % sg_name)
1108 SECGROUP = create_security_group(neutron_client,
1112 logger.error("Failed to create the security group...")
1115 sg_id = SECGROUP['id']
1117 logger.debug("Security group '%s' with ID=%s created successfully."
1118 % (SECGROUP['name'], sg_id))
1120 logger.debug("Adding ICMP rules in security group '%s'..."
1122 if not create_secgroup_rule(neutron_client, sg_id,
1124 logger.error("Failed to create the security group rule...")
1127 logger.debug("Adding SSH rules in security group '%s'..."
1129 if not create_secgroup_rule(
1130 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1131 logger.error("Failed to create the security group rule...")
1134 if not create_secgroup_rule(
1135 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1136 logger.error("Failed to create the security group rule...")
1141 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
1143 nova_client.servers.add_security_group(instance_id, secgroup_id)
1145 except Exception as e:
1146 logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
1147 "'%s')]: %s" % (instance_id, secgroup_id, e))
1151 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1152 json_body = {"quota": {
1153 "security_group": sg_quota,
1154 "security_group_rule": sg_rule_quota
1158 neutron_client.update_quota(tenant_id=tenant_id,
1161 except Exception as e:
1162 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1163 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1167 def delete_security_group(neutron_client, secgroup_id):
1169 neutron_client.delete_security_group(secgroup_id)
1171 except Exception as e:
1172 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1177 # *********************************************
1179 # *********************************************
1180 def get_images(glance_client):
1182 images = glance_client.images.list()
1184 except Exception as e:
1185 logger.error("Error [get_images]: %s" % e)
1189 def get_image_id(glance_client, image_name):
1190 images = glance_client.images.list()
1193 if i.name == image_name:
1199 def create_glance_image(glance_client,
1203 extra_properties={},
1206 if not os.path.isfile(file_path):
1207 logger.error("Error: file %s does not exist." % file_path)
1210 image_id = get_image_id(glance_client, image_name)
1212 logger.info("Image %s already exists." % image_name)
1214 logger.info("Creating image '%s' from '%s'..." % (image_name,
1217 image = glance_client.images.create(name=image_name,
1220 container_format=container,
1223 with open(file_path) as image_data:
1224 glance_client.images.upload(image_id, image_data)
1226 except Exception as e:
1227 logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1228 "'%s')]: %s" % (image_name, file_path, public, e))
1232 def get_or_create_image(name, path, format, extra_properties):
1233 image_exists = False
1234 glance_client = get_glance_client()
1236 image_id = get_image_id(glance_client, name)
1238 logger.info("Using existing image '%s'..." % name)
1241 logger.info("Creating image '%s' from '%s'..." % (name, path))
1242 image_id = create_glance_image(glance_client,
1248 logger.error("Failed to create a Glance image...")
1250 logger.debug("Image '%s' with ID=%s created successfully."
1253 return image_exists, image_id
1256 def delete_glance_image(glance_client, image_id):
1258 glance_client.images.delete(image_id)
1260 except Exception as e:
1261 logger.error("Error [delete_glance_image(glance_client, '%s')]: %s"
1266 # *********************************************
1268 # *********************************************
1269 def get_volumes(cinder_client):
1271 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1273 except Exception as e:
1274 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1278 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1279 snapshots_quota, gigabytes_quota):
1280 quotas_values = {"volumes": vols_quota,
1281 "snapshots": snapshots_quota,
1282 "gigabytes": gigabytes_quota}
1285 cinder_client.quotas.update(tenant_id, **quotas_values)
1287 except Exception as e:
1288 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1289 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1290 snapshots_quota, gigabytes_quota, e))
1294 def delete_volume(cinder_client, volume_id, forced=False):
1298 cinder_client.volumes.detach(volume_id)
1300 logger.error(sys.exc_info()[0])
1301 cinder_client.volumes.force_delete(volume_id)
1303 cinder_client.volumes.delete(volume_id)
1305 except Exception as e:
1306 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1307 % (volume_id, str(forced), e))
1311 # *********************************************
1313 # *********************************************
1314 def get_tenants(keystone_client):
1316 if is_keystone_v3():
1317 tenants = keystone_client.projects.list()
1319 tenants = keystone_client.tenants.list()
1321 except Exception as e:
1322 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1326 def get_users(keystone_client):
1328 users = keystone_client.users.list()
1330 except Exception as e:
1331 logger.error("Error [get_users(keystone_client)]: %s" % e)
1335 def get_tenant_id(keystone_client, tenant_name):
1336 tenants = get_tenants(keystone_client)
1339 if t.name == tenant_name:
1345 def get_user_id(keystone_client, user_name):
1346 users = get_users(keystone_client)
1349 if u.name == user_name:
1355 def get_role_id(keystone_client, role_name):
1356 roles = keystone_client.roles.list()
1359 if r.name == role_name:
1365 def get_domain_id(keystone_client, domain_name):
1366 domains = keystone_client.domains.list()
1369 if d.name == domain_name:
1375 def create_tenant(keystone_client, tenant_name, tenant_description):
1377 if is_keystone_v3():
1378 domain_name = CONST.__getattribute__('OS_PROJECT_DOMAIN_NAME')
1379 domain_id = get_domain_id(keystone_client, domain_name)
1380 tenant = keystone_client.projects.create(
1382 description=tenant_description,
1386 tenant = keystone_client.tenants.create(tenant_name,
1390 except Exception as e:
1391 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1392 % (tenant_name, tenant_description, e))
1396 def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
1397 tenant_id = get_tenant_id(keystone_client, tenant_name)
1399 tenant_id = create_tenant(keystone_client, tenant_name,
1405 def get_or_create_tenant_for_vnf(keystone_client, tenant_name,
1406 tenant_description):
1407 """Get or Create a Tenant
1410 keystone_client: keystone client reference
1411 tenant_name: the name of the tenant
1412 tenant_description: the description of the tenant
1414 return False if tenant retrieved though get
1415 return True if tenant created
1416 raise Exception if error during processing
1419 tenant_id = get_tenant_id(keystone_client, tenant_name)
1421 tenant_id = create_tenant(keystone_client, tenant_name,
1427 raise Exception("Impossible to create a Tenant for the VNF {}".format(
1431 def create_user(keystone_client, user_name, user_password,
1432 user_email, tenant_id):
1434 if is_keystone_v3():
1435 user = keystone_client.users.create(name=user_name,
1436 password=user_password,
1438 project_id=tenant_id,
1441 user = keystone_client.users.create(user_name,
1447 except Exception as e:
1448 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1449 "'%s')]: %s" % (user_name, user_password,
1450 user_email, tenant_id, e))
1454 def get_or_create_user(keystone_client, user_name, user_password,
1455 tenant_id, user_email=None):
1456 user_id = get_user_id(keystone_client, user_name)
1458 user_id = create_user(keystone_client, user_name, user_password,
1459 user_email, tenant_id)
1463 def get_or_create_user_for_vnf(keystone_client, vnf_ref):
1464 """Get or Create user for VNF
1467 keystone_client: keystone client reference
1468 vnf_ref: VNF reference used as user name & password, tenant name
1470 return False if user retrieved through get
1471 return True if user created
1472 raise Exception if error during processing
1475 user_id = get_user_id(keystone_client, vnf_ref)
1476 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1479 user_id = create_user(keystone_client, vnf_ref, vnf_ref,
1483 role_id = get_role_id(keystone_client, 'admin')
1484 tenant_id = get_tenant_id(keystone_client, vnf_ref)
1485 add_role_user(keystone_client, user_id, role_id, tenant_id)
1487 logger.warn("Cannot associate user to role admin on tenant")
1490 raise Exception("Impossible to create a user for the VNF {}".format(
1494 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1496 if is_keystone_v3():
1497 keystone_client.roles.grant(role=role_id,
1501 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1503 except Exception as e:
1504 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1505 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1509 def delete_tenant(keystone_client, tenant_id):
1511 if is_keystone_v3():
1512 keystone_client.projects.delete(tenant_id)
1514 keystone_client.tenants.delete(tenant_id)
1516 except Exception as e:
1517 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1522 def delete_user(keystone_client, user_id):
1524 keystone_client.users.delete(user_id)
1526 except Exception as e:
1527 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1532 # *********************************************
1534 # *********************************************
1535 def get_resource(heat_client, stack_id, resource):
1537 resources = heat_client.resources.get(stack_id, resource)
1539 except Exception as e:
1540 logger.error("Error [get_resource]: %s" % e)