blob: b0824a7ded38b79d9a208f655fb44acea311d535 [file] [log] [blame]
ghanshyamc0edda02015-02-06 15:51:40 +09001# Copyright 2015 NEC Corporation. All rights reserved.
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
15import json
Andrea Frittoli90012352015-02-25 21:58:02 +000016from tempest_lib.common import rest_client
Masayuki Igawa29d554f2015-01-20 12:36:42 +090017from tempest_lib import exceptions as lib_exc
ghanshyamc0edda02015-02-06 15:51:40 +090018
19from tempest.common import service_client
ghanshyamc0edda02015-02-06 15:51:40 +090020from tempest import exceptions
21
ghanshyamc0edda02015-02-06 15:51:40 +090022
Andrea Frittoli90012352015-02-25 21:58:02 +000023class V3TokenClientJSON(rest_client.RestClient):
ghanshyamc0edda02015-02-06 15:51:40 +090024
Andrea Frittoli90012352015-02-25 21:58:02 +000025 def __init__(self, auth_url, disable_ssl_certificate_validation=None,
26 ca_certs=None, trace_requests=None):
27 dscv = disable_ssl_certificate_validation
28 super(V3TokenClientJSON, self).__init__(
29 None, None, None, disable_ssl_certificate_validation=dscv,
30 ca_certs=ca_certs, trace_requests=trace_requests)
ghanshyamc0edda02015-02-06 15:51:40 +090031 if not auth_url:
32 raise exceptions.InvalidConfiguration('you must specify a v3 uri '
33 'if using the v3 identity '
34 'api')
35 if 'auth/tokens' not in auth_url:
36 auth_url = auth_url.rstrip('/') + '/auth/tokens'
37
38 self.auth_url = auth_url
39
Jamie Lennoxe5a95d42015-02-11 07:19:57 +000040 def auth(self, user=None, password=None, project=None, user_type='id',
41 user_domain=None, project_domain=None, token=None):
ghanshyamc0edda02015-02-06 15:51:40 +090042 """
43 :param user: user id or name, as specified in user_type
Jamie Lennoxe5a95d42015-02-11 07:19:57 +000044 :param user_domain: the user domain
45 :param project_domain: the project domain
ghanshyamc0edda02015-02-06 15:51:40 +090046 :param token: a token to re-scope.
47
48 Accepts different combinations of credentials. Restrictions:
Jamie Lennoxe5a95d42015-02-11 07:19:57 +000049 - project and domain are only name (no id)
ghanshyamc0edda02015-02-06 15:51:40 +090050 Sample sample valid combinations:
51 - token
Jamie Lennoxe5a95d42015-02-11 07:19:57 +000052 - token, project, project_domain
ghanshyamc0edda02015-02-06 15:51:40 +090053 - user_id, password
Jamie Lennoxe5a95d42015-02-11 07:19:57 +000054 - username, password, user_domain
55 - username, password, project, user_domain, project_domain
ghanshyamc0edda02015-02-06 15:51:40 +090056 Validation is left to the server side.
57 """
58 creds = {
59 'auth': {
60 'identity': {
61 'methods': [],
62 }
63 }
64 }
65 id_obj = creds['auth']['identity']
66 if token:
67 id_obj['methods'].append('token')
68 id_obj['token'] = {
69 'id': token
70 }
71 if user and password:
72 id_obj['methods'].append('password')
73 id_obj['password'] = {
74 'user': {
75 'password': password,
76 }
77 }
78 if user_type == 'id':
79 id_obj['password']['user']['id'] = user
80 else:
81 id_obj['password']['user']['name'] = user
Jamie Lennoxe5a95d42015-02-11 07:19:57 +000082 if user_domain is not None:
83 _domain = dict(name=user_domain)
ghanshyamc0edda02015-02-06 15:51:40 +090084 id_obj['password']['user']['domain'] = _domain
Jamie Lennoxe5a95d42015-02-11 07:19:57 +000085 if project is not None:
86 _domain = dict(name=project_domain)
87 _project = dict(name=project, domain=_domain)
88 scope = dict(project=_project)
ghanshyamc0edda02015-02-06 15:51:40 +090089 creds['auth']['scope'] = scope
90
91 body = json.dumps(creds)
92 resp, body = self.post(self.auth_url, body=body)
93 self.expected_success(201, resp.status)
94 return service_client.ResponseBody(resp, body)
95
96 def request(self, method, url, extra_headers=False, headers=None,
97 body=None):
98 """A simple HTTP request interface."""
99 if headers is None:
100 # Always accept 'json', for xml token client too.
101 # Because XML response is not easily
102 # converted to the corresponding JSON one
103 headers = self.get_headers(accept_type="json")
104 elif extra_headers:
105 try:
106 headers.update(self.get_headers(accept_type="json"))
107 except (ValueError, TypeError):
108 headers = self.get_headers(accept_type="json")
109
110 resp, resp_body = self.raw_request(url, method,
111 headers=headers, body=body)
112 self._log_request(method, url, resp)
113
114 if resp.status in [401, 403]:
115 resp_body = json.loads(resp_body)
Masayuki Igawa29d554f2015-01-20 12:36:42 +0900116 raise lib_exc.Unauthorized(resp_body['error']['message'])
ghanshyamc0edda02015-02-06 15:51:40 +0900117 elif resp.status not in [200, 201, 204]:
118 raise exceptions.IdentityError(
119 'Unexpected status code {0}'.format(resp.status))
120
121 return resp, json.loads(resp_body)
122
Jamie Lennoxe5a95d42015-02-11 07:19:57 +0000123 def get_token(self, user, password, project=None, project_domain='Default',
124 user_domain='Default', auth_data=False):
ghanshyamc0edda02015-02-06 15:51:40 +0900125 """
126 :param user: username
127 Returns (token id, token data) for supplied credentials
128 """
Jamie Lennoxe5a95d42015-02-11 07:19:57 +0000129 body = self.auth(user, password, project, user_type='name',
130 user_domain=user_domain,
131 project_domain=project_domain)
ghanshyamc0edda02015-02-06 15:51:40 +0900132
133 token = body.response.get('x-subject-token')
134 if auth_data:
135 return token, body['token']
136 else:
137 return token