blob: 23984cd90d290d3e2e215b7f041116934fd5459b [file] [log] [blame]
ZhiQiang Fan39f97222013-09-20 04:49:44 +08001# Copyright 2012 OpenStack Foundation
dwalleck5d734432012-10-04 01:11:47 -05002# 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
16import json
Matthew Treinish26dd0fa2012-12-04 17:14:37 -050017import urllib
Matthew Treinish96e9e882014-06-09 18:37:19 -040018from xml.etree import ElementTree as etree
dwalleck5d734432012-10-04 01:11:47 -050019
Mate Lakat23a58a32013-08-23 02:06:22 +010020from tempest.common import http
Matthew Treinish684d8992014-01-30 16:27:40 +000021from tempest import config
harika-vakadi2daed0a2013-01-01 20:51:39 +053022from tempest import exceptions
Ken'ichi Ohmichide398ac2014-12-17 08:34:34 +000023from tempest.services.object_storage import base
dwalleck5d734432012-10-04 01:11:47 -050024
Matthew Treinish684d8992014-01-30 16:27:40 +000025CONF = config.CONF
26
dwalleck5d734432012-10-04 01:11:47 -050027
Ken'ichi Ohmichide398ac2014-12-17 08:34:34 +000028class AccountClient(base.ObjectStorageClient):
dwalleck5d734432012-10-04 01:11:47 -050029
Daisuke Morita499bba32013-11-28 18:44:49 +090030 def create_account(self, data=None,
31 params=None,
Ghanshyam2a180b82014-06-16 13:54:22 +090032 metadata=None,
33 remove_metadata=None,
Daisuke Morita499bba32013-11-28 18:44:49 +090034 metadata_prefix='X-Account-Meta-',
35 remove_metadata_prefix='X-Remove-Account-Meta-'):
36 """Create an account."""
Ghanshyam2a180b82014-06-16 13:54:22 +090037 if metadata is None:
38 metadata = {}
39 if remove_metadata is None:
40 remove_metadata = {}
Daisuke Morita499bba32013-11-28 18:44:49 +090041 url = ''
42 if params:
43 url += '?%s' % urllib.urlencode(params)
44
45 headers = {}
46 for key in metadata:
47 headers[metadata_prefix + key] = metadata[key]
48 for key in remove_metadata:
49 headers[remove_metadata_prefix + key] = remove_metadata[key]
50
51 resp, body = self.put(url, data, headers)
JordanPa84dde32014-11-14 15:47:42 +010052 self.expected_success(200, resp.status)
Daisuke Morita499bba32013-11-28 18:44:49 +090053 return resp, body
54
55 def delete_account(self, data=None, params=None):
56 """Delete an account."""
57 url = ''
58 if params:
Daisuke Morita499bba32013-11-28 18:44:49 +090059 url = '?%s%s' % (url, urllib.urlencode(params))
60
vponomaryov67b58fe2014-02-06 19:05:41 +020061 resp, body = self.delete(url, headers={}, body=data)
JordanPa84dde32014-11-14 15:47:42 +010062 self.expected_success(200, resp.status)
Daisuke Morita499bba32013-11-28 18:44:49 +090063 return resp, body
64
dwalleck5d734432012-10-04 01:11:47 -050065 def list_account_metadata(self):
66 """
67 HEAD on the storage URL
68 Returns all account metadata headers
69 """
Chmouel Boudjnahdcf40ea2014-01-06 18:35:34 -080070 resp, body = self.head('')
JordanPa84dde32014-11-14 15:47:42 +010071 self.expected_success(204, resp.status)
dwalleck5d734432012-10-04 01:11:47 -050072 return resp, body
73
74 def create_account_metadata(self, metadata,
Daisuke Moritae3f6ed32014-08-25 11:34:21 +090075 metadata_prefix='X-Account-Meta-',
76 data=None, params=None):
Sean Daguef237ccb2013-01-04 15:19:14 -050077 """Creates an account metadata entry."""
dwalleck5d734432012-10-04 01:11:47 -050078 headers = {}
Daisuke Moritae3f6ed32014-08-25 11:34:21 +090079 if metadata:
80 for key in metadata:
81 headers[metadata_prefix + key] = metadata[key]
dwalleck5d734432012-10-04 01:11:47 -050082
Daisuke Moritae3f6ed32014-08-25 11:34:21 +090083 url = ''
84 if params:
85 url = '?%s%s' % (url, urllib.urlencode(params))
86
87 resp, body = self.post(url, headers=headers, body=data)
JordanPa84dde32014-11-14 15:47:42 +010088 self.expected_success([200, 204], resp.status)
dwalleck5d734432012-10-04 01:11:47 -050089 return resp, body
90
Larisa Ustalov6c3c7802012-11-05 12:25:19 +020091 def delete_account_metadata(self, metadata,
92 metadata_prefix='X-Remove-Account-Meta-'):
93 """
94 Deletes an account metadata entry.
95 """
96
Chmouel Boudjnahdcf40ea2014-01-06 18:35:34 -080097 headers = {}
Larisa Ustalov6c3c7802012-11-05 12:25:19 +020098 for item in metadata:
Daisuke Morita83441282014-01-14 18:56:17 +090099 headers[metadata_prefix + item] = metadata[item]
100 resp, body = self.post('', headers=headers, body=None)
JordanPa84dde32014-11-14 15:47:42 +0100101 self.expected_success(204, resp.status)
Daisuke Morita83441282014-01-14 18:56:17 +0900102 return resp, body
103
104 def create_and_delete_account_metadata(
105 self,
106 create_metadata=None,
107 delete_metadata=None,
108 create_metadata_prefix='X-Account-Meta-',
109 delete_metadata_prefix='X-Remove-Account-Meta-'):
110 """
111 Creates and deletes an account metadata entry.
112 """
113 headers = {}
114 for key in create_metadata:
115 headers[create_metadata_prefix + key] = create_metadata[key]
116 for key in delete_metadata:
117 headers[delete_metadata_prefix + key] = delete_metadata[key]
118
Larisa Ustalov6c3c7802012-11-05 12:25:19 +0200119 resp, body = self.post('', headers=headers, body=None)
JordanPa84dde32014-11-14 15:47:42 +0100120 self.expected_success(204, resp.status)
Larisa Ustalov6c3c7802012-11-05 12:25:19 +0200121 return resp, body
122
dwalleck5d734432012-10-04 01:11:47 -0500123 def list_account_containers(self, params=None):
124 """
125 GET on the (base) storage URL
Chmouel Boudjnahdcf40ea2014-01-06 18:35:34 -0800126 Given valid X-Auth-Token, returns a list of all containers for the
127 account.
dwalleck5d734432012-10-04 01:11:47 -0500128
129 Optional Arguments:
130 limit=[integer value N]
131 Limits the number of results to at most N values
132 DEFAULT: 10,000
133
134 marker=[string value X]
135 Given string value X, return object names greater in value
136 than the specified marker.
137 DEFAULT: No Marker
138
139 format=[string value, either 'json' or 'xml']
140 Specify either json or xml to return the respective serialized
141 response.
142 DEFAULT: Python-List returned in response body
143 """
Daisuke Morita83441282014-01-14 18:56:17 +0900144 url = '?%s' % urllib.urlencode(params) if params else ''
dwalleck5d734432012-10-04 01:11:47 -0500145
Daisuke Morita83441282014-01-14 18:56:17 +0900146 resp, body = self.get(url, headers={})
Daisuke Morita499bba32013-11-28 18:44:49 +0900147 if params and params.get('format') == 'json':
148 body = json.loads(body)
Daisuke Morita83441282014-01-14 18:56:17 +0900149 elif params and params.get('format') == 'xml':
150 body = etree.fromstring(body)
151 else:
152 body = body.strip().splitlines()
JordanPa84dde32014-11-14 15:47:42 +0100153 self.expected_success([200, 204], resp.status)
dwalleck5d734432012-10-04 01:11:47 -0500154 return resp, body
harika-vakadi2daed0a2013-01-01 20:51:39 +0530155
Joe H. Rahme9e07bf02014-01-13 18:58:02 +0100156 def list_extensions(self):
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000157 self.skip_path()
Daisuke Morita83441282014-01-14 18:56:17 +0900158 try:
159 resp, body = self.get('info')
160 finally:
161 self.reset_path()
Joe H. Rahme9e07bf02014-01-13 18:58:02 +0100162 body = json.loads(body)
JordanPa84dde32014-11-14 15:47:42 +0100163 self.expected_success(200, resp.status)
Joe H. Rahme9e07bf02014-01-13 18:58:02 +0100164 return resp, body
165
harika-vakadi2daed0a2013-01-01 20:51:39 +0530166
Ken'ichi Ohmichide398ac2014-12-17 08:34:34 +0000167class AccountClientCustomizedHeader(base.ObjectStorageClient):
harika-vakadi2daed0a2013-01-01 20:51:39 +0530168
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000169 # TODO(andreaf) This class is now redundant, to be removed in next patch
170
Sergey Murashov4fccd322014-03-22 09:58:52 +0400171 def request(self, method, url, extra_headers=False, headers=None,
172 body=None):
harika-vakadi2daed0a2013-01-01 20:51:39 +0530173 """A simple HTTP request interface."""
Rob Crittendena7db6692014-11-23 18:44:38 -0500174 dscv = CONF.identity.disable_ssl_certificate_validation
175 ca_certs = CONF.identity.ca_certificates_file
176 self.http_obj = http.ClosingHttp(
177 disable_ssl_certificate_validation=dscv,
178 ca_certs=ca_certs)
harika-vakadi2daed0a2013-01-01 20:51:39 +0530179 if headers is None:
180 headers = {}
Sergey Murashov4fccd322014-03-22 09:58:52 +0400181 elif extra_headers:
182 try:
183 headers.update(self.get_headers())
184 except (ValueError, TypeError):
185 headers = {}
harika-vakadi2daed0a2013-01-01 20:51:39 +0530186
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000187 # Authorize the request
188 req_url, req_headers, req_body = self.auth_provider.auth_request(
189 method=method, url=url, headers=headers, body=body,
190 filters=self.filters
191 )
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000192 # use original body
harika-vakadi2daed0a2013-01-01 20:51:39 +0530193 resp, resp_body = self.http_obj.request(req_url, method,
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000194 headers=req_headers,
195 body=req_body)
Sean Dague89a85912014-03-19 16:37:29 -0400196 self._log_request(method, req_url, resp)
harika-vakadi2daed0a2013-01-01 20:51:39 +0530197
198 if resp.status == 401 or resp.status == 403:
harika-vakadi2daed0a2013-01-01 20:51:39 +0530199 raise exceptions.Unauthorized()
200
201 return resp, resp_body
202
203 def list_account_containers(self, params=None, metadata=None):
204 """
205 GET on the (base) storage URL
Chmouel Boudjnahdcf40ea2014-01-06 18:35:34 -0800206 Given a valid X-Auth-Token, returns a list of all containers for the
207 account.
harika-vakadi2daed0a2013-01-01 20:51:39 +0530208
209 Optional Arguments:
210 limit=[integer value N]
211 Limits the number of results to at most N values
212 DEFAULT: 10,000
213
214 marker=[string value X]
215 Given string value X, return object names greater in value
216 than the specified marker.
217 DEFAULT: No Marker
218
219 format=[string value, either 'json' or 'xml']
220 Specify either json or xml to return the respective serialized
221 response.
222 DEFAULT: Python-List returned in response body
223 """
224
225 url = '?format=%s' % self.format
226 if params:
Rob Crittenden184c69b2014-11-17 00:13:12 -0500227 url += '&%s' % urllib.urlencode(params)
harika-vakadi2daed0a2013-01-01 20:51:39 +0530228
229 headers = {}
230 if metadata:
231 for key in metadata:
232 headers[str(key)] = metadata[key]
233
234 resp, body = self.get(url, headers=headers)
JordanPa84dde32014-11-14 15:47:42 +0100235 self.expected_success(200, resp.status)
harika-vakadi2daed0a2013-01-01 20:51:39 +0530236 return resp, body