blob: 94045b8ba0a71cd96ee9fe608d2ff2e9cbc177f6 [file] [log] [blame]
Sean Dague556add52013-07-19 14:28:44 -04001# vim: tabstop=4 shiftwidth=4 softtabstop=4
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
chris fattarsi8ed39ac2012-04-30 14:11:27 -070015import json
16
Mate Lakat23a58a32013-08-23 02:06:22 +010017from tempest.common import http
Matthew Treinisha83a16e2012-12-07 13:44:02 -050018from tempest.common.rest_client import RestClient
19from tempest import exceptions
20
chris fattarsi8ed39ac2012-04-30 14:11:27 -070021
Attila Fazekas407b6db2013-01-19 12:48:36 +010022class IdentityClientJSON(RestClient):
chris fattarsi8ed39ac2012-04-30 14:11:27 -070023
24 def __init__(self, config, username, password, auth_url, tenant_name=None):
Attila Fazekas407b6db2013-01-19 12:48:36 +010025 super(IdentityClientJSON, self).__init__(config, username, password,
26 auth_url, tenant_name)
chris fattarsi8ed39ac2012-04-30 14:11:27 -070027 self.service = self.config.identity.catalog_type
28 self.endpoint_url = 'adminURL'
29
30 def has_admin_extensions(self):
31 """
32 Returns True if the KSADM Admin Extensions are supported
33 False otherwise
34 """
35 if hasattr(self, '_has_admin_extensions'):
36 return self._has_admin_extensions
37 resp, body = self.list_roles()
38 self._has_admin_extensions = ('status' in resp and resp.status != 503)
39 return self._has_admin_extensions
40
41 def create_role(self, name):
Sean Daguef237ccb2013-01-04 15:19:14 -050042 """Create a role."""
chris fattarsi8ed39ac2012-04-30 14:11:27 -070043 post_body = {
44 'name': name,
45 }
46 post_body = json.dumps({'role': post_body})
Zhongyue Luoe0884a32012-09-25 17:24:17 +080047 resp, body = self.post('OS-KSADM/roles', post_body, self.headers)
chris fattarsi8ed39ac2012-04-30 14:11:27 -070048 body = json.loads(body)
49 return resp, body['role']
50
chris fattarsi9ba7b0e2012-05-07 13:55:51 -070051 def create_tenant(self, name, **kwargs):
52 """
53 Create a tenant
54 name (required): New tenant name
55 description: Description of new tenant (default is none)
56 enabled <true|false>: Initial tenant status (default is true)
57 """
58 post_body = {
59 'name': name,
60 'description': kwargs.get('description', ''),
Gordon Chungad873602013-02-18 19:26:27 -050061 'enabled': kwargs.get('enabled', True),
chris fattarsi9ba7b0e2012-05-07 13:55:51 -070062 }
63 post_body = json.dumps({'tenant': post_body})
Zhongyue Luoe0884a32012-09-25 17:24:17 +080064 resp, body = self.post('tenants', post_body, self.headers)
chris fattarsi9ba7b0e2012-05-07 13:55:51 -070065 body = json.loads(body)
66 return resp, body['tenant']
67
chris fattarsi8ed39ac2012-04-30 14:11:27 -070068 def delete_role(self, role_id):
Sean Daguef237ccb2013-01-04 15:19:14 -050069 """Delete a role."""
chris fattarsi9ba7b0e2012-05-07 13:55:51 -070070 resp, body = self.delete('OS-KSADM/roles/%s' % str(role_id))
chris fattarsi8ed39ac2012-04-30 14:11:27 -070071 return resp, body
72
rajalakshmi-ganesan8ba945e2012-08-01 15:43:19 +053073 def list_user_roles(self, tenant_id, user_id):
Sean Daguef237ccb2013-01-04 15:19:14 -050074 """Returns a list of roles assigned to a user for a tenant."""
rajalakshmi-ganesan8ba945e2012-08-01 15:43:19 +053075 url = '/tenants/%s/users/%s/roles' % (tenant_id, user_id)
76 resp, body = self.get(url)
Rohit Karajgi69e80a02012-05-15 03:54:04 -070077 body = json.loads(body)
78 return resp, body['roles']
79
rajalakshmi-ganesan8ba945e2012-08-01 15:43:19 +053080 def assign_user_role(self, tenant_id, user_id, role_id):
Sean Daguef237ccb2013-01-04 15:19:14 -050081 """Add roles to a user on a tenant."""
rajalakshmi-ganesan8ba945e2012-08-01 15:43:19 +053082 post_body = json.dumps({})
Zhongyue Luoe0884a32012-09-25 17:24:17 +080083 resp, body = self.put('/tenants/%s/users/%s/roles/OS-KSADM/%s' %
84 (tenant_id, user_id, role_id), post_body,
85 self.headers)
Rohit Karajgi69e80a02012-05-15 03:54:04 -070086 body = json.loads(body)
87 return resp, body['role']
88
rajalakshmi-ganesan8ba945e2012-08-01 15:43:19 +053089 def remove_user_role(self, tenant_id, user_id, role_id):
Sean Daguef237ccb2013-01-04 15:19:14 -050090 """Removes a role assignment for a user on a tenant."""
Zhongyue Luo79d8d362012-09-25 13:49:27 +080091 return self.delete('/tenants/%s/users/%s/roles/OS-KSADM/%s' %
92 (tenant_id, user_id, role_id))
Rohit Karajgi69e80a02012-05-15 03:54:04 -070093
chris fattarsi9ba7b0e2012-05-07 13:55:51 -070094 def delete_tenant(self, tenant_id):
Sean Daguef237ccb2013-01-04 15:19:14 -050095 """Delete a tenant."""
chris fattarsi9ba7b0e2012-05-07 13:55:51 -070096 resp, body = self.delete('tenants/%s' % str(tenant_id))
97 return resp, body
98
99 def get_tenant(self, tenant_id):
Sean Daguef237ccb2013-01-04 15:19:14 -0500100 """Get tenant details."""
chris fattarsi9ba7b0e2012-05-07 13:55:51 -0700101 resp, body = self.get('tenants/%s' % str(tenant_id))
102 body = json.loads(body)
103 return resp, body['tenant']
104
chris fattarsi8ed39ac2012-04-30 14:11:27 -0700105 def list_roles(self):
Sean Daguef237ccb2013-01-04 15:19:14 -0500106 """Returns roles."""
chris fattarsi8ed39ac2012-04-30 14:11:27 -0700107 resp, body = self.get('OS-KSADM/roles')
108 body = json.loads(body)
109 return resp, body['roles']
chris fattarsi9ba7b0e2012-05-07 13:55:51 -0700110
111 def list_tenants(self):
Sean Daguef237ccb2013-01-04 15:19:14 -0500112 """Returns tenants."""
chris fattarsi9ba7b0e2012-05-07 13:55:51 -0700113 resp, body = self.get('tenants')
114 body = json.loads(body)
115 return resp, body['tenants']
116
Dan Smithd6ff6b72012-08-23 10:29:41 -0700117 def get_tenant_by_name(self, tenant_name):
118 resp, tenants = self.list_tenants()
119 for tenant in tenants:
120 if tenant['name'] == tenant_name:
121 return tenant
122 raise exceptions.NotFound('No such tenant')
123
chris fattarsi9ba7b0e2012-05-07 13:55:51 -0700124 def update_tenant(self, tenant_id, **kwargs):
Sean Daguef237ccb2013-01-04 15:19:14 -0500125 """Updates a tenant."""
chris fattarsi9ba7b0e2012-05-07 13:55:51 -0700126 resp, body = self.get_tenant(tenant_id)
127 name = kwargs.get('name', body['name'])
128 desc = kwargs.get('description', body['description'])
129 en = kwargs.get('enabled', body['enabled'])
130 post_body = {
131 'id': tenant_id,
132 'name': name,
133 'description': desc,
134 'enabled': en,
135 }
136 post_body = json.dumps({'tenant': post_body})
137 resp, body = self.post('tenants/%s' % tenant_id, post_body,
Zhongyue Luoe0884a32012-09-25 17:24:17 +0800138 self.headers)
chris fattarsi9ba7b0e2012-05-07 13:55:51 -0700139 body = json.loads(body)
140 return resp, body['tenant']
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700141
huangtianhuafc8db4f2013-10-08 12:05:58 +0800142 def create_user(self, name, password, tenant_id, email, **kwargs):
Sean Daguef237ccb2013-01-04 15:19:14 -0500143 """Create a user."""
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700144 post_body = {
145 'name': name,
146 'password': password,
147 'tenantId': tenant_id,
148 'email': email
149 }
huangtianhuafc8db4f2013-10-08 12:05:58 +0800150 if kwargs.get('enabled') is not None:
151 post_body['enabled'] = kwargs.get('enabled')
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700152 post_body = json.dumps({'user': post_body})
153 resp, body = self.post('users', post_body, self.headers)
154 body = json.loads(body)
155 return resp, body['user']
156
Chang Bo Guob36b2f12013-09-13 04:52:00 -0700157 def update_user(self, user_id, **kwargs):
158 """Updates a user."""
159 put_body = json.dumps({'user': kwargs})
160 resp, body = self.put('users/%s' % user_id, put_body,
161 self.headers)
162 body = json.loads(body)
163 return resp, body['user']
164
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530165 def get_user(self, user_id):
166 """GET a user."""
167 resp, body = self.get("users/%s" % user_id)
168 body = json.loads(body)
169 return resp, body['user']
170
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700171 def delete_user(self, user_id):
Sean Daguef237ccb2013-01-04 15:19:14 -0500172 """Delete a user."""
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700173 resp, body = self.delete("users/%s" % user_id)
174 return resp, body
175
176 def get_users(self):
Sean Daguef237ccb2013-01-04 15:19:14 -0500177 """Get the list of users."""
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700178 resp, body = self.get("users")
179 body = json.loads(body)
180 return resp, body['users']
181
182 def enable_disable_user(self, user_id, enabled):
Sean Daguef237ccb2013-01-04 15:19:14 -0500183 """Enables or disables a user."""
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700184 put_body = {
Sean Dague14c68182013-04-14 15:34:30 -0400185 'enabled': enabled
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700186 }
187 put_body = json.dumps({'user': put_body})
188 resp, body = self.put('users/%s/enabled' % user_id,
Zhongyue Luo79d8d362012-09-25 13:49:27 +0800189 put_body, self.headers)
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700190 body = json.loads(body)
191 return resp, body
192
193 def delete_token(self, token_id):
Sean Daguef237ccb2013-01-04 15:19:14 -0500194 """Delete a token."""
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700195 resp, body = self.delete("tokens/%s" % token_id)
196 return resp, body
197
rajalakshmi-ganesanefc8bd72012-05-30 17:52:11 +0530198 def list_users_for_tenant(self, tenant_id):
Sean Daguef237ccb2013-01-04 15:19:14 -0500199 """List users for a Tenant."""
rajalakshmi-ganesanefc8bd72012-05-30 17:52:11 +0530200 resp, body = self.get('/tenants/%s/users' % tenant_id)
201 body = json.loads(body)
202 return resp, body['users']
203
Dan Smithd6ff6b72012-08-23 10:29:41 -0700204 def get_user_by_username(self, tenant_id, username):
205 resp, users = self.list_users_for_tenant(tenant_id)
206 for user in users:
207 if user['name'] == username:
208 return user
209 raise exceptions.NotFound('No such user')
210
rajalakshmi-ganesanefc8bd72012-05-30 17:52:11 +0530211 def create_service(self, name, type, **kwargs):
Sean Daguef237ccb2013-01-04 15:19:14 -0500212 """Create a service."""
rajalakshmi-ganesanefc8bd72012-05-30 17:52:11 +0530213 post_body = {
Zhongyue Luoa1343de2013-01-04 16:21:35 +0800214 'name': name,
215 'type': type,
216 'description': kwargs.get('description')
217 }
rajalakshmi-ganesanefc8bd72012-05-30 17:52:11 +0530218 post_body = json.dumps({'OS-KSADM:service': post_body})
Zhongyue Luoe0884a32012-09-25 17:24:17 +0800219 resp, body = self.post('/OS-KSADM/services', post_body, self.headers)
rajalakshmi-ganesanefc8bd72012-05-30 17:52:11 +0530220 body = json.loads(body)
221 return resp, body['OS-KSADM:service']
222
223 def get_service(self, service_id):
Sean Daguef237ccb2013-01-04 15:19:14 -0500224 """Get Service."""
rajalakshmi-ganesanefc8bd72012-05-30 17:52:11 +0530225 url = '/OS-KSADM/services/%s' % service_id
226 resp, body = self.get(url)
227 body = json.loads(body)
228 return resp, body['OS-KSADM:service']
229
umamohanb51ad002013-01-24 18:13:15 +0000230 def list_services(self):
231 """List Service - Returns Services."""
232 resp, body = self.get('/OS-KSADM/services/')
233 body = json.loads(body)
234 return resp, body['OS-KSADM:services']
235
rajalakshmi-ganesanefc8bd72012-05-30 17:52:11 +0530236 def delete_service(self, service_id):
Sean Daguef237ccb2013-01-04 15:19:14 -0500237 """Delete Service."""
rajalakshmi-ganesanefc8bd72012-05-30 17:52:11 +0530238 url = '/OS-KSADM/services/%s' % service_id
239 return self.delete(url)
240
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700241
Vincent Hou6b8a7b72012-08-25 01:24:33 +0800242class TokenClientJSON(RestClient):
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700243
244 def __init__(self, config):
Jay Pipes7c88eb22013-01-16 21:32:43 -0500245 auth_url = config.identity.uri
246
247 # TODO(jaypipes) Why is this all repeated code in here?
248 # Normalize URI to ensure /tokens is in it.
249 if 'tokens' not in auth_url:
250 auth_url = auth_url.rstrip('/') + '/tokens'
251
252 self.auth_url = auth_url
Jay Pipescd8eaec2013-01-16 21:03:48 -0500253 self.config = config
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700254
255 def auth(self, user, password, tenant):
Zhongyue Luo30a563f2012-09-30 23:43:50 +0900256 creds = {
257 'auth': {
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700258 'passwordCredentials': {
259 'username': user,
260 'password': password,
261 },
Zhongyue Luo30a563f2012-09-30 23:43:50 +0900262 'tenantName': tenant,
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700263 }
264 }
265 headers = {'Content-Type': 'application/json'}
266 body = json.dumps(creds)
267 resp, body = self.post(self.auth_url, headers=headers, body=body)
268 return resp, body
269
270 def request(self, method, url, headers=None, body=None):
271 """A simple HTTP request interface."""
Jay Pipescd8eaec2013-01-16 21:03:48 -0500272 dscv = self.config.identity.disable_ssl_certificate_validation
Mate Lakat23a58a32013-08-23 02:06:22 +0100273 self.http_obj = http.ClosingHttp(
274 disable_ssl_certificate_validation=dscv)
Zhongyue Luoe471d6e2012-09-17 17:02:43 +0800275 if headers is None:
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700276 headers = {}
277
Attila Fazekas7b487be2013-02-12 11:14:41 +0100278 self._log_request(method, url, headers, body)
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700279 resp, resp_body = self.http_obj.request(url, method,
280 headers=headers, body=body)
Attila Fazekas7b487be2013-02-12 11:14:41 +0100281 self._log_response(resp, resp_body)
Rohit Karajgi6b1e1542012-05-14 05:55:54 -0700282
283 if resp.status in (401, 403):
284 resp_body = json.loads(resp_body)
285 raise exceptions.Unauthorized(resp_body['error']['message'])
286
287 return resp, resp_body
288
289 def get_token(self, user, password, tenant):
290 resp, body = self.auth(user, password, tenant)
291 if resp['status'] != '202':
292 body = json.loads(body)
293 access = body['access']
294 token = access['token']
295 return token['id']