blob: 038528f8f480e4a77d45d5bafd98bc95f9f24684 [file] [log] [blame]
Matthew Treinishb86cda92013-07-29 11:22:23 -04001# Copyright 2013 IBM Corp.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
zhongjun5b68f502017-07-04 15:28:05 +080015import ipaddress
16
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050017import netaddr
Doug Hellmann583ce2c2015-03-11 14:55:46 +000018from oslo_log import log as logging
Andrea Frittolic3280152015-02-26 12:42:34 +000019import six
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050020
Matthew Treinish3787e4c2016-10-07 21:25:33 -040021from tempest.lib.common import cred_client
Matthew Treinish00ab6be2016-10-07 16:29:18 -040022from tempest.lib.common import cred_provider
Matthew Treinish0650aed2016-10-07 16:36:46 -040023from tempest.lib.common.utils import data_utils
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050024from tempest.lib import exceptions as lib_exc
Andrea Frittolidcd91002017-07-18 11:34:13 +010025from tempest.lib.services import clients
Matthew Treinishb86cda92013-07-29 11:22:23 -040026
27LOG = logging.getLogger(__name__)
28
29
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -070030class DynamicCredentialProvider(cred_provider.CredentialProvider):
Masayuki Igawaa1c3af32017-09-07 10:22:37 +090031 """Creates credentials dynamically for tests
32
33 A credential provider that, based on an initial set of
34 admin credentials, creates new credentials on the fly for
35 tests to use and then discard.
36
37 :param str identity_version: identity API version to use `v2` or `v3`
38 :param str admin_role: name of the admin role added to admin users
39 :param str name: names of dynamic resources include this parameter
40 when specified
41 :param str credentials_domain: name of the domain where the users
42 are created. If not defined, the project
43 domain from admin_credentials is used
44 :param dict network_resources: network resources to be created for
45 the created credentials
46 :param Credentials admin_creds: initial admin credentials
47 :param bool identity_admin_domain_scope: Set to true if admin should be
48 scoped to the domain. By
49 default this is False and the
50 admin role is scoped to the
51 project.
52 :param str identity_admin_role: The role name to use for admin
53 :param list extra_roles: A list of strings for extra roles that should
54 be assigned to all created users
55 :param bool neutron_available: Whether we are running in an environemnt
56 with neutron
57 :param bool create_networks: Whether dynamic project networks should be
58 created or not
59 :param project_network_cidr: The CIDR to use for created project
60 networks
61 :param project_network_mask_bits: The network mask bits to use for
62 created project networks
63 :param public_network_id: The id for the public network to use
64 :param identity_admin_endpoint_type: The endpoint type for identity
65 admin clients. Defaults to public.
66 :param identity_uri: Identity URI of the target cloud
67 """
Matthew Treinishb86cda92013-07-29 11:22:23 -040068
Andrea Frittoli (andreaf)1eb04962015-10-09 14:48:06 +010069 def __init__(self, identity_version, name=None, network_resources=None,
Matthew Treinish75abbcf2016-10-07 16:19:12 -040070 credentials_domain=None, admin_role=None, admin_creds=None,
71 identity_admin_domain_scope=False,
72 identity_admin_role='admin', extra_roles=None,
73 neutron_available=False, create_networks=True,
74 project_network_cidr=None, project_network_mask_bits=None,
Andrea Frittolidcd91002017-07-18 11:34:13 +010075 public_network_id=None, resource_prefix=None,
76 identity_admin_endpoint_type='public', identity_uri=None):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -070077 super(DynamicCredentialProvider, self).__init__(
Andrea Frittolidcd91002017-07-18 11:34:13 +010078 identity_version=identity_version, identity_uri=identity_uri,
79 admin_role=admin_role, name=name,
80 credentials_domain=credentials_domain,
Andrea Frittoli (andreaf)290b3e12015-10-08 10:25:02 +010081 network_resources=network_resources)
82 self.network_resources = network_resources
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -070083 self._creds = {}
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050084 self.ports = []
Matthew Treinish0650aed2016-10-07 16:36:46 -040085 self.resource_prefix = resource_prefix or ''
Matthew Treinish75abbcf2016-10-07 16:19:12 -040086 self.neutron_available = neutron_available
87 self.create_networks = create_networks
88 self.project_network_cidr = project_network_cidr
89 self.project_network_mask_bits = project_network_mask_bits
90 self.public_network_id = public_network_id
Andrea Frittoli (andreaf)290b3e12015-10-08 10:25:02 +010091 self.default_admin_creds = admin_creds
Matthew Treinish75abbcf2016-10-07 16:19:12 -040092 self.identity_admin_domain_scope = identity_admin_domain_scope
93 self.identity_admin_role = identity_admin_role or 'admin'
Andrea Frittolidcd91002017-07-18 11:34:13 +010094 self.identity_admin_endpoint_type = identity_admin_endpoint_type
Matthew Treinish75abbcf2016-10-07 16:19:12 -040095 self.extra_roles = extra_roles or []
Yaroslav Lobankov47a93ab2016-02-07 16:32:49 -060096 (self.identity_admin_client,
97 self.tenants_admin_client,
Daniel Mellado82c83a52015-12-09 15:16:49 +000098 self.users_admin_client,
Daniel Mellado7aea5342016-02-09 09:10:12 +000099 self.roles_admin_client,
Daniel Mellado91a26b62016-02-11 11:13:04 +0000100 self.domains_admin_client,
John Warren3961acd2015-10-02 14:38:53 -0400101 self.networks_admin_client,
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000102 self.routers_admin_client,
John Warren49c0fe52015-10-22 12:35:54 -0400103 self.subnets_admin_client,
John Warrenf9606e92015-12-10 12:12:42 -0500104 self.ports_admin_client,
Andrea Frittolidcd91002017-07-18 11:34:13 +0100105 self.security_groups_admin_client) = self._get_admin_clients(
106 identity_admin_endpoint_type)
John Warren3961acd2015-10-02 14:38:53 -0400107 # Domain where isolated credentials are provisioned (v3 only).
Andrea Frittolic3280152015-02-26 12:42:34 +0000108 # Use that of the admin account is None is configured.
109 self.creds_domain_name = None
110 if self.identity_version == 'v3':
111 self.creds_domain_name = (
David Kranz87fc7e92015-07-28 14:05:20 -0400112 self.default_admin_creds.project_domain_name or
Andrea Frittoli (andreaf)1eb04962015-10-09 14:48:06 +0100113 self.credentials_domain)
Jamie Lennox15350172015-08-17 10:54:25 +1000114 self.creds_client = cred_client.get_creds_client(
Daniel Melladob04da902015-11-20 17:43:12 +0100115 self.identity_admin_client,
116 self.tenants_admin_client,
Daniel Mellado82c83a52015-12-09 15:16:49 +0000117 self.users_admin_client,
Daniel Mellado7aea5342016-02-09 09:10:12 +0000118 self.roles_admin_client,
Daniel Mellado91a26b62016-02-11 11:13:04 +0000119 self.domains_admin_client,
Daniel Melladob04da902015-11-20 17:43:12 +0100120 self.creds_domain_name)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400121
Andrea Frittolidcd91002017-07-18 11:34:13 +0100122 def _get_admin_clients(self, endpoint_type):
Ken'ichi Ohmichicb67d2d2015-11-19 08:23:22 +0000123 """Returns a tuple with instances of the following admin clients
124
125 (in this order):
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500126 identity
127 network
Matthew Treinishb86cda92013-07-29 11:22:23 -0400128 """
Andrea Frittolidcd91002017-07-18 11:34:13 +0100129 os = clients.ServiceClients(self.default_admin_creds,
130 self.identity_uri)
131 params = {'endpoint_type': endpoint_type}
Andrea Frittolic3280152015-02-26 12:42:34 +0000132 if self.identity_version == 'v2':
Andrea Frittolidcd91002017-07-18 11:34:13 +0100133 return (os.identity_v2.IdentityClient(**params),
134 os.identity_v2.TenantsClient(**params),
135 os.identity_v2.UsersClient(**params),
136 os.identity_v2.RolesClient(**params), None,
137 os.network.NetworksClient(),
138 os.network.RoutersClient(),
139 os.network.SubnetsClient(),
140 os.network.PortsClient(),
141 os.network.SecurityGroupsClient())
Andrea Frittolic3280152015-02-26 12:42:34 +0000142 else:
Andrea Frittoli (andreaf)100d18d2016-05-05 23:34:52 +0100143 # We use a dedicated client manager for identity client in case we
144 # need a different token scope for them.
Colleen Murphycd0bbbd2019-10-01 16:18:36 -0700145 if self.default_admin_creds.system:
146 scope = 'system'
147 elif (self.default_admin_creds.domain_id or
148 self.default_admin_creds.domain_name or
149 self.identity_admin_domain_scope):
150 scope = 'domain'
151 else:
152 scope = 'project'
Andrea Frittolidcd91002017-07-18 11:34:13 +0100153 identity_os = clients.ServiceClients(self.default_admin_creds,
154 self.identity_uri,
155 scope=scope)
156 return (identity_os.identity_v3.IdentityClient(**params),
157 identity_os.identity_v3.ProjectsClient(**params),
158 identity_os.identity_v3.UsersClient(**params),
159 identity_os.identity_v3.RolesClient(**params),
160 identity_os.identity_v3.DomainsClient(**params),
161 os.network.NetworksClient(),
162 os.network.RoutersClient(),
163 os.network.SubnetsClient(),
164 os.network.PortsClient(),
165 os.network.SecurityGroupsClient())
Matthew Treinishb86cda92013-07-29 11:22:23 -0400166
Colleen Murphy06374e22019-10-02 14:28:22 -0700167 def _create_creds(self, admin=False, roles=None, scope='project'):
Genadi Chereshnya88ea9ab2016-05-15 14:47:07 +0300168 """Create credentials with random name.
Sean Dague6969b902014-01-28 06:48:37 -0500169
Colleen Murphy06374e22019-10-02 14:28:22 -0700170 Creates user and role assignments on a project, domain, or system. When
171 the admin flag is True, creates user with the admin role on the
172 resource. If roles are provided, assigns those roles on the resource.
173 Otherwise, assigns the user the 'member' role on the resource.
Sean Dague6969b902014-01-28 06:48:37 -0500174
Genadi Chereshnya88ea9ab2016-05-15 14:47:07 +0300175 :param admin: Flag if to assign to the user admin role
176 :type admin: bool
177 :param roles: Roles to assign for the user
178 :type roles: list
Colleen Murphy06374e22019-10-02 14:28:22 -0700179 :param str scope: The scope for the role assignment, may be one of
180 'project', 'domain', or 'system'.
Genadi Chereshnya88ea9ab2016-05-15 14:47:07 +0300181 :return: Readonly Credentials with network resources
Colleen Murphy06374e22019-10-02 14:28:22 -0700182 :raises: Exception if scope is invalid
Sean Dague6969b902014-01-28 06:48:37 -0500183 """
Colleen Murphy06374e22019-10-02 14:28:22 -0700184 if not roles:
185 roles = []
Genadi Chereshnya88ea9ab2016-05-15 14:47:07 +0300186 root = self.name
Sean Dague6969b902014-01-28 06:48:37 -0500187
Colleen Murphy06374e22019-10-02 14:28:22 -0700188 cred_params = {
189 'project': None,
190 'domain': None,
191 'system': None
192 }
193 if scope == 'project':
194 project_name = data_utils.rand_name(
195 root, prefix=self.resource_prefix)
196 project_desc = project_name + '-desc'
197 project = self.creds_client.create_project(
198 name=project_name, description=project_desc)
Sean Dague6969b902014-01-28 06:48:37 -0500199
Colleen Murphy06374e22019-10-02 14:28:22 -0700200 # NOTE(andreaf) User and project can be distinguished from the
201 # context, having the same ID in both makes it easier to match them
202 # and debug.
203 username = project_name + '-project'
204 cred_params['project'] = project
205 elif scope == 'domain':
206 domain_name = data_utils.rand_name(
207 root, prefix=self.resource_prefix)
208 domain_desc = domain_name + '-desc'
209 domain = self.creds_client.create_domain(
210 name=domain_name, description=domain_desc)
211 username = domain_name + '-domain'
212 cred_params['domain'] = domain
213 elif scope == 'system':
214 prefix = data_utils.rand_name(root, prefix=self.resource_prefix)
215 username = prefix + '-system'
216 cred_params['system'] = 'all'
217 else:
218 raise lib_exc.InvalidScopeType(scope=scope)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400219 if admin:
Colleen Murphy06374e22019-10-02 14:28:22 -0700220 username += '-admin'
221 elif roles and len(roles) == 1:
222 username += '-' + roles[0]
223 user_password = data_utils.rand_password()
224 cred_params['password'] = user_password
225 user = self.creds_client.create_user(
226 username, user_password)
227 cred_params['user'] = user
228 roles_to_assign = [r for r in roles]
229 if admin:
230 roles_to_assign.append(self.admin_role)
231 self.creds_client.assign_user_role(
232 user, project, self.identity_admin_role)
Andrea Frittoli (andreaf)100d18d2016-05-05 23:34:52 +0100233 if (self.identity_version == 'v3' and
Matthew Treinish75abbcf2016-10-07 16:19:12 -0400234 self.identity_admin_domain_scope):
Andrea Frittoli (andreaf)4bee2e72015-09-22 13:06:18 +0100235 self.creds_client.assign_user_role_on_domain(
Matthew Treinish75abbcf2016-10-07 16:19:12 -0400236 user, self.identity_admin_role)
Matthew Treinish976e8df2014-12-19 14:21:54 -0500237 # Add roles specified in config file
Colleen Murphy06374e22019-10-02 14:28:22 -0700238 roles_to_assign.extend(self.extra_roles)
239 # If there are still no roles, default to 'member'
Matthew Treinish32f98a42015-07-14 19:58:46 -0400240 # NOTE(mtreinish) For a user to have access to a project with v3 auth
241 # it must beassigned a role on the project. So we need to ensure that
242 # our newly created user has a role on the newly created project.
Colleen Murphy06374e22019-10-02 14:28:22 -0700243 if not roles_to_assign and self.identity_version == 'v3':
244 roles_to_assign = ['member']
Adam Youngb226f8e2016-06-25 21:41:36 -0400245 try:
Martin Kopec99d4dae2020-05-27 10:33:17 +0000246 self.creds_client.create_user_role('member')
Adam Youngb226f8e2016-06-25 21:41:36 -0400247 except lib_exc.Conflict:
Martin Kopec99d4dae2020-05-27 10:33:17 +0000248 LOG.warning('member role already exists, ignoring conflict.')
Colleen Murphy06374e22019-10-02 14:28:22 -0700249 for role in roles_to_assign:
250 if scope == 'project':
251 self.creds_client.assign_user_role(user, project, role)
252 elif scope == 'domain':
253 self.creds_client.assign_user_role_on_domain(
254 user, role, domain)
255 elif scope == 'system':
256 self.creds_client.assign_user_role_on_system(user, role)
Matthew Treinish32f98a42015-07-14 19:58:46 -0400257
Colleen Murphy06374e22019-10-02 14:28:22 -0700258 creds = self.creds_client.get_credentials(**cred_params)
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400259 return cred_provider.TestResources(creds)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500260
261 def _create_network_resources(self, tenant_id):
edannon6cc6fbc2016-05-03 11:56:12 +0300262 """The function creates network resources in the given tenant.
263
264 The function checks if network_resources class member is empty,
265 In case it is, it will create a network, a subnet and a router for
266 the tenant according to the given tenant id parameter.
267 Otherwise it will create a network resource according
268 to the values from network_resources dict.
269
270 :param tenant_id: The tenant id to create resources for.
271 :type tenant_id: str
272 :raises: InvalidConfiguration, Exception
273 :returns: network resources(network,subnet,router)
274 :rtype: tuple
275 """
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500276 network = None
277 subnet = None
278 router = None
Matthew Treinish9f756a02014-01-15 10:26:07 -0500279 # Make sure settings
280 if self.network_resources:
281 if self.network_resources['router']:
282 if (not self.network_resources['subnet'] or
283 not self.network_resources['network']):
Matthew Treinish4217a702016-10-07 17:27:11 -0400284 raise lib_exc.InvalidConfiguration(
Matthew Treinish9f756a02014-01-15 10:26:07 -0500285 'A router requires a subnet and network')
286 elif self.network_resources['subnet']:
287 if not self.network_resources['network']:
Matthew Treinish4217a702016-10-07 17:27:11 -0400288 raise lib_exc.InvalidConfiguration(
Matthew Treinish9f756a02014-01-15 10:26:07 -0500289 'A subnet requires a network')
290 elif self.network_resources['dhcp']:
Matthew Treinish4217a702016-10-07 17:27:11 -0400291 raise lib_exc.InvalidConfiguration('DHCP requires a subnet')
Matthew Treinish9f756a02014-01-15 10:26:07 -0500292
Matthew Treinish0650aed2016-10-07 16:36:46 -0400293 rand_name_root = data_utils.rand_name(
294 self.name, prefix=self.resource_prefix)
Matthew Treinish9f756a02014-01-15 10:26:07 -0500295 if not self.network_resources or self.network_resources['network']:
Matthew Treinish0650aed2016-10-07 16:36:46 -0400296 network_name = rand_name_root + "-network"
Matthew Treinish9f756a02014-01-15 10:26:07 -0500297 network = self._create_network(network_name, tenant_id)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500298 try:
Matthew Treinish9f756a02014-01-15 10:26:07 -0500299 if not self.network_resources or self.network_resources['subnet']:
Matthew Treinish0650aed2016-10-07 16:36:46 -0400300 subnet_name = rand_name_root + "-subnet"
Matthew Treinish9f756a02014-01-15 10:26:07 -0500301 subnet = self._create_subnet(subnet_name, tenant_id,
302 network['id'])
303 if not self.network_resources or self.network_resources['router']:
Matthew Treinish0650aed2016-10-07 16:36:46 -0400304 router_name = rand_name_root + "-router"
Matthew Treinish9f756a02014-01-15 10:26:07 -0500305 router = self._create_router(router_name, tenant_id)
306 self._add_router_interface(router['id'], subnet['id'])
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500307 except Exception:
Andrea Frittoli (andreaf)d9a18b02016-02-29 15:27:34 +0000308 try:
309 if router:
310 self._clear_isolated_router(router['id'], router['name'])
311 if subnet:
312 self._clear_isolated_subnet(subnet['id'], subnet['name'])
313 if network:
314 self._clear_isolated_network(network['id'],
315 network['name'])
316 except Exception as cleanup_exception:
317 msg = "There was an exception trying to setup network " \
318 "resources for tenant %s, and this error happened " \
319 "trying to clean them up: %s"
Jordan Pittier525ec712016-12-07 17:51:26 +0100320 LOG.warning(msg, tenant_id, cleanup_exception)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500321 raise
322 return network, subnet, router
323
324 def _create_network(self, name, tenant_id):
John Warren94d8faf2015-09-15 12:22:24 -0400325 resp_body = self.networks_admin_client.create_network(
Andrea Frittoliae9aca02014-09-25 11:43:11 +0100326 name=name, tenant_id=tenant_id)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500327 return resp_body['network']
328
329 def _create_subnet(self, subnet_name, tenant_id, network_id):
Matthew Treinish75abbcf2016-10-07 16:19:12 -0400330 base_cidr = netaddr.IPNetwork(self.project_network_cidr)
331 mask_bits = self.project_network_mask_bits
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500332 for subnet_cidr in base_cidr.subnet(mask_bits):
333 try:
Andrea Frittoliae9aca02014-09-25 11:43:11 +0100334 if self.network_resources:
John Warren3961acd2015-10-02 14:38:53 -0400335 resp_body = self.subnets_admin_client.\
Andrea Frittoliae9aca02014-09-25 11:43:11 +0100336 create_subnet(
337 network_id=network_id, cidr=str(subnet_cidr),
338 name=subnet_name,
339 tenant_id=tenant_id,
340 enable_dhcp=self.network_resources['dhcp'],
zhongjun5b68f502017-07-04 15:28:05 +0800341 ip_version=(ipaddress.ip_network(
342 six.text_type(subnet_cidr)).version))
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500343 else:
John Warren3961acd2015-10-02 14:38:53 -0400344 resp_body = self.subnets_admin_client.\
Andrea Frittoliae9aca02014-09-25 11:43:11 +0100345 create_subnet(network_id=network_id,
346 cidr=str(subnet_cidr),
347 name=subnet_name,
348 tenant_id=tenant_id,
zhongjun5b68f502017-07-04 15:28:05 +0800349 ip_version=(ipaddress.ip_network(
350 six.text_type(subnet_cidr)).version))
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500351 break
Masayuki Igawa4b29e472015-02-16 10:41:54 +0900352 except lib_exc.BadRequest as e:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500353 if 'overlaps with another subnet' not in str(e):
354 raise
355 else:
David Kranzd4210412014-11-21 08:37:45 -0500356 message = 'Available CIDR for subnet creation could not be found'
357 raise Exception(message)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500358 return resp_body['subnet']
359
360 def _create_router(self, router_name, tenant_id):
zhufl6b7040a2017-01-18 16:38:34 +0800361 kwargs = {'name': router_name,
362 'tenant_id': tenant_id}
363 if self.public_network_id:
364 kwargs['external_gateway_info'] = dict(
365 network_id=self.public_network_id)
366 resp_body = self.routers_admin_client.create_router(**kwargs)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500367 return resp_body['router']
368
369 def _add_router_interface(self, router_id, subnet_id):
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000370 self.routers_admin_client.add_router_interface(router_id,
piyush11078694aca952015-12-17 12:54:44 +0530371 subnet_id=subnet_id)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500372
Colleen Murphy06374e22019-10-02 14:28:22 -0700373 def get_credentials(self, credential_type, scope=None):
374 if not scope and self._creds.get(str(credential_type)):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700375 credentials = self._creds[str(credential_type)]
Colleen Murphy06374e22019-10-02 14:28:22 -0700376 elif scope and self._creds.get("%s_%s" % (scope, credential_type[0])):
377 credentials = self._creds["%s_%s" % (scope, credential_type[0])]
Matthew Treinishb86cda92013-07-29 11:22:23 -0400378 else:
Matthew Treinish976e8df2014-12-19 14:21:54 -0500379 if credential_type in ['primary', 'alt', 'admin']:
380 is_admin = (credential_type == 'admin')
381 credentials = self._create_creds(admin=is_admin)
382 else:
Colleen Murphy06374e22019-10-02 14:28:22 -0700383 if scope:
384 credentials = self._create_creds(
385 roles=credential_type, scope=scope)
386 else:
387 credentials = self._create_creds(roles=credential_type)
388 if scope:
389 self._creds["%s_%s" %
390 (scope, credential_type[0])] = credentials
391 else:
392 self._creds[str(credential_type)] = credentials
Andrea Frittolifc315902014-03-20 09:21:44 +0000393 # Maintained until tests are ported
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200394 LOG.info("Acquired dynamic creds:\n"
395 " credentials: %s", credentials)
396 if (self.neutron_available and self.create_networks):
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500397 network, subnet, router = self._create_network_resources(
Andrea Frittolifc315902014-03-20 09:21:44 +0000398 credentials.tenant_id)
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400399 credentials.set_resources(network=network, subnet=subnet,
400 router=router)
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200401 LOG.info("Created isolated network resources for:\n"
402 " credentials: %s", credentials)
Andrea Frittoli9612e812014-03-13 10:57:26 +0000403 return credentials
Matthew Treinishb86cda92013-07-29 11:22:23 -0400404
Andrea Frittoli9612e812014-03-13 10:57:26 +0000405 def get_primary_creds(self):
406 return self.get_credentials('primary')
Matthew Treinishb86cda92013-07-29 11:22:23 -0400407
Andrea Frittoli9612e812014-03-13 10:57:26 +0000408 def get_admin_creds(self):
409 return self.get_credentials('admin')
Andrea Frittolifc315902014-03-20 09:21:44 +0000410
Andrea Frittoli9612e812014-03-13 10:57:26 +0000411 def get_alt_creds(self):
412 return self.get_credentials('alt')
Matthew Treinishb86cda92013-07-29 11:22:23 -0400413
Colleen Murphy06374e22019-10-02 14:28:22 -0700414 def get_system_admin_creds(self):
415 return self.get_credentials(['admin'], scope='system')
416
417 def get_system_member_creds(self):
418 return self.get_credentials(['member'], scope='system')
419
420 def get_system_reader_creds(self):
421 return self.get_credentials(['reader'], scope='system')
422
423 def get_domain_admin_creds(self):
424 return self.get_credentials(['admin'], scope='domain')
425
426 def get_domain_member_creds(self):
427 return self.get_credentials(['member'], scope='domain')
428
429 def get_domain_reader_creds(self):
430 return self.get_credentials(['reader'], scope='domain')
431
432 def get_project_admin_creds(self):
433 return self.get_credentials(['admin'], scope='project')
434
435 def get_project_member_creds(self):
436 return self.get_credentials(['member'], scope='project')
437
438 def get_project_reader_creds(self):
439 return self.get_credentials(['reader'], scope='project')
440
Matthew Treinish976e8df2014-12-19 14:21:54 -0500441 def get_creds_by_roles(self, roles, force_new=False):
442 roles = list(set(roles))
443 # The roles list as a str will become the index as the dict key for
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700444 # the created credentials set in the dynamic_creds dict.
445 exist_creds = self._creds.get(str(roles))
Matthew Treinish976e8df2014-12-19 14:21:54 -0500446 # If force_new flag is True 2 cred sets with the same roles are needed
447 # handle this by creating a separate index for old one to store it
448 # separately for cleanup
449 if exist_creds and force_new:
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700450 new_index = str(roles) + '-' + str(len(self._creds))
451 self._creds[new_index] = exist_creds
452 del self._creds[str(roles)]
Matthew Treinish976e8df2014-12-19 14:21:54 -0500453 return self.get_credentials(roles)
454
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500455 def _clear_isolated_router(self, router_id, router_name):
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000456 client = self.routers_admin_client
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500457 try:
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000458 client.delete_router(router_id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900459 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100460 LOG.warning('router with name: %s not found for delete',
zhangguoqing6c096642016-01-04 06:17:21 +0000461 router_name)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500462
463 def _clear_isolated_subnet(self, subnet_id, subnet_name):
John Warren3961acd2015-10-02 14:38:53 -0400464 client = self.subnets_admin_client
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500465 try:
John Warren3961acd2015-10-02 14:38:53 -0400466 client.delete_subnet(subnet_id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900467 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100468 LOG.warning('subnet with name: %s not found for delete',
zhangguoqing6c096642016-01-04 06:17:21 +0000469 subnet_name)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500470
471 def _clear_isolated_network(self, network_id, network_name):
John Warren94d8faf2015-09-15 12:22:24 -0400472 net_client = self.networks_admin_client
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500473 try:
474 net_client.delete_network(network_id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900475 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100476 LOG.warning('network with name: %s not found for delete',
zhangguoqing6c096642016-01-04 06:17:21 +0000477 network_name)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500478
Ala Rezmerita846eb7c2014-03-10 09:06:03 +0100479 def _cleanup_default_secgroup(self, tenant):
John Warrenf9606e92015-12-10 12:12:42 -0500480 nsg_client = self.security_groups_admin_client
481 resp_body = nsg_client.list_security_groups(tenant_id=tenant,
David Kranz34e88122014-12-11 15:24:05 -0500482 name="default")
Ala Rezmerita846eb7c2014-03-10 09:06:03 +0100483 secgroups_to_delete = resp_body['security_groups']
484 for secgroup in secgroups_to_delete:
485 try:
John Warrenf9606e92015-12-10 12:12:42 -0500486 nsg_client.delete_security_group(secgroup['id'])
Masayuki Igawabfa07602015-01-20 18:47:17 +0900487 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100488 LOG.warning('Security group %s, id %s not found for clean-up',
489 secgroup['name'], secgroup['id'])
Ala Rezmerita846eb7c2014-03-10 09:06:03 +0100490
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500491 def _clear_isolated_net_resources(self):
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000492 client = self.routers_admin_client
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700493 for cred in self._creds:
494 creds = self._creds.get(cred)
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400495 if (not creds or not any([creds.router, creds.network,
496 creds.subnet])):
497 continue
Salvatore Orlandocf996c62014-01-30 09:15:18 -0800498 LOG.debug("Clearing network: %(network)s, "
Matthew Treinishfe094ea2014-12-09 01:19:27 +0000499 "subnet: %(subnet)s, router: %(router)s",
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400500 {'network': creds.network, 'subnet': creds.subnet,
501 'router': creds.router})
Salvatore Orlandocf996c62014-01-30 09:15:18 -0800502 if (not self.network_resources or
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400503 (self.network_resources.get('router') and creds.subnet)):
Matthew Treinish9f756a02014-01-15 10:26:07 -0500504 try:
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000505 client.remove_router_interface(
piyush11078694aca952015-12-17 12:54:44 +0530506 creds.router['id'],
507 subnet_id=creds.subnet['id'])
Masayuki Igawabfa07602015-01-20 18:47:17 +0900508 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100509 LOG.warning('router with name: %s not found for delete',
zhangguoqing6c096642016-01-04 06:17:21 +0000510 creds.router['name'])
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400511 self._clear_isolated_router(creds.router['id'],
512 creds.router['name'])
Salvatore Orlandocf996c62014-01-30 09:15:18 -0800513 if (not self.network_resources or
Salvatore Orlandocf996c62014-01-30 09:15:18 -0800514 self.network_resources.get('subnet')):
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400515 self._clear_isolated_subnet(creds.subnet['id'],
516 creds.subnet['name'])
Salvatore Orlandocf996c62014-01-30 09:15:18 -0800517 if (not self.network_resources or
518 self.network_resources.get('network')):
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400519 self._clear_isolated_network(creds.network['id'],
520 creds.network['name'])
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500521
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700522 def clear_creds(self):
523 if not self._creds:
Matthew Treinishb86cda92013-07-29 11:22:23 -0400524 return
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500525 self._clear_isolated_net_resources()
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700526 for creds in six.itervalues(self._creds):
Matthew Treinishb86cda92013-07-29 11:22:23 -0400527 try:
Andrea Frittolic3280152015-02-26 12:42:34 +0000528 self.creds_client.delete_user(creds.user_id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900529 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100530 LOG.warning("user with name: %s not found for delete",
zhangguoqing6c096642016-01-04 06:17:21 +0000531 creds.username)
zhufl2344ea62016-06-01 14:44:00 +0800532 # NOTE(zhufl): Only when neutron's security_group ext is
533 # enabled, _cleanup_default_secgroup will not raise error. But
Andrea Frittolicd368412017-08-14 21:37:56 +0100534 # here cannot use test_utils.is_extension_enabled for it will cause
zhufl2344ea62016-06-01 14:44:00 +0800535 # "circular dependency". So here just use try...except to
536 # ensure tenant deletion without big changes.
Matthew Treinishb86cda92013-07-29 11:22:23 -0400537 try:
Matthew Treinish75abbcf2016-10-07 16:19:12 -0400538 if self.neutron_available:
Andrea Frittolic3280152015-02-26 12:42:34 +0000539 self._cleanup_default_secgroup(creds.tenant_id)
zhufl2344ea62016-06-01 14:44:00 +0800540 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100541 LOG.warning("failed to cleanup tenant %s's secgroup",
zhufl2344ea62016-06-01 14:44:00 +0800542 creds.tenant_name)
543 try:
Andrea Frittolic3280152015-02-26 12:42:34 +0000544 self.creds_client.delete_project(creds.tenant_id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900545 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100546 LOG.warning("tenant with name: %s not found for delete",
zhangguoqing6c096642016-01-04 06:17:21 +0000547 creds.tenant_name)
Colleen Murphy06374e22019-10-02 14:28:22 -0700548
549 # if cred is domain scoped, delete ephemeral domain
550 # do not delete default domain
551 if (hasattr(creds, 'domain_id') and
552 creds.domain_id != creds.project_domain_id):
553 try:
554 self.creds_client.delete_domain(creds.domain_id)
555 except lib_exc.NotFound:
556 LOG.warning("domain with name: %s not found for delete",
557 creds.domain_name)
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700558 self._creds = {}
Andrea Frittoli8283b4e2014-07-17 13:28:58 +0100559
560 def is_multi_user(self):
561 return True
Yair Fried76488d72014-10-21 10:13:19 +0300562
563 def is_multi_tenant(self):
564 return True
Matthew Treinish4a596932015-03-06 20:37:01 -0500565
566 def is_role_available(self, role):
567 return True