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'
90 def get_credentials(other_creds={}):
91 """Returns a creds dictionary filled with parsed from env
94 env_vars = get_rc_env_vars()
95 env_cred_dict = get_env_cred_dict()
97 for envvar in env_vars:
98 if os.getenv(envvar) is None:
99 raise MissingEnvVar(envvar)
101 creds_key = env_cred_dict.get(envvar)
102 creds.update({creds_key: os.getenv(envvar)})
104 if 'tenant' in other_creds.keys():
106 tenant = 'project_name'
108 tenant = 'tenant_name'
109 other_creds[tenant] = other_creds.pop('tenant')
111 creds.update(other_creds)
116 def source_credentials(rc_file):
117 with open(rc_file, "r") as f:
119 var = line.rstrip('"\n').replace('export ', '').split("=")
120 # The two next lines should be modified as soon as rc_file
121 # conforms with common rules. Be aware that it could induce
122 # issues if value starts with '
123 key = re.sub(r'^["\' ]*|[ \'"]*$', '', var[0])
124 value = re.sub(r'^["\' ]*|[ \'"]*$', '', "".join(var[1:]))
125 os.environ[key] = value
128 def get_credentials_for_rally():
129 creds = get_credentials()
130 env_cred_dict = get_env_cred_dict()
131 rally_conf = {"type": "ExistingCloud", "admin": {}}
133 if key == 'auth_url':
134 rally_conf[key] = creds[key]
136 rally_conf['admin'][key] = creds[key]
138 endpoint_types = [('internalURL', 'internal'),
139 ('publicURL', 'public'), ('adminURL', 'admin')]
141 endpoint_type = os.getenv('OS_ENDPOINT_TYPE')
142 if endpoint_type is not None:
143 cred_key = env_cred_dict.get('OS_ENDPOINT_TYPE')
144 for k, v in endpoint_types:
145 if endpoint_type == k:
146 rally_conf[cred_key] = v
148 region_name = os.getenv('OS_REGION_NAME')
149 if region_name is not None:
150 cred_key = env_cred_dict.get('OS_REGION_NAME')
151 rally_conf[cred_key] = region_name
155 def get_session_auth(other_creds={}):
156 loader = loading.get_plugin_loader('password')
157 creds = get_credentials(other_creds)
158 auth = loader.load_from_options(**creds)
162 def get_endpoint(service_type, endpoint_type='publicURL'):
163 auth = get_session_auth()
164 return get_session().get_endpoint(auth=auth,
165 service_type=service_type,
166 endpoint_type=endpoint_type)
169 def get_session(other_creds={}):
170 auth = get_session_auth(other_creds)
171 return session.Session(auth=auth)
174 # *********************************************
176 # *********************************************
177 def get_keystone_client_version():
178 api_version = os.getenv('OS_IDENTITY_API_VERSION')
179 if api_version is not None:
180 logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
183 return DEFAULT_API_VERSION
186 def get_keystone_client(other_creds={}):
187 sess = get_session(other_creds)
188 return keystoneclient.Client(get_keystone_client_version(), session=sess)
191 def get_nova_client_version():
192 api_version = os.getenv('OS_COMPUTE_API_VERSION')
193 if api_version is not None:
194 logger.info("OS_COMPUTE_API_VERSION is set in env as '%s'",
197 return DEFAULT_API_VERSION
200 def get_nova_client(other_creds={}):
201 sess = get_session(other_creds)
202 return novaclient.Client(get_nova_client_version(), session=sess)
205 def get_cinder_client_version():
206 api_version = os.getenv('OS_VOLUME_API_VERSION')
207 if api_version is not None:
208 logger.info("OS_VOLUME_API_VERSION is set in env as '%s'",
211 return DEFAULT_API_VERSION
214 def get_cinder_client(other_creds={}):
215 sess = get_session(other_creds)
216 return cinderclient.Client(get_cinder_client_version(), session=sess)
219 def get_neutron_client_version():
220 api_version = os.getenv('OS_NETWORK_API_VERSION')
221 if api_version is not None:
222 logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
225 return DEFAULT_API_VERSION
228 def get_neutron_client(other_creds={}):
229 sess = get_session(other_creds)
230 return neutronclient.Client(get_neutron_client_version(), session=sess)
233 def get_glance_client_version():
234 api_version = os.getenv('OS_IMAGE_API_VERSION')
235 if api_version is not None:
236 logger.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version)
238 return DEFAULT_API_VERSION
241 def get_glance_client(other_creds={}):
242 sess = get_session(other_creds)
243 return glanceclient.Client(get_glance_client_version(), session=sess)
246 def get_heat_client_version():
247 api_version = os.getenv('OS_ORCHESTRATION_API_VERSION')
248 if api_version is not None:
249 logger.info("OS_ORCHESTRATION_API_VERSION is set in env as '%s'",
252 return DEFAULT_HEAT_API_VERSION
255 def get_heat_client(other_creds={}):
256 sess = get_session(other_creds)
257 return heatclient.Client(get_heat_client_version(), session=sess)
260 # *********************************************
262 # *********************************************
263 def get_instances(nova_client):
265 instances = nova_client.servers.list(search_opts={'all_tenants': 1})
268 logger.error("Error [get_instances(nova_client)]: %s" % e)
272 def get_instance_status(nova_client, instance):
274 instance = nova_client.servers.get(instance.id)
275 return instance.status
277 logger.error("Error [get_instance_status(nova_client)]: %s" % e)
281 def get_instance_by_name(nova_client, instance_name):
283 instance = nova_client.servers.find(name=instance_name)
286 logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
287 % (instance_name, e))
291 def get_flavor_id(nova_client, flavor_name):
292 flavors = nova_client.flavors.list(detailed=True)
295 if f.name == flavor_name:
301 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
302 flavors = nova_client.flavors.list(detailed=True)
305 if min_ram <= f.ram and f.ram <= max_ram:
311 def get_aggregates(nova_client):
313 aggregates = nova_client.aggregates.list()
316 logger.error("Error [get_aggregates(nova_client)]: %s" % e)
320 def get_aggregate_id(nova_client, aggregate_name):
322 aggregates = get_aggregates(nova_client)
323 _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
326 logger.error("Error [get_aggregate_id(nova_client, %s)]:"
327 " %s" % (aggregate_name, e))
331 def get_availability_zones(nova_client):
333 availability_zones = nova_client.availability_zones.list()
334 return availability_zones
336 logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
340 def get_availability_zone_names(nova_client):
342 az_names = [az.zoneName for az in get_availability_zones(nova_client)]
345 logger.error("Error [get_availability_zone_names(nova_client)]:"
350 def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
352 flavor = nova_client.flavors.create(
353 flavor_name, ram, vcpus, disk, is_public=public)
355 extra_specs = ft_utils.get_functest_config(
356 'general.flavor_extra_specs')
357 flavor.set_keys(extra_specs)
359 # flavor extra specs are not configured, therefore skip the update
363 logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
364 "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
369 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
370 flavor_exists = False
371 nova_client = get_nova_client()
373 flavor_id = get_flavor_id(nova_client, flavor_name)
375 logger.info("Using existing flavor '%s'..." % flavor_name)
378 logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
379 "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
380 flavor_id = create_flavor(
381 nova_client, flavor_name, ram, disk, vcpus, public=public)
383 logger.error("Failed to create flavor '%s'..." % (flavor_name))
385 logger.debug("Flavor '%s' with ID=%s created successfully."
386 % (flavor_name, flavor_id))
388 return flavor_exists, flavor_id
391 def get_floating_ips(nova_client):
393 floating_ips = nova_client.floating_ips.list()
396 logger.error("Error [get_floating_ips(nova_client)]: %s" % e)
400 def get_hypervisors(nova_client):
403 hypervisors = nova_client.hypervisors.list()
404 for hypervisor in hypervisors:
405 if hypervisor.state == "up":
406 nodes.append(hypervisor.hypervisor_hostname)
409 logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
413 def create_aggregate(nova_client, aggregate_name, av_zone):
415 nova_client.aggregates.create(aggregate_name, av_zone)
418 logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
419 % (aggregate_name, av_zone, e))
423 def add_host_to_aggregate(nova_client, aggregate_name, compute_host):
425 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
426 nova_client.aggregates.add_host(aggregate_id, compute_host)
429 logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
430 % (aggregate_name, compute_host, e))
434 def create_aggregate_with_host(
435 nova_client, aggregate_name, av_zone, compute_host):
437 create_aggregate(nova_client, aggregate_name, av_zone)
438 add_host_to_aggregate(nova_client, aggregate_name, compute_host)
441 logger.error("Error [create_aggregate_with_host("
442 "nova_client, %s, %s, %s)]: %s"
443 % (aggregate_name, av_zone, compute_host, e))
447 def create_instance(flavor_name,
450 instance_name="functest-vm",
456 nova_client = get_nova_client()
458 flavor = nova_client.flavors.find(name=flavor_name)
460 flavors = nova_client.flavors.list()
461 logger.error("Error: Flavor '%s' not found. Available flavors are: "
462 "\n%s" % (flavor_name, flavors))
464 if fixed_ip is not None:
465 nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
467 nics = {"net-id": network_id}
469 instance = nova_client.servers.create(
474 availability_zone=av_zone,
478 instance = nova_client.servers.create(
483 config_drive=confdrive,
485 availability_zone=av_zone,
491 def create_instance_and_wait_for_active(flavor_name,
501 VM_BOOT_TIMEOUT = 180
502 nova_client = get_nova_client()
503 instance = create_instance(flavor_name,
512 count = VM_BOOT_TIMEOUT / SLEEP
513 for n in range(count, -1, -1):
514 status = get_instance_status(nova_client, instance)
515 if status.lower() == "active":
517 elif status.lower() == "error":
518 logger.error("The instance %s went to ERROR status."
522 logger.error("Timeout booting the instance %s." % instance_name)
526 def create_floating_ip(neutron_client):
527 extnet_id = get_external_net_id(neutron_client)
528 props = {'floating_network_id': extnet_id}
530 ip_json = neutron_client.create_floatingip({'floatingip': props})
531 fip_addr = ip_json['floatingip']['floating_ip_address']
532 fip_id = ip_json['floatingip']['id']
534 logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
536 return {'fip_addr': fip_addr, 'fip_id': fip_id}
539 def add_floating_ip(nova_client, server_id, floatingip_addr):
541 nova_client.servers.add_floating_ip(server_id, floatingip_addr)
544 logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
545 % (server_id, floatingip_addr, e))
549 def delete_instance(nova_client, instance_id):
551 nova_client.servers.force_delete(instance_id)
554 logger.error("Error [delete_instance(nova_client, '%s')]: %s"
559 def delete_floating_ip(nova_client, floatingip_id):
561 nova_client.floating_ips.delete(floatingip_id)
564 logger.error("Error [delete_floating_ip(nova_client, '%s')]: %s"
565 % (floatingip_id, e))
569 def remove_host_from_aggregate(nova_client, aggregate_name, compute_host):
571 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
572 nova_client.aggregates.remove_host(aggregate_id, compute_host)
575 logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
576 " %s" % (aggregate_name, compute_host, e))
580 def remove_hosts_from_aggregate(nova_client, aggregate_name):
581 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
582 hosts = nova_client.aggregates.get(aggregate_id).hosts
584 all(remove_host_from_aggregate(nova_client, aggregate_name, host)
588 def delete_aggregate(nova_client, aggregate_name):
590 remove_hosts_from_aggregate(nova_client, aggregate_name)
591 nova_client.aggregates.delete(aggregate_name)
594 logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
595 % (aggregate_name, e))
599 # *********************************************
601 # *********************************************
602 def get_network_list(neutron_client):
603 network_list = neutron_client.list_networks()['networks']
604 if len(network_list) == 0:
610 def get_router_list(neutron_client):
611 router_list = neutron_client.list_routers()['routers']
612 if len(router_list) == 0:
618 def get_port_list(neutron_client):
619 port_list = neutron_client.list_ports()['ports']
620 if len(port_list) == 0:
626 def get_network_id(neutron_client, network_name):
627 networks = neutron_client.list_networks()['networks']
630 if n['name'] == network_name:
636 def get_subnet_id(neutron_client, subnet_name):
637 subnets = neutron_client.list_subnets()['subnets']
640 if s['name'] == subnet_name:
646 def get_router_id(neutron_client, router_name):
647 routers = neutron_client.list_routers()['routers']
650 if r['name'] == router_name:
656 def get_private_net(neutron_client):
657 # Checks if there is an existing shared private network
658 networks = neutron_client.list_networks()['networks']
659 if len(networks) == 0:
662 if (net['router:external'] is False) and (net['shared'] is True):
667 def get_external_net(neutron_client):
668 for network in neutron_client.list_networks()['networks']:
669 if network['router:external']:
670 return network['name']
674 def get_external_net_id(neutron_client):
675 for network in neutron_client.list_networks()['networks']:
676 if network['router:external']:
681 def check_neutron_net(neutron_client, net_name):
682 for network in neutron_client.list_networks()['networks']:
683 if network['name'] == net_name:
684 for subnet in network['subnets']:
689 def create_neutron_net(neutron_client, name):
690 json_body = {'network': {'name': name,
691 'admin_state_up': True}}
693 network = neutron_client.create_network(body=json_body)
694 network_dict = network['network']
695 return network_dict['id']
697 logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
702 def create_neutron_subnet(neutron_client, name, cidr, net_id):
703 json_body = {'subnets': [{'name': name, 'cidr': cidr,
704 'ip_version': 4, 'network_id': net_id}]}
706 subnet = neutron_client.create_subnet(body=json_body)
707 return subnet['subnets'][0]['id']
709 logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
710 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
714 def create_neutron_router(neutron_client, name):
715 json_body = {'router': {'name': name, 'admin_state_up': True}}
717 router = neutron_client.create_router(json_body)
718 return router['router']['id']
720 logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
725 def create_neutron_port(neutron_client, name, network_id, ip):
726 json_body = {'port': {
727 'admin_state_up': True,
729 'network_id': network_id,
730 'fixed_ips': [{"ip_address": ip}]
733 port = neutron_client.create_port(body=json_body)
734 return port['port']['id']
736 logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
737 "'%s')]: %s" % (name, network_id, ip, e))
741 def update_neutron_net(neutron_client, network_id, shared=False):
742 json_body = {'network': {'shared': shared}}
744 neutron_client.update_network(network_id, body=json_body)
747 logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
748 "%s" % (network_id, str(shared), e))
752 def update_neutron_port(neutron_client, port_id, device_owner):
753 json_body = {'port': {
754 'device_owner': device_owner,
757 port = neutron_client.update_port(port=port_id,
759 return port['port']['id']
761 logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
762 " %s" % (port_id, device_owner, e))
766 def add_interface_router(neutron_client, router_id, subnet_id):
767 json_body = {"subnet_id": subnet_id}
769 neutron_client.add_interface_router(router=router_id, body=json_body)
772 logger.error("Error [add_interface_router(neutron_client, '%s', "
773 "'%s')]: %s" % (router_id, subnet_id, e))
777 def add_gateway_router(neutron_client, router_id):
778 ext_net_id = get_external_net_id(neutron_client)
779 router_dict = {'network_id': ext_net_id}
781 neutron_client.add_gateway_router(router_id, router_dict)
784 logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
789 def delete_neutron_net(neutron_client, network_id):
791 neutron_client.delete_network(network_id)
794 logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
799 def delete_neutron_subnet(neutron_client, subnet_id):
801 neutron_client.delete_subnet(subnet_id)
804 logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
809 def delete_neutron_router(neutron_client, router_id):
811 neutron_client.delete_router(router=router_id)
814 logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
819 def delete_neutron_port(neutron_client, port_id):
821 neutron_client.delete_port(port_id)
824 logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
829 def remove_interface_router(neutron_client, router_id, subnet_id):
830 json_body = {"subnet_id": subnet_id}
832 neutron_client.remove_interface_router(router=router_id,
836 logger.error("Error [remove_interface_router(neutron_client, '%s', "
837 "'%s')]: %s" % (router_id, subnet_id, e))
841 def remove_gateway_router(neutron_client, router_id):
843 neutron_client.remove_gateway_router(router_id)
846 logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
851 def create_network_full(neutron_client,
857 # Check if the network already exists
858 network_id = get_network_id(neutron_client, net_name)
859 subnet_id = get_subnet_id(neutron_client, subnet_name)
860 router_id = get_router_id(neutron_client, router_name)
862 if network_id != '' and subnet_id != '' and router_id != '':
863 logger.info("A network with name '%s' already exists..." % net_name)
865 neutron_client.format = 'json'
866 logger.info('Creating neutron network %s...' % net_name)
867 network_id = create_neutron_net(neutron_client, net_name)
872 logger.debug("Network '%s' created successfully" % network_id)
873 logger.debug('Creating Subnet....')
874 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
879 logger.debug("Subnet '%s' created successfully" % subnet_id)
880 logger.debug('Creating Router...')
881 router_id = create_neutron_router(neutron_client, router_name)
886 logger.debug("Router '%s' created successfully" % router_id)
887 logger.debug('Adding router to subnet...')
889 if not add_interface_router(neutron_client, router_id, subnet_id):
892 logger.debug("Interface added successfully.")
894 logger.debug('Adding gateway to router...')
895 if not add_gateway_router(neutron_client, router_id):
898 logger.debug("Gateway added successfully.")
900 network_dic = {'net_id': network_id,
901 'subnet_id': subnet_id,
902 'router_id': router_id}
906 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
907 neutron_client = get_neutron_client()
909 network_dic = create_network_full(neutron_client,
915 if not update_neutron_net(neutron_client,
916 network_dic['net_id'],
918 logger.error("Failed to update network %s..." % net_name)
921 logger.debug("Network '%s' is available..." % net_name)
923 logger.error("Network %s creation failed" % net_name)
928 def create_bgpvpn(neutron_client, **kwargs):
929 # route_distinguishers
931 json_body = {"bgpvpn": kwargs}
932 return neutron_client.create_bgpvpn(json_body)
935 def create_network_association(neutron_client, bgpvpn_id, neutron_network_id):
936 json_body = {"network_association": {"network_id": neutron_network_id}}
937 return neutron_client.create_network_association(bgpvpn_id, json_body)
940 def create_router_association(neutron_client, bgpvpn_id, router_id):
941 json_body = {"router_association": {"router_id": router_id}}
942 return neutron_client.create_router_association(bgpvpn_id, json_body)
945 def update_bgpvpn(neutron_client, bgpvpn_id, **kwargs):
946 json_body = {"bgpvpn": kwargs}
947 return neutron_client.update_bgpvpn(bgpvpn_id, json_body)
950 def delete_bgpvpn(neutron_client, bgpvpn_id):
951 return neutron_client.delete_bgpvpn(bgpvpn_id)
954 def get_bgpvpn(neutron_client, bgpvpn_id):
955 return neutron_client.show_bgpvpn(bgpvpn_id)
958 def get_bgpvpn_routers(neutron_client, bgpvpn_id):
959 return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['routers']
962 def get_bgpvpn_networks(neutron_client, bgpvpn_id):
963 return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['networks']
965 # *********************************************
967 # *********************************************
970 def get_security_groups(neutron_client):
972 security_groups = neutron_client.list_security_groups()[
974 return security_groups
976 logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
980 def get_security_group_id(neutron_client, sg_name):
981 security_groups = get_security_groups(neutron_client)
983 for sg in security_groups:
984 if sg['name'] == sg_name:
990 def create_security_group(neutron_client, sg_name, sg_description):
991 json_body = {'security_group': {'name': sg_name,
992 'description': sg_description}}
994 secgroup = neutron_client.create_security_group(json_body)
995 return secgroup['security_group']
997 logger.error("Error [create_security_group(neutron_client, '%s', "
998 "'%s')]: %s" % (sg_name, sg_description, e))
1002 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
1003 port_range_min=None, port_range_max=None):
1004 # We create a security group in 2 steps
1005 # 1 - we check the format and set the json body accordingly
1006 # 2 - we call neturon client to create the security group
1009 json_body = {'security_group_rule': {'direction': direction,
1010 'security_group_id': sg_id,
1011 'protocol': protocol}}
1013 # - both None => we do nothing
1014 # - both Not None => we add them to the json description
1015 # but one cannot be None is the other is not None
1016 if (port_range_min is not None and port_range_max is not None):
1017 # add port_range in json description
1018 json_body['security_group_rule']['port_range_min'] = port_range_min
1019 json_body['security_group_rule']['port_range_max'] = port_range_max
1020 logger.debug("Security_group format set (port range included)")
1022 # either both port range are set to None => do nothing
1023 # or one is set but not the other => log it and return False
1024 if port_range_min is None and port_range_max is None:
1025 logger.debug("Security_group format set (no port range mentioned)")
1027 logger.error("Bad security group format."
1028 "One of the port range is not properly set:"
1030 "range max: {}".format(port_range_min,
1034 # Create security group using neutron client
1036 neutron_client.create_security_group_rule(json_body)
1039 logger.exception("Impossible to create_security_group_rule,"
1040 "security group rule probably already exists")
1044 def create_security_group_full(neutron_client,
1045 sg_name, sg_description):
1046 sg_id = get_security_group_id(neutron_client, sg_name)
1048 logger.info("Using existing security group '%s'..." % sg_name)
1050 logger.info("Creating security group '%s'..." % sg_name)
1051 SECGROUP = create_security_group(neutron_client,
1055 logger.error("Failed to create the security group...")
1058 sg_id = SECGROUP['id']
1060 logger.debug("Security group '%s' with ID=%s created successfully."
1061 % (SECGROUP['name'], sg_id))
1063 logger.debug("Adding ICMP rules in security group '%s'..."
1065 if not create_secgroup_rule(neutron_client, sg_id,
1067 logger.error("Failed to create the security group rule...")
1070 logger.debug("Adding SSH rules in security group '%s'..."
1072 if not create_secgroup_rule(
1073 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1074 logger.error("Failed to create the security group rule...")
1077 if not create_secgroup_rule(
1078 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1079 logger.error("Failed to create the security group rule...")
1084 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
1086 nova_client.servers.add_security_group(instance_id, secgroup_id)
1088 except Exception, e:
1089 logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
1090 "'%s')]: %s" % (instance_id, secgroup_id, e))
1094 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1095 json_body = {"quota": {
1096 "security_group": sg_quota,
1097 "security_group_rule": sg_rule_quota
1101 neutron_client.update_quota(tenant_id=tenant_id,
1104 except Exception, e:
1105 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1106 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1110 def delete_security_group(neutron_client, secgroup_id):
1112 neutron_client.delete_security_group(secgroup_id)
1114 except Exception, e:
1115 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1120 # *********************************************
1122 # *********************************************
1123 def get_images(nova_client):
1125 images = nova_client.images.list()
1127 except Exception, e:
1128 logger.error("Error [get_images]: %s" % e)
1132 def get_image_id(glance_client, image_name):
1133 images = glance_client.images.list()
1136 if i.name == image_name:
1142 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
1143 container="bare", public="public"):
1144 if not os.path.isfile(file_path):
1145 logger.error("Error: file %s does not exist." % file_path)
1148 image_id = get_image_id(glance_client, image_name)
1150 logger.info("Image %s already exists." % image_name)
1152 logger.info("Creating image '%s' from '%s'..." % (image_name,
1155 image = glance_client.images.create(name=image_name,
1158 container_format=container)
1160 with open(file_path) as image_data:
1161 glance_client.images.upload(image_id, image_data)
1163 except Exception, e:
1164 logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1165 "'%s')]: %s" % (image_name, file_path, public, e))
1169 def get_or_create_image(name, path, format):
1170 image_exists = False
1171 glance_client = get_glance_client()
1173 image_id = get_image_id(glance_client, name)
1175 logger.info("Using existing image '%s'..." % name)
1178 logger.info("Creating image '%s' from '%s'..." % (name, path))
1179 image_id = create_glance_image(glance_client, name, path, format)
1181 logger.error("Failed to create a Glance image...")
1183 logger.debug("Image '%s' with ID=%s created successfully."
1186 return image_exists, image_id
1189 def delete_glance_image(nova_client, image_id):
1191 nova_client.images.delete(image_id)
1193 except Exception, e:
1194 logger.error("Error [delete_glance_image(nova_client, '%s')]: %s"
1199 # *********************************************
1201 # *********************************************
1202 def get_volumes(cinder_client):
1204 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1206 except Exception, e:
1207 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1211 def list_volume_types(cinder_client, public=True, private=True):
1213 volume_types = cinder_client.volume_types.list()
1215 volume_types = [vt for vt in volume_types if not vt.is_public]
1217 volume_types = [vt for vt in volume_types if vt.is_public]
1219 except Exception, e:
1220 logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
1224 def create_volume_type(cinder_client, name):
1226 volume_type = cinder_client.volume_types.create(name)
1228 except Exception, e:
1229 logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
1234 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1235 snapshots_quota, gigabytes_quota):
1236 quotas_values = {"volumes": vols_quota,
1237 "snapshots": snapshots_quota,
1238 "gigabytes": gigabytes_quota}
1241 cinder_client.quotas.update(tenant_id, **quotas_values)
1243 except Exception, e:
1244 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1245 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1246 snapshots_quota, gigabytes_quota, e))
1250 def delete_volume(cinder_client, volume_id, forced=False):
1254 cinder_client.volumes.detach(volume_id)
1256 logger.error(sys.exc_info()[0])
1257 cinder_client.volumes.force_delete(volume_id)
1259 cinder_client.volumes.delete(volume_id)
1261 except Exception, e:
1262 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1263 % (volume_id, str(forced), e))
1267 def delete_volume_type(cinder_client, volume_type):
1269 cinder_client.volume_types.delete(volume_type)
1271 except Exception, e:
1272 logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
1277 # *********************************************
1279 # *********************************************
1280 def get_tenants(keystone_client):
1282 if is_keystone_v3():
1283 tenants = keystone_client.projects.list()
1285 tenants = keystone_client.tenants.list()
1287 except Exception, e:
1288 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1292 def get_users(keystone_client):
1294 users = keystone_client.users.list()
1296 except Exception, e:
1297 logger.error("Error [get_users(keystone_client)]: %s" % e)
1301 def get_tenant_id(keystone_client, tenant_name):
1302 tenants = get_tenants(keystone_client)
1305 if t.name == tenant_name:
1311 def get_user_id(keystone_client, user_name):
1312 users = get_users(keystone_client)
1315 if u.name == user_name:
1321 def get_role_id(keystone_client, role_name):
1322 roles = keystone_client.roles.list()
1325 if r.name == role_name:
1331 def create_tenant(keystone_client, tenant_name, tenant_description):
1333 if is_keystone_v3():
1334 tenant = keystone_client.projects.create(
1336 description=tenant_description,
1340 tenant = keystone_client.tenants.create(tenant_name,
1344 except Exception, e:
1345 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1346 % (tenant_name, tenant_description, e))
1350 def create_user(keystone_client, user_name, user_password,
1351 user_email, tenant_id):
1353 if is_keystone_v3():
1354 user = keystone_client.users.create(name=user_name,
1355 password=user_password,
1357 project_id=tenant_id,
1360 user = keystone_client.users.create(user_name,
1366 except Exception, e:
1367 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1368 "'%s')]: %s" % (user_name, user_password,
1369 user_email, tenant_id, e))
1373 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1375 if is_keystone_v3():
1376 keystone_client.roles.grant(role=role_id,
1380 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1382 except Exception, e:
1383 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1384 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1388 def delete_tenant(keystone_client, tenant_id):
1390 if is_keystone_v3():
1391 keystone_client.projects.delete(tenant_id)
1393 keystone_client.tenants.delete(tenant_id)
1395 except Exception, e:
1396 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1401 def delete_user(keystone_client, user_id):
1403 keystone_client.users.delete(user_id)
1405 except Exception, e:
1406 logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1411 # *********************************************
1413 # *********************************************
1414 def get_resource(heat_client, stack_id, resource):
1416 resources = heat_client.resources.get(stack_id, resource)
1418 except Exception, e:
1419 logger.error("Error [get_resource]: %s" % e)