blob: 5c436929fc178dc11cff0cb52e09da8fdc381a29 [file] [log] [blame]
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +05301# Copyright 2013 OpenStack Foundation
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000016import json
nayna-patel2db83b32014-05-15 11:41:03 +000017import urllib
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053018
19from lxml import etree
20
vponomaryov960eeb42014-02-22 18:25:25 +020021from tempest.common import rest_client
Matthew Treinish28f164c2014-03-04 18:55:06 +000022from tempest.common import xml_utils as common
Matthew Treinish684d8992014-01-30 16:27:40 +000023from tempest import config
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000024from tempest import exceptions
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053025
Matthew Treinish684d8992014-01-30 16:27:40 +000026CONF = config.CONF
27
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053028XMLNS = "http://docs.openstack.org/identity/api/v3"
29
30
vponomaryov960eeb42014-02-22 18:25:25 +020031class IdentityV3ClientXML(rest_client.RestClient):
32 TYPE = "xml"
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053033
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000034 def __init__(self, auth_provider):
35 super(IdentityV3ClientXML, self).__init__(auth_provider)
Matthew Treinish684d8992014-01-30 16:27:40 +000036 self.service = CONF.identity.catalog_type
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053037 self.endpoint_url = 'adminURL'
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000038 self.api_version = "v3"
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053039
40 def _parse_projects(self, node):
41 array = []
42 for child in node.getchildren():
43 tag_list = child.tag.split('}', 1)
44 if tag_list[1] == "project":
Haiwei Xuaad85db2014-03-05 05:17:39 +090045 array.append(common.xml_to_json(child))
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053046 return array
47
nayna-patel4df72dc2013-05-29 10:27:24 +000048 def _parse_domains(self, node):
49 array = []
50 for child in node.getchildren():
51 tag_list = child.tag.split('}', 1)
52 if tag_list[1] == "domain":
Haiwei Xuaad85db2014-03-05 05:17:39 +090053 array.append(common.xml_to_json(child))
nayna-patel4df72dc2013-05-29 10:27:24 +000054 return array
55
wanglianmin29b0f4c2014-03-06 19:09:16 +080056 def _parse_groups(self, node):
57 array = []
58 for child in node.getchildren():
59 tag_list = child.tag.split('}', 1)
60 if tag_list[1] == "group":
61 array.append(common.xml_to_json(child))
62 return array
63
Zhi Kun Liue8136f02014-01-07 18:56:28 +080064 def _parse_group_users(self, node):
65 array = []
66 for child in node.getchildren():
67 tag_list = child.tag.split('}', 1)
68 if tag_list[1] == "user":
Haiwei Xuaad85db2014-03-05 05:17:39 +090069 array.append(common.xml_to_json(child))
Zhi Kun Liue8136f02014-01-07 18:56:28 +080070 return array
71
nayna-patel755d8142013-07-16 06:45:34 +000072 def _parse_roles(self, node):
73 array = []
74 for child in node.getchildren():
75 tag_list = child.tag.split('}', 1)
76 if tag_list[1] == "role":
Haiwei Xuaad85db2014-03-05 05:17:39 +090077 array.append(common.xml_to_json(child))
nayna-patel755d8142013-07-16 06:45:34 +000078 return array
79
nayna-patel2db83b32014-05-15 11:41:03 +000080 def _parse_users(self, node):
81 array = []
82 for child in node.getchildren():
83 tag_list = child.tag.split('}', 1)
84 if tag_list[1] == "user":
85 array.append(common.xml_to_json(child))
86 return array
87
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053088 def _parse_array(self, node):
89 array = []
90 for child in node.getchildren():
Haiwei Xuaad85db2014-03-05 05:17:39 +090091 array.append(common.xml_to_json(child))
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053092 return array
93
94 def _parse_body(self, body):
Haiwei Xuaad85db2014-03-05 05:17:39 +090095 _json = common.xml_to_json(body)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000096 return _json
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053097
98 def create_user(self, user_name, **kwargs):
99 """Creates a user."""
100 password = kwargs.get('password', None)
101 email = kwargs.get('email', None)
102 en = kwargs.get('enabled', 'true')
103 project_id = kwargs.get('project_id', None)
104 description = kwargs.get('description', None)
105 domain_id = kwargs.get('domain_id', 'default')
Haiwei Xuaad85db2014-03-05 05:17:39 +0900106 post_body = common.Element("user",
107 xmlns=XMLNS,
108 name=user_name,
109 password=password,
110 description=description,
111 email=email,
112 enabled=str(en).lower(),
113 project_id=project_id,
114 domain_id=domain_id)
115 resp, body = self.post('users', str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400116 self.expected_success(201, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530117 body = self._parse_body(etree.fromstring(body))
118 return resp, body
119
120 def update_user(self, user_id, name, **kwargs):
121 """Updates a user."""
David Kranze9d2f422014-07-02 13:57:41 -0400122 _, body = self.get_user(user_id)
nayna-patel755d8142013-07-16 06:45:34 +0000123 email = kwargs.get('email', body['email'])
124 en = kwargs.get('enabled', body['enabled'])
125 project_id = kwargs.get('project_id', body['project_id'])
126 description = kwargs.get('description', body['description'])
127 domain_id = kwargs.get('domain_id', body['domain_id'])
Haiwei Xuaad85db2014-03-05 05:17:39 +0900128 update_user = common.Element("user",
129 xmlns=XMLNS,
130 name=name,
131 email=email,
132 project_id=project_id,
133 domain_id=domain_id,
134 description=description,
135 enabled=str(en).lower())
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530136 resp, body = self.patch('users/%s' % user_id,
Haiwei Xuaad85db2014-03-05 05:17:39 +0900137 str(common.Document(update_user)))
David Kranze9d2f422014-07-02 13:57:41 -0400138 self.expected_success(200, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530139 body = self._parse_body(etree.fromstring(body))
140 return resp, body
141
ravikumar-venkatesand35d6442014-05-05 12:14:45 +0000142 def update_user_password(self, user_id, password, original_password):
143 """Updates a user password."""
144 update_user = common.Element("user",
145 xmlns=XMLNS,
146 password=password,
147 original_password=original_password)
148 resp, _ = self.post('users/%s/password' % user_id,
149 str(common.Document(update_user)))
150 self.expected_success(204, resp.status)
151 return resp
152
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530153 def list_user_projects(self, user_id):
154 """Lists the projects on which a user has roles assigned."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200155 resp, body = self.get('users/%s/projects' % user_id)
David Kranze9d2f422014-07-02 13:57:41 -0400156 self.expected_success(200, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530157 body = self._parse_projects(etree.fromstring(body))
158 return resp, body
159
nayna-patel2db83b32014-05-15 11:41:03 +0000160 def get_users(self, params=None):
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530161 """Get the list of users."""
nayna-patel2db83b32014-05-15 11:41:03 +0000162 url = 'users'
163 if params:
164 url += '?%s' % urllib.urlencode(params)
165 resp, body = self.get(url)
David Kranze9d2f422014-07-02 13:57:41 -0400166 self.expected_success(200, resp.status)
nayna-patel2db83b32014-05-15 11:41:03 +0000167 body = self._parse_users(etree.fromstring(body))
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530168 return resp, body
169
170 def get_user(self, user_id):
171 """GET a user."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200172 resp, body = self.get("users/%s" % user_id)
David Kranze9d2f422014-07-02 13:57:41 -0400173 self.expected_success(200, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530174 body = self._parse_body(etree.fromstring(body))
175 return resp, body
176
177 def delete_user(self, user_id):
178 """Deletes a User."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200179 resp, body = self.delete("users/%s" % user_id)
David Kranze9d2f422014-07-02 13:57:41 -0400180 self.expected_success(204, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530181 return resp, body
182
183 def create_project(self, name, **kwargs):
184 """Creates a project."""
185 description = kwargs.get('description', None)
186 en = kwargs.get('enabled', 'true')
187 domain_id = kwargs.get('domain_id', 'default')
Haiwei Xuaad85db2014-03-05 05:17:39 +0900188 post_body = common.Element("project",
189 xmlns=XMLNS,
190 description=description,
191 domain_id=domain_id,
192 enabled=str(en).lower(),
193 name=name)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530194 resp, body = self.post('projects',
Haiwei Xuaad85db2014-03-05 05:17:39 +0900195 str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400196 self.expected_success(201, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530197 body = self._parse_body(etree.fromstring(body))
198 return resp, body
199
nayna-patel153e9dd2014-05-16 09:00:05 +0000200 def list_projects(self, params=None):
Nayna Patele6331362013-08-12 06:59:48 +0000201 """Get the list of projects."""
nayna-patel153e9dd2014-05-16 09:00:05 +0000202 url = 'projects'
203 if params:
204 url += '?%s' % urllib.urlencode(params)
205 resp, body = self.get(url)
David Kranze9d2f422014-07-02 13:57:41 -0400206 self.expected_success(200, resp.status)
Nayna Patele6331362013-08-12 06:59:48 +0000207 body = self._parse_projects(etree.fromstring(body))
208 return resp, body
209
210 def update_project(self, project_id, **kwargs):
211 """Updates a Project."""
212 resp, body = self.get_project(project_id)
213 name = kwargs.get('name', body['name'])
214 desc = kwargs.get('description', body['description'])
215 en = kwargs.get('enabled', body['enabled'])
216 domain_id = kwargs.get('domain_id', body['domain_id'])
Haiwei Xuaad85db2014-03-05 05:17:39 +0900217 post_body = common.Element("project",
218 xmlns=XMLNS,
219 name=name,
220 description=desc,
221 enabled=str(en).lower(),
222 domain_id=domain_id)
Nayna Patele6331362013-08-12 06:59:48 +0000223 resp, body = self.patch('projects/%s' % project_id,
Haiwei Xuaad85db2014-03-05 05:17:39 +0900224 str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400225 self.expected_success(200, resp.status)
Nayna Patele6331362013-08-12 06:59:48 +0000226 body = self._parse_body(etree.fromstring(body))
227 return resp, body
228
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530229 def get_project(self, project_id):
230 """GET a Project."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200231 resp, body = self.get("projects/%s" % project_id)
David Kranze9d2f422014-07-02 13:57:41 -0400232 self.expected_success(200, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530233 body = self._parse_body(etree.fromstring(body))
234 return resp, body
235
236 def delete_project(self, project_id):
237 """Delete a project."""
238 resp, body = self.delete('projects/%s' % str(project_id))
David Kranze9d2f422014-07-02 13:57:41 -0400239 self.expected_success(204, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530240 return resp, body
241
242 def create_role(self, name):
243 """Create a Role."""
Haiwei Xuaad85db2014-03-05 05:17:39 +0900244 post_body = common.Element("role",
245 xmlns=XMLNS,
246 name=name)
247 resp, body = self.post('roles', str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400248 self.expected_success(201, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530249 body = self._parse_body(etree.fromstring(body))
250 return resp, body
251
252 def get_role(self, role_id):
253 """GET a Role."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200254 resp, body = self.get('roles/%s' % str(role_id))
David Kranze9d2f422014-07-02 13:57:41 -0400255 self.expected_success(200, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530256 body = self._parse_body(etree.fromstring(body))
257 return resp, body
258
wanglianmina3e84ea2014-03-26 17:30:33 +0800259 def list_roles(self):
260 """Get the list of Roles."""
261 resp, body = self.get("roles")
David Kranze9d2f422014-07-02 13:57:41 -0400262 self.expected_success(200, resp.status)
wanglianmina3e84ea2014-03-26 17:30:33 +0800263 body = self._parse_roles(etree.fromstring(body))
264 return resp, body
265
nayna-patel755d8142013-07-16 06:45:34 +0000266 def update_role(self, name, role_id):
267 """Updates a Role."""
Haiwei Xuaad85db2014-03-05 05:17:39 +0900268 post_body = common.Element("role",
269 xmlns=XMLNS,
270 name=name)
nayna-patel755d8142013-07-16 06:45:34 +0000271 resp, body = self.patch('roles/%s' % str(role_id),
Haiwei Xuaad85db2014-03-05 05:17:39 +0900272 str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400273 self.expected_success(200, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000274 body = self._parse_body(etree.fromstring(body))
275 return resp, body
276
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530277 def delete_role(self, role_id):
278 """Delete a role."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200279 resp, body = self.delete('roles/%s' % str(role_id))
David Kranze9d2f422014-07-02 13:57:41 -0400280 self.expected_success(204, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530281 return resp, body
282
283 def assign_user_role(self, project_id, user_id, role_id):
284 """Add roles to a user on a tenant."""
285 resp, body = self.put('projects/%s/users/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200286 (project_id, user_id, role_id), '')
David Kranze9d2f422014-07-02 13:57:41 -0400287 self.expected_success(204, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530288 return resp, body
nayna-patel4df72dc2013-05-29 10:27:24 +0000289
290 def create_domain(self, name, **kwargs):
291 """Creates a domain."""
292 description = kwargs.get('description', None)
293 en = kwargs.get('enabled', True)
Haiwei Xuaad85db2014-03-05 05:17:39 +0900294 post_body = common.Element("domain",
295 xmlns=XMLNS,
296 name=name,
297 description=description,
298 enabled=str(en).lower())
299 resp, body = self.post('domains', str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400300 self.expected_success(201, resp.status)
nayna-patel4df72dc2013-05-29 10:27:24 +0000301 body = self._parse_body(etree.fromstring(body))
302 return resp, body
303
304 def list_domains(self):
305 """Get the list of domains."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200306 resp, body = self.get("domains")
David Kranze9d2f422014-07-02 13:57:41 -0400307 self.expected_success(200, resp.status)
nayna-patel4df72dc2013-05-29 10:27:24 +0000308 body = self._parse_domains(etree.fromstring(body))
309 return resp, body
310
311 def delete_domain(self, domain_id):
312 """Delete a domain."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200313 resp, body = self.delete('domains/%s' % domain_id)
David Kranze9d2f422014-07-02 13:57:41 -0400314 self.expected_success(204, resp.status)
nayna-patel4df72dc2013-05-29 10:27:24 +0000315 return resp, body
316
317 def update_domain(self, domain_id, **kwargs):
318 """Updates a domain."""
David Kranze9d2f422014-07-02 13:57:41 -0400319 _, body = self.get_domain(domain_id)
nayna-patel4df72dc2013-05-29 10:27:24 +0000320 description = kwargs.get('description', body['description'])
321 en = kwargs.get('enabled', body['enabled'])
322 name = kwargs.get('name', body['name'])
Haiwei Xuaad85db2014-03-05 05:17:39 +0900323 post_body = common.Element("domain",
324 xmlns=XMLNS,
325 name=name,
326 description=description,
327 enabled=str(en).lower())
nayna-patel4df72dc2013-05-29 10:27:24 +0000328 resp, body = self.patch('domains/%s' % domain_id,
Haiwei Xuaad85db2014-03-05 05:17:39 +0900329 str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400330 self.expected_success(200, resp.status)
nayna-patel4df72dc2013-05-29 10:27:24 +0000331 body = self._parse_body(etree.fromstring(body))
332 return resp, body
333
334 def get_domain(self, domain_id):
335 """Get Domain details."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200336 resp, body = self.get('domains/%s' % domain_id)
David Kranze9d2f422014-07-02 13:57:41 -0400337 self.expected_success(200, resp.status)
nayna-patel4df72dc2013-05-29 10:27:24 +0000338 body = self._parse_body(etree.fromstring(body))
339 return resp, body
nayna-patelb35f7232013-06-28 07:08:44 +0000340
341 def get_token(self, resp_token):
342 """GET a Token Details."""
343 headers = {'Content-Type': 'application/xml',
344 'Accept': 'application/xml',
345 'X-Subject-Token': resp_token}
346 resp, body = self.get("auth/tokens", headers=headers)
David Kranze9d2f422014-07-02 13:57:41 -0400347 self.expected_success(200, resp.status)
nayna-patelb35f7232013-06-28 07:08:44 +0000348 body = self._parse_body(etree.fromstring(body))
349 return resp, body
350
351 def delete_token(self, resp_token):
352 """Delete a Given Token."""
353 headers = {'X-Subject-Token': resp_token}
354 resp, body = self.delete("auth/tokens", headers=headers)
David Kranze9d2f422014-07-02 13:57:41 -0400355 self.expected_success(204, resp.status)
nayna-patelb35f7232013-06-28 07:08:44 +0000356 return resp, body
357
nayna-patel755d8142013-07-16 06:45:34 +0000358 def create_group(self, name, **kwargs):
359 """Creates a group."""
360 description = kwargs.get('description', None)
361 domain_id = kwargs.get('domain_id', 'default')
362 project_id = kwargs.get('project_id', None)
Haiwei Xuaad85db2014-03-05 05:17:39 +0900363 post_body = common.Element("group",
364 xmlns=XMLNS,
365 name=name,
366 description=description,
367 domain_id=domain_id,
368 project_id=project_id)
369 resp, body = self.post('groups', str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400370 self.expected_success(201, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000371 body = self._parse_body(etree.fromstring(body))
372 return resp, body
373
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800374 def get_group(self, group_id):
375 """Get group details."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200376 resp, body = self.get('groups/%s' % group_id)
David Kranze9d2f422014-07-02 13:57:41 -0400377 self.expected_success(200, resp.status)
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800378 body = self._parse_body(etree.fromstring(body))
379 return resp, body
380
381 def update_group(self, group_id, **kwargs):
382 """Updates a group."""
David Kranze9d2f422014-07-02 13:57:41 -0400383 _, body = self.get_group(group_id)
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800384 name = kwargs.get('name', body['name'])
385 description = kwargs.get('description', body['description'])
Haiwei Xuaad85db2014-03-05 05:17:39 +0900386 post_body = common.Element("group",
387 xmlns=XMLNS,
388 name=name,
389 description=description)
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800390 resp, body = self.patch('groups/%s' % group_id,
Haiwei Xuaad85db2014-03-05 05:17:39 +0900391 str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400392 self.expected_success(200, resp.status)
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800393 body = self._parse_body(etree.fromstring(body))
394 return resp, body
395
nayna-patel755d8142013-07-16 06:45:34 +0000396 def delete_group(self, group_id):
397 """Delete a group."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200398 resp, body = self.delete('groups/%s' % group_id)
David Kranze9d2f422014-07-02 13:57:41 -0400399 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000400 return resp, body
401
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800402 def add_group_user(self, group_id, user_id):
403 """Add user into group."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200404 resp, body = self.put('groups/%s/users/%s' % (group_id, user_id), '')
David Kranze9d2f422014-07-02 13:57:41 -0400405 self.expected_success(204, resp.status)
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800406 return resp, body
407
408 def list_group_users(self, group_id):
409 """List users in group."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200410 resp, body = self.get('groups/%s/users' % group_id)
David Kranze9d2f422014-07-02 13:57:41 -0400411 self.expected_success(200, resp.status)
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800412 body = self._parse_group_users(etree.fromstring(body))
413 return resp, body
414
wanglianmin29b0f4c2014-03-06 19:09:16 +0800415 def list_user_groups(self, user_id):
416 """Lists the groups which a user belongs to."""
417 resp, body = self.get('users/%s/groups' % user_id)
David Kranze9d2f422014-07-02 13:57:41 -0400418 self.expected_success(200, resp.status)
wanglianmin29b0f4c2014-03-06 19:09:16 +0800419 body = self._parse_groups(etree.fromstring(body))
420 return resp, body
421
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800422 def delete_group_user(self, group_id, user_id):
423 """Delete user in group."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200424 resp, body = self.delete('groups/%s/users/%s' % (group_id, user_id))
David Kranze9d2f422014-07-02 13:57:41 -0400425 self.expected_success(204, resp.status)
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800426 return resp, body
427
nayna-patel755d8142013-07-16 06:45:34 +0000428 def assign_user_role_on_project(self, project_id, user_id, role_id):
429 """Add roles to a user on a project."""
430 resp, body = self.put('projects/%s/users/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200431 (project_id, user_id, role_id), '')
David Kranze9d2f422014-07-02 13:57:41 -0400432 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000433 return resp, body
434
435 def assign_user_role_on_domain(self, domain_id, user_id, role_id):
436 """Add roles to a user on a domain."""
437 resp, body = self.put('domains/%s/users/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200438 (domain_id, user_id, role_id), '')
David Kranze9d2f422014-07-02 13:57:41 -0400439 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000440 return resp, body
441
442 def list_user_roles_on_project(self, project_id, user_id):
443 """list roles of a user on a project."""
444 resp, body = self.get('projects/%s/users/%s/roles' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200445 (project_id, user_id))
David Kranze9d2f422014-07-02 13:57:41 -0400446 self.expected_success(200, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000447 body = self._parse_roles(etree.fromstring(body))
448 return resp, body
449
450 def list_user_roles_on_domain(self, domain_id, user_id):
451 """list roles of a user on a domain."""
452 resp, body = self.get('domains/%s/users/%s/roles' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200453 (domain_id, user_id))
David Kranze9d2f422014-07-02 13:57:41 -0400454 self.expected_success(200, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000455 body = self._parse_roles(etree.fromstring(body))
456 return resp, body
457
458 def revoke_role_from_user_on_project(self, project_id, user_id, role_id):
459 """Delete role of a user on a project."""
460 resp, body = self.delete('projects/%s/users/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200461 (project_id, user_id, role_id))
David Kranze9d2f422014-07-02 13:57:41 -0400462 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000463 return resp, body
464
465 def revoke_role_from_user_on_domain(self, domain_id, user_id, role_id):
466 """Delete role of a user on a domain."""
467 resp, body = self.delete('domains/%s/users/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200468 (domain_id, user_id, role_id))
David Kranze9d2f422014-07-02 13:57:41 -0400469 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000470 return resp, body
471
472 def assign_group_role_on_project(self, project_id, group_id, role_id):
473 """Add roles to a user on a project."""
474 resp, body = self.put('projects/%s/groups/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200475 (project_id, group_id, role_id), '')
David Kranze9d2f422014-07-02 13:57:41 -0400476 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000477 return resp, body
478
479 def assign_group_role_on_domain(self, domain_id, group_id, role_id):
480 """Add roles to a user on a domain."""
481 resp, body = self.put('domains/%s/groups/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200482 (domain_id, group_id, role_id), '')
David Kranze9d2f422014-07-02 13:57:41 -0400483 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000484 return resp, body
485
486 def list_group_roles_on_project(self, project_id, group_id):
487 """list roles of a user on a project."""
488 resp, body = self.get('projects/%s/groups/%s/roles' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200489 (project_id, group_id))
David Kranze9d2f422014-07-02 13:57:41 -0400490 self.expected_success(200, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000491 body = self._parse_roles(etree.fromstring(body))
492 return resp, body
493
494 def list_group_roles_on_domain(self, domain_id, group_id):
495 """list roles of a user on a domain."""
496 resp, body = self.get('domains/%s/groups/%s/roles' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200497 (domain_id, group_id))
David Kranze9d2f422014-07-02 13:57:41 -0400498 self.expected_success(200, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000499 body = self._parse_roles(etree.fromstring(body))
500 return resp, body
501
502 def revoke_role_from_group_on_project(self, project_id, group_id, role_id):
503 """Delete role of a user on a project."""
504 resp, body = self.delete('projects/%s/groups/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200505 (project_id, group_id, role_id))
David Kranze9d2f422014-07-02 13:57:41 -0400506 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000507 return resp, body
508
509 def revoke_role_from_group_on_domain(self, domain_id, group_id, role_id):
510 """Delete role of a user on a domain."""
511 resp, body = self.delete('domains/%s/groups/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200512 (domain_id, group_id, role_id))
David Kranze9d2f422014-07-02 13:57:41 -0400513 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000514 return resp, body
515
nayna-patelb35f7232013-06-28 07:08:44 +0000516
vponomaryov960eeb42014-02-22 18:25:25 +0200517class V3TokenClientXML(rest_client.RestClient):
518 TYPE = "xml"
nayna-patelb35f7232013-06-28 07:08:44 +0000519
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000520 def __init__(self):
521 super(V3TokenClientXML, self).__init__(None)
522 auth_url = CONF.identity.uri_v3
ajayaa1fdc78a2014-07-09 16:51:13 +0530523 if not auth_url:
Matthew Treinishdb2c5972014-01-31 22:18:59 +0000524 raise exceptions.InvalidConfiguration('you must specify a v3 uri '
525 'if using the v3 identity '
526 'api')
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000527 if 'auth/tokens' not in auth_url:
528 auth_url = auth_url.rstrip('/') + '/auth/tokens'
nayna-patelb35f7232013-06-28 07:08:44 +0000529
530 self.auth_url = auth_url
nayna-patelb35f7232013-06-28 07:08:44 +0000531
Brant Knudsonc5553292014-03-15 11:06:05 -0500532 def auth(self, user=None, password=None, tenant=None, user_type='id',
533 domain=None, token=None):
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000534 """
535 :param user: user id or name, as specified in user_type
Brant Knudsonc5553292014-03-15 11:06:05 -0500536 :param domain: the user and tenant domain
537 :param token: a token to re-scope.
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000538
539 Accepts different combinations of credentials. Restrictions:
540 - tenant and domain are only name (no id)
541 - user domain and tenant domain are assumed identical
Brant Knudsonc5553292014-03-15 11:06:05 -0500542 - domain scope is not supported here
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000543 Sample sample valid combinations:
Brant Knudsonc5553292014-03-15 11:06:05 -0500544 - token
545 - token, tenant, domain
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000546 - user_id, password
547 - username, password, domain
548 - username, password, tenant, domain
549 Validation is left to the server side.
550 """
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000551
Haiwei Xuaad85db2014-03-05 05:17:39 +0900552 methods = common.Element('methods')
Haiwei Xuaad85db2014-03-05 05:17:39 +0900553 identity = common.Element('identity')
Brant Knudsonc5553292014-03-15 11:06:05 -0500554
555 if token:
556 method = common.Element('method')
557 method.append(common.Text('token'))
558 methods.append(method)
559
560 token = common.Element('token', id=token)
561 identity.append(token)
562
563 if user and password:
564 if user_type == 'id':
565 _user = common.Element('user', id=user, password=password)
566 else:
567 _user = common.Element('user', name=user, password=password)
568 if domain is not None:
569 _domain = common.Element('domain', name=domain)
570 _user.append(_domain)
571
572 password = common.Element('password')
573 password.append(_user)
574 method = common.Element('method')
575 method.append(common.Text('password'))
576 methods.append(method)
577 identity.append(password)
578
nayna-patelb35f7232013-06-28 07:08:44 +0000579 identity.append(methods)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000580
Haiwei Xuaad85db2014-03-05 05:17:39 +0900581 auth = common.Element('auth')
nayna-patelb35f7232013-06-28 07:08:44 +0000582 auth.append(identity)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000583
584 if tenant is not None:
Haiwei Xuaad85db2014-03-05 05:17:39 +0900585 project = common.Element('project', name=tenant)
Brant Knudsonc5553292014-03-15 11:06:05 -0500586 _domain = common.Element('domain', name=domain)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000587 project.append(_domain)
Haiwei Xuaad85db2014-03-05 05:17:39 +0900588 scope = common.Element('scope')
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000589 scope.append(project)
590 auth.append(scope)
591
Haiwei Xuaad85db2014-03-05 05:17:39 +0900592 resp, body = self.post(self.auth_url, body=str(common.Document(auth)))
David Kranzfb3efa72014-08-28 16:58:25 -0400593 self.expected_success(201, resp.status)
nayna-patelb35f7232013-06-28 07:08:44 +0000594 return resp, body
595
Sergey Murashov4fccd322014-03-22 09:58:52 +0400596 def request(self, method, url, extra_headers=False, headers=None,
597 body=None):
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000598 """A simple HTTP request interface."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200599 if headers is None:
600 # Always accept 'json', for xml token client too.
601 # Because XML response is not easily
602 # converted to the corresponding JSON one
603 headers = self.get_headers(accept_type="json")
Sergey Murashov4fccd322014-03-22 09:58:52 +0400604 elif extra_headers:
605 try:
606 headers.update(self.get_headers(accept_type="json"))
607 except (ValueError, TypeError):
608 headers = self.get_headers(accept_type="json")
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000609 resp, resp_body = self.http_obj.request(url, method,
610 headers=headers, body=body)
Sean Dague89a85912014-03-19 16:37:29 -0400611 self._log_request(method, url, resp)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000612
613 if resp.status in [401, 403]:
614 resp_body = json.loads(resp_body)
615 raise exceptions.Unauthorized(resp_body['error']['message'])
616 elif resp.status not in [200, 201, 204]:
617 raise exceptions.IdentityError(
618 'Unexpected status code {0}'.format(resp.status))
619
620 return resp, json.loads(resp_body)
621
622 def get_token(self, user, password, tenant, domain='Default',
623 auth_data=False):
624 """
625 :param user: username
626 Returns (token id, token data) for supplied credentials
627 """
628 resp, body = self.auth(user, password, tenant, user_type='name',
629 domain=domain)
630
631 token = resp.get('x-subject-token')
632 if auth_data:
633 return token, body['token']
634 else:
635 return token