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 novaclient import client as novaclient
22 from keystoneclient import client as keystoneclient
23 from neutronclient.neutron import client as neutronclient
25 import functest.utils.functest_logger as ft_logger
26 import functest.utils.functest_utils as ft_utils
28 logger = ft_logger.Logger("openstack_utils").getLogger()
30 DEFAULT_API_VERSION = '2'
33 # *********************************************
35 # *********************************************
36 class MissingEnvVar(Exception):
38 def __init__(self, var):
42 return str.format("Please set the mandatory env var: {}", self.var)
46 keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
47 if (keystone_api_version is None or
48 keystone_api_version == '2'):
54 def get_rc_env_vars():
55 env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD']
57 env_vars.extend(['OS_PROJECT_NAME',
58 'OS_USER_DOMAIN_NAME',
59 'OS_PROJECT_DOMAIN_NAME'])
61 env_vars.extend(['OS_TENANT_NAME'])
65 def check_credentials():
67 Check if the OpenStack credentials (openrc) are sourced
69 env_vars = get_rc_env_vars()
70 return all(map(lambda v: v in os.environ and os.environ[v], env_vars))
73 def get_env_cred_dict():
75 'OS_USERNAME': 'username',
76 'OS_PASSWORD': 'password',
77 'OS_AUTH_URL': 'auth_url',
78 'OS_TENANT_NAME': 'tenant_name',
79 'OS_USER_DOMAIN_NAME': 'user_domain_name',
80 'OS_PROJECT_DOMAIN_NAME': 'project_domain_name',
81 'OS_PROJECT_NAME': 'project_name',
82 'OS_ENDPOINT_TYPE': 'endpoint_type',
83 'OS_REGION_NAME': 'region_name'
88 def get_credentials(other_creds={}):
89 """Returns a creds dictionary filled with parsed from env
92 env_vars = get_rc_env_vars()
93 env_cred_dict = get_env_cred_dict()
95 for envvar in env_vars:
96 if os.getenv(envvar) is None:
97 raise MissingEnvVar(envvar)
99 creds_key = env_cred_dict.get(envvar)
100 creds.update({creds_key: os.getenv(envvar)})
102 if 'tenant' in other_creds.keys():
104 tenant = 'project_name'
106 tenant = 'tenant_name'
107 other_creds[tenant] = other_creds.pop('tenant')
109 creds.update(other_creds)
114 def source_credentials(rc_file):
115 with open(rc_file, "r") as f:
117 var = line.rstrip('"\n').replace('export ', '').split("=")
118 # The two next lines should be modified as soon as rc_file
119 # conforms with common rules. Be aware that it could induce
120 # issues if value starts with '
121 key = re.sub(r'^["\' ]*|[ \'"]*$', '', var[0])
122 value = re.sub(r'^["\' ]*|[ \'"]*$', '', "".join(var[1:]))
123 os.environ[key] = value
126 def get_credentials_for_rally():
127 creds = get_credentials()
128 env_cred_dict = get_env_cred_dict()
129 rally_conf = {"type": "ExistingCloud", "admin": {}}
131 if key == 'auth_url':
132 rally_conf[key] = creds[key]
134 rally_conf['admin'][key] = creds[key]
136 endpoint_types = [('internalURL', 'internal'),
137 ('publicURL', 'public'), ('adminURL', 'admin')]
139 endpoint_type = os.getenv('OS_ENDPOINT_TYPE')
140 if endpoint_type is not None:
141 cred_key = env_cred_dict.get('OS_ENDPOINT_TYPE')
142 for k, v in endpoint_types:
143 if endpoint_type == k:
144 rally_conf[cred_key] = v
146 region_name = os.getenv('OS_REGION_NAME')
147 if region_name is not None:
148 cred_key = env_cred_dict.get('OS_REGION_NAME')
149 rally_conf[cred_key] = region_name
153 def get_session_auth(other_creds={}):
154 loader = loading.get_plugin_loader('password')
155 creds = get_credentials(other_creds)
156 auth = loader.load_from_options(**creds)
160 def get_endpoint(service_type, endpoint_type='publicURL'):
161 auth = get_session_auth()
162 return get_session().get_endpoint(auth=auth,
163 service_type=service_type,
164 endpoint_type=endpoint_type)
167 def get_session(other_creds={}):
168 auth = get_session_auth(other_creds)
169 return session.Session(auth=auth)
172 # *********************************************
174 # *********************************************
175 def get_keystone_client_version():
176 api_version = os.getenv('OS_IDENTITY_API_VERSION')
177 if api_version is not None:
178 logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
181 return DEFAULT_API_VERSION
184 def get_keystone_client(other_creds={}):
185 sess = get_session(other_creds)
186 return keystoneclient.Client(get_keystone_client_version(), session=sess)
189 def get_nova_client_version():
190 api_version = os.getenv('OS_COMPUTE_API_VERSION')
191 if api_version is not None:
192 logger.info("OS_COMPUTE_API_VERSION is set in env as '%s'",
195 return DEFAULT_API_VERSION
198 def get_nova_client(other_creds={}):
199 sess = get_session(other_creds)
200 return novaclient.Client(get_nova_client_version(), session=sess)
203 def get_cinder_client_version():
204 api_version = os.getenv('OS_VOLUME_API_VERSION')
205 if api_version is not None:
206 logger.info("OS_VOLUME_API_VERSION is set in env as '%s'",
209 return DEFAULT_API_VERSION
212 def get_cinder_client(other_creds={}):
213 sess = get_session(other_creds)
214 return cinderclient.Client(get_cinder_client_version(), session=sess)
217 def get_neutron_client_version():
218 api_version = os.getenv('OS_NETWORK_API_VERSION')
219 if api_version is not None:
220 logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
223 return DEFAULT_API_VERSION
226 def get_neutron_client(other_creds={}):
227 sess = get_session(other_creds)
228 return neutronclient.Client(get_neutron_client_version(), session=sess)
231 def get_glance_client_version():
232 api_version = os.getenv('OS_IMAGE_API_VERSION')
233 if api_version is not None:
234 logger.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version)
236 return DEFAULT_API_VERSION
239 def get_glance_client(other_creds={}):
240 sess = get_session(other_creds)
241 return glanceclient.Client(get_glance_client_version(), session=sess)
244 # *********************************************
246 # *********************************************
247 def get_instances(nova_client):
249 instances = nova_client.servers.list(search_opts={'all_tenants': 1})
252 logger.error("Error [get_instances(nova_client)]: %s" % e)
256 def get_instance_status(nova_client, instance):
258 instance = nova_client.servers.get(instance.id)
259 return instance.status
261 logger.error("Error [get_instance_status(nova_client)]: %s" % e)
265 def get_instance_by_name(nova_client, instance_name):
267 instance = nova_client.servers.find(name=instance_name)
270 logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
271 % (instance_name, e))
275 def get_flavor_id(nova_client, flavor_name):
276 flavors = nova_client.flavors.list(detailed=True)
279 if f.name == flavor_name:
285 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
286 flavors = nova_client.flavors.list(detailed=True)
289 if min_ram <= f.ram and f.ram <= max_ram:
295 def get_aggregates(nova_client):
297 aggregates = nova_client.aggregates.list()
300 logger.error("Error [get_aggregates(nova_client)]: %s" % e)
304 def get_aggregate_id(nova_client, aggregate_name):
306 aggregates = get_aggregates(nova_client)
307 _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
310 logger.error("Error [get_aggregate_id(nova_client, %s)]:"
311 " %s" % (aggregate_name, e))
315 def get_availability_zones(nova_client):
317 availability_zones = nova_client.availability_zones.list()
318 return availability_zones
320 logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
324 def get_availability_zone_names(nova_client):
326 az_names = [az.zoneName for az in get_availability_zones(nova_client)]
329 logger.error("Error [get_availability_zone_names(nova_client)]:"
334 def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
336 flavor = nova_client.flavors.create(
337 flavor_name, ram, vcpus, disk, is_public=public)
339 extra_specs = ft_utils.get_functest_config(
340 'general.flavor_extra_specs')
341 flavor.set_keys(extra_specs)
343 # flavor extra specs are not configured, therefore skip the update
347 logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
348 "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
353 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
354 flavor_exists = False
355 nova_client = get_nova_client()
357 flavor_id = get_flavor_id(nova_client, flavor_name)
359 logger.info("Using existing flavor '%s'..." % flavor_name)
362 logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
363 "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
364 flavor_id = create_flavor(
365 nova_client, flavor_name, ram, disk, vcpus, public=public)
367 logger.error("Failed to create flavor '%s'..." % (flavor_name))
369 logger.debug("Flavor '%s' with ID=%s created successfully."
370 % (flavor_name, flavor_id))
372 return flavor_exists, flavor_id
375 def get_floating_ips(nova_client):
377 floating_ips = nova_client.floating_ips.list()
380 logger.error("Error [get_floating_ips(nova_client)]: %s" % e)
384 def get_hypervisors(nova_client):
387 hypervisors = nova_client.hypervisors.list()
388 for hypervisor in hypervisors:
389 if hypervisor.state == "up":
390 nodes.append(hypervisor.hypervisor_hostname)
393 logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
397 def create_aggregate(nova_client, aggregate_name, av_zone):
399 nova_client.aggregates.create(aggregate_name, av_zone)
402 logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
403 % (aggregate_name, av_zone, e))
407 def add_host_to_aggregate(nova_client, aggregate_name, compute_host):
409 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
410 nova_client.aggregates.add_host(aggregate_id, compute_host)
413 logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
414 % (aggregate_name, compute_host, e))
418 def create_aggregate_with_host(
419 nova_client, aggregate_name, av_zone, compute_host):
421 create_aggregate(nova_client, aggregate_name, av_zone)
422 add_host_to_aggregate(nova_client, aggregate_name, compute_host)
425 logger.error("Error [create_aggregate_with_host("
426 "nova_client, %s, %s, %s)]: %s"
427 % (aggregate_name, av_zone, compute_host, e))
431 def create_instance(flavor_name,
434 instance_name="functest-vm",
440 nova_client = get_nova_client()
442 flavor = nova_client.flavors.find(name=flavor_name)
444 flavors = nova_client.flavors.list()
445 logger.error("Error: Flavor '%s' not found. Available flavors are: "
446 "\n%s" % (flavor_name, flavors))
448 if fixed_ip is not None:
449 nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
451 nics = {"net-id": network_id}
453 instance = nova_client.servers.create(
458 availability_zone=av_zone,
462 instance = nova_client.servers.create(
467 config_drive=confdrive,
469 availability_zone=av_zone,
475 def create_instance_and_wait_for_active(flavor_name,
485 VM_BOOT_TIMEOUT = 180
486 nova_client = get_nova_client()
487 instance = create_instance(flavor_name,
496 count = VM_BOOT_TIMEOUT / SLEEP
497 for n in range(count, -1, -1):
498 status = get_instance_status(nova_client, instance)
499 if status.lower() == "active":
501 elif status.lower() == "error":
502 logger.error("The instance %s went to ERROR status."
506 logger.error("Timeout booting the instance %s." % instance_name)
510 def create_floating_ip(neutron_client):
511 extnet_id = get_external_net_id(neutron_client)
512 props = {'floating_network_id': extnet_id}
514 ip_json = neutron_client.create_floatingip({'floatingip': props})
515 fip_addr = ip_json['floatingip']['floating_ip_address']
516 fip_id = ip_json['floatingip']['id']
518 logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
520 return {'fip_addr': fip_addr, 'fip_id': fip_id}
523 def add_floating_ip(nova_client, server_id, floatingip_addr):
525 nova_client.servers.add_floating_ip(server_id, floatingip_addr)
528 logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
529 % (server_id, floatingip_addr, e))
533 def delete_instance(nova_client, instance_id):
535 nova_client.servers.force_delete(instance_id)
538 logger.error("Error [delete_instance(nova_client, '%s')]: %s"
543 def delete_floating_ip(nova_client, floatingip_id):
545 nova_client.floating_ips.delete(floatingip_id)
548 logger.error("Error [delete_floating_ip(nova_client, '%s')]: %s"
549 % (floatingip_id, e))
553 def remove_host_from_aggregate(nova_client, aggregate_name, compute_host):
555 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
556 nova_client.aggregates.remove_host(aggregate_id, compute_host)
559 logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
560 " %s" % (aggregate_name, compute_host, e))
564 def remove_hosts_from_aggregate(nova_client, aggregate_name):
565 aggregate_id = get_aggregate_id(nova_client, aggregate_name)
566 hosts = nova_client.aggregates.get(aggregate_id).hosts
568 all(remove_host_from_aggregate(nova_client, aggregate_name, host)
572 def delete_aggregate(nova_client, aggregate_name):
574 remove_hosts_from_aggregate(nova_client, aggregate_name)
575 nova_client.aggregates.delete(aggregate_name)
578 logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
579 % (aggregate_name, e))
583 # *********************************************
585 # *********************************************
586 def get_network_list(neutron_client):
587 network_list = neutron_client.list_networks()['networks']
588 if len(network_list) == 0:
594 def get_router_list(neutron_client):
595 router_list = neutron_client.list_routers()['routers']
596 if len(router_list) == 0:
602 def get_port_list(neutron_client):
603 port_list = neutron_client.list_ports()['ports']
604 if len(port_list) == 0:
610 def get_network_id(neutron_client, network_name):
611 networks = neutron_client.list_networks()['networks']
614 if n['name'] == network_name:
620 def get_subnet_id(neutron_client, subnet_name):
621 subnets = neutron_client.list_subnets()['subnets']
624 if s['name'] == subnet_name:
630 def get_router_id(neutron_client, router_name):
631 routers = neutron_client.list_routers()['routers']
634 if r['name'] == router_name:
640 def get_private_net(neutron_client):
641 # Checks if there is an existing shared private network
642 networks = neutron_client.list_networks()['networks']
643 if len(networks) == 0:
646 if (net['router:external'] is False) and (net['shared'] is True):
651 def get_external_net(neutron_client):
652 for network in neutron_client.list_networks()['networks']:
653 if network['router:external']:
654 return network['name']
658 def get_external_net_id(neutron_client):
659 for network in neutron_client.list_networks()['networks']:
660 if network['router:external']:
665 def check_neutron_net(neutron_client, net_name):
666 for network in neutron_client.list_networks()['networks']:
667 if network['name'] == net_name:
668 for subnet in network['subnets']:
673 def create_neutron_net(neutron_client, name):
674 json_body = {'network': {'name': name,
675 'admin_state_up': True}}
677 network = neutron_client.create_network(body=json_body)
678 network_dict = network['network']
679 return network_dict['id']
681 logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
686 def create_neutron_subnet(neutron_client, name, cidr, net_id):
687 json_body = {'subnets': [{'name': name, 'cidr': cidr,
688 'ip_version': 4, 'network_id': net_id}]}
690 subnet = neutron_client.create_subnet(body=json_body)
691 return subnet['subnets'][0]['id']
693 logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
694 "'%s', '%s')]: %s" % (name, cidr, net_id, e))
698 def create_neutron_router(neutron_client, name):
699 json_body = {'router': {'name': name, 'admin_state_up': True}}
701 router = neutron_client.create_router(json_body)
702 return router['router']['id']
704 logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
709 def create_neutron_port(neutron_client, name, network_id, ip):
710 json_body = {'port': {
711 'admin_state_up': True,
713 'network_id': network_id,
714 'fixed_ips': [{"ip_address": ip}]
717 port = neutron_client.create_port(body=json_body)
718 return port['port']['id']
720 logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
721 "'%s')]: %s" % (name, network_id, ip, e))
725 def update_neutron_net(neutron_client, network_id, shared=False):
726 json_body = {'network': {'shared': shared}}
728 neutron_client.update_network(network_id, body=json_body)
731 logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
732 "%s" % (network_id, str(shared), e))
736 def update_neutron_port(neutron_client, port_id, device_owner):
737 json_body = {'port': {
738 'device_owner': device_owner,
741 port = neutron_client.update_port(port=port_id,
743 return port['port']['id']
745 logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
746 " %s" % (port_id, device_owner, e))
750 def add_interface_router(neutron_client, router_id, subnet_id):
751 json_body = {"subnet_id": subnet_id}
753 neutron_client.add_interface_router(router=router_id, body=json_body)
756 logger.error("Error [add_interface_router(neutron_client, '%s', "
757 "'%s')]: %s" % (router_id, subnet_id, e))
761 def add_gateway_router(neutron_client, router_id):
762 ext_net_id = get_external_net_id(neutron_client)
763 router_dict = {'network_id': ext_net_id}
765 neutron_client.add_gateway_router(router_id, router_dict)
768 logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
773 def delete_neutron_net(neutron_client, network_id):
775 neutron_client.delete_network(network_id)
778 logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
783 def delete_neutron_subnet(neutron_client, subnet_id):
785 neutron_client.delete_subnet(subnet_id)
788 logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
793 def delete_neutron_router(neutron_client, router_id):
795 neutron_client.delete_router(router=router_id)
798 logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
803 def delete_neutron_port(neutron_client, port_id):
805 neutron_client.delete_port(port_id)
808 logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
813 def remove_interface_router(neutron_client, router_id, subnet_id):
814 json_body = {"subnet_id": subnet_id}
816 neutron_client.remove_interface_router(router=router_id,
820 logger.error("Error [remove_interface_router(neutron_client, '%s', "
821 "'%s')]: %s" % (router_id, subnet_id, e))
825 def remove_gateway_router(neutron_client, router_id):
827 neutron_client.remove_gateway_router(router_id)
830 logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
835 def create_network_full(neutron_client,
841 # Check if the network already exists
842 network_id = get_network_id(neutron_client, net_name)
843 subnet_id = get_subnet_id(neutron_client, subnet_name)
844 router_id = get_router_id(neutron_client, router_name)
846 if network_id != '' and subnet_id != '' and router_id != '':
847 logger.info("A network with name '%s' already exists..." % net_name)
849 neutron_client.format = 'json'
850 logger.info('Creating neutron network %s...' % net_name)
851 network_id = create_neutron_net(neutron_client, net_name)
856 logger.debug("Network '%s' created successfully" % network_id)
857 logger.debug('Creating Subnet....')
858 subnet_id = create_neutron_subnet(neutron_client, subnet_name,
863 logger.debug("Subnet '%s' created successfully" % subnet_id)
864 logger.debug('Creating Router...')
865 router_id = create_neutron_router(neutron_client, router_name)
870 logger.debug("Router '%s' created successfully" % router_id)
871 logger.debug('Adding router to subnet...')
873 if not add_interface_router(neutron_client, router_id, subnet_id):
876 logger.debug("Interface added successfully.")
878 logger.debug('Adding gateway to router...')
879 if not add_gateway_router(neutron_client, router_id):
882 logger.debug("Gateway added successfully.")
884 network_dic = {'net_id': network_id,
885 'subnet_id': subnet_id,
886 'router_id': router_id}
890 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
891 neutron_client = get_neutron_client()
893 network_dic = create_network_full(neutron_client,
899 if not update_neutron_net(neutron_client,
900 network_dic['net_id'],
902 logger.error("Failed to update network %s..." % net_name)
905 logger.debug("Network '%s' is available..." % net_name)
907 logger.error("Network %s creation failed" % net_name)
912 def create_bgpvpn(neutron_client, **kwargs):
913 # route_distinguishers
915 json_body = {"bgpvpn": kwargs}
916 return neutron_client.create_bgpvpn(json_body)
919 def create_network_association(neutron_client, bgpvpn_id, neutron_network_id):
920 json_body = {"network_association": {"network_id": neutron_network_id}}
921 return neutron_client.create_network_association(bgpvpn_id, json_body)
924 def create_router_association(neutron_client, bgpvpn_id, router_id):
925 json_body = {"router_association": {"router_id": router_id}}
926 return neutron_client.create_router_association(bgpvpn_id, json_body)
929 def update_bgpvpn(neutron_client, bgpvpn_id, **kwargs):
930 json_body = {"bgpvpn": kwargs}
931 return neutron_client.update_bgpvpn(bgpvpn_id, json_body)
934 def delete_bgpvpn(neutron_client, bgpvpn_id):
935 return neutron_client.delete_bgpvpn(bgpvpn_id)
938 def get_bgpvpn(neutron_client, bgpvpn_id):
939 return neutron_client.show_bgpvpn(bgpvpn_id)
942 def get_bgpvpn_routers(neutron_client, bgpvpn_id):
943 return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['routers']
946 def get_bgpvpn_networks(neutron_client, bgpvpn_id):
947 return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['networks']
949 # *********************************************
951 # *********************************************
954 def get_security_groups(neutron_client):
956 security_groups = neutron_client.list_security_groups()[
958 return security_groups
960 logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
964 def get_security_group_id(neutron_client, sg_name):
965 security_groups = get_security_groups(neutron_client)
967 for sg in security_groups:
968 if sg['name'] == sg_name:
974 def create_security_group(neutron_client, sg_name, sg_description):
975 json_body = {'security_group': {'name': sg_name,
976 'description': sg_description}}
978 secgroup = neutron_client.create_security_group(json_body)
979 return secgroup['security_group']
981 logger.error("Error [create_security_group(neutron_client, '%s', "
982 "'%s')]: %s" % (sg_name, sg_description, e))
986 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
987 port_range_min=None, port_range_max=None):
988 # We create a security group in 2 steps
989 # 1 - we check the format and set the json body accordingly
990 # 2 - we call neturon client to create the security group
993 json_body = {'security_group_rule': {'direction': direction,
994 'security_group_id': sg_id,
995 'protocol': protocol}}
997 # - both None => we do nothing
998 # - both Not None => we add them to the json description
999 # but one cannot be None is the other is not None
1000 if (port_range_min is not None and port_range_max is not None):
1001 # add port_range in json description
1002 json_body['security_group_rule']['port_range_min'] = port_range_min
1003 json_body['security_group_rule']['port_range_max'] = port_range_max
1004 logger.debug("Security_group format set (port range included)")
1006 # either both port range are set to None => do nothing
1007 # or one is set but not the other => log it and return False
1008 if port_range_min is None and port_range_max is None:
1009 logger.debug("Security_group format set (no port range mentioned)")
1011 logger.error("Bad security group format."
1012 "One of the port range is not properly set:"
1014 "range max: {}".format(port_range_min,
1018 # Create security group using neutron client
1020 neutron_client.create_security_group_rule(json_body)
1023 logger.exception("Impossible to create_security_group_rule,"
1024 "security group rule probably already exists")
1028 def create_security_group_full(neutron_client,
1029 sg_name, sg_description):
1030 sg_id = get_security_group_id(neutron_client, sg_name)
1032 logger.info("Using existing security group '%s'..." % sg_name)
1034 logger.info("Creating security group '%s'..." % sg_name)
1035 SECGROUP = create_security_group(neutron_client,
1039 logger.error("Failed to create the security group...")
1042 sg_id = SECGROUP['id']
1044 logger.debug("Security group '%s' with ID=%s created successfully."
1045 % (SECGROUP['name'], sg_id))
1047 logger.debug("Adding ICMP rules in security group '%s'..."
1049 if not create_secgroup_rule(neutron_client, sg_id,
1051 logger.error("Failed to create the security group rule...")
1054 logger.debug("Adding SSH rules in security group '%s'..."
1056 if not create_secgroup_rule(
1057 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1058 logger.error("Failed to create the security group rule...")
1061 if not create_secgroup_rule(
1062 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1063 logger.error("Failed to create the security group rule...")
1068 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
1070 nova_client.servers.add_security_group(instance_id, secgroup_id)
1072 except Exception, e:
1073 logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
1074 "'%s')]: %s" % (instance_id, secgroup_id, e))
1078 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1079 json_body = {"quota": {
1080 "security_group": sg_quota,
1081 "security_group_rule": sg_rule_quota
1085 neutron_client.update_quota(tenant_id=tenant_id,
1088 except Exception, e:
1089 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1090 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1094 def delete_security_group(neutron_client, secgroup_id):
1096 neutron_client.delete_security_group(secgroup_id)
1098 except Exception, e:
1099 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1104 # *********************************************
1106 # *********************************************
1107 def get_images(nova_client):
1109 images = nova_client.images.list()
1111 except Exception, e:
1112 logger.error("Error [get_images]: %s" % e)
1116 def get_image_id(glance_client, image_name):
1117 images = glance_client.images.list()
1120 if i.name == image_name:
1126 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
1127 container="bare", public="public"):
1128 if not os.path.isfile(file_path):
1129 logger.error("Error: file %s does not exist." % file_path)
1132 image_id = get_image_id(glance_client, image_name)
1134 logger.info("Image %s already exists." % image_name)
1136 logger.info("Creating image '%s' from '%s'..." % (image_name,
1139 image = glance_client.images.create(name=image_name,
1142 container_format=container)
1144 with open(file_path) as image_data:
1145 glance_client.images.upload(image_id, image_data)
1147 except Exception, e:
1148 logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1149 "'%s')]: %s" % (image_name, file_path, public, e))
1153 def get_or_create_image(name, path, format):
1154 image_exists = False
1155 glance_client = get_glance_client()
1157 image_id = get_image_id(glance_client, name)
1159 logger.info("Using existing image '%s'..." % name)
1162 logger.info("Creating image '%s' from '%s'..." % (name, path))
1163 image_id = create_glance_image(glance_client, name, path, format)
1165 logger.error("Failed to create a Glance image...")
1167 logger.debug("Image '%s' with ID=%s created successfully."
1170 return image_exists, image_id
1173 def delete_glance_image(nova_client, image_id):
1175 nova_client.images.delete(image_id)
1177 except Exception, e:
1178 logger.error("Error [delete_glance_image(nova_client, '%s')]: %s"
1183 # *********************************************
1185 # *********************************************
1186 def get_volumes(cinder_client):
1188 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1190 except Exception, e:
1191 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1195 def list_volume_types(cinder_client, public=True, private=True):
1197 volume_types = cinder_client.volume_types.list()
1199 volume_types = [vt for vt in volume_types if not vt.is_public]
1201 volume_types = [vt for vt in volume_types if vt.is_public]
1203 except Exception, e:
1204 logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
1208 def create_volume_type(cinder_client, name):
1210 volume_type = cinder_client.volume_types.create(name)
1212 except Exception, e:
1213 logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
1218 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1219 snapshots_quota, gigabytes_quota):
1220 quotas_values = {"volumes": vols_quota,
1221 "snapshots": snapshots_quota,
1222 "gigabytes": gigabytes_quota}
1225 cinder_client.quotas.update(tenant_id, **quotas_values)
1227 except Exception, e:
1228 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1229 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1230 snapshots_quota, gigabytes_quota, e))
1234 def delete_volume(cinder_client, volume_id, forced=False):
1238 cinder_client.volumes.detach(volume_id)
1240 logger.error(sys.exc_info()[0])
1241 cinder_client.volumes.force_delete(volume_id)
1243 cinder_client.volumes.delete(volume_id)
1245 except Exception, e:
1246 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1247 % (volume_id, str(forced), e))
1251 def delete_volume_type(cinder_client, volume_type):
1253 cinder_client.volume_types.delete(volume_type)
1255 except Exception, e:
1256 logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
1261 # *********************************************
1263 # *********************************************
1264 def get_tenants(keystone_client):
1266 if is_keystone_v3():
1267 tenants = keystone_client.projects.list()
1269 tenants = keystone_client.tenants.list()
1271 except Exception, e:
1272 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1276 def get_users(keystone_client):
1278 users = keystone_client.users.list()
1280 except Exception, e:
1281 logger.error("Error [get_users(keystone_client)]: %s" % e)
1285 def get_tenant_id(keystone_client, tenant_name):
1286 tenants = get_tenants(keystone_client)
1289 if t.name == tenant_name:
1295 def get_user_id(keystone_client, user_name):
1296 users = get_users(keystone_client)
1299 if u.name == user_name:
1305 def get_role_id(keystone_client, role_name):
1306 roles = keystone_client.roles.list()
1309 if r.name == role_name:
1315 def create_tenant(keystone_client, tenant_name, tenant_description):
1317 if is_keystone_v3():
1318 tenant = keystone_client.projects.create(
1320 description=tenant_description,
1324 tenant = keystone_client.tenants.create(tenant_name,
1328 except Exception, e:
1329 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1330 % (tenant_name, tenant_description, e))
1334 def create_user(keystone_client, user_name, user_password,
1335 user_email, tenant_id):
1337 if is_keystone_v3():
1338 user = keystone_client.users.create(name=user_name,
1339 password=user_password,
1341 project_id=tenant_id,
1344 user = keystone_client.users.create(user_name,
1350 except Exception, e:
1351 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1352 "'%s')]: %s" % (user_name, user_password,
1353 user_email, tenant_id, e))
1357 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1359 if is_keystone_v3():
1360 keystone_client.roles.grant(role=role_id,
1364 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1366 except Exception, e:
1367 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1368 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1372 def delete_tenant(keystone_client, tenant_id):
1374 if is_keystone_v3():
1375 keystone_client.projects.delete(tenant_id)
1377 keystone_client.tenants.delete(tenant_id)
1379 except Exception, e:
1380 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1385 def delete_user(keystone_client, user_id):
1387 keystone_client.users.delete(user_id)
1389 except Exception, e:
1390 logger.error("Error [delete_user(keystone_client, '%s')]: %s"