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 if port_range_min is None and port_range_max is None:
989 json_body = {'security_group_rule': {'direction': direction,
990 'security_group_id': sg_id,
991 'protocol': protocol}}
992 elif port_range_min is not None and port_range_max is not None:
993 json_body = {'security_group_rule': {'direction': direction,
994 'security_group_id': sg_id,
995 'port_range_min': port_range_min,
996 'port_range_max': port_range_max,
997 'protocol': protocol}}
999 logger.error("Error [create_secgroup_rule(neutron_client, '%s', '%s', "
1000 "'%s', '%s', '%s', '%s')]:" % (neutron_client,
1005 " Invalid values for port_range_min, port_range_max")
1008 neutron_client.create_security_group_rule(json_body)
1010 except Exception, e:
1011 logger.error("Error [create_secgroup_rule(neutron_client, '%s', '%s', "
1012 "'%s', '%s', '%s', '%s')]: %s" % (neutron_client,
1021 def create_security_group_full(neutron_client,
1022 sg_name, sg_description):
1023 sg_id = get_security_group_id(neutron_client, sg_name)
1025 logger.info("Using existing security group '%s'..." % sg_name)
1027 logger.info("Creating security group '%s'..." % sg_name)
1028 SECGROUP = create_security_group(neutron_client,
1032 logger.error("Failed to create the security group...")
1035 sg_id = SECGROUP['id']
1037 logger.debug("Security group '%s' with ID=%s created successfully."
1038 % (SECGROUP['name'], sg_id))
1040 logger.debug("Adding ICMP rules in security group '%s'..."
1042 if not create_secgroup_rule(neutron_client, sg_id,
1044 logger.error("Failed to create the security group rule...")
1047 logger.debug("Adding SSH rules in security group '%s'..."
1049 if not create_secgroup_rule(
1050 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
1051 logger.error("Failed to create the security group rule...")
1054 if not create_secgroup_rule(
1055 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
1056 logger.error("Failed to create the security group rule...")
1061 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
1063 nova_client.servers.add_security_group(instance_id, secgroup_id)
1065 except Exception, e:
1066 logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
1067 "'%s')]: %s" % (instance_id, secgroup_id, e))
1071 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
1072 json_body = {"quota": {
1073 "security_group": sg_quota,
1074 "security_group_rule": sg_rule_quota
1078 neutron_client.update_quota(tenant_id=tenant_id,
1081 except Exception, e:
1082 logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
1083 "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
1087 def delete_security_group(neutron_client, secgroup_id):
1089 neutron_client.delete_security_group(secgroup_id)
1091 except Exception, e:
1092 logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
1097 # *********************************************
1099 # *********************************************
1100 def get_images(nova_client):
1102 images = nova_client.images.list()
1104 except Exception, e:
1105 logger.error("Error [get_images]: %s" % e)
1109 def get_image_id(glance_client, image_name):
1110 images = glance_client.images.list()
1113 if i.name == image_name:
1119 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
1120 container="bare", public="public"):
1121 if not os.path.isfile(file_path):
1122 logger.error("Error: file %s does not exist." % file_path)
1125 image_id = get_image_id(glance_client, image_name)
1127 logger.info("Image %s already exists." % image_name)
1129 logger.info("Creating image '%s' from '%s'..." % (image_name,
1132 image = glance_client.images.create(name=image_name,
1135 container_format=container)
1137 with open(file_path) as image_data:
1138 glance_client.images.upload(image_id, image_data)
1140 except Exception, e:
1141 logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1142 "'%s')]: %s" % (image_name, file_path, public, e))
1146 def get_or_create_image(name, path, format):
1147 image_exists = False
1148 glance_client = get_glance_client()
1150 image_id = get_image_id(glance_client, name)
1152 logger.info("Using existing image '%s'..." % name)
1155 logger.info("Creating image '%s' from '%s'..." % (name, path))
1156 image_id = create_glance_image(glance_client, name, path, format)
1158 logger.error("Failed to create a Glance image...")
1160 logger.debug("Image '%s' with ID=%s created successfully."
1163 return image_exists, image_id
1166 def delete_glance_image(nova_client, image_id):
1168 nova_client.images.delete(image_id)
1170 except Exception, e:
1171 logger.error("Error [delete_glance_image(nova_client, '%s')]: %s"
1176 # *********************************************
1178 # *********************************************
1179 def get_volumes(cinder_client):
1181 volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1183 except Exception, e:
1184 logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1188 def list_volume_types(cinder_client, public=True, private=True):
1190 volume_types = cinder_client.volume_types.list()
1192 volume_types = [vt for vt in volume_types if not vt.is_public]
1194 volume_types = [vt for vt in volume_types if vt.is_public]
1196 except Exception, e:
1197 logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
1201 def create_volume_type(cinder_client, name):
1203 volume_type = cinder_client.volume_types.create(name)
1205 except Exception, e:
1206 logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
1211 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1212 snapshots_quota, gigabytes_quota):
1213 quotas_values = {"volumes": vols_quota,
1214 "snapshots": snapshots_quota,
1215 "gigabytes": gigabytes_quota}
1218 cinder_client.quotas.update(tenant_id, **quotas_values)
1220 except Exception, e:
1221 logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1222 "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1223 snapshots_quota, gigabytes_quota, e))
1227 def delete_volume(cinder_client, volume_id, forced=False):
1231 cinder_client.volumes.detach(volume_id)
1233 logger.error(sys.exc_info()[0])
1234 cinder_client.volumes.force_delete(volume_id)
1236 cinder_client.volumes.delete(volume_id)
1238 except Exception, e:
1239 logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1240 % (volume_id, str(forced), e))
1244 def delete_volume_type(cinder_client, volume_type):
1246 cinder_client.volume_types.delete(volume_type)
1248 except Exception, e:
1249 logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
1254 # *********************************************
1256 # *********************************************
1257 def get_tenants(keystone_client):
1259 if is_keystone_v3():
1260 tenants = keystone_client.projects.list()
1262 tenants = keystone_client.tenants.list()
1264 except Exception, e:
1265 logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1269 def get_users(keystone_client):
1271 users = keystone_client.users.list()
1273 except Exception, e:
1274 logger.error("Error [get_users(keystone_client)]: %s" % e)
1278 def get_tenant_id(keystone_client, tenant_name):
1279 tenants = get_tenants(keystone_client)
1282 if t.name == tenant_name:
1288 def get_user_id(keystone_client, user_name):
1289 users = get_users(keystone_client)
1292 if u.name == user_name:
1298 def get_role_id(keystone_client, role_name):
1299 roles = keystone_client.roles.list()
1302 if r.name == role_name:
1308 def create_tenant(keystone_client, tenant_name, tenant_description):
1310 if is_keystone_v3():
1311 tenant = keystone_client.projects.create(
1313 description=tenant_description,
1317 tenant = keystone_client.tenants.create(tenant_name,
1321 except Exception, e:
1322 logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1323 % (tenant_name, tenant_description, e))
1327 def create_user(keystone_client, user_name, user_password,
1328 user_email, tenant_id):
1330 if is_keystone_v3():
1331 user = keystone_client.users.create(name=user_name,
1332 password=user_password,
1334 project_id=tenant_id,
1337 user = keystone_client.users.create(user_name,
1343 except Exception, e:
1344 logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1345 "'%s')]: %s" % (user_name, user_password,
1346 user_email, tenant_id, e))
1350 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1352 if is_keystone_v3():
1353 keystone_client.roles.grant(role=role_id,
1357 keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1359 except Exception, e:
1360 logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1361 "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1365 def delete_tenant(keystone_client, tenant_id):
1367 if is_keystone_v3():
1368 keystone_client.projects.delete(tenant_id)
1370 keystone_client.tenants.delete(tenant_id)
1372 except Exception, e:
1373 logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1378 def delete_user(keystone_client, user_id):
1380 keystone_client.users.delete(user_id)
1382 except Exception, e:
1383 logger.error("Error [delete_user(keystone_client, '%s')]: %s"