#!/usr/bin/env python
-# Copyright 2011 GRNET S.A. All rights reserved.
+# 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
from sys import argv, exit, stdin, stdout
from datetime import datetime
-from pithos.lib.client import Pithos_Client, Fault
-from pithos.lib.util import get_user, get_auth, get_server, get_api
-from pithos.lib.transfer import upload, download
+from pithos.tools.lib.client import Pithos_Client, Fault
+from pithos.tools.lib.util import get_user, get_auth, get_url
+from pithos.tools.lib.transfer import upload, download
import json
import logging
def __init__(self, name, argv):
parser = OptionParser('%%prog %s [options] %s' % (name, self.syntax))
- parser.add_option('--host', dest='host', metavar='HOST',
- default=get_server(), help='use server HOST')
- parser.add_option('--user', dest='user', metavar='USERNAME',
+ parser.add_option('--url', dest='url', metavar='URL',
+ default=get_url(), help='server URL (currently: %s)' % get_url())
+ parser.add_option('--user', dest='user', metavar='USER',
default=get_user(),
- help='use account USERNAME')
- parser.add_option('--token', dest='token', metavar='AUTH',
+ help='account USER (currently: %s)' % get_user())
+ parser.add_option('--token', dest='token', metavar='TOKEN',
default=get_auth(),
- help='use account AUTH')
- parser.add_option('--api', dest='api', metavar='API',
- default=get_api(), help='use api API')
+ help='account TOKEN (currently: %s)' % get_auth())
parser.add_option('-v', action='store_true', dest='verbose',
- default=False, help='use verbose output')
+ default=False, help='verbose output')
parser.add_option('-d', action='store_true', dest='debug',
- default=False, help='use debug output')
+ default=False, help='debug output')
self.add_options(parser)
options, args = parser.parse_args(argv)
val = getattr(options, key)
setattr(self, key, val)
- self.client = Pithos_Client(self.host, self.token, self.user, self.api, self.verbose,
+ self.client = Pithos_Client(self.url, self.token, self.user, self.verbose,
self.debug)
self.parser = parser
default=None, help='show metadata until that date')
parser.add_option('--format', action='store', dest='format',
default='%d/%m/%Y', help='format to parse until date')
+ parser.add_option('--shared', action='store_true', dest='shared',
+ default=False, help='show only shared')
+ parser.add_option('--public', action='store_true', dest='public',
+ default=False, help='show only public')
+
def execute(self, container=None):
if container:
def list_containers(self):
attrs = ['limit', 'marker', 'if_modified_since',
- 'if_unmodified_since']
+ 'if_unmodified_since', 'shared', 'public']
args = self._build_args(attrs)
args['format'] = 'json' if self.detail else 'text'
#prepate params
params = {}
attrs = ['limit', 'marker', 'prefix', 'delimiter', 'path',
- 'meta', 'if_modified_since', 'if_unmodified_since']
+ 'meta', 'if_modified_since', 'if_unmodified_since',
+ 'shared', 'public']
args = self._build_args(attrs)
args['format'] = 'json' if self.detail else 'text'
syntax = '<container> [key=val] [...]'
description = 'create a container'
+ def add_options(self, parser):
+ parser.add_option('--versioning', action='store', dest='versioning',
+ default=None, help='set container versioning (auto/none)')
+ parser.add_option('--quota', action='store', dest='quota',
+ default=None, help='set default container quota')
+
def execute(self, container, *args):
meta = {}
for arg in args:
key, sep, val = arg.partition('=')
meta[key] = val
- ret = self.client.create_container(container, **meta)
+ policy = {}
+ if getattr(self, 'versioning'):
+ policy['versioning'] = self.versioning
+ if getattr(self, 'quota'):
+ policy['quota'] = self.quota
+ ret = self.client.create_container(container, meta=meta, policies=policy)
if not ret:
print 'Container already exists'
default=None, help='remove history until that date')
parser.add_option('--format', action='store', dest='format',
default='%d/%m/%Y', help='format to parse until date')
+ parser.add_option('--delimiter', action='store', type='str',
+ dest='delimiter', default=None,
+ help='mass delete objects with path staring with <src object> + delimiter')
+ parser.add_option('-r', action='store_true',
+ dest='recursive', default=False,
+ help='mass delimiter objects with delimiter /')
def execute(self, path):
container, sep, object = path.partition('/')
until = int(_time.mktime(t))
if object:
- self.client.delete_object(container, object, until)
+ kwargs = {}
+ if self.delimiter:
+ kwargs['delimiter'] = self.delimiter
+ elif self.recursive:
+ kwargs['delimiter'] = '/'
+ self.client.delete_object(container, object, until, **kwargs)
else:
self.client.delete_container(container, until)
parser.add_option('--versionlist', action='store_true',
dest='versionlist', default=False,
help='get the full object version list')
+ parser.add_option('--hashmap', action='store_true',
+ dest='hashmap', default=False,
+ help='get the object hashmap instead')
def execute(self, path):
attrs = ['if_match', 'if_none_match', 'if_modified_since',
- 'if_unmodified_since']
+ 'if_unmodified_since', 'hashmap']
args = self._build_args(attrs)
args['format'] = 'json' if self.detail else 'text'
if self.range:
elif self.version:
data = self.client.retrieve_object_version(container, object,
self.version, **args)
+ elif self.hashmap:
+ if 'detail' in args.keys():
+ args.pop('detail')
+ args.pop('format')
+ self.detail = True
+ data = self.client.retrieve_object_hashmap(container, object, **args)
else:
data = self.client.retrieve_object(container, object, **args)
f = open(self.file, 'w') if self.file else stdout
- if self.detail:
+ if self.detail or type(data) == types.DictionaryType:
if self.versionlist:
print_versions(data, f=f)
else:
# help='use for large file support')
parser.add_option('--manifest', action='store',
dest='x_object_manifest', default=None,
- help='upload a manifestation file')
+ help='provide object parts prefix in <container>/<object> form')
parser.add_option('--content-type', action='store',
dest='content_type', default=None,
help='create object with specific content type')
meta=meta, **args)
elif self.use_hashes:
data = f.read()
- if data is object:
- hashmap = json.loads()
- self.client.create_object_by_hashmap(container, object, hashmap,
- meta=meta, **args)
- else:
- print "Expected object"
+ hashmap = json.loads(data)
+ self.client.create_object_by_hashmap(container, object, hashmap,
+ meta=meta, **args)
elif self.x_object_manifest:
self.client.create_manifestation(container, object, self.x_object_manifest)
elif not f:
parser.add_option('--content-type', action='store',
dest='content_type', default=None,
help='change object\'s content type')
+ parser.add_option('--delimiter', action='store', type='str',
+ dest='delimiter', default=None,
+ help='mass copy objects with path staring with <src object> + delimiter')
+ parser.add_option('-r', action='store_true',
+ dest='recursive', default=False,
+ help='mass copy with delimiter /')
def execute(self, src, dst, *args):
src_container, sep, src_object = src.partition('/')
dst_object = dst
args = {'content_type':self.content_type} if self.content_type else {}
+ if self.delimiter:
+ args['delimiter'] = self.delimiter
+ elif self.recursive:
+ args['delimiter'] = '/'
self.client.copy_object(src_container, src_object, dst_container,
dst_object, meta, self.public, self.version,
**args)
parser.add_option('--offset', action='store',
dest='offset',
default=None, help='starting offest to be updated')
- parser.add_option('--range', action='store', dest='content-range',
+ parser.add_option('--range', action='store', dest='content_range',
default=None, help='range of data to be updated')
parser.add_option('--chunked', action='store_true', dest='chunked',
default=False, help='set chunked transfer mode')
attrs = ['content_encoding', 'content_disposition', 'x_object_sharing',
- 'x_object_public', 'replace']
+ 'x_object_public', 'x_object_manifest', 'replace', 'offset',
+ 'content_range']
args = self._build_args(attrs)
if self.no_sharing:
parser.add_option('--content-type', action='store',
dest='content_type', default=None,
help='change object\'s content type')
+ parser.add_option('--delimiter', action='store', type='str',
+ dest='delimiter', default=None,
+ help='mass move objects with path staring with <src object> + delimiter')
+ parser.add_option('-r', action='store_true',
+ dest='recursive', default=False,
+ help='mass move objects with delimiter /')
def execute(self, src, dst, *args):
src_container, sep, src_object = src.partition('/')
meta[key] = val
args = {'content_type':self.content_type} if self.content_type else {}
+ if self.delimiter:
+ args['delimiter'] = self.delimiter
+ elif self.recursive:
+ args['delimiter'] = '/'
self.client.move_object(src_container, src_object, dst_container,
dst_object, meta, self.public, **args)