blob: 5dbb3a7dd1ea4572386e5686b658f33a8da3ea55 [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
28LOG = logging.getLogger(__name__)
29
30
31class IsolatedCreds(object):
32
33 def __init__(self, name, tempest_client=True, interface='json',
34 password='pass'):
35 self.isolated_creds = {}
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050036 self.isolated_net_resources = {}
37 self.ports = []
Matthew Treinishb86cda92013-07-29 11:22:23 -040038 self.name = name
39 self.config = config.TempestConfig()
40 self.tempest_client = tempest_client
41 self.interface = interface
42 self.password = password
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050043 self.identity_admin_client, self.network_admin_client = (
44 self._get_admin_clients())
Matthew Treinishb86cda92013-07-29 11:22:23 -040045
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050046 def _get_official_admin_clients(self):
Matthew Treinishb86cda92013-07-29 11:22:23 -040047 username = self.config.identity.admin_username
48 password = self.config.identity.admin_password
49 tenant_name = self.config.identity.admin_tenant_name
50 auth_url = self.config.identity.uri
51 dscv = self.config.identity.disable_ssl_certificate_validation
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050052 identity_client = keystoneclient.Client(username=username,
53 password=password,
54 tenant_name=tenant_name,
55 auth_url=auth_url,
56 insecure=dscv)
57 network_client = neutronclient.Client(username=username,
58 password=password,
59 tenant_name=tenant_name,
60 auth_url=auth_url,
61 insecure=dscv)
62 return identity_client, network_client
Matthew Treinishb86cda92013-07-29 11:22:23 -040063
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050064 def _get_admin_clients(self):
Matthew Treinishb86cda92013-07-29 11:22:23 -040065 """
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050066 Returns a tuple with instances of the following admin clients (in this
67 order):
68 identity
69 network
Matthew Treinishb86cda92013-07-29 11:22:23 -040070 """
71 if self.tempest_client:
72 os = clients.AdminManager(interface=self.interface)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050073 admin_clients = (os.identity_client,
74 os.network_client,)
Matthew Treinishb86cda92013-07-29 11:22:23 -040075 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050076 admin_clients = self._get_official_admin_clients()
77 return admin_clients
Matthew Treinishb86cda92013-07-29 11:22:23 -040078
79 def _create_tenant(self, name, description):
80 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050081 resp, tenant = self.identity_admin_client.create_tenant(
Matthew Treinishb86cda92013-07-29 11:22:23 -040082 name=name, description=description)
83 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050084 tenant = self.identity_admin_client.tenants.create(
85 name,
86 description=description)
Matthew Treinishb86cda92013-07-29 11:22:23 -040087 return tenant
88
89 def _get_tenant_by_name(self, name):
90 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050091 resp, tenant = self.identity_admin_client.get_tenant_by_name(name)
Matthew Treinishb86cda92013-07-29 11:22:23 -040092 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -050093 tenants = self.identity_admin_client.tenants.list()
Matthew Treinishb86cda92013-07-29 11:22:23 -040094 for ten in tenants:
95 if ten['name'] == name:
96 tenant = ten
DennyZhang1eb40462013-09-26 14:18:30 -050097 break
98 else:
99 raise exceptions.NotFound('No such tenant')
Matthew Treinishb86cda92013-07-29 11:22:23 -0400100 return tenant
101
102 def _create_user(self, username, password, tenant, email):
103 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500104 resp, user = self.identity_admin_client.create_user(username,
105 password,
106 tenant['id'],
107 email)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400108 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500109 user = self.identity_admin_client.users.create(username, password,
110 email,
111 tenant_id=tenant.id)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400112 return user
113
114 def _get_user(self, tenant, username):
115 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500116 resp, user = self.identity_admin_client.get_user_by_username(
117 tenant['id'],
118 username)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400119 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500120 user = self.identity_admin_client.users.get(username)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400121 return user
122
123 def _list_roles(self):
124 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500125 resp, roles = self.identity_admin_client.list_roles()
Matthew Treinishb86cda92013-07-29 11:22:23 -0400126 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500127 roles = self.identity_admin_client.roles.list()
Matthew Treinishb86cda92013-07-29 11:22:23 -0400128 return roles
129
130 def _assign_user_role(self, tenant, user, role):
131 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500132 self.identity_admin_client.assign_user_role(tenant, user, role)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400133 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500134 self.identity_admin_client.roles.add_user_role(user,
135 role, tenant=tenant)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400136
137 def _delete_user(self, user):
138 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500139 self.identity_admin_client.delete_user(user)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400140 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500141 self.identity_admin_client.users.delete(user)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400142
143 def _delete_tenant(self, tenant):
144 if self.tempest_client:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500145 self.identity_admin_client.delete_tenant(tenant)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400146 else:
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500147 self.identity_admin_client.tenants.delete(tenant)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400148
149 def _create_creds(self, suffix=None, admin=False):
Masayuki Igawa259c1132013-10-31 17:48:44 +0900150 data_utils.rand_name_root = data_utils.rand_name(self.name)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400151 if suffix:
Masayuki Igawa259c1132013-10-31 17:48:44 +0900152 data_utils.rand_name_root += suffix
153 tenant_name = data_utils.rand_name_root + "-tenant"
Matthew Treinishb86cda92013-07-29 11:22:23 -0400154 tenant_desc = tenant_name + "-desc"
Matthew Treinishb86cda92013-07-29 11:22:23 -0400155 tenant = self._create_tenant(name=tenant_name,
156 description=tenant_desc)
157 if suffix:
Masayuki Igawa259c1132013-10-31 17:48:44 +0900158 data_utils.rand_name_root += suffix
159 username = data_utils.rand_name_root + "-user"
160 email = data_utils.rand_name_root + "@example.com"
Matthew Treinishb86cda92013-07-29 11:22:23 -0400161 user = self._create_user(username, self.password,
162 tenant, email)
163 if admin:
164 role = None
165 try:
166 roles = self._list_roles()
Russell Sim7f894a52013-09-13 10:35:21 +1000167 admin_role = self.config.identity.admin_role
Matthew Treinishb86cda92013-07-29 11:22:23 -0400168 if self.tempest_client:
Russell Sim7f894a52013-09-13 10:35:21 +1000169 role = next(r for r in roles if r['name'] == admin_role)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400170 else:
Russell Sim7f894a52013-09-13 10:35:21 +1000171 role = next(r for r in roles if r.name == admin_role)
Matthew Treinishb86cda92013-07-29 11:22:23 -0400172 except StopIteration:
173 msg = "No admin role found"
174 raise exceptions.NotFound(msg)
175 if self.tempest_client:
176 self._assign_user_role(tenant['id'], user['id'], role['id'])
177 else:
178 self._assign_user_role(tenant.id, user.id, role.id)
179 return user, tenant
180
181 def _get_cred_names(self, user, tenant):
182 if self.tempest_client:
183 username = user.get('name')
184 tenant_name = tenant.get('name')
185 else:
186 username = user.name
187 tenant_name = tenant.name
188 return username, tenant_name
189
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500190 def _get_tenant_id(self, tenant):
191 if self.tempest_client:
192 return tenant.get('id')
193 else:
194 return tenant.id
195
196 def _create_network_resources(self, tenant_id):
197 network = None
198 subnet = None
199 router = None
Masayuki Igawa259c1132013-10-31 17:48:44 +0900200 data_utils.rand_name_root = data_utils.rand_name(self.name)
201 network_name = data_utils.rand_name_root + "-network"
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500202 network = self._create_network(network_name, tenant_id)
203 try:
Masayuki Igawa259c1132013-10-31 17:48:44 +0900204 subnet_name = data_utils.rand_name_root + "-subnet"
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500205 subnet = self._create_subnet(subnet_name, tenant_id, network['id'])
Masayuki Igawa259c1132013-10-31 17:48:44 +0900206 router_name = data_utils.rand_name_root + "-router"
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500207 router = self._create_router(router_name, tenant_id)
208 self._add_router_interface(router['id'], subnet['id'])
209 except Exception:
210 if router:
211 self._clear_isolated_router(router['id'], router['name'])
212 if subnet:
213 self._clear_isolated_subnet(subnet['id'], subnet['name'])
214 if network:
215 self._clear_isolated_network(network['id'], network['name'])
216 raise
217 return network, subnet, router
218
219 def _create_network(self, name, tenant_id):
220 if self.tempest_client:
221 resp, resp_body = self.network_admin_client.create_network(
222 name, tenant_id=tenant_id)
223 else:
224 body = {'network': {'tenant_id': tenant_id, 'name': name}}
225 resp_body = self.network_admin_client.create_network(body)
226 return resp_body['network']
227
228 def _create_subnet(self, subnet_name, tenant_id, network_id):
229 if not self.tempest_client:
230 body = {'subnet': {'name': subnet_name, 'tenant_id': tenant_id,
231 'network_id': network_id, 'ip_version': 4}}
232 base_cidr = netaddr.IPNetwork(self.config.network.tenant_network_cidr)
233 mask_bits = self.config.network.tenant_network_mask_bits
234 for subnet_cidr in base_cidr.subnet(mask_bits):
235 try:
236 if self.tempest_client:
237 resp, resp_body = self.network_admin_client.create_subnet(
238 network_id, str(subnet_cidr), name=subnet_name,
239 tenant_id=tenant_id)
240 else:
241 body['subnet']['cidr'] = str(subnet_cidr)
242 resp_body = self.network_admin_client.create_subnet(body)
243 break
244 except exceptions.BadRequest as e:
245 if 'overlaps with another subnet' not in str(e):
246 raise
247 else:
248 e = exceptions.BuildErrorException()
249 e.message = 'Available CIDR for subnet creation could not be found'
250 raise e
251 return resp_body['subnet']
252
253 def _create_router(self, router_name, tenant_id):
254 external_net_id = dict(
255 network_id=self.config.network.public_network_id)
256 if self.tempest_client:
257 resp, resp_body = self.network_admin_client.create_router(
258 router_name,
259 external_gateway_info=external_net_id,
260 tenant_id=tenant_id)
261 else:
262 body = {'router': {'name': router_name, 'tenant_id': tenant_id,
263 'external_gateway_info': external_net_id,
264 'admin_state_up': True}}
265 resp_body = self.network_admin_client.create_router(body)
266 return resp_body['router']
267
268 def _add_router_interface(self, router_id, subnet_id):
269 if self.tempest_client:
270 self.network_admin_client.add_router_interface_with_subnet_id(
271 router_id, subnet_id)
272 else:
273 body = {'subnet_id': subnet_id}
274 self.network_admin_client.add_interface_router(router_id, body)
275
Matthew Treinishb86cda92013-07-29 11:22:23 -0400276 def get_primary_tenant(self):
277 return self.isolated_creds.get('primary')[1]
278
279 def get_primary_user(self):
280 return self.isolated_creds.get('primary')[0]
281
282 def get_alt_tenant(self):
283 return self.isolated_creds.get('alt')[1]
284
285 def get_alt_user(self):
286 return self.isolated_creds.get('alt')[0]
287
288 def get_admin_tenant(self):
289 return self.isolated_creds.get('admin')[1]
290
291 def get_admin_user(self):
292 return self.isolated_creds.get('admin')[0]
293
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500294 def get_primary_network(self):
295 return self.isolated_net_resources.get('primary')[0]
296
297 def get_primary_subnet(self):
298 return self.isolated_net_resources.get('primary')[1]
299
300 def get_primary_router(self):
301 return self.isolated_net_resources.get('primary')[2]
302
303 def get_admin_network(self):
304 return self.isolated_net_resources.get('admin')[0]
305
306 def get_admin_subnet(self):
307 return self.isolated_net_resources.get('admin')[1]
308
309 def get_admin_router(self):
310 return self.isolated_net_resources.get('admin')[2]
311
312 def get_alt_network(self):
313 return self.isolated_net_resources.get('alt')[0]
314
315 def get_alt_subnet(self):
316 return self.isolated_net_resources.get('alt')[1]
317
318 def get_alt_router(self):
319 return self.isolated_net_resources.get('alt')[2]
320
Matthew Treinishb86cda92013-07-29 11:22:23 -0400321 def get_primary_creds(self):
322 if self.isolated_creds.get('primary'):
323 user, tenant = self.isolated_creds['primary']
324 username, tenant_name = self._get_cred_names(user, tenant)
325 else:
326 user, tenant = self._create_creds()
327 username, tenant_name = self._get_cred_names(user, tenant)
328 self.isolated_creds['primary'] = (user, tenant)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500329 LOG.info("Acquired isolated creds:\n user: %s, tenant: %s"
Matthew Treinishb86cda92013-07-29 11:22:23 -0400330 % (username, tenant_name))
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500331 if self.config.service_available.neutron:
332 network, subnet, router = self._create_network_resources(
333 self._get_tenant_id(tenant))
334 self.isolated_net_resources['primary'] = (
335 network, subnet, router,)
336 LOG.info("Created isolated network resources for : \n"
337 + " user: %s, tenant: %s" % (username, tenant_name))
Matthew Treinishb86cda92013-07-29 11:22:23 -0400338 return username, tenant_name, self.password
339
340 def get_admin_creds(self):
341 if self.isolated_creds.get('admin'):
342 user, tenant = self.isolated_creds['admin']
343 username, tenant_name = self._get_cred_names(user, tenant)
344 else:
345 user, tenant = self._create_creds(admin=True)
346 username, tenant_name = self._get_cred_names(user, tenant)
347 self.isolated_creds['admin'] = (user, tenant)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500348 LOG.info("Acquired admin isolated creds:\n user: %s, tenant: %s"
Matthew Treinishb86cda92013-07-29 11:22:23 -0400349 % (username, tenant_name))
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500350 if self.config.service_available.neutron:
351 network, subnet, router = self._create_network_resources(
352 self._get_tenant_id(tenant))
353 self.isolated_net_resources['admin'] = (
354 network, subnet, router,)
355 LOG.info("Created isolated network resources for : \n"
356 + " user: %s, tenant: %s" % (username, tenant_name))
357 return username, tenant_name, self.password
Matthew Treinishb86cda92013-07-29 11:22:23 -0400358
359 def get_alt_creds(self):
360 if self.isolated_creds.get('alt'):
361 user, tenant = self.isolated_creds['alt']
362 username, tenant_name = self._get_cred_names(user, tenant)
363 else:
364 user, tenant = self._create_creds()
365 username, tenant_name = self._get_cred_names(user, tenant)
366 self.isolated_creds['alt'] = (user, tenant)
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500367 LOG.info("Acquired alt isolated creds:\n user: %s, tenant: %s"
Matthew Treinishb86cda92013-07-29 11:22:23 -0400368 % (username, tenant_name))
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500369 if self.config.service_available.neutron:
370 network, subnet, router = self._create_network_resources(
371 self._get_tenant_id(tenant))
372 self.isolated_net_resources['alt'] = (
373 network, subnet, router,)
374 LOG.info("Created isolated network resources for : \n"
375 + " user: %s, tenant: %s" % (username, tenant_name))
Matthew Treinishb86cda92013-07-29 11:22:23 -0400376 return username, tenant_name, self.password
377
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500378 def _clear_isolated_router(self, router_id, router_name):
379 net_client = self.network_admin_client
380 try:
381 net_client.delete_router(router_id)
382 except exceptions.NotFound:
383 LOG.warn('router with name: %s not found for delete' %
384 router_name)
385 pass
386
387 def _clear_isolated_subnet(self, subnet_id, subnet_name):
388 net_client = self.network_admin_client
389 try:
390 net_client.delete_subnet(subnet_id)
391 except exceptions.NotFound:
392 LOG.warn('subnet with name: %s not found for delete' %
393 subnet_name)
394 pass
395
396 def _clear_isolated_network(self, network_id, network_name):
397 net_client = self.network_admin_client
398 try:
399 net_client.delete_network(network_id)
400 except exceptions.NotFound:
401 LOG.warn('network with name: %s not found for delete' %
402 network_name)
403 pass
404
405 def _cleanup_ports(self, network_id):
406 # TODO(mlavalle) This method will be removed once patch
407 # https://review.openstack.org/#/c/46563/ merges in Neutron
408 if not self.ports:
409 if self.tempest_client:
410 resp, resp_body = self.network_admin_client.list_ports()
411 else:
412 resp_body = self.network_admin_client.list_ports()
413 self.ports = resp_body['ports']
414 ports_to_delete = [
armando-migliaccio96a86ae2013-11-21 17:26:16 -0800415 port
416 for port in self.ports
417 if (port['network_id'] == network_id and
418 port['device_owner'] != 'network:router_interface')
419 ]
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500420 for port in ports_to_delete:
421 try:
422 LOG.info('Cleaning up port id %s, name %s' %
423 (port['id'], port['name']))
424 self.network_admin_client.delete_port(port['id'])
425 except exceptions.NotFound:
426 LOG.warn('Port id: %s, name %s not found for clean-up' %
427 (port['id'], port['name']))
428
429 def _clear_isolated_net_resources(self):
430 net_client = self.network_admin_client
431 for cred in self.isolated_net_resources:
432 network, subnet, router = self.isolated_net_resources.get(cred)
433 try:
434 if self.tempest_client:
435 net_client.remove_router_interface_with_subnet_id(
436 router['id'], subnet['id'])
437 else:
438 body = {'subnet_id': subnet['id']}
439 net_client.remove_interface_router(router['id'], body)
440 except exceptions.NotFound:
441 LOG.warn('router with name: %s not found for delete' %
442 router['name'])
443 pass
444 self._clear_isolated_router(router['id'], router['name'])
445 # TODO(mlavalle) This method call will be removed once patch
446 # https://review.openstack.org/#/c/46563/ merges in Neutron
447 self._cleanup_ports(network['id'])
448 self._clear_isolated_subnet(subnet['id'], subnet['name'])
449 self._clear_isolated_network(network['id'], network['name'])
450 LOG.info("Cleared isolated network resources: \n"
451 + " network: %s, subnet: %s, router: %s"
452 % (network['name'], subnet['name'], router['name']))
453
Matthew Treinishb86cda92013-07-29 11:22:23 -0400454 def clear_isolated_creds(self):
455 if not self.isolated_creds:
456 return
Miguel Lavalleb8fabc52013-08-23 11:19:57 -0500457 self._clear_isolated_net_resources()
Matthew Treinishb86cda92013-07-29 11:22:23 -0400458 for cred in self.isolated_creds:
459 user, tenant = self.isolated_creds.get(cred)
460 try:
461 if self.tempest_client:
462 self._delete_user(user['id'])
463 else:
464 self._delete_user(user.id)
465 except exceptions.NotFound:
466 if self.tempest_client:
467 name = user['name']
468 else:
469 name = user.name
470 LOG.warn("user with name: %s not found for delete" % name)
471 pass
472 try:
473 if self.tempest_client:
474 self._delete_tenant(tenant['id'])
475 else:
476 self._delete_tenant(tenant.id)
477 except exceptions.NotFound:
478 if self.tempest_client:
479 name = tenant['name']
480 else:
481 name = tenant.name
482 LOG.warn("tenant with name: %s not found for delete" % name)
483 pass