blob: b31fe1bcad773bd7aacd135d3b86cf1f1df5cf71 [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
Matthew Treinish96e9e882014-06-09 18:37:19 -040016from xml.etree import ElementTree as etree
dwalleck5d734432012-10-04 01:11:47 -050017
Matthew Treinish21905512015-07-13 10:33:35 -040018from oslo_serialization import jsonutils as json
Matthew Treinish89128142015-04-23 10:44:30 -040019from six.moves.urllib import parse as urllib
20
Ken'ichi Ohmichi564b2ad2015-01-22 02:08:59 +000021from tempest.common import service_client
dwalleck5d734432012-10-04 01:11:47 -050022
23
Ken'ichi Ohmichi564b2ad2015-01-22 02:08:59 +000024class ContainerClient(service_client.ServiceClient):
dwalleck5d734432012-10-04 01:11:47 -050025
Daisuke Morita1d591582014-01-14 19:49:23 +090026 def create_container(
27 self, container_name,
28 metadata=None,
29 remove_metadata=None,
30 metadata_prefix='X-Container-Meta-',
31 remove_metadata_prefix='X-Remove-Container-Meta-'):
dwalleck5d734432012-10-04 01:11:47 -050032 """
33 Creates a container, with optional metadata passed in as a
Chang Bo Guocc1623c2013-09-13 20:11:27 -070034 dictionary
dwalleck5d734432012-10-04 01:11:47 -050035 """
Matthew Treinish26dd0fa2012-12-04 17:14:37 -050036 url = str(container_name)
dwalleck5d734432012-10-04 01:11:47 -050037 headers = {}
38
39 if metadata is not None:
40 for key in metadata:
41 headers[metadata_prefix + key] = metadata[key]
Daisuke Morita1d591582014-01-14 19:49:23 +090042 if remove_metadata is not None:
43 for key in remove_metadata:
44 headers[remove_metadata_prefix + key] = remove_metadata[key]
dwalleck5d734432012-10-04 01:11:47 -050045
46 resp, body = self.put(url, body=None, headers=headers)
JordanPa84dde32014-11-14 15:47:42 +010047 self.expected_success([201, 202], resp.status)
dwalleck5d734432012-10-04 01:11:47 -050048 return resp, body
49
50 def delete_container(self, container_name):
Sean Daguef237ccb2013-01-04 15:19:14 -050051 """Deletes the container (if it's empty)."""
Matthew Treinish26dd0fa2012-12-04 17:14:37 -050052 url = str(container_name)
dwalleck5d734432012-10-04 01:11:47 -050053 resp, body = self.delete(url)
JordanPa84dde32014-11-14 15:47:42 +010054 self.expected_success(204, resp.status)
dwalleck5d734432012-10-04 01:11:47 -050055 return resp, body
56
Daisuke Morita1d591582014-01-14 19:49:23 +090057 def update_container_metadata(
58 self, container_name,
59 metadata=None,
60 remove_metadata=None,
61 metadata_prefix='X-Container-Meta-',
62 remove_metadata_prefix='X-Remove-Container-Meta-'):
Sean Daguef237ccb2013-01-04 15:19:14 -050063 """Updates arbitrary metadata on container."""
Matthew Treinish26dd0fa2012-12-04 17:14:37 -050064 url = str(container_name)
dwalleck5d734432012-10-04 01:11:47 -050065 headers = {}
66
67 if metadata is not None:
68 for key in metadata:
69 headers[metadata_prefix + key] = metadata[key]
Daisuke Morita1d591582014-01-14 19:49:23 +090070 if remove_metadata is not None:
71 for key in remove_metadata:
72 headers[remove_metadata_prefix + key] = remove_metadata[key]
dwalleck5d734432012-10-04 01:11:47 -050073
74 resp, body = self.post(url, body=None, headers=headers)
JordanPa84dde32014-11-14 15:47:42 +010075 self.expected_success(204, resp.status)
Larisa Ustalov6c3c7802012-11-05 12:25:19 +020076 return resp, body
dwalleck5d734432012-10-04 01:11:47 -050077
Larisa Ustalov6c3c7802012-11-05 12:25:19 +020078 def delete_container_metadata(self, container_name, metadata,
79 metadata_prefix='X-Remove-Container-Meta-'):
Sean Daguef237ccb2013-01-04 15:19:14 -050080 """Deletes arbitrary metadata on container."""
Matthew Treinish26dd0fa2012-12-04 17:14:37 -050081 url = str(container_name)
Larisa Ustalov6c3c7802012-11-05 12:25:19 +020082 headers = {}
83
84 if metadata is not None:
85 for item in metadata:
Daisuke Morita1d591582014-01-14 19:49:23 +090086 headers[metadata_prefix + item] = metadata[item]
Larisa Ustalov6c3c7802012-11-05 12:25:19 +020087
88 resp, body = self.post(url, body=None, headers=headers)
JordanPa84dde32014-11-14 15:47:42 +010089 self.expected_success(204, resp.status)
Larisa Ustalov6c3c7802012-11-05 12:25:19 +020090 return resp, body
91
92 def list_container_metadata(self, container_name):
93 """
94 Retrieves container metadata headers
95 """
Matthew Treinish26dd0fa2012-12-04 17:14:37 -050096 url = str(container_name)
Chmouel Boudjnahdcf40ea2014-01-06 18:35:34 -080097 resp, body = self.head(url)
JordanPa84dde32014-11-14 15:47:42 +010098 self.expected_success(204, resp.status)
Larisa Ustalov6c3c7802012-11-05 12:25:19 +020099 return resp, body
dwalleck5d734432012-10-04 01:11:47 -0500100
101 def list_all_container_objects(self, container, params=None):
102 """
103 Returns complete list of all objects in the container, even if
104 item count is beyond 10,000 item listing limit.
Chang Bo Guocc1623c2013-09-13 20:11:27 -0700105 Does not require any parameters aside from container name.
dwalleck5d734432012-10-04 01:11:47 -0500106 """
Chang Bo Guocc1623c2013-09-13 20:11:27 -0700107 # TODO(dwalleck): Rewrite using json format to avoid newlines at end of
Attila Fazekasa8b5fe72013-08-01 16:59:06 +0200108 # obj names. Set limit to API limit - 1 (max returned items = 9999)
dwalleck5d734432012-10-04 01:11:47 -0500109 limit = 9999
dwalleck5d734432012-10-04 01:11:47 -0500110 if params is not None:
111 if 'limit' in params:
112 limit = params['limit']
113
114 if 'marker' in params:
115 limit = params['marker']
116
Daisuke Morita1d591582014-01-14 19:49:23 +0900117 resp, objlist = self.list_container_contents(
118 container,
119 params={'limit': limit, 'format': 'json'})
JordanPa84dde32014-11-14 15:47:42 +0100120 self.expected_success(200, resp.status)
dwalleck5d734432012-10-04 01:11:47 -0500121 return objlist
122 """tmp = []
123 for obj in objlist:
124 tmp.append(obj['name'])
125 objlist = tmp
126
127 if len(objlist) >= limit:
128
Attila Fazekasa8b5fe72013-08-01 16:59:06 +0200129 # Increment marker
dwalleck5d734432012-10-04 01:11:47 -0500130 marker = objlist[len(objlist) - 1]
131
Attila Fazekasa8b5fe72013-08-01 16:59:06 +0200132 # Get the next chunk of the list
dwalleck5d734432012-10-04 01:11:47 -0500133 objlist.extend(_list_all_container_objects(container,
134 params={'marker': marker,
135 'limit': limit}))
136 return objlist
137 else:
Attila Fazekasa8b5fe72013-08-01 16:59:06 +0200138 # Return final, complete list
dwalleck5d734432012-10-04 01:11:47 -0500139 return objlist"""
140
141 def list_container_contents(self, container, params=None):
142 """
143 List the objects in a container, given the container name
144
145 Returns the container object listing as a plain text list, or as
146 xml or json if that option is specified via the 'format' argument.
147
148 Optional Arguments:
149 limit = integer
150 For an integer value n, limits the number of results to at most
151 n values.
152
153 marker = 'string'
154 Given a string value x, return object names greater in value
155 than the specified marker.
156
157 prefix = 'string'
158 For a string value x, causes the results to be limited to names
159 beginning with the substring x.
160
161 format = 'json' or 'xml'
162 Specify either json or xml to return the respective serialized
163 response.
164 If json, returns a list of json objects
165 if xml, returns a string of xml
166
167 path = 'string'
168 For a string value x, return the object names nested in the
169 pseudo path (assuming preconditions are met - see below).
170
171 delimiter = 'character'
172 For a character c, return all the object names nested in the
173 container (without the need for the directory marker objects).
174 """
175
176 url = str(container)
Matthew Treinish26dd0fa2012-12-04 17:14:37 -0500177 if params:
Daisuke Morita1d591582014-01-14 19:49:23 +0900178 url += '?'
Matthew Treinish26dd0fa2012-12-04 17:14:37 -0500179 url += '&%s' % urllib.urlencode(params)
dwalleck5d734432012-10-04 01:11:47 -0500180
vponomaryov67b58fe2014-02-06 19:05:41 +0200181 resp, body = self.get(url, headers={})
Daisuke Morita1d591582014-01-14 19:49:23 +0900182 if params and params.get('format') == 'json':
183 body = json.loads(body)
184 elif params and params.get('format') == 'xml':
185 body = etree.fromstring(body)
JordanPa84dde32014-11-14 15:47:42 +0100186 self.expected_success([200, 204], resp.status)
dwalleck5d734432012-10-04 01:11:47 -0500187 return resp, body