blob: b641542d7de8239bde9939c295ae224ee79d858a [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'
Martin Kopeca28849f2021-01-21 14:06:21 +0000147 elif (self.identity_admin_domain_scope and
148 (self.default_admin_creds.domain_id or
149 self.default_admin_creds.domain_name)):
Colleen Murphycd0bbbd2019-10-01 16:18:36 -0700150 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)
Lance Bragstadef13f402021-03-04 17:12:10 +0000231 if scope == 'project':
232 self.creds_client.assign_user_role(
233 user, project, self.identity_admin_role)
Andrea Frittoli (andreaf)100d18d2016-05-05 23:34:52 +0100234 if (self.identity_version == 'v3' and
Matthew Treinish75abbcf2016-10-07 16:19:12 -0400235 self.identity_admin_domain_scope):
Andrea Frittoli (andreaf)4bee2e72015-09-22 13:06:18 +0100236 self.creds_client.assign_user_role_on_domain(
Matthew Treinish75abbcf2016-10-07 16:19:12 -0400237 user, self.identity_admin_role)
Matthew Treinish976e8df2014-12-19 14:21:54 -0500238 # Add roles specified in config file
Colleen Murphy06374e22019-10-02 14:28:22 -0700239 roles_to_assign.extend(self.extra_roles)
240 # If there are still no roles, default to 'member'
Matthew Treinish32f98a42015-07-14 19:58:46 -0400241 # NOTE(mtreinish) For a user to have access to a project with v3 auth
242 # it must beassigned a role on the project. So we need to ensure that
243 # our newly created user has a role on the newly created project.
Colleen Murphy06374e22019-10-02 14:28:22 -0700244 if not roles_to_assign and self.identity_version == 'v3':
245 roles_to_assign = ['member']
Adam Youngb226f8e2016-06-25 21:41:36 -0400246 try:
Martin Kopec99d4dae2020-05-27 10:33:17 +0000247 self.creds_client.create_user_role('member')
Adam Youngb226f8e2016-06-25 21:41:36 -0400248 except lib_exc.Conflict:
Martin Kopec99d4dae2020-05-27 10:33:17 +0000249 LOG.warning('member role already exists, ignoring conflict.')
Colleen Murphy06374e22019-10-02 14:28:22 -0700250 for role in roles_to_assign:
251 if scope == 'project':
252 self.creds_client.assign_user_role(user, project, role)
253 elif scope == 'domain':
254 self.creds_client.assign_user_role_on_domain(
255 user, role, domain)
256 elif scope == 'system':
257 self.creds_client.assign_user_role_on_system(user, role)
Ghanshyam Mannf97c5cc2021-02-16 12:16:10 -0600258 LOG.info("Roles assigned to the user %s are: %s",
259 user['id'], roles_to_assign)
Matthew Treinish32f98a42015-07-14 19:58:46 -0400260
Colleen Murphy06374e22019-10-02 14:28:22 -0700261 creds = self.creds_client.get_credentials(**cred_params)
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400262 return cred_provider.TestResources(creds)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500263
264 def _create_network_resources(self, tenant_id):
edannon6cc6fbc2016-05-03 11:56:12 +0300265 """The function creates network resources in the given tenant.
266
267 The function checks if network_resources class member is empty,
268 In case it is, it will create a network, a subnet and a router for
269 the tenant according to the given tenant id parameter.
270 Otherwise it will create a network resource according
271 to the values from network_resources dict.
272
273 :param tenant_id: The tenant id to create resources for.
274 :type tenant_id: str
275 :raises: InvalidConfiguration, Exception
276 :returns: network resources(network,subnet,router)
277 :rtype: tuple
278 """
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500279 network = None
280 subnet = None
281 router = None
Matthew Treinish9f756a02014-01-15 10:26:07 -0500282 # Make sure settings
283 if self.network_resources:
284 if self.network_resources['router']:
285 if (not self.network_resources['subnet'] or
286 not self.network_resources['network']):
Matthew Treinish4217a702016-10-07 17:27:11 -0400287 raise lib_exc.InvalidConfiguration(
Matthew Treinish9f756a02014-01-15 10:26:07 -0500288 'A router requires a subnet and network')
289 elif self.network_resources['subnet']:
290 if not self.network_resources['network']:
Matthew Treinish4217a702016-10-07 17:27:11 -0400291 raise lib_exc.InvalidConfiguration(
Matthew Treinish9f756a02014-01-15 10:26:07 -0500292 'A subnet requires a network')
293 elif self.network_resources['dhcp']:
Matthew Treinish4217a702016-10-07 17:27:11 -0400294 raise lib_exc.InvalidConfiguration('DHCP requires a subnet')
Matthew Treinish9f756a02014-01-15 10:26:07 -0500295
Matthew Treinish0650aed2016-10-07 16:36:46 -0400296 rand_name_root = data_utils.rand_name(
297 self.name, prefix=self.resource_prefix)
Matthew Treinish9f756a02014-01-15 10:26:07 -0500298 if not self.network_resources or self.network_resources['network']:
Matthew Treinish0650aed2016-10-07 16:36:46 -0400299 network_name = rand_name_root + "-network"
Matthew Treinish9f756a02014-01-15 10:26:07 -0500300 network = self._create_network(network_name, tenant_id)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500301 try:
Matthew Treinish9f756a02014-01-15 10:26:07 -0500302 if not self.network_resources or self.network_resources['subnet']:
Matthew Treinish0650aed2016-10-07 16:36:46 -0400303 subnet_name = rand_name_root + "-subnet"
Matthew Treinish9f756a02014-01-15 10:26:07 -0500304 subnet = self._create_subnet(subnet_name, tenant_id,
305 network['id'])
306 if not self.network_resources or self.network_resources['router']:
Matthew Treinish0650aed2016-10-07 16:36:46 -0400307 router_name = rand_name_root + "-router"
Matthew Treinish9f756a02014-01-15 10:26:07 -0500308 router = self._create_router(router_name, tenant_id)
309 self._add_router_interface(router['id'], subnet['id'])
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500310 except Exception:
Andrea Frittoli (andreaf)d9a18b02016-02-29 15:27:34 +0000311 try:
312 if router:
313 self._clear_isolated_router(router['id'], router['name'])
314 if subnet:
315 self._clear_isolated_subnet(subnet['id'], subnet['name'])
316 if network:
317 self._clear_isolated_network(network['id'],
318 network['name'])
319 except Exception as cleanup_exception:
320 msg = "There was an exception trying to setup network " \
321 "resources for tenant %s, and this error happened " \
322 "trying to clean them up: %s"
Jordan Pittier525ec712016-12-07 17:51:26 +0100323 LOG.warning(msg, tenant_id, cleanup_exception)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500324 raise
325 return network, subnet, router
326
327 def _create_network(self, name, tenant_id):
John Warren94d8faf2015-09-15 12:22:24 -0400328 resp_body = self.networks_admin_client.create_network(
Andrea Frittoliae9aca02014-09-25 11:43:11 +0100329 name=name, tenant_id=tenant_id)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500330 return resp_body['network']
331
332 def _create_subnet(self, subnet_name, tenant_id, network_id):
Matthew Treinish75abbcf2016-10-07 16:19:12 -0400333 base_cidr = netaddr.IPNetwork(self.project_network_cidr)
334 mask_bits = self.project_network_mask_bits
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500335 for subnet_cidr in base_cidr.subnet(mask_bits):
336 try:
Andrea Frittoliae9aca02014-09-25 11:43:11 +0100337 if self.network_resources:
John Warren3961acd2015-10-02 14:38:53 -0400338 resp_body = self.subnets_admin_client.\
Andrea Frittoliae9aca02014-09-25 11:43:11 +0100339 create_subnet(
340 network_id=network_id, cidr=str(subnet_cidr),
341 name=subnet_name,
342 tenant_id=tenant_id,
343 enable_dhcp=self.network_resources['dhcp'],
zhongjun5b68f502017-07-04 15:28:05 +0800344 ip_version=(ipaddress.ip_network(
likui19b70a32020-12-02 13:25:18 +0800345 str(subnet_cidr)).version))
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500346 else:
John Warren3961acd2015-10-02 14:38:53 -0400347 resp_body = self.subnets_admin_client.\
Andrea Frittoliae9aca02014-09-25 11:43:11 +0100348 create_subnet(network_id=network_id,
349 cidr=str(subnet_cidr),
350 name=subnet_name,
351 tenant_id=tenant_id,
zhongjun5b68f502017-07-04 15:28:05 +0800352 ip_version=(ipaddress.ip_network(
likui19b70a32020-12-02 13:25:18 +0800353 str(subnet_cidr)).version))
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500354 break
Masayuki Igawa4b29e472015-02-16 10:41:54 +0900355 except lib_exc.BadRequest as e:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500356 if 'overlaps with another subnet' not in str(e):
357 raise
358 else:
David Kranzd4210412014-11-21 08:37:45 -0500359 message = 'Available CIDR for subnet creation could not be found'
360 raise Exception(message)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500361 return resp_body['subnet']
362
363 def _create_router(self, router_name, tenant_id):
zhufl6b7040a2017-01-18 16:38:34 +0800364 kwargs = {'name': router_name,
365 'tenant_id': tenant_id}
366 if self.public_network_id:
367 kwargs['external_gateway_info'] = dict(
368 network_id=self.public_network_id)
369 resp_body = self.routers_admin_client.create_router(**kwargs)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500370 return resp_body['router']
371
372 def _add_router_interface(self, router_id, subnet_id):
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000373 self.routers_admin_client.add_router_interface(router_id,
piyush11078694aca952015-12-17 12:54:44 +0530374 subnet_id=subnet_id)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500375
Colleen Murphy06374e22019-10-02 14:28:22 -0700376 def get_credentials(self, credential_type, scope=None):
377 if not scope and self._creds.get(str(credential_type)):
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700378 credentials = self._creds[str(credential_type)]
Colleen Murphy06374e22019-10-02 14:28:22 -0700379 elif scope and self._creds.get("%s_%s" % (scope, credential_type[0])):
380 credentials = self._creds["%s_%s" % (scope, credential_type[0])]
Matthew Treinishb86cda92013-07-29 11:22:23 -0400381 else:
Ghanshyam Mann7f394252021-01-29 13:07:23 -0600382 if scope:
Ghanshyam Mann420586c2021-01-29 13:23:18 -0600383 if credential_type in [['admin'], ['alt_admin']]:
Ghanshyam Mann7f394252021-01-29 13:07:23 -0600384 credentials = self._create_creds(
385 admin=True, scope=scope)
386 else:
Ghanshyam Mann420586c2021-01-29 13:23:18 -0600387 cred_type = credential_type
388 if credential_type in [['alt_member'], ['alt_reader']]:
389 cred_type = credential_type[0][4:]
Lance Bragstadef13f402021-03-04 17:12:10 +0000390 if isinstance(cred_type, str):
391 cred_type = [cred_type]
Ghanshyam Mann7f394252021-01-29 13:07:23 -0600392 credentials = self._create_creds(
Lance Bragstadef13f402021-03-04 17:12:10 +0000393 roles=cred_type, scope=scope)
Ghanshyam Mann7f394252021-01-29 13:07:23 -0600394 elif credential_type in ['primary', 'alt', 'admin']:
Matthew Treinish976e8df2014-12-19 14:21:54 -0500395 is_admin = (credential_type == 'admin')
396 credentials = self._create_creds(admin=is_admin)
397 else:
Ghanshyam Mann7f394252021-01-29 13:07:23 -0600398 credentials = self._create_creds(roles=credential_type)
Colleen Murphy06374e22019-10-02 14:28:22 -0700399 if scope:
400 self._creds["%s_%s" %
401 (scope, credential_type[0])] = credentials
402 else:
403 self._creds[str(credential_type)] = credentials
Andrea Frittolifc315902014-03-20 09:21:44 +0000404 # Maintained until tests are ported
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200405 LOG.info("Acquired dynamic creds:\n"
406 " credentials: %s", credentials)
407 if (self.neutron_available and self.create_networks):
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500408 network, subnet, router = self._create_network_resources(
Andrea Frittolifc315902014-03-20 09:21:44 +0000409 credentials.tenant_id)
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400410 credentials.set_resources(network=network, subnet=subnet,
411 router=router)
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200412 LOG.info("Created isolated network resources for:\n"
413 " credentials: %s", credentials)
Andrea Frittoli9612e812014-03-13 10:57:26 +0000414 return credentials
Matthew Treinishb86cda92013-07-29 11:22:23 -0400415
Ghanshyam Mann32e05572021-01-29 11:24:56 -0600416 # TODO(gmann): Remove this method in favor of get_project_member_creds()
417 # after the deprecation phase.
Andrea Frittoli9612e812014-03-13 10:57:26 +0000418 def get_primary_creds(self):
419 return self.get_credentials('primary')
Matthew Treinishb86cda92013-07-29 11:22:23 -0400420
Ghanshyam Mann32e05572021-01-29 11:24:56 -0600421 # TODO(gmann): Remove this method in favor of get_project_admin_creds()
422 # after the deprecation phase.
Andrea Frittoli9612e812014-03-13 10:57:26 +0000423 def get_admin_creds(self):
424 return self.get_credentials('admin')
Andrea Frittolifc315902014-03-20 09:21:44 +0000425
Ghanshyam Mann32e05572021-01-29 11:24:56 -0600426 # TODO(gmann): Replace this method with more appropriate name.
427 # like get_project_alt_member_creds()
Andrea Frittoli9612e812014-03-13 10:57:26 +0000428 def get_alt_creds(self):
429 return self.get_credentials('alt')
Matthew Treinishb86cda92013-07-29 11:22:23 -0400430
Colleen Murphy06374e22019-10-02 14:28:22 -0700431 def get_system_admin_creds(self):
432 return self.get_credentials(['admin'], scope='system')
433
434 def get_system_member_creds(self):
435 return self.get_credentials(['member'], scope='system')
436
437 def get_system_reader_creds(self):
438 return self.get_credentials(['reader'], scope='system')
439
440 def get_domain_admin_creds(self):
441 return self.get_credentials(['admin'], scope='domain')
442
443 def get_domain_member_creds(self):
444 return self.get_credentials(['member'], scope='domain')
445
446 def get_domain_reader_creds(self):
447 return self.get_credentials(['reader'], scope='domain')
448
449 def get_project_admin_creds(self):
450 return self.get_credentials(['admin'], scope='project')
451
Ghanshyam Mann420586c2021-01-29 13:23:18 -0600452 def get_project_alt_admin_creds(self):
453 return self.get_credentials(['alt_admin'], scope='project')
454
Colleen Murphy06374e22019-10-02 14:28:22 -0700455 def get_project_member_creds(self):
456 return self.get_credentials(['member'], scope='project')
457
Ghanshyam Mann420586c2021-01-29 13:23:18 -0600458 def get_project_alt_member_creds(self):
459 return self.get_credentials(['alt_member'], scope='project')
460
Colleen Murphy06374e22019-10-02 14:28:22 -0700461 def get_project_reader_creds(self):
462 return self.get_credentials(['reader'], scope='project')
463
Ghanshyam Mann420586c2021-01-29 13:23:18 -0600464 def get_project_alt_reader_creds(self):
465 return self.get_credentials(['alt_reader'], scope='project')
466
Matthew Treinish976e8df2014-12-19 14:21:54 -0500467 def get_creds_by_roles(self, roles, force_new=False):
468 roles = list(set(roles))
469 # The roles list as a str will become the index as the dict key for
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700470 # the created credentials set in the dynamic_creds dict.
471 exist_creds = self._creds.get(str(roles))
Matthew Treinish976e8df2014-12-19 14:21:54 -0500472 # If force_new flag is True 2 cred sets with the same roles are needed
473 # handle this by creating a separate index for old one to store it
474 # separately for cleanup
475 if exist_creds and force_new:
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700476 new_index = str(roles) + '-' + str(len(self._creds))
477 self._creds[new_index] = exist_creds
478 del self._creds[str(roles)]
Matthew Treinish976e8df2014-12-19 14:21:54 -0500479 return self.get_credentials(roles)
480
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500481 def _clear_isolated_router(self, router_id, router_name):
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000482 client = self.routers_admin_client
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500483 try:
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000484 client.delete_router(router_id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900485 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100486 LOG.warning('router with name: %s not found for delete',
zhangguoqing6c096642016-01-04 06:17:21 +0000487 router_name)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500488
489 def _clear_isolated_subnet(self, subnet_id, subnet_name):
John Warren3961acd2015-10-02 14:38:53 -0400490 client = self.subnets_admin_client
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500491 try:
John Warren3961acd2015-10-02 14:38:53 -0400492 client.delete_subnet(subnet_id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900493 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100494 LOG.warning('subnet with name: %s not found for delete',
zhangguoqing6c096642016-01-04 06:17:21 +0000495 subnet_name)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500496
497 def _clear_isolated_network(self, network_id, network_name):
John Warren94d8faf2015-09-15 12:22:24 -0400498 net_client = self.networks_admin_client
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500499 try:
500 net_client.delete_network(network_id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900501 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100502 LOG.warning('network with name: %s not found for delete',
zhangguoqing6c096642016-01-04 06:17:21 +0000503 network_name)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500504
Ala Rezmerita846eb7c2014-03-10 09:06:03 +0100505 def _cleanup_default_secgroup(self, tenant):
John Warrenf9606e92015-12-10 12:12:42 -0500506 nsg_client = self.security_groups_admin_client
507 resp_body = nsg_client.list_security_groups(tenant_id=tenant,
David Kranz34e88122014-12-11 15:24:05 -0500508 name="default")
Ala Rezmerita846eb7c2014-03-10 09:06:03 +0100509 secgroups_to_delete = resp_body['security_groups']
510 for secgroup in secgroups_to_delete:
511 try:
John Warrenf9606e92015-12-10 12:12:42 -0500512 nsg_client.delete_security_group(secgroup['id'])
Masayuki Igawabfa07602015-01-20 18:47:17 +0900513 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100514 LOG.warning('Security group %s, id %s not found for clean-up',
515 secgroup['name'], secgroup['id'])
Ala Rezmerita846eb7c2014-03-10 09:06:03 +0100516
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500517 def _clear_isolated_net_resources(self):
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000518 client = self.routers_admin_client
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700519 for cred in self._creds:
520 creds = self._creds.get(cred)
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400521 if (not creds or not any([creds.router, creds.network,
522 creds.subnet])):
523 continue
Salvatore Orlandocf996c62014-01-30 09:15:18 -0800524 LOG.debug("Clearing network: %(network)s, "
Matthew Treinishfe094ea2014-12-09 01:19:27 +0000525 "subnet: %(subnet)s, router: %(router)s",
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400526 {'network': creds.network, 'subnet': creds.subnet,
527 'router': creds.router})
Salvatore Orlandocf996c62014-01-30 09:15:18 -0800528 if (not self.network_resources or
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400529 (self.network_resources.get('router') and creds.subnet)):
Matthew Treinish9f756a02014-01-15 10:26:07 -0500530 try:
Ken'ichi Ohmichie35f4722015-12-22 04:57:11 +0000531 client.remove_router_interface(
piyush11078694aca952015-12-17 12:54:44 +0530532 creds.router['id'],
533 subnet_id=creds.subnet['id'])
Masayuki Igawabfa07602015-01-20 18:47:17 +0900534 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100535 LOG.warning('router with name: %s not found for delete',
zhangguoqing6c096642016-01-04 06:17:21 +0000536 creds.router['name'])
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400537 self._clear_isolated_router(creds.router['id'],
538 creds.router['name'])
Salvatore Orlandocf996c62014-01-30 09:15:18 -0800539 if (not self.network_resources or
Salvatore Orlandocf996c62014-01-30 09:15:18 -0800540 self.network_resources.get('subnet')):
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400541 self._clear_isolated_subnet(creds.subnet['id'],
542 creds.subnet['name'])
Salvatore Orlandocf996c62014-01-30 09:15:18 -0800543 if (not self.network_resources or
544 self.network_resources.get('network')):
Andrea Frittoli (andreaf)9540dfd2015-03-25 17:06:50 -0400545 self._clear_isolated_network(creds.network['id'],
546 creds.network['name'])
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500547
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700548 def clear_creds(self):
549 if not self._creds:
Matthew Treinishb86cda92013-07-29 11:22:23 -0400550 return
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500551 self._clear_isolated_net_resources()
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700552 for creds in six.itervalues(self._creds):
Matthew Treinishb86cda92013-07-29 11:22:23 -0400553 try:
Andrea Frittolic3280152015-02-26 12:42:34 +0000554 self.creds_client.delete_user(creds.user_id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900555 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100556 LOG.warning("user with name: %s not found for delete",
zhangguoqing6c096642016-01-04 06:17:21 +0000557 creds.username)
zhufl2344ea62016-06-01 14:44:00 +0800558 # NOTE(zhufl): Only when neutron's security_group ext is
559 # enabled, _cleanup_default_secgroup will not raise error. But
Andrea Frittolicd368412017-08-14 21:37:56 +0100560 # here cannot use test_utils.is_extension_enabled for it will cause
zhufl2344ea62016-06-01 14:44:00 +0800561 # "circular dependency". So here just use try...except to
562 # ensure tenant deletion without big changes.
Matthew Treinishb86cda92013-07-29 11:22:23 -0400563 try:
Matthew Treinish75abbcf2016-10-07 16:19:12 -0400564 if self.neutron_available:
Andrea Frittolic3280152015-02-26 12:42:34 +0000565 self._cleanup_default_secgroup(creds.tenant_id)
zhufl2344ea62016-06-01 14:44:00 +0800566 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100567 LOG.warning("failed to cleanup tenant %s's secgroup",
zhufl2344ea62016-06-01 14:44:00 +0800568 creds.tenant_name)
569 try:
Andrea Frittolic3280152015-02-26 12:42:34 +0000570 self.creds_client.delete_project(creds.tenant_id)
Masayuki Igawabfa07602015-01-20 18:47:17 +0900571 except lib_exc.NotFound:
Jordan Pittier525ec712016-12-07 17:51:26 +0100572 LOG.warning("tenant with name: %s not found for delete",
zhangguoqing6c096642016-01-04 06:17:21 +0000573 creds.tenant_name)
Colleen Murphy06374e22019-10-02 14:28:22 -0700574
575 # if cred is domain scoped, delete ephemeral domain
576 # do not delete default domain
577 if (hasattr(creds, 'domain_id') and
578 creds.domain_id != creds.project_domain_id):
579 try:
580 self.creds_client.delete_domain(creds.domain_id)
581 except lib_exc.NotFound:
582 LOG.warning("domain with name: %s not found for delete",
583 creds.domain_name)
Andrea Frittoli (andreaf)17209bb2015-05-22 10:16:57 -0700584 self._creds = {}
Andrea Frittoli8283b4e2014-07-17 13:28:58 +0100585
586 def is_multi_user(self):
587 return True
Yair Fried76488d72014-10-21 10:13:19 +0300588
589 def is_multi_tenant(self):
590 return True
Matthew Treinish4a596932015-03-06 20:37:01 -0500591
592 def is_role_available(self, role):
593 return True