blob: 0ace18408e670050c05146eb2bd90ed983c8819f [file] [log] [blame]
Vincent Hou6b8a7b72012-08-25 01:24:33 +08001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2#
3# Copyright 2012 IBM
4# All Rights Reserved.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17
18import logging
19from lxml import etree
20from tempest.common.rest_client import RestClient
21from tempest.common.rest_client import RestClientXML
dwallecke62b9f02012-10-10 23:34:42 -050022from tempest.services.compute.xml.common import Document
23from tempest.services.compute.xml.common import Element
24from tempest.services.compute.xml.common import Text
25from tempest.services.compute.xml.common import xml_to_json
Vincent Hou6b8a7b72012-08-25 01:24:33 +080026from tempest import exceptions
27import httplib2
28import json
29
30XMLNS = "http://docs.openstack.org/identity/api/v2.0"
31
32
33class AdminClientXML(RestClientXML):
34
35 def __init__(self, config, username, password, auth_url, tenant_name=None):
36 super(AdminClientXML, self).__init__(config, username, password,
Zhongyue Luoe0884a32012-09-25 17:24:17 +080037 auth_url, tenant_name)
Vincent Hou6b8a7b72012-08-25 01:24:33 +080038 self.service = self.config.identity.catalog_type
39 self.endpoint_url = 'adminURL'
40
41 def _parse_array(self, node):
42 array = []
43 for child in node.getchildren():
44 array.append(xml_to_json(child))
45 return array
46
47 def _parse_body(self, body):
48 json = xml_to_json(body)
49 return json
50
51 def has_admin_extensions(self):
52 """
53 Returns True if the KSADM Admin Extensions are supported
54 False otherwise
55 """
56 if hasattr(self, '_has_admin_extensions'):
57 return self._has_admin_extensions
58 resp, body = self.list_roles()
59 self._has_admin_extensions = ('status' in resp and resp.status != 503)
60 return self._has_admin_extensions
61
62 def create_role(self, name):
63 """Create a role"""
Zhongyue Luoe0884a32012-09-25 17:24:17 +080064 create_role = Element("role", xmlns=XMLNS, name=name)
Vincent Hou6b8a7b72012-08-25 01:24:33 +080065 resp, body = self.post('OS-KSADM/roles', str(Document(create_role)),
Zhongyue Luoe0884a32012-09-25 17:24:17 +080066 self.headers)
Vincent Hou6b8a7b72012-08-25 01:24:33 +080067 body = self._parse_body(etree.fromstring(body))
68 return resp, body
69
70 def create_tenant(self, name, **kwargs):
71 """
72 Create a tenant
73 name (required): New tenant name
74 description: Description of new tenant (default is none)
75 enabled <true|false>: Initial tenant status (default is true)
76 """
77 en = kwargs.get('enabled', 'true')
78 create_tenant = Element("tenant",
79 xmlns=XMLNS,
80 name=name,
81 description=kwargs.get('description', ''),
82 enabled=str(en).lower())
83 resp, body = self.post('tenants', str(Document(create_tenant)),
Zhongyue Luoe0884a32012-09-25 17:24:17 +080084 self.headers)
Vincent Hou6b8a7b72012-08-25 01:24:33 +080085 body = self._parse_body(etree.fromstring(body))
86 return resp, body
87
88 def delete_role(self, role_id):
89 """Delete a role"""
90 resp, body = self.delete('OS-KSADM/roles/%s' % str(role_id),
91 self.headers)
92 return resp, body
93
94 def list_user_roles(self, tenant_id, user_id):
95 """Returns a list of roles assigned to a user for a tenant"""
96 url = '/tenants/%s/users/%s/roles' % (tenant_id, user_id)
97 resp, body = self.get(url, self.headers)
98 body = self._parse_array(etree.fromstring(body))
99 return resp, body
100
101 def assign_user_role(self, tenant_id, user_id, role_id):
102 """Add roles to a user on a tenant"""
Zhongyue Luoe0884a32012-09-25 17:24:17 +0800103 resp, body = self.put('/tenants/%s/users/%s/roles/OS-KSADM/%s' %
104 (tenant_id, user_id, role_id), '', self.headers)
Vincent Hou6b8a7b72012-08-25 01:24:33 +0800105 body = self._parse_body(etree.fromstring(body))
106 return resp, body
107
108 def remove_user_role(self, tenant_id, user_id, role_id):
109 """Removes a role assignment for a user on a tenant"""
Zhongyue Luo79d8d362012-09-25 13:49:27 +0800110 return self.delete('/tenants/%s/users/%s/roles/OS-KSADM/%s' %
111 (tenant_id, user_id, role_id), self.headers)
Vincent Hou6b8a7b72012-08-25 01:24:33 +0800112
113 def delete_tenant(self, tenant_id):
114 """Delete a tenant"""
115 resp, body = self.delete('tenants/%s' % str(tenant_id), self.headers)
116 return resp, body
117
118 def get_tenant(self, tenant_id):
119 """Get tenant details"""
120 resp, body = self.get('tenants/%s' % str(tenant_id), self.headers)
121 body = self._parse_body(etree.fromstring(body))
122 return resp, body
123
124 def list_roles(self):
125 """Returns roles"""
126 resp, body = self.get('OS-KSADM/roles', self.headers)
127 body = self._parse_array(etree.fromstring(body))
128 return resp, body
129
130 def list_tenants(self):
131 """Returns tenants"""
132 resp, body = self.get('tenants', self.headers)
133 body = self._parse_array(etree.fromstring(body))
134 return resp, body
135
136 def update_tenant(self, tenant_id, **kwargs):
137 """Updates a tenant"""
138 resp, body = self.get_tenant(tenant_id)
139 name = kwargs.get('name', body['name'])
140 desc = kwargs.get('description', body['description'])
141 en = kwargs.get('enabled', body['enabled'])
142 update_tenant = Element("tenant",
143 xmlns=XMLNS,
144 id=tenant_id,
145 name=name,
146 description=desc,
147 enabled=str(en).lower())
148
149 resp, body = self.post('tenants/%s' % tenant_id,
150 str(Document(update_tenant)),
151 self.headers)
152 body = self._parse_body(etree.fromstring(body))
153 return resp, body
154
155 def create_user(self, name, password, tenant_id, email):
156 """Create a user"""
157 create_user = Element("user",
Zhongyue Luoe0884a32012-09-25 17:24:17 +0800158 xmlns=XMLNS,
159 name=name,
160 password=password,
161 tenantId=tenant_id,
162 email=email)
Vincent Hou6b8a7b72012-08-25 01:24:33 +0800163 resp, body = self.post('users', str(Document(create_user)),
164 self.headers)
165 body = self._parse_body(etree.fromstring(body))
166 return resp, body
167
168 def delete_user(self, user_id):
169 """Delete a user"""
170 resp, body = self.delete("users/%s" % user_id, self.headers)
171 return resp, body
172
173 def get_users(self):
174 """Get the list of users"""
175 resp, body = self.get("users", self.headers)
176 body = self._parse_array(etree.fromstring(body))
177 return resp, body
178
179 def enable_disable_user(self, user_id, enabled):
180 """Enables or disables a user"""
Zhongyue Luoe0884a32012-09-25 17:24:17 +0800181 enable_user = Element("user", enabled=str(enabled).lower())
Vincent Hou6b8a7b72012-08-25 01:24:33 +0800182 resp, body = self.put('users/%s/enabled' % user_id,
Zhongyue Luo79d8d362012-09-25 13:49:27 +0800183 str(Document(enable_user)), self.headers)
Vincent Hou6b8a7b72012-08-25 01:24:33 +0800184 body = self._parse_array(etree.fromstring(body))
185 return resp, body
186
187 def delete_token(self, token_id):
188 """Delete a token"""
189 resp, body = self.delete("tokens/%s" % token_id, self.headers)
190 return resp, body
191
192 def list_users_for_tenant(self, tenant_id):
193 """List users for a Tenant"""
194 resp, body = self.get('/tenants/%s/users' % tenant_id, self.headers)
195 body = self._parse_array(etree.fromstring(body))
196 return resp, body
197
198 def create_service(self, name, type, **kwargs):
199 """Create a service"""
200 OS_KSADM = "http://docs.openstack.org/identity/api/ext/OS-KSADM/v1.0"
201 create_service = Element("service",
Zhongyue Luo79d8d362012-09-25 13:49:27 +0800202 xmlns=OS_KSADM,
203 name=name,
204 type=type,
205 description=kwargs.get('description'))
Vincent Hou6b8a7b72012-08-25 01:24:33 +0800206 resp, body = self.post('OS-KSADM/services',
207 str(Document(create_service)),
Zhongyue Luoe0884a32012-09-25 17:24:17 +0800208 self.headers)
Vincent Hou6b8a7b72012-08-25 01:24:33 +0800209 body = self._parse_body(etree.fromstring(body))
210 return resp, body
211
212 def get_service(self, service_id):
213 """Get Service"""
214 url = '/OS-KSADM/services/%s' % service_id
215 resp, body = self.get(url, self.headers)
216 body = self._parse_body(etree.fromstring(body))
217 return resp, body
218
219 def delete_service(self, service_id):
220 """Delete Service"""
221 url = '/OS-KSADM/services/%s' % service_id
222 return self.delete(url, self.headers)
223
224
225class TokenClientXML(RestClientXML):
226
227 def __init__(self, config):
228 self.auth_url = config.identity.auth_url
229
230 def auth(self, user, password, tenant):
231 passwordCreds = Element("passwordCredentials",
Zhongyue Luo79d8d362012-09-25 13:49:27 +0800232 username=user,
233 password=password)
Zhongyue Luoe0884a32012-09-25 17:24:17 +0800234 auth = Element("auth", tenantName=tenant)
Vincent Hou6b8a7b72012-08-25 01:24:33 +0800235 auth.append(passwordCreds)
236 headers = {'Content-Type': 'application/xml'}
237 resp, body = self.post(self.auth_url, headers=headers,
238 body=str(Document(auth)))
239 return resp, body
240
241 def request(self, method, url, headers=None, body=None):
242 """A simple HTTP request interface."""
243 self.http_obj = httplib2.Http()
Zhongyue Luoe471d6e2012-09-17 17:02:43 +0800244 if headers is None:
Vincent Hou6b8a7b72012-08-25 01:24:33 +0800245 headers = {}
246
247 resp, resp_body = self.http_obj.request(url, method,
248 headers=headers, body=body)
249
250 if resp.status in (401, 403):
251 resp_body = json.loads(resp_body)
252 raise exceptions.Unauthorized(resp_body['error']['message'])
253
254 return resp, resp_body
255
256 def get_token(self, user, password, tenant):
257 resp, body = self.auth(user, password, tenant)
258 if resp['status'] != '202':
259 body = json.loads(body)
260 access = body['access']
261 token = access['token']
262 return token['id']