blob: 458c862ad6a27470ad8533629a5e938df2215be9 [file] [log] [blame]
Matthew Treinish9e26ca82016-02-23 11:43:20 -05001# 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
15from oslo_log import log as logging
16from oslo_serialization import jsonutils as json
17
18from tempest.lib.common import rest_client
19from tempest.lib import exceptions
20
21
22class TokenClient(rest_client.RestClient):
23
24 def __init__(self, auth_url, disable_ssl_certificate_validation=None,
zhufl071e94c2016-07-12 10:26:34 +080025 ca_certs=None, trace_requests=None, **kwargs):
Andrea Frittoli8b8db532016-12-22 11:21:47 +000026 """Initialises the Token client
27
28 :param auth_url: URL to which the token request is sent
29 :param disable_ssl_certificate_validation: pass-through to rest client
30 :param ca_certs: pass-through to rest client
31 :param trace_requests: pass-through to rest client
32 :param kwargs: any extra parameter to pass through the rest client.
33 region, service and auth_provider will be ignored, if passed,
34 as they are not meaningful for token client
35 """
Matthew Treinish9e26ca82016-02-23 11:43:20 -050036 dscv = disable_ssl_certificate_validation
Andrea Frittoli8b8db532016-12-22 11:21:47 +000037 # NOTE(andreaf) region, service and auth_provider are passed
38 # positionally with None. Having them in kwargs would raise a
39 # "multiple values for keyword arguments" error
40 for unwanted_kwargs in ['region', 'service', 'auth_provider']:
41 kwargs.pop(unwanted_kwargs, None)
Matthew Treinish9e26ca82016-02-23 11:43:20 -050042 super(TokenClient, self).__init__(
43 None, None, None, disable_ssl_certificate_validation=dscv,
zhufl071e94c2016-07-12 10:26:34 +080044 ca_certs=ca_certs, trace_requests=trace_requests, **kwargs)
Matthew Treinish9e26ca82016-02-23 11:43:20 -050045
46 if auth_url is None:
47 raise exceptions.IdentityError("Couldn't determine auth_url")
48
49 # Normalize URI to ensure /tokens is in it.
50 if 'tokens' not in auth_url:
51 auth_url = auth_url.rstrip('/') + '/tokens'
52
53 self.auth_url = auth_url
54
55 def auth(self, user, password, tenant=None):
56 creds = {
57 'auth': {
58 'passwordCredentials': {
59 'username': user,
60 'password': password,
61 },
62 }
63 }
64
65 if tenant:
66 creds['auth']['tenantName'] = tenant
67
68 body = json.dumps(creds, sort_keys=True)
69 resp, body = self.post(self.auth_url, body=body)
70 self.expected_success(200, resp.status)
71
72 return rest_client.ResponseBody(resp, body['access'])
73
74 def auth_token(self, token_id, tenant=None):
75 creds = {
76 'auth': {
77 'token': {
78 'id': token_id,
79 },
80 }
81 }
82
83 if tenant:
84 creds['auth']['tenantName'] = tenant
85
86 body = json.dumps(creds)
87 resp, body = self.post(self.auth_url, body=body)
88 self.expected_success(200, resp.status)
89
90 return rest_client.ResponseBody(resp, body['access'])
91
92 def request(self, method, url, extra_headers=False, headers=None,
Jordan Pittier4408c4a2016-04-29 15:05:09 +020093 body=None, chunked=False):
94 """A simple HTTP request interface.
95
96 Note: this overloads the `request` method from the parent class and
97 thus must implement the same method signature.
98 """
Matthew Treinish9e26ca82016-02-23 11:43:20 -050099 if headers is None:
100 headers = self.get_headers(accept_type="json")
101 elif extra_headers:
102 try:
103 headers.update(self.get_headers(accept_type="json"))
104 except (ValueError, TypeError):
105 headers = self.get_headers(accept_type="json")
106
107 resp, resp_body = self.raw_request(url, method,
108 headers=headers, body=body)
109 self._log_request(method, url, resp, req_headers=headers,
110 req_body='<omitted>', resp_body=resp_body)
111
112 if resp.status in [401, 403]:
113 resp_body = json.loads(resp_body)
114 raise exceptions.Unauthorized(resp_body['error']['message'])
115 elif resp.status not in [200, 201]:
116 raise exceptions.IdentityError(
117 'Unexpected status code {0}'.format(resp.status))
118
119 return resp, json.loads(resp_body)
120
121 def get_token(self, user, password, tenant, auth_data=False):
122 """Returns (token id, token data) for supplied credentials."""
123 body = self.auth(user, password, tenant)
124
125 if auth_data:
126 return body['token']['id'], body
127 else:
128 return body['token']['id']
129
130
131class TokenClientJSON(TokenClient):
132 LOG = logging.getLogger(__name__)
133
134 def _warn(self):
Jordan Pittier525ec712016-12-07 17:51:26 +0100135 self.LOG.warning("%s class was deprecated and renamed to %s",
136 self.__class__.__name__, 'TokenClient')
Matthew Treinish9e26ca82016-02-23 11:43:20 -0500137
138 def __init__(self, *args, **kwargs):
139 self._warn()
140 super(TokenClientJSON, self).__init__(*args, **kwargs)