from . import clients
from .config import Config
-from .utils import print_addresses, print_dict, print_items, format_size
+from .utils import print_addresses, print_dict, print_items, format_size, dict_from_args
_commands = OrderedDict()
print_dict(reply)
@command(api='storage')
+class store_set_account_meta(_store_account_command):
+ """Set account meta-content"""
+
+ def main(self, metakey, metaval, *more):
+ super(store_set_account_meta, self).main()
+ args_len = len(more)
+ if args_len%2 == 1:
+ print('Parameter %s will be ignored' % more[-1])
+ pairs = dict_from_args(*more)
+ pairs[metakey] = metaval
+ self.client.set_account_meta(pairs)
+
+@command(api='storage')
+class store_policy(_store_account_command):
+ """Get policy for account [, container [or object]]"""
+
+ def main(self, container = None):
+ super(store_policy, self).main()
+ if container is None:
+ reply = self.client.get_account_policy()
+ else:
+ reply = self.client.get_container_policy(container)
+ print_dict(reply)
+
+@command(api='storage')
class store_create(_store_account_command):
"""Create a container [or a directory object]"""
raw = kwargs.pop('raw', False)
success = kwargs.pop('success', 200)
directory = kwargs.pop('directory', False)
+ meta = kwargs.pop('meta', False)
data = kwargs.pop('data', None)
headers = kwargs.pop('headers', {})
if data:
headers.setdefault('Content-Length', str(len(data)))
+ if meta:
+ for key in meta.keys():
+ headers[key] = meta[key]
+
url = self.base_url + path
kwargs.setdefault('verify', False) # Disable certificate verification
r = requests.request(method, url, headers=headers, data=data, **kwargs)
def purge_container(self, container):
self.assert_account()
-
path = '/%s/%s' % (self.account, container)
- #params = {'until': int(time())}
- #self.delete(path, params=params, success=204)
- self.delete(path, success=204)
+ params = {'until': int(time())}
+ self.delete(path, params=params, success=204)
def put_block(self, data, hash):
path = '/%s/%s' % (self.account, self.container)
# or implied, of GRNET S.A.
from . import Client, ClientError
-
-def filter_dict_with_prefix(d, prefix):
- return {key:d[key] for key in d if key.startswith(prefix)}
+from .utils import filter_dict_with_prefix, prefix_keys
class StorageClient(Client):
"""OpenStack Object Storage API 1.0 client"""
def get_account_meta(self):
return filter_dict_with_prefix(self.get_account_info(), 'X-Account-Meta-')
+ def set_account_meta(self, metapairs):
+ self.assert_account()
+ path = '/%s' % self.account
+ meta = prefix_keys(metapairs, 'X-Account-Meta-')
+ self.post(path, meta=meta, success=202)
+
+ def get_account_policy(self):
+ return filter_dict_with_prefix(self.get_account_info(), 'X-Account-Policy-')
+
def create_container(self, container):
self.assert_account()
path = '/%s/%s' % (self.account, container)
def get_container_meta(self, container):
return filter_dict_with_prefix(self.get_container_info(container), 'X-Container-Meta-')
+ def get_container_policy(self, container):
+ return filter_dict_with_prefix(self.get_container_info(container), 'X-Container-Policy-')
+
def delete_container(self, container):
#Response codes
# Success 204
r = self.get(path, params = params, success = (200, 204))
return r.json
- """def create_object(self, object, f, size=None, hash_cb=None,
+ def create_object(self, object, f, size=None, hash_cb=None,
upload_cb=None):
# This is a naive implementation, it loads the whole file in memory
#Look in pithos for a nice implementation
path = '/%s/%s/%s' % (self.account, self.container, object)
data = f.read(size) if size is not None else f.read()
self.put(path, data=data, success=201)
- """
def create_directory(self, object):
self.assert_container()
def get_object_meta(self, object):
return filter_dict_with_prefix(self.get_object_info(object), 'X-Object-Meta-')
+
def get_object(self, object):
self.assert_container()
path = '/%s/%s/%s' % (self.account, self.container, object)
--- /dev/null
+# Copyright 2011-2012 GRNET S.A. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+# 1. Redistributions of source code must retain the above
+# copyright notice, this list of conditions and the following
+# disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials
+# provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# The views and conclusions contained in the software and
+# documentation are those of the authors and should not be
+# interpreted as representing official policies, either expressed
+# or implied, of GRNET S.A.
+
+def filter_dict_with_prefix(d, prefix):
+ """@return a dict that contains only the entries of d that are prefixed with prefic
+ """
+ return {key:d[key] for key in d if key.lower().startswith(prefix.lower())}
+
+def prefix_keys(d, prefix):
+ """@return a sallow copy of d with all its keys prefixed with prefix
+ """
+ return {prefix+key:d[key] for key in d.keys()}
+
s = ('%.1f' % size).rstrip('.0')
return s + unit
+def dict_from_args(*args):
+ return {args[i]:args[i+1] for i in range(0, len(args)/2)}
+