blob: 5a26bfcde5e374a2698948bb4f117af9f251ed70 [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 Ohmichi19f68812016-03-02 14:09:17 +090021from tempest.lib.common import rest_client
dwalleck5d734432012-10-04 01:11:47 -050022
23
Ken'ichi Ohmichi19f68812016-03-02 14:09:17 +090024class ContainerClient(rest_client.RestClient):
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-'):
Ken'ichi Ohmichib2790842015-11-17 11:46:13 +000032 """Creates a container
33
34 with optional metadata passed in as a 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):
Ken'ichi Ohmichib2790842015-11-17 11:46:13 +000093 """Retrieves container metadata headers"""
Matthew Treinish26dd0fa2012-12-04 17:14:37 -050094 url = str(container_name)
Chmouel Boudjnahdcf40ea2014-01-06 18:35:34 -080095 resp, body = self.head(url)
JordanPa84dde32014-11-14 15:47:42 +010096 self.expected_success(204, resp.status)
Larisa Ustalov6c3c7802012-11-05 12:25:19 +020097 return resp, body
dwalleck5d734432012-10-04 01:11:47 -050098
99 def list_all_container_objects(self, container, params=None):
Ken'ichi Ohmichib2790842015-11-17 11:46:13 +0000100 """Returns complete list of all objects in the container
101
102 even if item count is beyond 10,000 item listing limit.
103 Does not require any parameters aside from container name.
dwalleck5d734432012-10-04 01:11:47 -0500104 """
Chang Bo Guocc1623c2013-09-13 20:11:27 -0700105 # TODO(dwalleck): Rewrite using json format to avoid newlines at end of
Attila Fazekasa8b5fe72013-08-01 16:59:06 +0200106 # obj names. Set limit to API limit - 1 (max returned items = 9999)
dwalleck5d734432012-10-04 01:11:47 -0500107 limit = 9999
dwalleck5d734432012-10-04 01:11:47 -0500108 if params is not None:
109 if 'limit' in params:
110 limit = params['limit']
111
112 if 'marker' in params:
113 limit = params['marker']
114
Daisuke Morita1d591582014-01-14 19:49:23 +0900115 resp, objlist = self.list_container_contents(
116 container,
117 params={'limit': limit, 'format': 'json'})
JordanPa84dde32014-11-14 15:47:42 +0100118 self.expected_success(200, resp.status)
dwalleck5d734432012-10-04 01:11:47 -0500119 return objlist
dwalleck5d734432012-10-04 01:11:47 -0500120
121 def list_container_contents(self, container, params=None):
Ken'ichi Ohmichib2790842015-11-17 11:46:13 +0000122 """List the objects in a container, given the container name
dwalleck5d734432012-10-04 01:11:47 -0500123
124 Returns the container object listing as a plain text list, or as
125 xml or json if that option is specified via the 'format' argument.
126
127 Optional Arguments:
128 limit = integer
129 For an integer value n, limits the number of results to at most
130 n values.
131
132 marker = 'string'
133 Given a string value x, return object names greater in value
134 than the specified marker.
135
136 prefix = 'string'
137 For a string value x, causes the results to be limited to names
138 beginning with the substring x.
139
140 format = 'json' or 'xml'
141 Specify either json or xml to return the respective serialized
142 response.
143 If json, returns a list of json objects
144 if xml, returns a string of xml
145
146 path = 'string'
147 For a string value x, return the object names nested in the
148 pseudo path (assuming preconditions are met - see below).
149
150 delimiter = 'character'
151 For a character c, return all the object names nested in the
152 container (without the need for the directory marker objects).
153 """
154
155 url = str(container)
Matthew Treinish26dd0fa2012-12-04 17:14:37 -0500156 if params:
Daisuke Morita1d591582014-01-14 19:49:23 +0900157 url += '?'
Matthew Treinish26dd0fa2012-12-04 17:14:37 -0500158 url += '&%s' % urllib.urlencode(params)
dwalleck5d734432012-10-04 01:11:47 -0500159
vponomaryov67b58fe2014-02-06 19:05:41 +0200160 resp, body = self.get(url, headers={})
Daisuke Morita1d591582014-01-14 19:49:23 +0900161 if params and params.get('format') == 'json':
162 body = json.loads(body)
163 elif params and params.get('format') == 'xml':
164 body = etree.fromstring(body)
JordanPa84dde32014-11-14 15:47:42 +0100165 self.expected_success([200, 204], resp.status)
dwalleck5d734432012-10-04 01:11:47 -0500166 return resp, body