blob: be314cca0df478a5f1e40b44c6a9745de8ee150d [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
dwalleck5d734432012-10-04 01:11:47 -050018
Mate Lakat23a58a32013-08-23 02:06:22 +010019from tempest.common import http
dwalleck5d734432012-10-04 01:11:47 -050020from tempest.common.rest_client import RestClient
Matthew Treinish684d8992014-01-30 16:27:40 +000021from tempest import config
harika-vakadi2daed0a2013-01-01 20:51:39 +053022from tempest import exceptions
Daisuke Morita83441282014-01-14 18:56:17 +090023from xml.etree import ElementTree as etree
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
28class AccountClient(RestClient):
Andrea Frittoli8bbdb162014-01-06 11:06:13 +000029 def __init__(self, auth_provider):
30 super(AccountClient, self).__init__(auth_provider)
Matthew Treinish684d8992014-01-30 16:27:40 +000031 self.service = CONF.object_storage.catalog_type
dwalleck5d734432012-10-04 01:11:47 -050032
Daisuke Morita499bba32013-11-28 18:44:49 +090033 def create_account(self, data=None,
34 params=None,
35 metadata={},
36 remove_metadata={},
37 metadata_prefix='X-Account-Meta-',
38 remove_metadata_prefix='X-Remove-Account-Meta-'):
39 """Create an account."""
40 url = ''
41 if params:
42 url += '?%s' % urllib.urlencode(params)
43
44 headers = {}
45 for key in metadata:
46 headers[metadata_prefix + key] = metadata[key]
47 for key in remove_metadata:
48 headers[remove_metadata_prefix + key] = remove_metadata[key]
49
50 resp, body = self.put(url, data, headers)
51 return resp, body
52
53 def delete_account(self, data=None, params=None):
54 """Delete an account."""
55 url = ''
56 if params:
57 if 'bulk-delete' in params:
58 url += 'bulk-delete&'
59 url = '?%s%s' % (url, urllib.urlencode(params))
60
vponomaryov67b58fe2014-02-06 19:05:41 +020061 resp, body = self.delete(url, headers={}, body=data)
Daisuke Morita499bba32013-11-28 18:44:49 +090062 return resp, body
63
dwalleck5d734432012-10-04 01:11:47 -050064 def list_account_metadata(self):
65 """
66 HEAD on the storage URL
67 Returns all account metadata headers
68 """
Chmouel Boudjnahdcf40ea2014-01-06 18:35:34 -080069 resp, body = self.head('')
dwalleck5d734432012-10-04 01:11:47 -050070 return resp, body
71
72 def create_account_metadata(self, metadata,
73 metadata_prefix='X-Account-Meta-'):
Sean Daguef237ccb2013-01-04 15:19:14 -050074 """Creates an account metadata entry."""
dwalleck5d734432012-10-04 01:11:47 -050075 headers = {}
76 for key in metadata:
77 headers[metadata_prefix + key] = metadata[key]
78
79 resp, body = self.post('', headers=headers, body=None)
80 return resp, body
81
Larisa Ustalov6c3c7802012-11-05 12:25:19 +020082 def delete_account_metadata(self, metadata,
83 metadata_prefix='X-Remove-Account-Meta-'):
84 """
85 Deletes an account metadata entry.
86 """
87
Chmouel Boudjnahdcf40ea2014-01-06 18:35:34 -080088 headers = {}
Larisa Ustalov6c3c7802012-11-05 12:25:19 +020089 for item in metadata:
Daisuke Morita83441282014-01-14 18:56:17 +090090 headers[metadata_prefix + item] = metadata[item]
91 resp, body = self.post('', headers=headers, body=None)
92 return resp, body
93
94 def create_and_delete_account_metadata(
95 self,
96 create_metadata=None,
97 delete_metadata=None,
98 create_metadata_prefix='X-Account-Meta-',
99 delete_metadata_prefix='X-Remove-Account-Meta-'):
100 """
101 Creates and deletes an account metadata entry.
102 """
103 headers = {}
104 for key in create_metadata:
105 headers[create_metadata_prefix + key] = create_metadata[key]
106 for key in delete_metadata:
107 headers[delete_metadata_prefix + key] = delete_metadata[key]
108
Larisa Ustalov6c3c7802012-11-05 12:25:19 +0200109 resp, body = self.post('', headers=headers, body=None)
110 return resp, body
111
dwalleck5d734432012-10-04 01:11:47 -0500112 def list_account_containers(self, params=None):
113 """
114 GET on the (base) storage URL
Chmouel Boudjnahdcf40ea2014-01-06 18:35:34 -0800115 Given valid X-Auth-Token, returns a list of all containers for the
116 account.
dwalleck5d734432012-10-04 01:11:47 -0500117
118 Optional Arguments:
119 limit=[integer value N]
120 Limits the number of results to at most N values
121 DEFAULT: 10,000
122
123 marker=[string value X]
124 Given string value X, return object names greater in value
125 than the specified marker.
126 DEFAULT: No Marker
127
128 format=[string value, either 'json' or 'xml']
129 Specify either json or xml to return the respective serialized
130 response.
131 DEFAULT: Python-List returned in response body
132 """
Daisuke Morita83441282014-01-14 18:56:17 +0900133 url = '?%s' % urllib.urlencode(params) if params else ''
dwalleck5d734432012-10-04 01:11:47 -0500134
Daisuke Morita83441282014-01-14 18:56:17 +0900135 resp, body = self.get(url, headers={})
Daisuke Morita499bba32013-11-28 18:44:49 +0900136 if params and params.get('format') == 'json':
137 body = json.loads(body)
Daisuke Morita83441282014-01-14 18:56:17 +0900138 elif params and params.get('format') == 'xml':
139 body = etree.fromstring(body)
140 else:
141 body = body.strip().splitlines()
dwalleck5d734432012-10-04 01:11:47 -0500142 return resp, body
harika-vakadi2daed0a2013-01-01 20:51:39 +0530143
Joe H. Rahme9e07bf02014-01-13 18:58:02 +0100144 def list_extensions(self):
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000145 self.skip_path()
Daisuke Morita83441282014-01-14 18:56:17 +0900146 try:
147 resp, body = self.get('info')
148 finally:
149 self.reset_path()
Joe H. Rahme9e07bf02014-01-13 18:58:02 +0100150 body = json.loads(body)
151 return resp, body
152
harika-vakadi2daed0a2013-01-01 20:51:39 +0530153
154class AccountClientCustomizedHeader(RestClient):
155
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000156 # TODO(andreaf) This class is now redundant, to be removed in next patch
157
158 def __init__(self, auth_provider):
159 super(AccountClientCustomizedHeader, self).__init__(
160 auth_provider)
Attila Fazekasa8b5fe72013-08-01 16:59:06 +0200161 # Overwrites json-specific header encoding in RestClient
Matthew Treinish684d8992014-01-30 16:27:40 +0000162 self.service = CONF.object_storage.catalog_type
harika-vakadi2daed0a2013-01-01 20:51:39 +0530163 self.format = 'json'
164
Attila Fazekasb8aa7592013-01-26 01:25:45 +0100165 def request(self, method, url, headers=None, body=None):
harika-vakadi2daed0a2013-01-01 20:51:39 +0530166 """A simple HTTP request interface."""
Mate Lakat23a58a32013-08-23 02:06:22 +0100167 self.http_obj = http.ClosingHttp()
harika-vakadi2daed0a2013-01-01 20:51:39 +0530168 if headers is None:
169 headers = {}
harika-vakadi2daed0a2013-01-01 20:51:39 +0530170
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000171 # Authorize the request
172 req_url, req_headers, req_body = self.auth_provider.auth_request(
173 method=method, url=url, headers=headers, body=body,
174 filters=self.filters
175 )
Attila Fazekas11d2a772013-01-29 17:46:52 +0100176 self._log_request(method, req_url, headers, body)
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000177 # use original body
harika-vakadi2daed0a2013-01-01 20:51:39 +0530178 resp, resp_body = self.http_obj.request(req_url, method,
Andrea Frittoli8bbdb162014-01-06 11:06:13 +0000179 headers=req_headers,
180 body=req_body)
Attila Fazekas11d2a772013-01-29 17:46:52 +0100181 self._log_response(resp, resp_body)
harika-vakadi2daed0a2013-01-01 20:51:39 +0530182
183 if resp.status == 401 or resp.status == 403:
harika-vakadi2daed0a2013-01-01 20:51:39 +0530184 raise exceptions.Unauthorized()
185
186 return resp, resp_body
187
188 def list_account_containers(self, params=None, metadata=None):
189 """
190 GET on the (base) storage URL
Chmouel Boudjnahdcf40ea2014-01-06 18:35:34 -0800191 Given a valid X-Auth-Token, returns a list of all containers for the
192 account.
harika-vakadi2daed0a2013-01-01 20:51:39 +0530193
194 Optional Arguments:
195 limit=[integer value N]
196 Limits the number of results to at most N values
197 DEFAULT: 10,000
198
199 marker=[string value X]
200 Given string value X, return object names greater in value
201 than the specified marker.
202 DEFAULT: No Marker
203
204 format=[string value, either 'json' or 'xml']
205 Specify either json or xml to return the respective serialized
206 response.
207 DEFAULT: Python-List returned in response body
208 """
209
210 url = '?format=%s' % self.format
211 if params:
212 url += '&%s' + urllib.urlencode(params)
213
214 headers = {}
215 if metadata:
216 for key in metadata:
217 headers[str(key)] = metadata[key]
218
219 resp, body = self.get(url, headers=headers)
220 return resp, body