blob: da6031841eda1af29b3ca96a04b4eb0e40e72e56 [file] [log] [blame]
Matthew Treinishb86cda92013-07-29 11:22:23 -04001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2013 IBM Corp.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050017import netaddr
18
19import keystoneclient.v2_0.client as keystoneclient
20import neutronclient.v2_0.client as neutronclient
Matthew Treinishb86cda92013-07-29 11:22:23 -040021
22from tempest import clients
Masayuki Igawa259c1132013-10-31 17:48:44 +090023from tempest.common.utils import data_utils
Matthew Treinishb86cda92013-07-29 11:22:23 -040024from tempest import config
25from tempest import exceptions
26from tempest.openstack.common import log as logging
27
Sean Dague86bd8422013-12-20 09:56:44 -050028CONF = config.CONF
Matthew Treinishb86cda92013-07-29 11:22:23 -040029LOG = logging.getLogger(__name__)
30
31
32class IsolatedCreds(object):
33
34 def __init__(self, name, tempest_client=True, interface='json',
35 password='pass'):
36 self.isolated_creds = {}
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050037 self.isolated_net_resources = {}
38 self.ports = []
Matthew Treinishb86cda92013-07-29 11:22:23 -040039 self.name = name
Sean Dague86bd8422013-12-20 09:56:44 -050040 self.config = CONF
Matthew Treinishb86cda92013-07-29 11:22:23 -040041 self.tempest_client = tempest_client
42 self.interface = interface
43 self.password = password
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050044 self.identity_admin_client, self.network_admin_client = (
45 self._get_admin_clients())
Matthew Treinishb86cda92013-07-29 11:22:23 -040046
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050047 def _get_official_admin_clients(self):
Sean Dague86bd8422013-12-20 09:56:44 -050048 username = CONF.identity.admin_username
49 password = CONF.identity.admin_password
50 tenant_name = CONF.identity.admin_tenant_name
51 auth_url = CONF.identity.uri
52 dscv = CONF.identity.disable_ssl_certificate_validation
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050053 identity_client = keystoneclient.Client(username=username,
54 password=password,
55 tenant_name=tenant_name,
56 auth_url=auth_url,
57 insecure=dscv)
58 network_client = neutronclient.Client(username=username,
59 password=password,
60 tenant_name=tenant_name,
61 auth_url=auth_url,
62 insecure=dscv)
63 return identity_client, network_client
Matthew Treinishb86cda92013-07-29 11:22:23 -040064
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050065 def _get_admin_clients(self):
Matthew Treinishb86cda92013-07-29 11:22:23 -040066 """
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050067 Returns a tuple with instances of the following admin clients (in this
68 order):
69 identity
70 network
Matthew Treinishb86cda92013-07-29 11:22:23 -040071 """
72 if self.tempest_client:
73 os = clients.AdminManager(interface=self.interface)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050074 admin_clients = (os.identity_client,
75 os.network_client,)
Matthew Treinishb86cda92013-07-29 11:22:23 -040076 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050077 admin_clients = self._get_official_admin_clients()
78 return admin_clients
Matthew Treinishb86cda92013-07-29 11:22:23 -040079
80 def _create_tenant(self, name, description):
81 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050082 resp, tenant = self.identity_admin_client.create_tenant(
Matthew Treinishb86cda92013-07-29 11:22:23 -040083 name=name, description=description)
84 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050085 tenant = self.identity_admin_client.tenants.create(
86 name,
87 description=description)
Matthew Treinishb86cda92013-07-29 11:22:23 -040088 return tenant
89
90 def _get_tenant_by_name(self, name):
91 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050092 resp, tenant = self.identity_admin_client.get_tenant_by_name(name)
Matthew Treinishb86cda92013-07-29 11:22:23 -040093 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050094 tenants = self.identity_admin_client.tenants.list()
Matthew Treinishb86cda92013-07-29 11:22:23 -040095 for ten in tenants:
96 if ten['name'] == name:
97 tenant = ten
DennyZhang1eb40462013-09-26 14:18:30 -050098 break
99 else:
100 raise exceptions.NotFound('No such tenant')
Matthew Treinishb86cda92013-07-29 11:22:23 -0400101 return tenant
102
103 def _create_user(self, username, password, tenant, email):
104 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500105 resp, user = self.identity_admin_client.create_user(username,
106 password,
107 tenant['id'],
108 email)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400109 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500110 user = self.identity_admin_client.users.create(username, password,
111 email,
112 tenant_id=tenant.id)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400113 return user
114
115 def _get_user(self, tenant, username):
116 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500117 resp, user = self.identity_admin_client.get_user_by_username(
118 tenant['id'],
119 username)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400120 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500121 user = self.identity_admin_client.users.get(username)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400122 return user
123
124 def _list_roles(self):
125 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500126 resp, roles = self.identity_admin_client.list_roles()
Matthew Treinishb86cda92013-07-29 11:22:23 -0400127 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500128 roles = self.identity_admin_client.roles.list()
Matthew Treinishb86cda92013-07-29 11:22:23 -0400129 return roles
130
131 def _assign_user_role(self, tenant, user, role):
132 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500133 self.identity_admin_client.assign_user_role(tenant, user, role)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400134 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500135 self.identity_admin_client.roles.add_user_role(user,
136 role, tenant=tenant)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400137
138 def _delete_user(self, user):
139 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500140 self.identity_admin_client.delete_user(user)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400141 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500142 self.identity_admin_client.users.delete(user)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400143
144 def _delete_tenant(self, tenant):
145 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500146 self.identity_admin_client.delete_tenant(tenant)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400147 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500148 self.identity_admin_client.tenants.delete(tenant)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400149
150 def _create_creds(self, suffix=None, admin=False):
Masayuki Igawa259c1132013-10-31 17:48:44 +0900151 data_utils.rand_name_root = data_utils.rand_name(self.name)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400152 if suffix:
Masayuki Igawa259c1132013-10-31 17:48:44 +0900153 data_utils.rand_name_root += suffix
154 tenant_name = data_utils.rand_name_root + "-tenant"
Matthew Treinishb86cda92013-07-29 11:22:23 -0400155 tenant_desc = tenant_name + "-desc"
Matthew Treinishb86cda92013-07-29 11:22:23 -0400156 tenant = self._create_tenant(name=tenant_name,
157 description=tenant_desc)
158 if suffix:
Masayuki Igawa259c1132013-10-31 17:48:44 +0900159 data_utils.rand_name_root += suffix
160 username = data_utils.rand_name_root + "-user"
161 email = data_utils.rand_name_root + "@example.com"
Matthew Treinishb86cda92013-07-29 11:22:23 -0400162 user = self._create_user(username, self.password,
163 tenant, email)
164 if admin:
165 role = None
166 try:
167 roles = self._list_roles()
Sean Dague86bd8422013-12-20 09:56:44 -0500168 admin_role = CONF.identity.admin_role
Matthew Treinishb86cda92013-07-29 11:22:23 -0400169 if self.tempest_client:
Russell Sim7f894a52013-09-13 10:35:21 +1000170 role = next(r for r in roles if r['name'] == admin_role)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400171 else:
Russell Sim7f894a52013-09-13 10:35:21 +1000172 role = next(r for r in roles if r.name == admin_role)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400173 except StopIteration:
174 msg = "No admin role found"
175 raise exceptions.NotFound(msg)
176 if self.tempest_client:
177 self._assign_user_role(tenant['id'], user['id'], role['id'])
178 else:
179 self._assign_user_role(tenant.id, user.id, role.id)
180 return user, tenant
181
182 def _get_cred_names(self, user, tenant):
183 if self.tempest_client:
184 username = user.get('name')
185 tenant_name = tenant.get('name')
186 else:
187 username = user.name
188 tenant_name = tenant.name
189 return username, tenant_name
190
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500191 def _get_tenant_id(self, tenant):
192 if self.tempest_client:
193 return tenant.get('id')
194 else:
195 return tenant.id
196
197 def _create_network_resources(self, tenant_id):
198 network = None
199 subnet = None
200 router = None
Masayuki Igawa259c1132013-10-31 17:48:44 +0900201 data_utils.rand_name_root = data_utils.rand_name(self.name)
202 network_name = data_utils.rand_name_root + "-network"
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500203 network = self._create_network(network_name, tenant_id)
204 try:
Masayuki Igawa259c1132013-10-31 17:48:44 +0900205 subnet_name = data_utils.rand_name_root + "-subnet"
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500206 subnet = self._create_subnet(subnet_name, tenant_id, network['id'])
Masayuki Igawa259c1132013-10-31 17:48:44 +0900207 router_name = data_utils.rand_name_root + "-router"
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500208 router = self._create_router(router_name, tenant_id)
209 self._add_router_interface(router['id'], subnet['id'])
210 except Exception:
211 if router:
212 self._clear_isolated_router(router['id'], router['name'])
213 if subnet:
214 self._clear_isolated_subnet(subnet['id'], subnet['name'])
215 if network:
216 self._clear_isolated_network(network['id'], network['name'])
217 raise
218 return network, subnet, router
219
220 def _create_network(self, name, tenant_id):
221 if self.tempest_client:
222 resp, resp_body = self.network_admin_client.create_network(
223 name, tenant_id=tenant_id)
224 else:
225 body = {'network': {'tenant_id': tenant_id, 'name': name}}
226 resp_body = self.network_admin_client.create_network(body)
227 return resp_body['network']
228
229 def _create_subnet(self, subnet_name, tenant_id, network_id):
230 if not self.tempest_client:
231 body = {'subnet': {'name': subnet_name, 'tenant_id': tenant_id,
232 'network_id': network_id, 'ip_version': 4}}
Sean Dague86bd8422013-12-20 09:56:44 -0500233 base_cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
234 mask_bits = CONF.network.tenant_network_mask_bits
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500235 for subnet_cidr in base_cidr.subnet(mask_bits):
236 try:
237 if self.tempest_client:
238 resp, resp_body = self.network_admin_client.create_subnet(
239 network_id, str(subnet_cidr), name=subnet_name,
240 tenant_id=tenant_id)
241 else:
242 body['subnet']['cidr'] = str(subnet_cidr)
243 resp_body = self.network_admin_client.create_subnet(body)
244 break
245 except exceptions.BadRequest as e:
246 if 'overlaps with another subnet' not in str(e):
247 raise
248 else:
249 e = exceptions.BuildErrorException()
250 e.message = 'Available CIDR for subnet creation could not be found'
251 raise e
252 return resp_body['subnet']
253
254 def _create_router(self, router_name, tenant_id):
255 external_net_id = dict(
Sean Dague86bd8422013-12-20 09:56:44 -0500256 network_id=CONF.network.public_network_id)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500257 if self.tempest_client:
258 resp, resp_body = self.network_admin_client.create_router(
259 router_name,
260 external_gateway_info=external_net_id,
261 tenant_id=tenant_id)
262 else:
263 body = {'router': {'name': router_name, 'tenant_id': tenant_id,
264 'external_gateway_info': external_net_id,
265 'admin_state_up': True}}
266 resp_body = self.network_admin_client.create_router(body)
267 return resp_body['router']
268
269 def _add_router_interface(self, router_id, subnet_id):
270 if self.tempest_client:
271 self.network_admin_client.add_router_interface_with_subnet_id(
272 router_id, subnet_id)
273 else:
274 body = {'subnet_id': subnet_id}
275 self.network_admin_client.add_interface_router(router_id, body)
276
Matthew Treinishb86cda92013-07-29 11:22:23 -0400277 def get_primary_tenant(self):
278 return self.isolated_creds.get('primary')[1]
279
280 def get_primary_user(self):
281 return self.isolated_creds.get('primary')[0]
282
283 def get_alt_tenant(self):
284 return self.isolated_creds.get('alt')[1]
285
286 def get_alt_user(self):
287 return self.isolated_creds.get('alt')[0]
288
289 def get_admin_tenant(self):
290 return self.isolated_creds.get('admin')[1]
291
292 def get_admin_user(self):
293 return self.isolated_creds.get('admin')[0]
294
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500295 def get_primary_network(self):
296 return self.isolated_net_resources.get('primary')[0]
297
298 def get_primary_subnet(self):
299 return self.isolated_net_resources.get('primary')[1]
300
301 def get_primary_router(self):
302 return self.isolated_net_resources.get('primary')[2]
303
304 def get_admin_network(self):
305 return self.isolated_net_resources.get('admin')[0]
306
307 def get_admin_subnet(self):
308 return self.isolated_net_resources.get('admin')[1]
309
310 def get_admin_router(self):
311 return self.isolated_net_resources.get('admin')[2]
312
313 def get_alt_network(self):
314 return self.isolated_net_resources.get('alt')[0]
315
316 def get_alt_subnet(self):
317 return self.isolated_net_resources.get('alt')[1]
318
319 def get_alt_router(self):
320 return self.isolated_net_resources.get('alt')[2]
321
Matthew Treinishb86cda92013-07-29 11:22:23 -0400322 def get_primary_creds(self):
323 if self.isolated_creds.get('primary'):
324 user, tenant = self.isolated_creds['primary']
325 username, tenant_name = self._get_cred_names(user, tenant)
326 else:
327 user, tenant = self._create_creds()
328 username, tenant_name = self._get_cred_names(user, tenant)
329 self.isolated_creds['primary'] = (user, tenant)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500330 LOG.info("Acquired isolated creds:\n user: %s, tenant: %s"
Matthew Treinishb86cda92013-07-29 11:22:23 -0400331 % (username, tenant_name))
Sean Dague86bd8422013-12-20 09:56:44 -0500332 if CONF.service_available.neutron:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500333 network, subnet, router = self._create_network_resources(
334 self._get_tenant_id(tenant))
335 self.isolated_net_resources['primary'] = (
336 network, subnet, router,)
337 LOG.info("Created isolated network resources for : \n"
338 + " user: %s, tenant: %s" % (username, tenant_name))
Matthew Treinishb86cda92013-07-29 11:22:23 -0400339 return username, tenant_name, self.password
340
341 def get_admin_creds(self):
342 if self.isolated_creds.get('admin'):
343 user, tenant = self.isolated_creds['admin']
344 username, tenant_name = self._get_cred_names(user, tenant)
345 else:
346 user, tenant = self._create_creds(admin=True)
347 username, tenant_name = self._get_cred_names(user, tenant)
348 self.isolated_creds['admin'] = (user, tenant)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500349 LOG.info("Acquired admin isolated creds:\n user: %s, tenant: %s"
Matthew Treinishb86cda92013-07-29 11:22:23 -0400350 % (username, tenant_name))
Sean Dague86bd8422013-12-20 09:56:44 -0500351 if CONF.service_available.neutron:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500352 network, subnet, router = self._create_network_resources(
353 self._get_tenant_id(tenant))
354 self.isolated_net_resources['admin'] = (
355 network, subnet, router,)
356 LOG.info("Created isolated network resources for : \n"
357 + " user: %s, tenant: %s" % (username, tenant_name))
358 return username, tenant_name, self.password
Matthew Treinishb86cda92013-07-29 11:22:23 -0400359
360 def get_alt_creds(self):
361 if self.isolated_creds.get('alt'):
362 user, tenant = self.isolated_creds['alt']
363 username, tenant_name = self._get_cred_names(user, tenant)
364 else:
365 user, tenant = self._create_creds()
366 username, tenant_name = self._get_cred_names(user, tenant)
367 self.isolated_creds['alt'] = (user, tenant)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500368 LOG.info("Acquired alt isolated creds:\n user: %s, tenant: %s"
Matthew Treinishb86cda92013-07-29 11:22:23 -0400369 % (username, tenant_name))
Sean Dague86bd8422013-12-20 09:56:44 -0500370 if CONF.service_available.neutron:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500371 network, subnet, router = self._create_network_resources(
372 self._get_tenant_id(tenant))
373 self.isolated_net_resources['alt'] = (
374 network, subnet, router,)
375 LOG.info("Created isolated network resources for : \n"
376 + " user: %s, tenant: %s" % (username, tenant_name))
Matthew Treinishb86cda92013-07-29 11:22:23 -0400377 return username, tenant_name, self.password
378
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500379 def _clear_isolated_router(self, router_id, router_name):
380 net_client = self.network_admin_client
381 try:
382 net_client.delete_router(router_id)
383 except exceptions.NotFound:
384 LOG.warn('router with name: %s not found for delete' %
385 router_name)
386 pass
387
388 def _clear_isolated_subnet(self, subnet_id, subnet_name):
389 net_client = self.network_admin_client
390 try:
391 net_client.delete_subnet(subnet_id)
392 except exceptions.NotFound:
393 LOG.warn('subnet with name: %s not found for delete' %
394 subnet_name)
395 pass
396
397 def _clear_isolated_network(self, network_id, network_name):
398 net_client = self.network_admin_client
399 try:
400 net_client.delete_network(network_id)
401 except exceptions.NotFound:
402 LOG.warn('network with name: %s not found for delete' %
403 network_name)
404 pass
405
406 def _cleanup_ports(self, network_id):
407 # TODO(mlavalle) This method will be removed once patch
408 # https://review.openstack.org/#/c/46563/ merges in Neutron
409 if not self.ports:
410 if self.tempest_client:
411 resp, resp_body = self.network_admin_client.list_ports()
412 else:
413 resp_body = self.network_admin_client.list_ports()
414 self.ports = resp_body['ports']
415 ports_to_delete = [
armando-migliaccio96a86ae2013-11-21 17:26:16 -0800416 port
417 for port in self.ports
418 if (port['network_id'] == network_id and
419 port['device_owner'] != 'network:router_interface')
420 ]
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500421 for port in ports_to_delete:
422 try:
423 LOG.info('Cleaning up port id %s, name %s' %
424 (port['id'], port['name']))
425 self.network_admin_client.delete_port(port['id'])
426 except exceptions.NotFound:
427 LOG.warn('Port id: %s, name %s not found for clean-up' %
428 (port['id'], port['name']))
429
430 def _clear_isolated_net_resources(self):
431 net_client = self.network_admin_client
432 for cred in self.isolated_net_resources:
433 network, subnet, router = self.isolated_net_resources.get(cred)
434 try:
435 if self.tempest_client:
436 net_client.remove_router_interface_with_subnet_id(
437 router['id'], subnet['id'])
438 else:
439 body = {'subnet_id': subnet['id']}
440 net_client.remove_interface_router(router['id'], body)
441 except exceptions.NotFound:
442 LOG.warn('router with name: %s not found for delete' %
443 router['name'])
444 pass
445 self._clear_isolated_router(router['id'], router['name'])
446 # TODO(mlavalle) This method call will be removed once patch
447 # https://review.openstack.org/#/c/46563/ merges in Neutron
448 self._cleanup_ports(network['id'])
449 self._clear_isolated_subnet(subnet['id'], subnet['name'])
450 self._clear_isolated_network(network['id'], network['name'])
451 LOG.info("Cleared isolated network resources: \n"
452 + " network: %s, subnet: %s, router: %s"
453 % (network['name'], subnet['name'], router['name']))
454
Matthew Treinishb86cda92013-07-29 11:22:23 -0400455 def clear_isolated_creds(self):
456 if not self.isolated_creds:
457 return
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500458 self._clear_isolated_net_resources()
Matthew Treinishb86cda92013-07-29 11:22:23 -0400459 for cred in self.isolated_creds:
460 user, tenant = self.isolated_creds.get(cred)
461 try:
462 if self.tempest_client:
463 self._delete_user(user['id'])
464 else:
465 self._delete_user(user.id)
466 except exceptions.NotFound:
467 if self.tempest_client:
468 name = user['name']
469 else:
470 name = user.name
471 LOG.warn("user with name: %s not found for delete" % name)
472 pass
473 try:
474 if self.tempest_client:
475 self._delete_tenant(tenant['id'])
476 else:
477 self._delete_tenant(tenant.id)
478 except exceptions.NotFound:
479 if self.tempest_client:
480 name = tenant['name']
481 else:
482 name = tenant.name
483 LOG.warn("tenant with name: %s not found for delete" % name)
484 pass