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 import functest.utils.functest_logger as ft_logger
27 import functest.utils.functest_utils as ft_utils
29 logger = ft_logger.Logger("openstack_utils").getLogger()
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'
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 source_credentials(rc_file):
118 with open(rc_file, "r") as f:
120 var = line.rstrip('"\n').replace('export ', '').split("=")
121 # The two next lines should be modified as soon as rc_file
122 # conforms with common rules. Be aware that it could induce
123 # issues if value starts with '
124 key = re.sub(r'^["\' ]*|[ \'"]*$', '', var[0])
125 value = re.sub(r'^["\' ]*|[ \'"]*$', '', "".join(var[1:]))
126 os.environ[key] = value
129 def get_credentials_for_rally():
130 creds = get_credentials()
131 env_cred_dict = get_env_cred_dict()
132 rally_conf = {"type": "ExistingCloud", "admin": {}}
134 if key == 'auth_url':
135 rally_conf[key] = creds[key]
137 rally_conf['admin'][key] = creds[key]
139 endpoint_types = [('internalURL', 'internal'),
140 ('publicURL', 'public'), ('adminURL', 'admin')]
142 endpoint_type = os.getenv('OS_ENDPOINT_TYPE')
143 if endpoint_type is not None:
144 cred_key = env_cred_dict.get('OS_ENDPOINT_TYPE')
145 for k, v in endpoint_types:
146 if endpoint_type == k:
147 rally_conf[cred_key] = v
149 region_name = os.getenv('OS_REGION_NAME')
150 if region_name is not None:
151 cred_key = env_cred_dict.get('OS_REGION_NAME')
152 rally_conf[cred_key] = region_name
154 cacert = os.getenv('OS_CACERT')
155 if cacert is not None:
156 cred_key = env_cred_dict.get('OS_CACERT')
157 rally_conf[cred_key] = cacert
161 def get_session_auth(other_creds={}):
162 loader = loading.get_plugin_loader('password')
163 creds = get_credentials(other_creds)
164 auth = loader.load_from_options(**creds)
168 def get_endpoint(service_type, endpoint_type='publicURL'):
169 auth = get_session_auth()
170 return get_session().get_endpoint(auth=auth,
171 service_type=service_type,
172 endpoint_type=endpoint_type)
175 def get_session(other_creds={}):
176 auth = get_session_auth(other_creds)
177 cacert = os.getenv('OS_CACERT')
178 if cacert is not None:
179 if not os.path.isfile(cacert):
180 raise Exception("The 'OS_CACERT' environment"
181 "variable is set to %s but the file"
182 "does not exist.", cacert)
184 return session.Session(auth=auth, verify=cacert)
187 # *********************************************
189 # *********************************************
190 def get_keystone_client_version():
191 api_version = os.getenv('OS_IDENTITY_API_VERSION')
192 if api_version is not None:
193 logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
196 return DEFAULT_API_VERSION
199 def get_keystone_client(other_creds={}):
200 sess = get_session(other_creds)
201 return keystoneclient.Client(get_keystone_client_version(), session=sess)
204 def get_nova_client_version():
205 api_version = os.getenv('OS_COMPUTE_API_VERSION')
206 if api_version is not None:
207 logger.info("OS_COMPUTE_API_VERSION is set in env as '%s'",
210 return DEFAULT_API_VERSION
213 def get_nova_client(other_creds={}):
214 sess = get_session(other_creds)
215 return novaclient.Client(get_nova_client_version(), session=sess)
218 def get_cinder_client_version():
219 api_version = os.getenv('OS_VOLUME_API_VERSION')
220 if api_version is not None:
221 logger.info("OS_VOLUME_API_VERSION is set in env as '%s'",
224 return DEFAULT_API_VERSION
227 def get_cinder_client(other_creds={}):
228 sess = get_session(other_creds)
229 return cinderclient.Client(get_cinder_client_version(), session=sess)
232 def get_neutron_client_version():
233 api_version = os.getenv('OS_NETWORK_API_VERSION')
234 if api_version is not None:
235 logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
238 return DEFAULT_API_VERSION
241 def get_neutron_client(other_creds={}):
242 sess = get_session(other_creds)
243 return neutronclient.Client(get_neutron_client_version(), session=sess)
246 def get_glance_client_version():
247 api_version = os.getenv('OS_IMAGE_API_VERSION')
248 if api_version is not None:
249 logger.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version)
251 return DEFAULT_API_VERSION
254 def get_glance_client(other_creds={}):
255 sess = get_session(other_creds)
256 return glanceclient.Client(get_glance_client_version(), session=sess)
259 def get_heat_client_version():
260 api_version = os.getenv('OS_ORCHESTRATION_API_VERSION')
261 if api_version is not None:
262 logger.info("OS_ORCHESTRATION_API_VERSION is set in env as '%s'",
265 return DEFAULT_HEAT_API_VERSION
268 def get_heat_client(other_creds={}):
269 sess = get_session(other_creds)
270 return heatclient.Client(get_heat_client_version(), session=sess)
273 # *********************************************
275 # *********************************************
276 def get_instances(nova_client):
278 instances = nova_client.servers.list(search_opts={'all_tenants': 1})
281 logger.error("Error [get_instances(nova_client)]: %s" % e)
285 def get_instance_status(nova_client, instance):
287 instance = nova_client.servers.get(instance.id)
288 return instance.status
290 logger.error("Error [get_instance_status(nova_client)]: %s" % e)
294 def get_instance_by_name(nova_client, instance_name):
296 instance = nova_client.servers.find(name=instance_name)
299 logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
300 % (instance_name, e))
304 def get_flavor_id(nova_client, flavor_name):
305 flavors = nova_client.flavors.list(detailed=True)
308 if f.name == flavor_name:
314 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
315 flavors = nova_client.flavors.list(detailed=True)
318 if min_ram <= f.ram and f.ram <= max_ram:
324 def get_aggregates(nova_client):
326 aggregates = nova_client.aggregates.list()
329 logger.error("Error [get_aggregates(nova_client)]: %s" % e)
333 def get_aggregate_id(nova_client, aggregate_name):
335 aggregates = get_aggregates(nova_client)
336 _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
339 logger.error("Error [get_aggregate_id(nova_client, %s)]:"
340 " %s" % (aggregate_name, e))
344 def get_availability_zones(nova_client):
346 availability_zones = nova_client.availability_zones.list()
347 return availability_zones
349 logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
353 def get_availability_zone_names(nova_client):
355 az_names = [az.zoneName for az in get_availability_zones(nova_client)]
358 logger.error("Error [get_availability_zone_names(nova_client)]:"
363 def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
365 flavor = nova_client.flavors.create(
366 flavor_name, ram, vcpus, disk, is_public=public)
368 extra_specs = ft_utils.get_functest_config(
369 'general.flavor_extra_specs')
370 flavor.set_keys(extra_specs)
372 # flavor extra specs are not configured, therefore skip the update
376 logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
377 "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
382 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
383 flavor_exists = False
384 nova_client = get_nova_client()
386 flavor_id = get_flavor_id(nova_client, flavor_name)
388 logger.info("Using existing flavor '%s'..." % flavor_name)
391 logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
392 "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
393 flavor_id = create_flavor(
394 nova_client, flavor_name, ram, disk, vcpus, public=public)
396 logger.error("Failed to create flavor '%s'..." % (flavor_name))
398 logger.debug("Flavor '%s' with ID=%s created successfully."
399 % (flavor_name, flavor_id))
401 return flavor_exists, flavor_id
404 def get_floating_ips(nova_client):
406 floating_ips = nova_client.floating_ips.list()
409 logger.error("Error [get_floating_ips(nova_client)]: %s" % e)
413 def get_hypervisors(nova_client):
416 hypervisors = nova_client.hypervisors.list()
417 for hypervisor in hypervisors:
418 if hypervisor.state == "up":
419 nodes.append(hypervisor.hypervisor_hostname)
422 logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
426 def create_aggregate(nova_client, aggregate_name, av_zone):
428 nova_client.aggregates.create(aggregate_name, av_zone)
431 logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
432 % (aggregate_name, av_zone, e))
436 def add_host_to_aggregate(nova_client, aggregate_name, compute_host):
438 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
439 nova_client.aggregates.add_host(aggregate_id, compute_host)
442 logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
443 % (aggregate_name, compute_host, e))
447 def create_aggregate_with_host(
448 nova_client, aggregate_name, av_zone, compute_host):
450 create_aggregate(nova_client, aggregate_name, av_zone)
451 add_host_to_aggregate(nova_client, aggregate_name, compute_host)
454 logger.error("Error [create_aggregate_with_host("
455 "nova_client, %s, %s, %s)]: %s"
456 % (aggregate_name, av_zone, compute_host, e))
460 def create_instance(flavor_name,
463 instance_name="functest-vm",
469 nova_client = get_nova_client()
471 flavor = nova_client.flavors.find(name=flavor_name)
473 flavors = nova_client.flavors.list()
474 logger.error("Error: Flavor '%s' not found. Available flavors are: "
475 "\n%s" % (flavor_name, flavors))
477 if fixed_ip is not None:
478 nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
480 nics = {"net-id": network_id}
482 instance = nova_client.servers.create(
487 availability_zone=av_zone,
491 instance = nova_client.servers.create(
496 config_drive=confdrive,
498 availability_zone=av_zone,
504 def create_instance_and_wait_for_active(flavor_name,
514 VM_BOOT_TIMEOUT = 180
515 nova_client = get_nova_client()
516 instance = create_instance(flavor_name,
525 count = VM_BOOT_TIMEOUT / SLEEP
526 for n in range(count, -1, -1):
527 status = get_instance_status(nova_client, instance)
528 if status.lower() == "active":
530 elif status.lower() == "error":
531 logger.error("The instance %s went to ERROR status."
535 logger.error("Timeout booting the instance %s." % instance_name)
539 def create_floating_ip(neutron_client):
540 extnet_id = get_external_net_id(neutron_client)
541 props = {'floating_network_id': extnet_id}
543 ip_json = neutron_client.create_floatingip({'floatingip': props})
544 fip_addr = ip_json['floatingip']['floating_ip_address']
545 fip_id = ip_json['floatingip']['id']
547 logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
549 return {'fip_addr': fip_addr, 'fip_id': fip_id}
552 def add_floating_ip(nova_client, server_id, floatingip_addr):
554 nova_client.servers.add_floating_ip(server_id, floatingip_addr)
557 logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
558 % (server_id, floatingip_addr, e))
562 def delete_instance(nova_client, instance_id):
564 nova_client.servers.force_delete(instance_id)
567 logger.error("Error [delete_instance(nova_client, '%s')]: %s"
572 def delete_floating_ip(nova_client, floatingip_id):
574 nova_client.floating_ips.delete(floatingip_id)
577 logger.error("Error [delete_floating_ip(nova_client, '%s')]: %s"
578 % (floatingip_id, e))
582 def remove_host_from_aggregate(nova_client, aggregate_name, compute_host):
584 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
585 nova_client.aggregates.remove_host(aggregate_id, compute_host)
588 logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
589 " %s" % (aggregate_name, compute_host, e))
593 def remove_hosts_from_aggregate(nova_client, aggregate_name):
594 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
595 hosts = nova_client.aggregates.get(aggregate_id).hosts
597 all(remove_host_from_aggregate(nova_client, aggregate_name, host)
601 def delete_aggregate(nova_client, aggregate_name):
603 remove_hosts_from_aggregate(nova_client, aggregate_name)
604 nova_client.aggregates.delete(aggregate_name)
607 logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
608 % (aggregate_name, e))
612 # *********************************************
614 # *********************************************
615 def get_network_list(neutron_client):
616 network_list = neutron_client.list_networks()['networks']
617 if len(network_list) == 0:
623 def get_router_list(neutron_client):
624 router_list = neutron_client.list_routers()['routers']
625 if len(router_list) == 0:
631 def get_port_list(neutron_client):
632 port_list = neutron_client.list_ports()['ports']
633 if len(port_list) == 0:
639 def get_network_id(neutron_client, network_name):
640 networks = neutron_client.list_networks()['networks']
643 if n['name'] == network_name:
649 def get_subnet_id(neutron_client, subnet_name):
650 subnets = neutron_client.list_subnets()['subnets']
653 if s['name'] == subnet_name:
659 def get_router_id(neutron_client, router_name):
660 routers = neutron_client.list_routers()['routers']
663 if r['name'] == router_name:
669 def get_private_net(neutron_client):
670 # Checks if there is an existing shared private network
671 networks = neutron_client.list_networks()['networks']
672 if len(networks) == 0:
675 if (net['router:external'] is False) and (net['shared'] is True):
680 def get_external_net(neutron_client):
681 for network in neutron_client.list_networks()['networks']:
682 if network['router:external']:
683 return network['name']
687 def get_external_net_id(neutron_client):
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']
710 logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
715 def create_neutron_subnet(neutron_client, name, cidr, net_id):
716 json_body = {'subnets': [{'name': name, 'cidr': cidr,
717 'ip_version': 4, 'network_id': net_id}]}
719 subnet = neutron_client.create_subnet(body=json_body)
720 return subnet['subnets'][0]['id']
722 logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
723 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
727 def create_neutron_router(neutron_client, name):
728 json_body = {'router': {'name': name, 'admin_state_up': True}}
730 router = neutron_client.create_router(json_body)
731 return router['router']['id']
733 logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
738 def create_neutron_port(neutron_client, name, network_id, ip):
739 json_body = {'port': {
740 'admin_state_up': True,
742 'network_id': network_id,
743 'fixed_ips': [{"ip_address": ip}]
746 port = neutron_client.create_port(body=json_body)
747 return port['port']['id']
749 logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
750 "'%s')]: %s" % (name, network_id, ip, e))
754 def update_neutron_net(neutron_client, network_id, shared=False):
755 json_body = {'network': {'shared': shared}}
757 neutron_client.update_network(network_id, body=json_body)
760 logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
761 "%s" % (network_id, str(shared), e))
765 def update_neutron_port(neutron_client, port_id, device_owner):
766 json_body = {'port': {
767 'device_owner': device_owner,
770 port = neutron_client.update_port(port=port_id,
772 return port['port']['id']
774 logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
775 " %s" % (port_id, device_owner, e))
779 def add_interface_router(neutron_client, router_id, subnet_id):
780 json_body = {"subnet_id": subnet_id}
782 neutron_client.add_interface_router(router=router_id, body=json_body)
785 logger.error("Error [add_interface_router(neutron_client, '%s', "
786 "'%s')]: %s" % (router_id, subnet_id, e))
790 def add_gateway_router(neutron_client, router_id):
791 ext_net_id = get_external_net_id(neutron_client)
792 router_dict = {'network_id': ext_net_id}
794 neutron_client.add_gateway_router(router_id, router_dict)
797 logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
802 def delete_neutron_net(neutron_client, network_id):
804 neutron_client.delete_network(network_id)
807 logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
812 def delete_neutron_subnet(neutron_client, subnet_id):
814 neutron_client.delete_subnet(subnet_id)
817 logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
822 def delete_neutron_router(neutron_client, router_id):
824 neutron_client.delete_router(router=router_id)
827 logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
832 def delete_neutron_port(neutron_client, port_id):
834 neutron_client.delete_port(port_id)
837 logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
842 def remove_interface_router(neutron_client, router_id, subnet_id):
843 json_body = {"subnet_id": subnet_id}
845 neutron_client.remove_interface_router(router=router_id,
849 logger.error("Error [remove_interface_router(neutron_client, '%s', "
850 "'%s')]: %s" % (router_id, subnet_id, e))
854 def remove_gateway_router(neutron_client, router_id):
856 neutron_client.remove_gateway_router(router_id)
859 logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
864 def create_network_full(neutron_client,
870 # Check if the network already exists
871 network_id = get_network_id(neutron_client, net_name)
872 subnet_id = get_subnet_id(neutron_client, subnet_name)
873 router_id = get_router_id(neutron_client, router_name)
875 if network_id != '' and subnet_id != '' and router_id != '':
876 logger.info("A network with name '%s' already exists..." % net_name)
878 neutron_client.format = 'json'
879 logger.info('Creating neutron network %s...' % net_name)
880 network_id = create_neutron_net(neutron_client, net_name)
885 logger.debug("Network '%s' created successfully" % network_id)
886 logger.debug('Creating Subnet....')
887 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
892 logger.debug("Subnet '%s' created successfully" % subnet_id)
893 logger.debug('Creating Router...')
894 router_id = create_neutron_router(neutron_client, router_name)
899 logger.debug("Router '%s' created successfully" % router_id)
900 logger.debug('Adding router to subnet...')
902 if not add_interface_router(neutron_client, router_id, subnet_id):
905 logger.debug("Interface added successfully.")
907 logger.debug('Adding gateway to router...')
908 if not add_gateway_router(neutron_client, router_id):
911 logger.debug("Gateway added successfully.")
913 network_dic = {'net_id': network_id,
914 'subnet_id': subnet_id,
915 'router_id': router_id}
919 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
920 neutron_client = get_neutron_client()
922 network_dic = create_network_full(neutron_client,
928 if not update_neutron_net(neutron_client,
929 network_dic['net_id'],
931 logger.error("Failed to update network %s..." % net_name)
934 logger.debug("Network '%s' is available..." % net_name)
936 logger.error("Network %s creation failed" % net_name)
941 def create_bgpvpn(neutron_client, **kwargs):
942 # route_distinguishers
944 json_body = {"bgpvpn": kwargs}
945 return neutron_client.create_bgpvpn(json_body)
948 def create_network_association(neutron_client, bgpvpn_id, neutron_network_id):
949 json_body = {"network_association": {"network_id": neutron_network_id}}
950 return neutron_client.create_network_association(bgpvpn_id, json_body)
953 def create_router_association(neutron_client, bgpvpn_id, router_id):
954 json_body = {"router_association": {"router_id": router_id}}
955 return neutron_client.create_router_association(bgpvpn_id, json_body)
958 def update_bgpvpn(neutron_client, bgpvpn_id, **kwargs):
959 json_body = {"bgpvpn": kwargs}
960 return neutron_client.update_bgpvpn(bgpvpn_id, json_body)
963 def delete_bgpvpn(neutron_client, bgpvpn_id):
964 return neutron_client.delete_bgpvpn(bgpvpn_id)
967 def get_bgpvpn(neutron_client, bgpvpn_id):
968 return neutron_client.show_bgpvpn(bgpvpn_id)
971 def get_bgpvpn_routers(neutron_client, bgpvpn_id):
972 return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['routers']
975 def get_bgpvpn_networks(neutron_client, bgpvpn_id):
976 return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['networks']
978 # *********************************************
980 # *********************************************
983 def get_security_groups(neutron_client):
985 security_groups = neutron_client.list_security_groups()[
987 return security_groups
989 logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
993 def get_security_group_id(neutron_client, sg_name):
994 security_groups = get_security_groups(neutron_client)
996 for sg in security_groups:
997 if sg['name'] == sg_name:
1003 def create_security_group(neutron_client, sg_name, sg_description):
1004 json_body = {'security_group': {'name': sg_name,
1005 'description': sg_description}}
1007 secgroup = neutron_client.create_security_group(json_body)
1008 return secgroup['security_group']
1009 except Exception, e:
1010 logger.error("Error [create_security_group(neutron_client, '%s', "
1011 "'%s')]: %s" % (sg_name, sg_description, e))
1015 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
1016 port_range_min=None, port_range_max=None):
1017 # We create a security group in 2 steps
1018 # 1 - we check the format and set the json body accordingly
1019 # 2 - we call neturon client to create the security group
1022 json_body = {'security_group_rule': {'direction': direction,
1023 'security_group_id': sg_id,
1024 'protocol': protocol}}
1026 # - both None => we do nothing
1027 # - both Not None => we add them to the json description
1028 # but one cannot be None is the other is not None
1029 if (port_range_min is not None and port_range_max is not None):
1030 # add port_range in json description
1031 json_body['security_group_rule']['port_range_min'] = port_range_min
1032 json_body['security_group_rule']['port_range_max'] = port_range_max
1033 logger.debug("Security_group format set (port range included)")
1035 # either both port range are set to None => do nothing
1036 # or one is set but not the other => log it and return False
1037 if port_range_min is None and port_range_max is None:
1038 logger.debug("Security_group format set (no port range mentioned)")
1040 logger.error("Bad security group format."
1041 "One of the port range is not properly set:"
1043 "range max: {}".format(port_range_min,
1047 # Create security group using neutron client
1049 neutron_client.create_security_group_rule(json_body)
1052 logger.exception("Impossible to create_security_group_rule,"
1053 "security group rule probably already exists")
1057 def create_security_group_full(neutron_client,
1058 sg_name, sg_description):
1059 sg_id = get_security_group_id(neutron_client, sg_name)
1061 logger.info("Using existing security group '%s'..." % sg_name)
1063 logger.info("Creating security group '%s'..." % sg_name)
1064 SECGROUP = create_security_group(neutron_client,
1068 logger.error("Failed to create the security group...")
1071 sg_id = SECGROUP['id']
1073 logger.debug("Security group '%s' with ID=%s created successfully."
1074 % (SECGROUP['name'], sg_id))
1076 logger.debug("Adding ICMP rules in security group '%s'..."
1078 if not create_secgroup_rule(neutron_client, sg_id,
1080 logger.error("Failed to create the security group rule...")
1083 logger.debug("Adding SSH rules in security group '%s'..."
1085 if not create_secgroup_rule(
1086 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1087 logger.error("Failed to create the security group rule...")
1090 if not create_secgroup_rule(
1091 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1092 logger.error("Failed to create the security group rule...")
1097 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
1099 nova_client.servers.add_security_group(instance_id, secgroup_id)
1101 except Exception, e:
1102 logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
1103 "'%s')]: %s" % (instance_id, secgroup_id, e))
1107 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1108 json_body = {"quota": {
1109 "security_group": sg_quota,
1110 "security_group_rule": sg_rule_quota
1114 neutron_client.update_quota(tenant_id=tenant_id,
1117 except Exception, e:
1118 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1119 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1123 def delete_security_group(neutron_client, secgroup_id):
1125 neutron_client.delete_security_group(secgroup_id)
1127 except Exception, e:
1128 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1133 # *********************************************
1135 # *********************************************
1136 def get_images(nova_client):
1138 images = nova_client.images.list()
1140 except Exception, e:
1141 logger.error("Error [get_images]: %s" % e)
1145 def get_image_id(glance_client, image_name):
1146 images = glance_client.images.list()
1149 if i.name == image_name:
1155 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
1156 container="bare", public="public"):
1157 if not os.path.isfile(file_path):
1158 logger.error("Error: file %s does not exist." % file_path)
1161 image_id = get_image_id(glance_client, image_name)
1163 logger.info("Image %s already exists." % image_name)
1165 logger.info("Creating image '%s' from '%s'..." % (image_name,
1168 image = glance_client.images.create(name=image_name,
1171 container_format=container)
1173 with open(file_path) as image_data:
1174 glance_client.images.upload(image_id, image_data)
1176 except Exception, e:
1177 logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1178 "'%s')]: %s" % (image_name, file_path, public, e))
1182 def get_or_create_image(name, path, format):
1183 image_exists = False
1184 glance_client = get_glance_client()
1186 image_id = get_image_id(glance_client, name)
1188 logger.info("Using existing image '%s'..." % name)
1191 logger.info("Creating image '%s' from '%s'..." % (name, path))
1192 image_id = create_glance_image(glance_client, name, path, format)
1194 logger.error("Failed to create a Glance image...")
1196 logger.debug("Image '%s' with ID=%s created successfully."
1199 return image_exists, image_id
1202 def delete_glance_image(nova_client, image_id):
1204 nova_client.images.delete(image_id)
1206 except Exception, e:
1207 logger.error("Error [delete_glance_image(nova_client, '%s')]: %s"
1212 # *********************************************
1214 # *********************************************
1215 def get_volumes(cinder_client):
1217 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1219 except Exception, e:
1220 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1224 def list_volume_types(cinder_client, public=True, private=True):
1226 volume_types = cinder_client.volume_types.list()
1228 volume_types = [vt for vt in volume_types if not vt.is_public]
1230 volume_types = [vt for vt in volume_types if vt.is_public]
1232 except Exception, e:
1233 logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
1237 def create_volume_type(cinder_client, name):
1239 volume_type = cinder_client.volume_types.create(name)
1241 except Exception, e:
1242 logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
1247 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1248 snapshots_quota, gigabytes_quota):
1249 quotas_values = {"volumes": vols_quota,
1250 "snapshots": snapshots_quota,
1251 "gigabytes": gigabytes_quota}
1254 cinder_client.quotas.update(tenant_id, **quotas_values)
1256 except Exception, e:
1257 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1258 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1259 snapshots_quota, gigabytes_quota, e))
1263 def delete_volume(cinder_client, volume_id, forced=False):
1267 cinder_client.volumes.detach(volume_id)
1269 logger.error(sys.exc_info()[0])
1270 cinder_client.volumes.force_delete(volume_id)
1272 cinder_client.volumes.delete(volume_id)
1274 except Exception, e:
1275 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1276 % (volume_id, str(forced), e))
1280 def delete_volume_type(cinder_client, volume_type):
1282 cinder_client.volume_types.delete(volume_type)
1284 except Exception, e:
1285 logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
1290 # *********************************************
1292 # *********************************************
1293 def get_tenants(keystone_client):
1295 if is_keystone_v3():
1296 tenants = keystone_client.projects.list()
1298 tenants = keystone_client.tenants.list()
1300 except Exception, e:
1301 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1305 def get_users(keystone_client):
1307 users = keystone_client.users.list()
1309 except Exception, e:
1310 logger.error("Error [get_users(keystone_client)]: %s" % e)
1314 def get_tenant_id(keystone_client, tenant_name):
1315 tenants = get_tenants(keystone_client)
1318 if t.name == tenant_name:
1324 def get_user_id(keystone_client, user_name):
1325 users = get_users(keystone_client)
1328 if u.name == user_name:
1334 def get_role_id(keystone_client, role_name):
1335 roles = keystone_client.roles.list()
1338 if r.name == role_name:
1344 def create_tenant(keystone_client, tenant_name, tenant_description):
1346 if is_keystone_v3():
1347 tenant = keystone_client.projects.create(
1349 description=tenant_description,
1353 tenant = keystone_client.tenants.create(tenant_name,
1357 except Exception, e:
1358 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1359 % (tenant_name, tenant_description, e))
1363 def create_user(keystone_client, user_name, user_password,
1364 user_email, tenant_id):
1366 if is_keystone_v3():
1367 user = keystone_client.users.create(name=user_name,
1368 password=user_password,
1370 project_id=tenant_id,
1373 user = keystone_client.users.create(user_name,
1379 except Exception, e:
1380 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1381 "'%s')]: %s" % (user_name, user_password,
1382 user_email, tenant_id, e))
1386 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1388 if is_keystone_v3():
1389 keystone_client.roles.grant(role=role_id,
1393 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1395 except Exception, e:
1396 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1397 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1401 def delete_tenant(keystone_client, tenant_id):
1403 if is_keystone_v3():
1404 keystone_client.projects.delete(tenant_id)
1406 keystone_client.tenants.delete(tenant_id)
1408 except Exception, e:
1409 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1414 def delete_user(keystone_client, user_id):
1416 keystone_client.users.delete(user_id)
1418 except Exception, e:
1419 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1424 # *********************************************
1426 # *********************************************
1427 def get_resource(heat_client, stack_id, resource):
1429 resources = heat_client.resources.get(stack_id, resource)
1431 except Exception, e:
1432 logger.error("Error [get_resource]: %s" % e)