blob: 242b0326a93cc3ae05df46727dc151b3df5b9990 [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
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053017
18from lxml import etree
19
vponomaryov960eeb42014-02-22 18:25:25 +020020from tempest.common import rest_client
Matthew Treinish28f164c2014-03-04 18:55:06 +000021from tempest.common import xml_utils as common
Matthew Treinish684d8992014-01-30 16:27:40 +000022from tempest import config
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000023from tempest import exceptions
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053024
Matthew Treinish684d8992014-01-30 16:27:40 +000025CONF = config.CONF
26
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053027XMLNS = "http://docs.openstack.org/identity/api/v3"
28
29
vponomaryov960eeb42014-02-22 18:25:25 +020030class IdentityV3ClientXML(rest_client.RestClient):
31 TYPE = "xml"
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053032
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000033 def __init__(self, auth_provider):
34 super(IdentityV3ClientXML, self).__init__(auth_provider)
Matthew Treinish684d8992014-01-30 16:27:40 +000035 self.service = CONF.identity.catalog_type
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053036 self.endpoint_url = 'adminURL'
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000037 self.api_version = "v3"
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053038
39 def _parse_projects(self, node):
40 array = []
41 for child in node.getchildren():
42 tag_list = child.tag.split('}', 1)
43 if tag_list[1] == "project":
Haiwei Xuaad85db2014-03-05 05:17:39 +090044 array.append(common.xml_to_json(child))
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053045 return array
46
nayna-patel4df72dc2013-05-29 10:27:24 +000047 def _parse_domains(self, node):
48 array = []
49 for child in node.getchildren():
50 tag_list = child.tag.split('}', 1)
51 if tag_list[1] == "domain":
Haiwei Xuaad85db2014-03-05 05:17:39 +090052 array.append(common.xml_to_json(child))
nayna-patel4df72dc2013-05-29 10:27:24 +000053 return array
54
wanglianmin29b0f4c2014-03-06 19:09:16 +080055 def _parse_groups(self, node):
56 array = []
57 for child in node.getchildren():
58 tag_list = child.tag.split('}', 1)
59 if tag_list[1] == "group":
60 array.append(common.xml_to_json(child))
61 return array
62
Zhi Kun Liue8136f02014-01-07 18:56:28 +080063 def _parse_group_users(self, node):
64 array = []
65 for child in node.getchildren():
66 tag_list = child.tag.split('}', 1)
67 if tag_list[1] == "user":
Haiwei Xuaad85db2014-03-05 05:17:39 +090068 array.append(common.xml_to_json(child))
Zhi Kun Liue8136f02014-01-07 18:56:28 +080069 return array
70
nayna-patel755d8142013-07-16 06:45:34 +000071 def _parse_roles(self, node):
72 array = []
73 for child in node.getchildren():
74 tag_list = child.tag.split('}', 1)
75 if tag_list[1] == "role":
Haiwei Xuaad85db2014-03-05 05:17:39 +090076 array.append(common.xml_to_json(child))
nayna-patel755d8142013-07-16 06:45:34 +000077 return array
78
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053079 def _parse_array(self, node):
80 array = []
81 for child in node.getchildren():
Haiwei Xuaad85db2014-03-05 05:17:39 +090082 array.append(common.xml_to_json(child))
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053083 return array
84
85 def _parse_body(self, body):
Haiwei Xuaad85db2014-03-05 05:17:39 +090086 _json = common.xml_to_json(body)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000087 return _json
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +053088
89 def create_user(self, user_name, **kwargs):
90 """Creates a user."""
91 password = kwargs.get('password', None)
92 email = kwargs.get('email', None)
93 en = kwargs.get('enabled', 'true')
94 project_id = kwargs.get('project_id', None)
95 description = kwargs.get('description', None)
96 domain_id = kwargs.get('domain_id', 'default')
Haiwei Xuaad85db2014-03-05 05:17:39 +090097 post_body = common.Element("user",
98 xmlns=XMLNS,
99 name=user_name,
100 password=password,
101 description=description,
102 email=email,
103 enabled=str(en).lower(),
104 project_id=project_id,
105 domain_id=domain_id)
106 resp, body = self.post('users', str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400107 self.expected_success(201, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530108 body = self._parse_body(etree.fromstring(body))
109 return resp, body
110
111 def update_user(self, user_id, name, **kwargs):
112 """Updates a user."""
David Kranze9d2f422014-07-02 13:57:41 -0400113 _, body = self.get_user(user_id)
nayna-patel755d8142013-07-16 06:45:34 +0000114 email = kwargs.get('email', body['email'])
115 en = kwargs.get('enabled', body['enabled'])
116 project_id = kwargs.get('project_id', body['project_id'])
117 description = kwargs.get('description', body['description'])
118 domain_id = kwargs.get('domain_id', body['domain_id'])
Haiwei Xuaad85db2014-03-05 05:17:39 +0900119 update_user = common.Element("user",
120 xmlns=XMLNS,
121 name=name,
122 email=email,
123 project_id=project_id,
124 domain_id=domain_id,
125 description=description,
126 enabled=str(en).lower())
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530127 resp, body = self.patch('users/%s' % user_id,
Haiwei Xuaad85db2014-03-05 05:17:39 +0900128 str(common.Document(update_user)))
David Kranze9d2f422014-07-02 13:57:41 -0400129 self.expected_success(200, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530130 body = self._parse_body(etree.fromstring(body))
131 return resp, body
132
133 def list_user_projects(self, user_id):
134 """Lists the projects on which a user has roles assigned."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200135 resp, body = self.get('users/%s/projects' % user_id)
David Kranze9d2f422014-07-02 13:57:41 -0400136 self.expected_success(200, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530137 body = self._parse_projects(etree.fromstring(body))
138 return resp, body
139
140 def get_users(self):
141 """Get the list of users."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200142 resp, body = self.get("users")
David Kranze9d2f422014-07-02 13:57:41 -0400143 self.expected_success(200, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530144 body = self._parse_array(etree.fromstring(body))
145 return resp, body
146
147 def get_user(self, user_id):
148 """GET a user."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200149 resp, body = self.get("users/%s" % user_id)
David Kranze9d2f422014-07-02 13:57:41 -0400150 self.expected_success(200, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530151 body = self._parse_body(etree.fromstring(body))
152 return resp, body
153
154 def delete_user(self, user_id):
155 """Deletes a User."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200156 resp, body = self.delete("users/%s" % user_id)
David Kranze9d2f422014-07-02 13:57:41 -0400157 self.expected_success(204, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530158 return resp, body
159
160 def create_project(self, name, **kwargs):
161 """Creates a project."""
162 description = kwargs.get('description', None)
163 en = kwargs.get('enabled', 'true')
164 domain_id = kwargs.get('domain_id', 'default')
Haiwei Xuaad85db2014-03-05 05:17:39 +0900165 post_body = common.Element("project",
166 xmlns=XMLNS,
167 description=description,
168 domain_id=domain_id,
169 enabled=str(en).lower(),
170 name=name)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530171 resp, body = self.post('projects',
Haiwei Xuaad85db2014-03-05 05:17:39 +0900172 str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400173 self.expected_success(201, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530174 body = self._parse_body(etree.fromstring(body))
175 return resp, body
176
Nayna Patele6331362013-08-12 06:59:48 +0000177 def list_projects(self):
178 """Get the list of projects."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200179 resp, body = self.get("projects")
David Kranze9d2f422014-07-02 13:57:41 -0400180 self.expected_success(200, resp.status)
Nayna Patele6331362013-08-12 06:59:48 +0000181 body = self._parse_projects(etree.fromstring(body))
182 return resp, body
183
184 def update_project(self, project_id, **kwargs):
185 """Updates a Project."""
186 resp, body = self.get_project(project_id)
187 name = kwargs.get('name', body['name'])
188 desc = kwargs.get('description', body['description'])
189 en = kwargs.get('enabled', body['enabled'])
190 domain_id = kwargs.get('domain_id', body['domain_id'])
Haiwei Xuaad85db2014-03-05 05:17:39 +0900191 post_body = common.Element("project",
192 xmlns=XMLNS,
193 name=name,
194 description=desc,
195 enabled=str(en).lower(),
196 domain_id=domain_id)
Nayna Patele6331362013-08-12 06:59:48 +0000197 resp, body = self.patch('projects/%s' % project_id,
Haiwei Xuaad85db2014-03-05 05:17:39 +0900198 str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400199 self.expected_success(200, resp.status)
Nayna Patele6331362013-08-12 06:59:48 +0000200 body = self._parse_body(etree.fromstring(body))
201 return resp, body
202
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530203 def get_project(self, project_id):
204 """GET a Project."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200205 resp, body = self.get("projects/%s" % project_id)
David Kranze9d2f422014-07-02 13:57:41 -0400206 self.expected_success(200, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530207 body = self._parse_body(etree.fromstring(body))
208 return resp, body
209
210 def delete_project(self, project_id):
211 """Delete a project."""
212 resp, body = self.delete('projects/%s' % str(project_id))
David Kranze9d2f422014-07-02 13:57:41 -0400213 self.expected_success(204, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530214 return resp, body
215
216 def create_role(self, name):
217 """Create a Role."""
Haiwei Xuaad85db2014-03-05 05:17:39 +0900218 post_body = common.Element("role",
219 xmlns=XMLNS,
220 name=name)
221 resp, body = self.post('roles', str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400222 self.expected_success(201, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530223 body = self._parse_body(etree.fromstring(body))
224 return resp, body
225
226 def get_role(self, role_id):
227 """GET a Role."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200228 resp, body = self.get('roles/%s' % str(role_id))
David Kranze9d2f422014-07-02 13:57:41 -0400229 self.expected_success(200, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530230 body = self._parse_body(etree.fromstring(body))
231 return resp, body
232
wanglianmina3e84ea2014-03-26 17:30:33 +0800233 def list_roles(self):
234 """Get the list of Roles."""
235 resp, body = self.get("roles")
David Kranze9d2f422014-07-02 13:57:41 -0400236 self.expected_success(200, resp.status)
wanglianmina3e84ea2014-03-26 17:30:33 +0800237 body = self._parse_roles(etree.fromstring(body))
238 return resp, body
239
nayna-patel755d8142013-07-16 06:45:34 +0000240 def update_role(self, name, role_id):
241 """Updates a Role."""
Haiwei Xuaad85db2014-03-05 05:17:39 +0900242 post_body = common.Element("role",
243 xmlns=XMLNS,
244 name=name)
nayna-patel755d8142013-07-16 06:45:34 +0000245 resp, body = self.patch('roles/%s' % str(role_id),
Haiwei Xuaad85db2014-03-05 05:17:39 +0900246 str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400247 self.expected_success(200, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000248 body = self._parse_body(etree.fromstring(body))
249 return resp, body
250
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530251 def delete_role(self, role_id):
252 """Delete a role."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200253 resp, body = self.delete('roles/%s' % str(role_id))
David Kranze9d2f422014-07-02 13:57:41 -0400254 self.expected_success(204, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530255 return resp, body
256
257 def assign_user_role(self, project_id, user_id, role_id):
258 """Add roles to a user on a tenant."""
259 resp, body = self.put('projects/%s/users/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200260 (project_id, user_id, role_id), '')
David Kranze9d2f422014-07-02 13:57:41 -0400261 self.expected_success(204, resp.status)
rajalakshmi-ganesan7312bb52013-01-29 20:03:42 +0530262 return resp, body
nayna-patel4df72dc2013-05-29 10:27:24 +0000263
264 def create_domain(self, name, **kwargs):
265 """Creates a domain."""
266 description = kwargs.get('description', None)
267 en = kwargs.get('enabled', True)
Haiwei Xuaad85db2014-03-05 05:17:39 +0900268 post_body = common.Element("domain",
269 xmlns=XMLNS,
270 name=name,
271 description=description,
272 enabled=str(en).lower())
273 resp, body = self.post('domains', str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400274 self.expected_success(201, resp.status)
nayna-patel4df72dc2013-05-29 10:27:24 +0000275 body = self._parse_body(etree.fromstring(body))
276 return resp, body
277
278 def list_domains(self):
279 """Get the list of domains."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200280 resp, body = self.get("domains")
David Kranze9d2f422014-07-02 13:57:41 -0400281 self.expected_success(200, resp.status)
nayna-patel4df72dc2013-05-29 10:27:24 +0000282 body = self._parse_domains(etree.fromstring(body))
283 return resp, body
284
285 def delete_domain(self, domain_id):
286 """Delete a domain."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200287 resp, body = self.delete('domains/%s' % domain_id)
David Kranze9d2f422014-07-02 13:57:41 -0400288 self.expected_success(204, resp.status)
nayna-patel4df72dc2013-05-29 10:27:24 +0000289 return resp, body
290
291 def update_domain(self, domain_id, **kwargs):
292 """Updates a domain."""
David Kranze9d2f422014-07-02 13:57:41 -0400293 _, body = self.get_domain(domain_id)
nayna-patel4df72dc2013-05-29 10:27:24 +0000294 description = kwargs.get('description', body['description'])
295 en = kwargs.get('enabled', body['enabled'])
296 name = kwargs.get('name', body['name'])
Haiwei Xuaad85db2014-03-05 05:17:39 +0900297 post_body = common.Element("domain",
298 xmlns=XMLNS,
299 name=name,
300 description=description,
301 enabled=str(en).lower())
nayna-patel4df72dc2013-05-29 10:27:24 +0000302 resp, body = self.patch('domains/%s' % domain_id,
Haiwei Xuaad85db2014-03-05 05:17:39 +0900303 str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400304 self.expected_success(200, resp.status)
nayna-patel4df72dc2013-05-29 10:27:24 +0000305 body = self._parse_body(etree.fromstring(body))
306 return resp, body
307
308 def get_domain(self, domain_id):
309 """Get Domain details."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200310 resp, body = self.get('domains/%s' % domain_id)
David Kranze9d2f422014-07-02 13:57:41 -0400311 self.expected_success(200, resp.status)
nayna-patel4df72dc2013-05-29 10:27:24 +0000312 body = self._parse_body(etree.fromstring(body))
313 return resp, body
nayna-patelb35f7232013-06-28 07:08:44 +0000314
315 def get_token(self, resp_token):
316 """GET a Token Details."""
317 headers = {'Content-Type': 'application/xml',
318 'Accept': 'application/xml',
319 'X-Subject-Token': resp_token}
320 resp, body = self.get("auth/tokens", headers=headers)
David Kranze9d2f422014-07-02 13:57:41 -0400321 self.expected_success(200, resp.status)
nayna-patelb35f7232013-06-28 07:08:44 +0000322 body = self._parse_body(etree.fromstring(body))
323 return resp, body
324
325 def delete_token(self, resp_token):
326 """Delete a Given Token."""
327 headers = {'X-Subject-Token': resp_token}
328 resp, body = self.delete("auth/tokens", headers=headers)
David Kranze9d2f422014-07-02 13:57:41 -0400329 self.expected_success(204, resp.status)
nayna-patelb35f7232013-06-28 07:08:44 +0000330 return resp, body
331
nayna-patel755d8142013-07-16 06:45:34 +0000332 def create_group(self, name, **kwargs):
333 """Creates a group."""
334 description = kwargs.get('description', None)
335 domain_id = kwargs.get('domain_id', 'default')
336 project_id = kwargs.get('project_id', None)
Haiwei Xuaad85db2014-03-05 05:17:39 +0900337 post_body = common.Element("group",
338 xmlns=XMLNS,
339 name=name,
340 description=description,
341 domain_id=domain_id,
342 project_id=project_id)
343 resp, body = self.post('groups', str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400344 self.expected_success(201, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000345 body = self._parse_body(etree.fromstring(body))
346 return resp, body
347
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800348 def get_group(self, group_id):
349 """Get group details."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200350 resp, body = self.get('groups/%s' % group_id)
David Kranze9d2f422014-07-02 13:57:41 -0400351 self.expected_success(200, resp.status)
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800352 body = self._parse_body(etree.fromstring(body))
353 return resp, body
354
355 def update_group(self, group_id, **kwargs):
356 """Updates a group."""
David Kranze9d2f422014-07-02 13:57:41 -0400357 _, body = self.get_group(group_id)
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800358 name = kwargs.get('name', body['name'])
359 description = kwargs.get('description', body['description'])
Haiwei Xuaad85db2014-03-05 05:17:39 +0900360 post_body = common.Element("group",
361 xmlns=XMLNS,
362 name=name,
363 description=description)
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800364 resp, body = self.patch('groups/%s' % group_id,
Haiwei Xuaad85db2014-03-05 05:17:39 +0900365 str(common.Document(post_body)))
David Kranze9d2f422014-07-02 13:57:41 -0400366 self.expected_success(200, resp.status)
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800367 body = self._parse_body(etree.fromstring(body))
368 return resp, body
369
nayna-patel755d8142013-07-16 06:45:34 +0000370 def delete_group(self, group_id):
371 """Delete a group."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200372 resp, body = self.delete('groups/%s' % group_id)
David Kranze9d2f422014-07-02 13:57:41 -0400373 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000374 return resp, body
375
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800376 def add_group_user(self, group_id, user_id):
377 """Add user into group."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200378 resp, body = self.put('groups/%s/users/%s' % (group_id, user_id), '')
David Kranze9d2f422014-07-02 13:57:41 -0400379 self.expected_success(204, resp.status)
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800380 return resp, body
381
382 def list_group_users(self, group_id):
383 """List users in group."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200384 resp, body = self.get('groups/%s/users' % group_id)
David Kranze9d2f422014-07-02 13:57:41 -0400385 self.expected_success(200, resp.status)
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800386 body = self._parse_group_users(etree.fromstring(body))
387 return resp, body
388
wanglianmin29b0f4c2014-03-06 19:09:16 +0800389 def list_user_groups(self, user_id):
390 """Lists the groups which a user belongs to."""
391 resp, body = self.get('users/%s/groups' % user_id)
David Kranze9d2f422014-07-02 13:57:41 -0400392 self.expected_success(200, resp.status)
wanglianmin29b0f4c2014-03-06 19:09:16 +0800393 body = self._parse_groups(etree.fromstring(body))
394 return resp, body
395
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800396 def delete_group_user(self, group_id, user_id):
397 """Delete user in group."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200398 resp, body = self.delete('groups/%s/users/%s' % (group_id, user_id))
David Kranze9d2f422014-07-02 13:57:41 -0400399 self.expected_success(204, resp.status)
Zhi Kun Liue8136f02014-01-07 18:56:28 +0800400 return resp, body
401
nayna-patel755d8142013-07-16 06:45:34 +0000402 def assign_user_role_on_project(self, project_id, user_id, role_id):
403 """Add roles to a user on a project."""
404 resp, body = self.put('projects/%s/users/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200405 (project_id, user_id, role_id), '')
David Kranze9d2f422014-07-02 13:57:41 -0400406 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000407 return resp, body
408
409 def assign_user_role_on_domain(self, domain_id, user_id, role_id):
410 """Add roles to a user on a domain."""
411 resp, body = self.put('domains/%s/users/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200412 (domain_id, user_id, role_id), '')
David Kranze9d2f422014-07-02 13:57:41 -0400413 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000414 return resp, body
415
416 def list_user_roles_on_project(self, project_id, user_id):
417 """list roles of a user on a project."""
418 resp, body = self.get('projects/%s/users/%s/roles' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200419 (project_id, user_id))
David Kranze9d2f422014-07-02 13:57:41 -0400420 self.expected_success(200, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000421 body = self._parse_roles(etree.fromstring(body))
422 return resp, body
423
424 def list_user_roles_on_domain(self, domain_id, user_id):
425 """list roles of a user on a domain."""
426 resp, body = self.get('domains/%s/users/%s/roles' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200427 (domain_id, user_id))
David Kranze9d2f422014-07-02 13:57:41 -0400428 self.expected_success(200, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000429 body = self._parse_roles(etree.fromstring(body))
430 return resp, body
431
432 def revoke_role_from_user_on_project(self, project_id, user_id, role_id):
433 """Delete role of a user on a project."""
434 resp, body = self.delete('projects/%s/users/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200435 (project_id, user_id, role_id))
David Kranze9d2f422014-07-02 13:57:41 -0400436 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000437 return resp, body
438
439 def revoke_role_from_user_on_domain(self, domain_id, user_id, role_id):
440 """Delete role of a user on a domain."""
441 resp, body = self.delete('domains/%s/users/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200442 (domain_id, user_id, role_id))
David Kranze9d2f422014-07-02 13:57:41 -0400443 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000444 return resp, body
445
446 def assign_group_role_on_project(self, project_id, group_id, role_id):
447 """Add roles to a user on a project."""
448 resp, body = self.put('projects/%s/groups/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200449 (project_id, group_id, role_id), '')
David Kranze9d2f422014-07-02 13:57:41 -0400450 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000451 return resp, body
452
453 def assign_group_role_on_domain(self, domain_id, group_id, role_id):
454 """Add roles to a user on a domain."""
455 resp, body = self.put('domains/%s/groups/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200456 (domain_id, group_id, role_id), '')
David Kranze9d2f422014-07-02 13:57:41 -0400457 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000458 return resp, body
459
460 def list_group_roles_on_project(self, project_id, group_id):
461 """list roles of a user on a project."""
462 resp, body = self.get('projects/%s/groups/%s/roles' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200463 (project_id, group_id))
David Kranze9d2f422014-07-02 13:57:41 -0400464 self.expected_success(200, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000465 body = self._parse_roles(etree.fromstring(body))
466 return resp, body
467
468 def list_group_roles_on_domain(self, domain_id, group_id):
469 """list roles of a user on a domain."""
470 resp, body = self.get('domains/%s/groups/%s/roles' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200471 (domain_id, group_id))
David Kranze9d2f422014-07-02 13:57:41 -0400472 self.expected_success(200, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000473 body = self._parse_roles(etree.fromstring(body))
474 return resp, body
475
476 def revoke_role_from_group_on_project(self, project_id, group_id, role_id):
477 """Delete role of a user on a project."""
478 resp, body = self.delete('projects/%s/groups/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200479 (project_id, group_id, role_id))
David Kranze9d2f422014-07-02 13:57:41 -0400480 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000481 return resp, body
482
483 def revoke_role_from_group_on_domain(self, domain_id, group_id, role_id):
484 """Delete role of a user on a domain."""
485 resp, body = self.delete('domains/%s/groups/%s/roles/%s' %
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200486 (domain_id, group_id, role_id))
David Kranze9d2f422014-07-02 13:57:41 -0400487 self.expected_success(204, resp.status)
nayna-patel755d8142013-07-16 06:45:34 +0000488 return resp, body
489
nayna-patelb35f7232013-06-28 07:08:44 +0000490
vponomaryov960eeb42014-02-22 18:25:25 +0200491class V3TokenClientXML(rest_client.RestClient):
492 TYPE = "xml"
nayna-patelb35f7232013-06-28 07:08:44 +0000493
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000494 def __init__(self):
495 super(V3TokenClientXML, self).__init__(None)
496 auth_url = CONF.identity.uri_v3
Matthew Treinishdb2c5972014-01-31 22:18:59 +0000497 if not auth_url and CONF.identity_feature_enabled.api_v3:
498 raise exceptions.InvalidConfiguration('you must specify a v3 uri '
499 'if using the v3 identity '
500 'api')
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000501 if 'auth/tokens' not in auth_url:
502 auth_url = auth_url.rstrip('/') + '/auth/tokens'
nayna-patelb35f7232013-06-28 07:08:44 +0000503
504 self.auth_url = auth_url
nayna-patelb35f7232013-06-28 07:08:44 +0000505
Brant Knudsonc5553292014-03-15 11:06:05 -0500506 def auth(self, user=None, password=None, tenant=None, user_type='id',
507 domain=None, token=None):
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000508 """
509 :param user: user id or name, as specified in user_type
Brant Knudsonc5553292014-03-15 11:06:05 -0500510 :param domain: the user and tenant domain
511 :param token: a token to re-scope.
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000512
513 Accepts different combinations of credentials. Restrictions:
514 - tenant and domain are only name (no id)
515 - user domain and tenant domain are assumed identical
Brant Knudsonc5553292014-03-15 11:06:05 -0500516 - domain scope is not supported here
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000517 Sample sample valid combinations:
Brant Knudsonc5553292014-03-15 11:06:05 -0500518 - token
519 - token, tenant, domain
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000520 - user_id, password
521 - username, password, domain
522 - username, password, tenant, domain
523 Validation is left to the server side.
524 """
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000525
Haiwei Xuaad85db2014-03-05 05:17:39 +0900526 methods = common.Element('methods')
Haiwei Xuaad85db2014-03-05 05:17:39 +0900527 identity = common.Element('identity')
Brant Knudsonc5553292014-03-15 11:06:05 -0500528
529 if token:
530 method = common.Element('method')
531 method.append(common.Text('token'))
532 methods.append(method)
533
534 token = common.Element('token', id=token)
535 identity.append(token)
536
537 if user and password:
538 if user_type == 'id':
539 _user = common.Element('user', id=user, password=password)
540 else:
541 _user = common.Element('user', name=user, password=password)
542 if domain is not None:
543 _domain = common.Element('domain', name=domain)
544 _user.append(_domain)
545
546 password = common.Element('password')
547 password.append(_user)
548 method = common.Element('method')
549 method.append(common.Text('password'))
550 methods.append(method)
551 identity.append(password)
552
nayna-patelb35f7232013-06-28 07:08:44 +0000553 identity.append(methods)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000554
Haiwei Xuaad85db2014-03-05 05:17:39 +0900555 auth = common.Element('auth')
nayna-patelb35f7232013-06-28 07:08:44 +0000556 auth.append(identity)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000557
558 if tenant is not None:
Haiwei Xuaad85db2014-03-05 05:17:39 +0900559 project = common.Element('project', name=tenant)
Brant Knudsonc5553292014-03-15 11:06:05 -0500560 _domain = common.Element('domain', name=domain)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000561 project.append(_domain)
Haiwei Xuaad85db2014-03-05 05:17:39 +0900562 scope = common.Element('scope')
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000563 scope.append(project)
564 auth.append(scope)
565
Haiwei Xuaad85db2014-03-05 05:17:39 +0900566 resp, body = self.post(self.auth_url, body=str(common.Document(auth)))
nayna-patelb35f7232013-06-28 07:08:44 +0000567 return resp, body
568
Sergey Murashov4fccd322014-03-22 09:58:52 +0400569 def request(self, method, url, extra_headers=False, headers=None,
570 body=None):
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000571 """A simple HTTP request interface."""
Valeriy Ponomaryov88686d82014-02-16 12:24:51 +0200572 if headers is None:
573 # Always accept 'json', for xml token client too.
574 # Because XML response is not easily
575 # converted to the corresponding JSON one
576 headers = self.get_headers(accept_type="json")
Sergey Murashov4fccd322014-03-22 09:58:52 +0400577 elif extra_headers:
578 try:
579 headers.update(self.get_headers(accept_type="json"))
580 except (ValueError, TypeError):
581 headers = self.get_headers(accept_type="json")
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000582 resp, resp_body = self.http_obj.request(url, method,
583 headers=headers, body=body)
Sean Dague89a85912014-03-19 16:37:29 -0400584 self._log_request(method, url, resp)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000585
586 if resp.status in [401, 403]:
587 resp_body = json.loads(resp_body)
588 raise exceptions.Unauthorized(resp_body['error']['message'])
589 elif resp.status not in [200, 201, 204]:
590 raise exceptions.IdentityError(
591 'Unexpected status code {0}'.format(resp.status))
592
593 return resp, json.loads(resp_body)
594
595 def get_token(self, user, password, tenant, domain='Default',
596 auth_data=False):
597 """
598 :param user: username
599 Returns (token id, token data) for supplied credentials
600 """
601 resp, body = self.auth(user, password, tenant, user_type='name',
602 domain=domain)
603
604 token = resp.get('x-subject-token')
605 if auth_data:
606 return token, body['token']
607 else:
608 return token