# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.command
-from kamaki.cli import command, set_api_description
-from kamaki.clients.utils import filter_in
-from kamaki.cli.errors import CLIError, raiseCLIError
-from kamaki.cli.utils import format_size, print_dict, pretty_keys, print_list
-set_api_description('store', 'Pithos+ storage commands')
+from kamaki.cli import command
+from kamaki.cli.command_tree import CommandTree
+from kamaki.cli.errors import raiseCLIError, CLISyntaxError
+from kamaki.cli.utils import format_size, print_dict, pretty_keys
+from kamaki.cli.argument import FlagArgument, ValueArgument, IntArgument
+from kamaki.cli.argument import KeyValueArgument
+from kamaki.cli.argument import ProgressBarArgument
+from kamaki.cli.commands import _command_init
from kamaki.clients.pithos import PithosClient, ClientError
-from colors import bold
-from sys import stdout, exit
-import signal
+from kamaki.cli.utils import bold
+from sys import stdout
from time import localtime, strftime
+from datetime import datetime as dtm
-from progress.bar import IncrementalBar
+pithos_cmds = CommandTree('store', 'Pithos+ storage commands')
+_commands = [pithos_cmds]
-class ProgressBar(IncrementalBar):
- #suffix = '%(percent)d%% - %(eta)ds'
- suffix = '%(percent)d%%'
-class _pithos_init(object):
+# Argument functionality
+
+
+class DelimiterArgument(ValueArgument):
+ """
+ :value type: string
+ :value returns: given string or /
+ """
+
+ def __init__(self, caller_obj, help='', parsed_name=None, default=None):
+ super(DelimiterArgument, self).__init__(help, parsed_name, default)
+ self.caller_obj = caller_obj
+
+ @property
+ def value(self):
+ if self.caller_obj.get_argument('recursive'):
+ return '/'
+ return getattr(self, '_value', self.default)
+
+ @value.setter
+ def value(self, newvalue):
+ self._value = newvalue
+
+
+class SharingArgument(ValueArgument):
+ """Set sharing (read and/or write) groups
+
+ :value type: "read=term1,term2,... write=term1,term2,..."
+
+ :value returns: {'read':['term1', 'term2', ...],
+ 'write':['term1', 'term2', ...]}
+ """
+
+ @property
+ def value(self):
+ return getattr(self, '_value', self.default)
+
+ @value.setter
+ def value(self, newvalue):
+ perms = {}
+ try:
+ permlist = newvalue.split(' ')
+ except AttributeError:
+ return
+ for p in permlist:
+ try:
+ (key, val) = p.split('=')
+ except ValueError as err:
+ raiseCLIError(err, 'Error in --sharing',
+ details='Incorrect format',
+ importance=1)
+ if key.lower() not in ('read', 'write'):
+ raiseCLIError(err, 'Error in --sharing',
+ details='Invalid permission key %s' % key,
+ importance=1)
+ val_list = val.split(',')
+ if not key in perms:
+ perms[key] = []
+ for item in val_list:
+ if item not in perms[key]:
+ perms[key].append(item)
+ self._value = perms
+
+
+class RangeArgument(ValueArgument):
+ """
+ :value type: string of the form <start>-<end>
+ where <start> and <end> are integers
+
+ :value returns: the input string, after type checking <start> and <end>
+ """
+
+ @property
+ def value(self):
+ return getattr(self, '_value', self.default)
+
+ @value.setter
+ def value(self, newvalue):
+ if newvalue is None:
+ self._value = self.default
+ return
+ (start, end) = newvalue.split('-')
+ (start, end) = (int(start), int(end))
+ self._value = '%s-%s' % (start, end)
+
+
+class DateArgument(ValueArgument):
+ """
+ :value type: a string formated in an acceptable date format
+
+ :value returns: same date in first of DATE_FORMATS
+ """
+
+ DATE_FORMATS = ["%a %b %d %H:%M:%S %Y",
+ "%A, %d-%b-%y %H:%M:%S GMT",
+ "%a, %d %b %Y %H:%M:%S GMT"]
+
+ INPUT_FORMATS = DATE_FORMATS + ["%d-%m-%Y", "%H:%M:%S %d-%m-%Y"]
+
+ @property
+ def value(self):
+ return getattr(self, '_value', self.default)
+
+ @value.setter
+ def value(self, newvalue):
+ if newvalue is None:
+ return
+ self._value = self.format_date(newvalue)
+
+ def format_date(self, datestr):
+ for format in self.INPUT_FORMATS:
+ try:
+ t = dtm.strptime(datestr, format)
+ except ValueError:
+ continue
+ self._value = t.strftime(self.DATE_FORMATS[0])
+ return
+ raiseCLIError(None,
+ 'Date Argument Error',
+ details='%s not a valid date. correct formats:\n\t%s'\
+ % (datestr, self.INPUT_FORMATS))
+
+
+# Command specs
+
+
+class _pithos_init(_command_init):
+ """Initialize a pithos+ kamaki client"""
+
def main(self):
- self.token = self.config.get('store', 'token') or self.config.get('global', 'token')
- self.base_url = self.config.get('store', 'url') or self.config.get('global', 'url')
- self.account = self.config.get('store', 'account') or self.config.get('global', 'account')
- self.container = self.config.get('store', 'container') or self.config.get('global', 'container')
- self.client = PithosClient(base_url=self.base_url, token=self.token, account=self.account,
+ self.token = self.config.get('store', 'token')\
+ or self.config.get('global', 'token')
+ self.base_url = self.config.get('store', 'url')\
+ or self.config.get('global', 'url')
+ self.account = self.config.get('store', 'account')\
+ or self.config.get('global', 'account')
+ self.container = self.config.get('store', 'container')\
+ or self.config.get('global', 'container')
+ self.client = PithosClient(base_url=self.base_url,
+ token=self.token,
+ account=self.account,
container=self.container)
+
class _store_account_command(_pithos_init):
"""Base class for account level storage commands"""
- def update_parser(self, parser):
- parser.add_argument('--account', dest='account', metavar='NAME',
- help="Specify an account to use")
-
- def progress(self, message):
- """Return a generator function to be used for progress tracking"""
-
- MESSAGE_LENGTH = 25
+ def __init__(self, arguments={}):
+ super(_store_account_command, self).__init__(arguments)
+ self.arguments['account'] =\
+ ValueArgument('Specify the account', '--account')
- def progress_gen(n):
- msg = message.ljust(MESSAGE_LENGTH)
- for i in ProgressBar(msg).iter(range(n)):
- yield
- yield
-
- return progress_gen
+ def generator(self, message):
+ return None
def main(self):
super(_store_account_command, self).main()
- if hasattr(self.args, 'account') and self.args.account is not None:
- self.client.account = self.args.account
+ if self.arguments['account'].value is not None:
+ self.client.account = self.arguments['account'].value
+
class _store_container_command(_store_account_command):
"""Base class for container level storage commands"""
- def __init__(self):
+ def __init__(self, arguments={}):
+ super(_store_container_command, self).__init__(arguments)
+ self.arguments['container'] =\
+ ValueArgument('Specify the container name', '--container')
self.container = None
self.path = None
- def update_parser(self, parser):
- super(_store_container_command, self).update_parser(parser)
- parser.add_argument('--container', dest='container', metavar='NAME', default=None,
- help="Specify a container to use")
-
- def extract_container_and_path(self, container_with_path, path_is_optional=True):
- assert isinstance(container_with_path, str)
- if ':' not in container_with_path:
- if hasattr(self.args, 'container'):
- self.container = getattr(self.args, 'container')
- else:
- self.container = self.client.container
- if self.container is None:
- self.container = container_with_path
- else:
- self.path = container_with_path
- if not path_is_optional and self.path is None:
- raise CLIError(message="Object path is missing", status=11)
- return
- cnp = container_with_path.split(':')
- self.container = cnp[0]
+ def extract_container_and_path(self,
+ container_with_path,
+ path_is_optional=True):
try:
- self.path = cnp[1]
- except IndexError:
- if path_is_optional:
+ assert isinstance(container_with_path, str)
+ except AssertionError as err:
+ raiseCLIError(err)
+
+ cont, sep, path = container_with_path.partition(':')
+
+ if sep:
+ if not cont:
+ raiseCLIError(None, 'Container is missing\n', importance=1)
+ alt_cont = self.get_argument('container')
+ if alt_cont and cont != alt_cont:
+ raiseCLIError(None,
+ 'Conflict: 2 containers (%s, %s)' % (cont, alt_cont),
+ importance=1)
+ self.container = cont
+ if not path:
+ raiseCLIError(None,
+ 'Path is missing for object in container %s' % cont,
+ importance=1,
+ details='Usage: <container>:<object path>')
+ self.path = path
+ else:
+ alt_cont = self.get_argument('container') or self.client.container
+ if alt_cont:
+ self.container = alt_cont
+ self.path = cont
+ elif path_is_optional:
+ self.container = cont
self.path = None
else:
- raise CLIError(message="Object path is missing", status=11)
+ self.container = cont
+ raiseCLIError(CLISyntaxError(
+ 'Syntax error: container and path are both required',
+ importance=1,
+ details='Usage: <container>:<object path>'))
def main(self, container_with_path=None, path_is_optional=True):
super(_store_container_command, self).main()
if container_with_path is not None:
- self.extract_container_and_path(container_with_path, path_is_optional)
+ self.extract_container_and_path(container_with_path,
+ path_is_optional)
self.client.container = self.container
- elif hasattr(self.args, 'container'):
- self.client.container = getattr(self.args,'container')
+ elif self.get_argument('container') is not None:
+ self.client.container = self.get_argument('container')
self.container = self.client.container
-"""
-@command()
-class store_test(_store_container_command):
- ""Test stuff""
- def main(self):
- super(self.__class__, self).main('pithos')
- r = self.client.container_get()
- print(unicode(r.content)+' '+unicode(r.json))
-"""
-
-@command()
+@command(pithos_cmds)
class store_list(_store_container_command):
"""List containers, object trees or objects in a directory
"""
- def update_parser(self, parser):
- super(self.__class__, self).update_parser(parser)
- parser.add_argument('-l', action='store_true', dest='detail', default=False,
- help='show detailed output')
- parser.add_argument('-N', action='store', dest='show_size', default=1000,
- help='print output in chunks of size N')
- parser.add_argument('-n', action='store', dest='limit', default=None,
- help='show limited output')
- parser.add_argument('--marker', action='store', dest='marker', default=None,
- help='show output greater then marker')
- parser.add_argument('--prefix', action='store', dest='prefix', default=None,
- help='show output starting with prefix')
- parser.add_argument('--delimiter', action='store', dest='delimiter', default=None,
- help='show output up to the delimiter')
- parser.add_argument('--path', action='store', dest='path', default=None,
- help='show output starting with prefix up to /')
- parser.add_argument('--meta', action='store', dest='meta', default=None,
- help='show output having the specified meta keys (e.g. --meta "meta1 meta2 ..."')
- parser.add_argument('--if-modified-since', action='store', dest='if_modified_since',
- default=None, help='show output if modified since then')
- parser.add_argument('--if-unmodified-since', action='store', dest='if_unmodified_since',
- default=None, help='show output if not modified since then')
- parser.add_argument('--until', action='store', dest='until', default=None,
- help='show metadata until that date')
- dateformat = '%d/%m/%Y %H:%M:%S'
- parser.add_argument('--format', action='store', dest='format', default=dateformat,
- help='format to parse until date (default: d/m/Y H:M:S)')
- parser.add_argument('--shared', action='store_true', dest='shared', default=False,
- help='show only shared')
- parser.add_argument('--public', action='store_true', dest='public', default=False,
- help='show only public')
+ def __init__(self, arguments={}):
+ super(store_list, self).__init__(arguments)
+ self.arguments['detail'] = FlagArgument('show detailed output', '-l')
+ self.arguments['show_size'] =\
+ ValueArgument('print output in chunks of size N', '-N')
+ self.arguments['limit'] = IntArgument('show limited output', '-n')
+ self.arguments['marker'] =\
+ ValueArgument('show output greater that marker', '--marker')
+ self.arguments['prefix'] =\
+ ValueArgument('show output staritng with prefix', '--prefix')
+ self.arguments['delimiter'] =\
+ ValueArgument('show output up to delimiter', '--delimiter')
+ self.arguments['path'] =\
+ ValueArgument('show output starting with prefix up to /', '--path')
+ self.arguments['meta'] =\
+ ValueArgument('show output haviung the specified meta keys',
+ '--meta', default=[])
+ self.arguments['if_modified_since'] =\
+ ValueArgument('show output modified since then',
+ '--if-modified-since')
+ self.arguments['if_unmodified_since'] =\
+ ValueArgument('show output not modified since then',
+ '--if-unmodified-since')
+ self.arguments['until'] =\
+ DateArgument('show metadata until then', '--until')
+ self.arguments['format'] =\
+ ValueArgument('format to parse until data (default: d/m/Y H:M:S',
+ '--format')
+ self.arguments['shared'] = FlagArgument('show only shared', '--shared')
+ self.arguments['public'] = FlagArgument('show only public', '--public')
def print_objects(self, object_list):
import sys
try:
- limit = getattr(self.args, 'show_size')
+ limit = self.get_argument('show_size')
limit = int(limit)
- except AttributeError:
- pass
+ except (AttributeError, TypeError):
+ limit = len(object_list) + 1
#index = 0
- for index,obj in enumerate(object_list):
- if not obj.has_key('content_type'):
+ for index, obj in enumerate(object_list):
+ if 'content_type' not in obj:
continue
pretty_obj = obj.copy()
index += 1
- empty_space = ' '*(len(str(len(object_list))) - len(str(index)))
+ empty_space = ' ' * (len(str(len(object_list))) - len(str(index)))
if obj['content_type'] == 'application/directory':
isDir = True
size = 'D'
else:
isDir = False
size = format_size(obj['bytes'])
- pretty_obj['bytes'] = '%s (%s)'%(obj['bytes'],size)
+ pretty_obj['bytes'] = '%s (%s)' % (obj['bytes'], size)
oname = bold(obj['name'])
- if getattr(self.args, 'detail'):
- print('%s%s. %s'%(empty_space, index, oname))
+ if self.get_argument('detail'):
+ print('%s%s. %s' % (empty_space, index, oname))
print_dict(pretty_keys(pretty_obj), exclude=('name'))
print
else:
- oname = '%s%s. %6s %s'%(empty_space, index, size, oname)
+ oname = '%s%s. %6s %s' % (empty_space, index, size, oname)
oname += '/' if isDir else ''
print(oname)
- if limit <= index < len(object_list) and index%limit == 0:
+ if limit <= index < len(object_list) and index % limit == 0:
print('(press "enter" to continue)')
sys.stdin.read(1)
def print_containers(self, container_list):
import sys
try:
- limit = getattr(self.args, 'show_size')
+ limit = self.get_argument('show_size')
limit = int(limit)
- except AttributeError:
- pass
- for index,container in enumerate(container_list):
- if container.has_key('bytes'):
- size = format_size(container['bytes'])
- cname = '%s. %s'%(index+1, bold(container['name']))
- if getattr(self.args, 'detail'):
+ except (AttributeError, TypeError):
+ limit = len(container_list) + 1
+ for index, container in enumerate(container_list):
+ if 'bytes' in container:
+ size = format_size(container['bytes'])
+ cname = '%s. %s' % (index + 1, bold(container['name']))
+ if self.get_argument('detail'):
print(cname)
pretty_c = container.copy()
- if container.has_key('bytes'):
- pretty_c['bytes'] = '%s (%s)'%(container['bytes'], size)
+ if 'bytes' in container:
+ pretty_c['bytes'] = '%s (%s)' % (container['bytes'], size)
print_dict(pretty_keys(pretty_c), exclude=('name'))
print
else:
- if container.has_key('count') and container.has_key('bytes'):
- print('%s (%s, %s objects)' % (cname, size, container['count']))
+ if 'count' in container and 'bytes' in container:
+ print('%s (%s, %s objects)'\
+ % (cname, size, container['count']))
else:
print(cname)
- if limit <= index < len(container_list) and index%limit == 0:
+ if limit <= index < len(container_list) and index % limit == 0:
print('(press "enter" to continue)')
sys.stdin.read(1)
- def getuntil(self, orelse=None):
- if hasattr(self.args, 'until'):
- import time
- until = getattr(self.args, 'until')
- if until is None:
- return None
- format = getattr(self.args, 'format')
- #except TypeError:
- try:
- t = time.strptime(until, format)
- except ValueError as err:
- raise CLIError(message='in --until: '+unicode(err), importance=1)
- return int(time.mktime(t))
- return orelse
-
- def getmeta(self, orelse=[]):
- if hasattr(self.args, 'meta'):
- meta = getattr(self.args, 'meta')
- if meta is None:
- return []
- return meta.split(' ')
- return orelse
-
- def getpath(self, orelse=None):
- if self.path is not None:
- return self.path
- if hasattr(self.args, 'path'):
- return getattr(self.args, 'path')
- return orelse
-
def main(self, container____path__=None):
super(self.__class__, self).main(container____path__)
try:
if self.container is None:
- r = self.client.account_get(limit=getattr(self.args, 'limit', None),
- marker=getattr(self.args, 'marker', None),
- if_modified_since=getattr(self.args, 'if_modified_since', None),
- if_unmodified_since=getattr(self.args, 'if_unmodified_since', None),
- until=self.getuntil(),
- show_only_shared=getattr(self.args, 'shared', False))
+ r = self.client.account_get(limit=self.get_argument('limit'),
+ marker=self.get_argument('marker'),
+ if_modified_since=self.get_argument('if_modified_since'),
+ if_unmodified_since=self.get_argument(\
+ 'if_unmodified_since'),
+ until=self.get_argument('until'),
+ show_only_shared=self.get_argument('shared'))
self.print_containers(r.json)
else:
- r = self.client.container_get(limit=getattr(self.args, 'limit', None),
- marker=getattr(self.args, 'marker', None),
- prefix=getattr(self.args, 'prefix', None),
- delimiter=getattr(self.args, 'delimiter', None), path=self.getpath(orelse=None),
- if_modified_since=getattr(self.args, 'if_modified_since', None),
- if_unmodified_since=getattr(self.args, 'if_unmodified_since', None),
- until=self.getuntil(),
- meta=self.getmeta(),
- show_only_shared=getattr(self.args, 'shared', False))
+ r = self.client.container_get(limit=self.get_argument('limit'),
+ marker=self.get_argument('marker'),
+ prefix=self.get_argument('prefix'),
+ delimiter=self.get_argument('delimiter'),
+ path=self.get_argument('path'),
+ if_modified_since=self.get_argument('if_modified_since'),
+ if_unmodified_since=self.get_argument(\
+ 'if_unmodified_since'),
+ until=self.get_argument('until'),
+ meta=self.get_argument('meta'),
+ show_only_shared=self.get_argument('shared'))
self.print_objects(r.json)
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_mkdir(_store_container_command):
"""Create a directory"""
def main(self, container___directory):
- super(self.__class__, self).main(container___directory, path_is_optional=False)
+ super(self.__class__,
+ self).main(container___directory, path_is_optional=False)
try:
self.client.create_directory(self.path)
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_create(_store_container_command):
"""Create a container or a directory object"""
- def update_parser(self, parser):
- super(self.__class__, self).update_parser(parser)
- parser.add_argument('--versioning', action='store', dest='versioning', default=None,
- help='set container versioning (auto/none)')
- parser.add_argument('--quota', action='store', dest='quota', default=None,
- help='set default container quota')
- parser.add_argument('--meta', action='store', dest='meta', default=None,
- help='set container metadata ("key1:val1 key2:val2 ...")')
-
- def getmeta(self, orelse=None):
- try:
- meta = getattr(self.args,'meta')
- metalist = meta.split(' ')
- except AttributeError:
- return orelse
- metadict = {}
- for metastr in metalist:
- (key,val) = metastr.split(':')
- metadict[key] = val
- return metadict
+ def __init__(self, arguments={}):
+ super(self.__class__, self).__init__(arguments)
+ self.arguments['versioning'] = \
+ ValueArgument('set container versioning (auto/none)',
+ '--versioning')
+ self.arguments['quota'] =\
+ IntArgument('set default container quota', '--quota')
+ self.arguments['meta'] =\
+ KeyValueArgument(
+ 'set container metadata (can be repeated)', '--meta')
+ # MetaArgument('set container metadata', '--meta')
def main(self, container____directory__):
super(self.__class__, self).main(container____directory__)
try:
if self.path is None:
- self.client.container_put(quota=getattr(self.args, 'quota'),
- versioning=getattr(self.args, 'versioning'), metadata=self.getmeta())
+ self.client.container_put(quota=self.get_argument('quota'),
+ versioning=self.get_argument('versioning'),
+ metadata=self.get_argument('meta'))
else:
self.client.create_directory(self.path)
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_copy(_store_container_command):
"""Copy an object"""
- def update_parser(self, parser):
- super(store_copy, self).update_parser(parser)
- parser.add_argument('--source-version', action='store', dest='source_version', default=None,
- help='copy specific version')
- parser.add_argument('--public', action='store_true', dest='public', default=False,
- help='make object publicly accessible')
- parser.add_argument('--content-type', action='store', dest='content_type', default=None,
- help='change object\'s content type')
- parser.add_argument('--delimiter', action='store', dest='delimiter', default=None,
- help=u'mass copy objects with path staring with src_object + delimiter')
- parser.add_argument('-r', action='store_true', dest='recursive', default=False,
- help='mass copy with delimiter /')
-
- def getdelimiter(self):
- if getattr(self.args, 'recursive'):
- return '/'
- return getattr(self.args, 'delimiter')
+ def __init__(self, arguments={}):
+ super(self.__class__, self).__init__(arguments)
+ self.arguments['source_version'] = ValueArgument(\
+ 'copy specific version', '--source-version')
+ self.arguments['public'] = ValueArgument(\
+ 'make object publicly accessible', '--public')
+ self.arguments['content_type'] = ValueArgument(\
+ 'change object\'s content type', '--content-type')
+ self.arguments['delimiter'] = DelimiterArgument(self,
+ parsed_name='--delimiter',
+ help=u'copy objects prefixed as src_object + delimiter')
+ self.arguments['recursive'] = FlagArgument(
+ 'mass copy with delimiter /', ('-r', '--recursive'))
def main(self, source_container___path, destination_container____path__):
- super(self.__class__, self).main(source_container___path, path_is_optional=False)
+ super(self.__class__,
+ self).main(source_container___path, path_is_optional=False)
try:
dst = destination_container____path__.split(':')
dst_cont = dst[0]
dst_path = dst[1] if len(dst) > 1 else False
- self.client.copy_object(src_container = self.container, src_object = self.path,
- dst_container = dst_cont, dst_object = dst_path,
- source_version=getattr(self.args, 'source_version'),
- public=getattr(self.args, 'public'),
- content_type=getattr(self.args,'content_type'), delimiter=self.getdelimiter())
+ self.client.copy_object(src_container=self.container,
+ src_object=self.path,
+ dst_container=dst_cont,
+ dst_object=dst_path,
+ source_version=self.get_argument('source_version'),
+ public=self.get_argument('public'),
+ content_type=self.get_argument('content_type'),
+ delimiter=self.get_argument('delimiter'))
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_move(_store_container_command):
"""Copy an object"""
- def update_parser(self, parser):
- super(store_move, self).update_parser(parser)
- parser.add_argument('--source-version', action='store', dest='source_version', default=None,
- help='copy specific version')
- parser.add_argument('--public', action='store_true', dest='public', default=False,
- help='make object publicly accessible')
- parser.add_argument('--content-type', action='store', dest='content_type', default=None,
- help='change object\'s content type')
- parser.add_argument('--delimiter', action='store', dest='delimiter', default=None,
- help=u'mass copy objects with path staring with src_object + delimiter')
- parser.add_argument('-r', action='store_true', dest='recursive', default=False,
- help='mass copy with delimiter /')
-
- def getdelimiter(self):
- if getattr(self.args, 'recursive'):
- return '/'
- return getattr(self.args, 'delimiter')
+ def __init__(self, arguments={}):
+ super(self.__class__, self).__init__(arguments)
+
+ self.arguments['source_version'] = ValueArgument(\
+ 'copy specific version', '--source-version')
+ self.arguments['public'] = FlagArgument(\
+ 'make object publicly accessible', '--public')
+ self.arguments['content_type'] = ValueArgument(\
+ 'change object\'s content type', '--content-type')
+ self.arguments['delimiter'] = DelimiterArgument(self,
+ parsed_name='--delimiter',
+ help='move objects prefixed as src_object + delimiter')
+ self.arguments['recursive'] = FlagArgument(\
+ 'copy with delimiter /', ('-r', '--recursive'))
def main(self, source_container___path, destination_container____path__):
- super(self.__class__, self).main(source_container___path, path_is_optional=False)
+ super(self.__class__,
+ self).main(source_container___path, path_is_optional=False)
try:
dst = destination_container____path__.split(':')
dst_cont = dst[0]
dst_path = dst[1] if len(dst) > 1 else False
- self.client.move_object(src_container = self.container, src_object = self.path,
- dst_container = dst_cont, dst_object = dst_path,
- source_version=getattr(self.args, 'source_version'),
- public=getattr(self.args, 'public'),
- content_type=getattr(self.args,'content_type'), delimiter=self.getdelimiter())
+ self.client.move_object(src_container=self.container,
+ src_object=self.path,
+ dst_container=dst_cont,
+ dst_object=dst_path,
+ source_version=self.get_argument('source_version'),
+ public=self.get_argument('public'),
+ content_type=self.get_argument('content_type'),
+ delimiter=self.get_argument('delimiter'))
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_append(_store_container_command):
"""Append local file to (existing) remote object"""
+ def __init__(self, arguments={}):
+ super(self.__class__, self).__init__(arguments)
+ self.arguments['progress_bar'] = ProgressBarArgument(\
+ 'do not show progress bar', '--no-progress-bar', False)
+
def main(self, local_path, container___path):
- super(self.__class__, self).main(container___path, path_is_optional=False)
+ super(self.__class__,
+ self).main(container___path, path_is_optional=False)
try:
- f = open(local_path, 'r')
- upload_cb = self.progress('Appending blocks')
- self.client.append_object(object=self.path, source_file = f, upload_cb = upload_cb)
+ f = open(local_path, 'rb')
+ progress_bar = self.arguments['progress_bar']
+ try:
+ upload_cb = progress_bar.get_generator('Appending blocks')
+ except Exception:
+ upload_cb = None
+ self.client.append_object(object=self.path,
+ source_file=f,
+ upload_cb=upload_cb)
except ClientError as err:
+ progress_bar.finish()
raiseCLIError(err)
+ finally:
+ progress_bar.finish()
+
-@command()
+@command(pithos_cmds)
class store_truncate(_store_container_command):
"""Truncate remote file up to a size"""
-
def main(self, container___path, size=0):
- super(self.__class__, self).main(container___path, path_is_optional=False)
+ super(self.__class__,
+ self).main(container___path, path_is_optional=False)
try:
self.client.truncate_object(self.path, size)
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_overwrite(_store_container_command):
"""Overwrite part (from start to end) of a remote file"""
+ def __init__(self, arguments={}):
+ super(self.__class__, self).__init__(arguments)
+ self.arguments['progress_bar'] = ProgressBarArgument(\
+ 'do not show progress bar', '--no-progress-bar', False)
+
def main(self, local_path, container___path, start, end):
- super(self.__class__, self).main(container___path, path_is_optional=False)
+ super(self.__class__,
+ self).main(container___path, path_is_optional=False)
try:
- f = open(local_path, 'r')
- upload_cb = self.progress('Overwritting blocks')
- self.client.overwrite_object(object=self.path, start=start, end=end,
- source_file=f, upload_cb = upload_cb)
+ f = open(local_path, 'rb')
+ progress_bar = self.arguments['progress_bar']
+ try:
+ upload_cb = progress_bar.get_generator('Overwritting blocks')
+ except Exception:
+ upload_cb = None
+ self.client.overwrite_object(object=self.path,
+ start=start,
+ end=end,
+ source_file=f,
+ upload_cb=upload_cb)
except ClientError as err:
+ progress_bar.finish()
raiseCLIError(err)
+ finally:
+ progress_bar.finish()
+
-@command()
+@command(pithos_cmds)
class store_manifest(_store_container_command):
"""Create a remote file with uploaded parts by manifestation"""
- def update_parser(self, parser):
- super(self.__class__, self).update_parser(parser)
- parser.add_argument('--etag', action='store', dest='etag', default=None,
- help='check written data')
- parser.add_argument('--content-encoding', action='store', dest='content_encoding',
- default=None, help='provide the object MIME content type')
- parser.add_argument('--content-disposition', action='store', dest='content_disposition',
- default=None, help='provide the presentation style of the object')
- parser.add_argument('--content-type', action='store', dest='content_type', default=None,
- help='create object with specific content type')
- parser.add_argument('--sharing', action='store', dest='sharing', default=None,
- help='define sharing object policy ( "read=user1,grp1,user2,... write=user1,grp2,...')
- parser.add_argument('--public', action='store_true', dest='public', default=False,
- help='make object publicly accessible')
-
- def getsharing(self, orelse={}):
- permstr = getattr(self.args, 'sharing')
- if permstr is None:
- return orelse
- perms = {}
- for p in permstr.split(' '):
- (key, val) = p.split('=')
- if key.lower() not in ('read', 'write'):
- raise CLIError(message='in --sharing: Invalid permition key', importance=1)
- val_list = val.split(',')
- if not perms.has_key(key):
- perms[key]=[]
- for item in val_list:
- if item not in perms[key]:
- perms[key].append(item)
- return perms
-
+ def __init__(self, arguments={}):
+ super(self.__class__, self).__init__(arguments)
+ self.arguments['etag'] = ValueArgument('check written data', '--etag')
+ self.arguments['content_encoding'] = ValueArgument(\
+ 'provide the object MIME content type', '--content-encoding')
+ self.arguments['content_disposition'] = ValueArgument(\
+ 'provide the presentation style of the object',
+ '--content-disposition')
+ self.arguments['content_type'] = ValueArgument(\
+ 'create object with specific content type', '--content-type')
+ self.arguments['sharing'] = SharingArgument(parsed_name='--sharing',
+ help='define object sharing policy ' +\
+ '( "read=user1,grp1,user2,... write=user1,grp2,..." )')
+ self.arguments['public'] = FlagArgument(\
+ 'make object publicly accessible', '--public')
+
def main(self, container___path):
- super(self.__class__, self).main(container___path, path_is_optional=False)
+ super(self.__class__,
+ self).main(container___path, path_is_optional=False)
try:
self.client.create_object_by_manifestation(self.path,
- content_encoding=getattr(self.args, 'content_encoding'),
- content_disposition=getattr(self.args, 'content_disposition'),
- content_type=getattr(self.args, 'content_type'), sharing=self.getsharing(),
- public=getattr(self.args, 'public'))
+ content_encoding=self.get_argument('content_encoding'),
+ content_disposition=self.get_argument('content_disposition'),
+ content_type=self.get_argument('content_type'),
+ sharing=self.get_argument('sharing'),
+ public=self.get_argument('public'))
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_upload(_store_container_command):
"""Upload a file"""
- def update_parser(self, parser):
- super(self.__class__, self).update_parser(parser)
- parser.add_argument('--use_hashes', action='store_true', dest='use_hashes', default=False,
- help='provide hashmap file instead of data')
- parser.add_argument('--unchunked', action='store_true', dest='unchunked', default=False,
- help='avoid chunked transfer mode')
- parser.add_argument('--etag', action='store', dest='etag', default=None,
- help='check written data')
- parser.add_argument('--content-encoding', action='store', dest='content_encoding',
- default=None, help='provide the object MIME content type')
- parser.add_argument('--content-disposition', action='store', dest='content_disposition',
- default=None, help='provide the presentation style of the object')
- parser.add_argument('--content-type', action='store', dest='content_type', default=None,
- help='create object with specific content type')
- parser.add_argument('--sharing', action='store', dest='sharing', default=None,
- help='define sharing object policy ( "read=user1,grp1,user2,... write=user1,grp2,...')
- parser.add_argument('--public', action='store_true', dest='public', default=False,
- help='make object publicly accessible')
- parser.add_argument('--with-pool-size', action='store', dest='poolsize', default=None,
- help='Set the greenlet pool size (advanced)')
-
- def getsharing(self, orelse={}):
- permstr = getattr(self.args, 'sharing')
- if permstr is None:
- return orelse
- perms = {}
- for p in permstr.split(' '):
- (key, val) = p.split('=')
- if key.lower() not in ('read', 'write'):
- raise CLIError(message='in --sharing: Invalid permition key', importance=1)
- val_list = val.split(',')
- if not perms.has_key(key):
- perms[key]=[]
- for item in val_list:
- if item not in perms[key]:
- perms[key].append(item)
- return perms
+ def __init__(self, arguments={}):
+ super(self.__class__, self).__init__(arguments)
+ self.arguments['use_hashes'] = FlagArgument(\
+ 'provide hashmap file instead of data', '--use-hashes')
+ self.arguments['etag'] = ValueArgument('check written data', '--etag')
+ self.arguments['unchunked'] = FlagArgument(\
+ 'avoid chunked transfer mode', '--unchunked')
+ self.arguments['content_encoding'] = ValueArgument(\
+ 'provide the object MIME content type', '--content-encoding')
+ self.arguments['content_disposition'] = ValueArgument(\
+ 'provide the presentation style of the object',
+ '--content-disposition')
+ self.arguments['content_type'] = ValueArgument(\
+ 'create object with specific content type', '--content-type')
+ self.arguments['sharing'] = SharingArgument(parsed_name='--sharing',
+ help='define sharing object policy ' +\
+ '( "read=user1,grp1,user2,... write=user1,grp2,...')
+ self.arguments['public'] = FlagArgument(\
+ 'make object publicly accessible', '--public')
+ self.arguments['poolsize'] = IntArgument(\
+ 'set pool size', '--with-pool-size')
+ self.arguments['progress_bar'] = ProgressBarArgument(\
+ 'do not show progress bar', '--no-progress-bar', False)
def main(self, local_path, container____path__):
super(self.__class__, self).main(container____path__)
remote_path = local_path if self.path is None else self.path
- poolsize = getattr(self.args, 'poolsize')
+ poolsize = self.get_argument('poolsize')
if poolsize is not None:
- self.POOL_SIZE = int(poolsize)
+ self.client.POOL_SIZE = int(poolsize)
+ params = dict(content_encoding=self.get_argument('content_encoding'),
+ content_type=self.get_argument('content_type'),
+ content_disposition=self.get_argument('content_disposition'),
+ sharing=self.get_argument('sharing'),
+ public=self.get_argument('public'))
try:
- with open(local_path) as f:
- if getattr(self.args, 'unchunked'):
+ progress_bar = self.arguments['progress_bar']
+ hash_bar = progress_bar.clone()
+ with open(local_path, 'rb') as f:
+ if self.get_argument('unchunked'):
self.client.upload_object_unchunked(remote_path, f,
- etag=getattr(self.args, 'etag'), withHashFile=getattr(self.args, 'use_hashes'),
- content_encoding=getattr(self.args, 'content_encoding'),
- content_disposition=getattr(self.args, 'content_disposition'),
- content_type=getattr(self.args, 'content_type'), sharing=self.getsharing(),
- public=getattr(self.args, 'public'))
+ etag=self.get_argument('etag'),
+ withHashFile=self.get_argument('use_hashes'),
+ **params)
else:
- hash_cb = self.progress('Calculating block hashes')
- upload_cb = self.progress('Uploading blocks')
- self.client.upload_object(remote_path, f, hash_cb=hash_cb, upload_cb=upload_cb,
- content_encoding=getattr(self.args, 'content_encoding'),
- content_disposition=getattr(self.args, 'content_disposition'),
- content_type=getattr(self.args, 'content_type'), sharing=self.getsharing(),
- public=getattr(self.args, 'public'))
+ hash_cb = hash_bar.get_generator(\
+ 'Calculating block hashes')
+ upload_cb = progress_bar.get_generator('Uploading')
+ self.client.upload_object(remote_path, f,
+ hash_cb=hash_cb,
+ upload_cb=upload_cb,
+ **params)
+ progress_bar.finish()
+ hash_bar.finish()
except ClientError as err:
- raiseCLIError(err)
+ progress_bar.finish()
+ hash_bar.finish()
+ raiseCLIError(err, '"%s" not accessible' % container____path__)
+ except IOError as err:
+ progress_bar.finish()
+ hash_bar.finish()
+ raiseCLIError(err, 'Failed to read form file %s' % local_path, 2)
print 'Upload completed'
-@command()
+
+@command(pithos_cmds)
+class store_cat(_store_container_command):
+ """Print a file to console"""
+
+ def __init__(self, arguments={}):
+ super(self.__class__, self).__init__(arguments)
+ self.arguments['range'] =\
+ RangeArgument('show range of data', '--range')
+ self.arguments['if_match'] =\
+ ValueArgument('show output if ETags match', '--if-match')
+ self.arguments['if_none_match'] =\
+ ValueArgument('show output if ETags match', '--if-none-match')
+ self.arguments['if_modified_since'] =\
+ DateArgument('show output modified since then',
+ '--if-modified-since')
+ self.arguments['if_unmodified_since'] =\
+ DateArgument('show output unmodified since then',
+ '--if-unmodified-since')
+ self.arguments['object_version'] =\
+ ValueArgument('get the specific version', '--object-version')
+
+ def main(self, container___path):
+ super(self.__class__,
+ self).main(container___path, path_is_optional=False)
+ try:
+ self.client.download_object(self.path, stdout,
+ range=self.get_argument('range'),
+ version=self.get_argument('object_version'),
+ if_match=self.get_argument('if_match'),
+ if_none_match=self.get_argument('if_none_match'),
+ if_modified_since=self.get_argument('if_modified_since'),
+ if_unmodified_since=self.get_argument('if_unmodified_since'))
+ except ClientError as err:
+ raiseCLIError(err)
+
+
+@command(pithos_cmds)
class store_download(_store_container_command):
"""Download a file"""
- def update_parser(self, parser):
- super(self.__class__, self).update_parser(parser)
- parser.add_argument('--no-progress-bar', action='store_true', dest='no_progress_bar',
- default=False, help='Dont display progress bars')
- parser.add_argument('--resume', action='store_true', dest='resume', default=False,
+ def __init__(self, arguments={}):
+ super(self.__class__, self).__init__(arguments)
+ self.arguments['resume'] = FlagArgument(parsed_name='--resume',
help='Resume a previous download instead of overwritting it')
- parser.add_argument('--range', action='store', dest='range', default=None,
- help='show range of data')
- parser.add_argument('--if-match', action='store', dest='if_match', default=None,
- help='show output if ETags match')
- parser.add_argument('--if-none-match', action='store', dest='if_none_match', default=None,
- help='show output if ETags don\'t match')
- parser.add_argument('--if-modified-since', action='store', dest='if_modified_since',
- default=None, help='show output if modified since then')
- parser.add_argument('--if-unmodified-since', action='store', dest='if_unmodified_since',
- default=None, help='show output if not modified since then')
- parser.add_argument('--object-version', action='store', dest='object_version', default=None,
- help='get the specific version')
- parser.add_argument('--with-pool-size', action='store', dest='poolsize', default=None,
- help='Set the greenlet pool size (advanced)')
-
- def main(self, container___path, local_path=None):
- super(self.__class__, self).main(container___path, path_is_optional=False)
-
- #setup output stream
- parallel = False
+ self.arguments['range'] = RangeArgument(\
+ 'show range of data', '--range')
+ self.arguments['if_match'] = ValueArgument(\
+ 'show output if ETags match', '--if-match')
+ self.arguments['if_none_match'] = ValueArgument(\
+ 'show output if ETags match', '--if-none-match')
+ self.arguments['if_modified_since'] = DateArgument(\
+ 'show output modified since then', '--if-modified-since')
+ self.arguments['if_unmodified_since'] = DateArgument(\
+ 'show output unmodified since then', '--if-unmodified-since')
+ self.arguments['object_version'] = ValueArgument(\
+ 'get the specific version', '--object-version')
+ self.arguments['poolsize'] = IntArgument(\
+ 'set pool size', '--with-pool-size')
+ self.arguments['progress_bar'] = ProgressBarArgument(\
+ 'do not show progress bar', '--no-progress-bar', False)
+
+ def main(self, container___path, local_path):
+ super(self.__class__,
+ self).main(container___path, path_is_optional=False)
+
+ # setup output stream
if local_path is None:
out = stdout
else:
try:
- if hasattr(self.args, 'resume') and getattr(self.args, 'resume'):
- out=open(local_path, 'rwb+')
+ if self.get_argument('resume'):
+ out = open(local_path, 'rwb+')
else:
- out=open(local_path, 'wb+')
+ out = open(local_path, 'wb+')
except IOError as err:
- raise CLIError(message='Cannot write to file %s - %s'%(local_path,unicode(err)),
- importance=1)
- download_cb = None if getattr(self.args, 'no_progress_bar') \
- else self.progress('Downloading')
- poolsize = getattr(self.args, 'poolsize')
+ raiseCLIError(err, 'Cannot write to file %s' % local_path, 1)
+ poolsize = self.get_argument('poolsize')
if poolsize is not None:
- self.POOL_SIZE = int(poolsize)
+ self.client.POOL_SIZE = int(poolsize)
try:
- self.client.download_object(self.path, out, download_cb,
- range=getattr(self.args, 'range'), version=getattr(self.args,'object_version'),
- if_match=getattr(self.args, 'if_match'), resume=getattr(self.args, 'resume'),
- if_none_match=getattr(self.args, 'if_none_match'),
- if_modified_since=getattr(self.args, 'if_modified_since'),
- if_unmodified_since=getattr(self.args, 'if_unmodified_since'))
+ progress_bar = self.arguments['progress_bar']
+ download_cb = progress_bar.get_generator('Downloading')
+ self.client.download_object(self.path, out,
+ download_cb=download_cb,
+ range=self.get_argument('range'),
+ version=self.get_argument('object_version'),
+ if_match=self.get_argument('if_match'),
+ resume=self.get_argument('resume'),
+ if_none_match=self.get_argument('if_none_match'),
+ if_modified_since=self.get_argument('if_modified_since'),
+ if_unmodified_since=self.get_argument('if_unmodified_since'))
+ progress_bar.finish()
except ClientError as err:
+ progress_bar.finish()
raiseCLIError(err)
except KeyboardInterrupt:
+ from threading import enumerate as activethreads
+ stdout.write('\nFinishing active threads ')
+ for thread in activethreads():
+ stdout.flush()
+ try:
+ thread.join()
+ stdout.write('.')
+ except RuntimeError:
+ continue
+ progress_bar.finish()
print('\ndownload canceled by user')
if local_path is not None:
print('to resume, re-run with --resume')
+ except Exception as e:
+ progress_bar.finish()
+ raiseCLIError(e)
print
-@command()
+
+@command(pithos_cmds)
class store_hashmap(_store_container_command):
"""Get the hashmap of an object"""
- def update_parser(self, parser):
- super(self.__class__, self).update_parser(parser)
- parser.add_argument('--if-match', action='store', dest='if_match', default=None,
- help='show output if ETags match')
- parser.add_argument('--if-none-match', action='store', dest='if_none_match', default=None,
- help='show output if ETags dont match')
- parser.add_argument('--if-modified-since', action='store', dest='if_modified_since',
- default=None, help='show output if modified since then')
- parser.add_argument('--if-unmodified-since', action='store', dest='if_unmodified_since',
- default=None, help='show output if not modified since then')
- parser.add_argument('--object-version', action='store', dest='object_version', default=None,
- help='get the specific version')
+ def __init__(self, arguments={}):
+ super(self.__class__, self).__init__(arguments)
+ self.arguments['if_match'] =\
+ ValueArgument('show output if ETags match', '--if-match')
+ self.arguments['if_none_match'] =\
+ ValueArgument('show output if ETags match', '--if-none-match')
+ self.arguments['if_modified_since'] =\
+ DateArgument('show output modified since then',
+ '--if-modified-since')
+ self.arguments['if_unmodified_since'] =\
+ DateArgument('show output unmodified since then',
+ '--if-unmodified-since')
+ self.arguments['object_version'] =\
+ ValueArgument('get the specific version', '--object-version')
def main(self, container___path):
- super(self.__class__, self).main(container___path, path_is_optional=False)
+ super(self.__class__,
+ self).main(container___path, path_is_optional=False)
try:
data = self.client.get_object_hashmap(self.path,
- version=getattr(self.args, 'object_version'),
- if_match=getattr(self.args, 'if_match'),
- if_none_match=getattr(self.args, 'if_none_match'),
- if_modified_since=getattr(self.args, 'if_modified_since'),
- if_unmodified_since=getattr(self.args, 'if_unmodified_since'))
+ version=self.get_argument('object_version'),
+ if_match=self.get_argument('if_match'),
+ if_none_match=self.get_argument('if_none_match'),
+ if_modified_since=self.get_argument('if_modified_since'),
+ if_unmodified_since=self.get_argument('if_unmodified_since'))
except ClientError as err:
raiseCLIError(err)
print_dict(data)
-@command()
+
+@command(pithos_cmds)
class store_delete(_store_container_command):
"""Delete a container [or an object]"""
- def update_parser(self, parser):
- super(self.__class__, self).update_parser(parser)
- parser.add_argument('--until', action='store', dest='until', default=None,
- help='remove history until that date')
- parser.add_argument('--format', action='store', dest='format', default='%d/%m/%Y %H:%M:%S',
- help='format to parse until date (default: d/m/Y H:M:S)')
- parser.add_argument('--delimiter', action='store', dest='delimiter',
- default=None,
- help='mass delete objects with path staring with <object><delimiter>')
- parser.add_argument('-r', action='store_true', dest='recursive', default=False,
- help='empty dir or container and delete (if dir)')
-
- def getuntil(self, orelse=None):
- if hasattr(self.args, 'until'):
- import time
- until = getattr(self.args, 'until')
- if until is None:
- return None
- format = getattr(self.args, 'format')
- try:
- t = time.strptime(until, format)
- except ValueError as err:
- raise CLIError(message='in --until: '+unicode(err), importance=1)
- return int(time.mktime(t))
- return orelse
-
- def getdelimiter(self, orelse=None):
- try:
- dlm = getattr(self.args, 'delimiter')
- if dlm is None:
- return '/' if getattr(self.args, 'recursive') else orelse
- except AttributeError:
- return orelse
- return dlm
+ def __init__(self, arguments={}):
+ super(self.__class__, self).__init__(arguments)
+ self.arguments['until'] = DateArgument(\
+ 'remove history until that date', '--until')
+ self.arguments['recursive'] = FlagArgument(\
+ 'empty dir or container and delete (if dir)',
+ ('-r', '--recursive'))
+ self.arguments['delimiter'] = DelimiterArgument(self,
+ parsed_name='--delimiter',
+ help='delete objects prefixed with <object><delimiter>')
def main(self, container____path__):
super(self.__class__, self).main(container____path__)
try:
if self.path is None:
- self.client.del_container(until=self.getuntil(), delimiter=self.getdelimiter())
+ self.client.del_container(until=self.get_argument('until'),
+ delimiter=self.get_argument('delimiter'))
else:
- #self.client.delete_object(self.path)
- self.client.del_object(self.path, until=self.getuntil(),
- delimiter=self.getdelimiter())
+ # self.client.delete_object(self.path)
+ self.client.del_object(self.path,
+ until=self.get_argument('until'),
+ delimiter=self.get_argument('delimiter'))
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_purge(_store_container_command):
"""Purge a container"""
-
+
def main(self, container):
super(self.__class__, self).main(container)
try:
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_publish(_store_container_command):
"""Publish an object"""
def main(self, container___path):
- super(self.__class__, self).main(container___path, path_is_optional=False)
+ super(self.__class__,
+ self).main(container___path, path_is_optional=False)
try:
- self.client.publish_object(self.path)
+ url = self.client.publish_object(self.path)
except ClientError as err:
raiseCLIError(err)
+ print(url)
-@command()
+
+@command(pithos_cmds)
class store_unpublish(_store_container_command):
"""Unpublish an object"""
def main(self, container___path):
- super(self.__class__, self).main(container___path, path_is_optional=False)
+ super(self.__class__,
+ self).main(container___path, path_is_optional=False)
try:
self.client.unpublish_object(self.path)
except ClientError as err:
raiseCLIError(err)
-@command()
-class store_permitions(_store_container_command):
- """Get object read/write permitions"""
+
+@command(pithos_cmds)
+class store_permissions(_store_container_command):
+ """Get object read / write permissions """
def main(self, container___path):
- super(self.__class__, self).main(container___path, path_is_optional=False)
+ super(self.__class__,
+ self).main(container___path, path_is_optional=False)
try:
reply = self.client.get_object_sharing(self.path)
print_dict(reply)
except ClientError as err:
raiseCLIError(err)
-@command()
-class store_setpermitions(_store_container_command):
- """Set sharing permitions"""
- def format_permition_dict(self,permitions):
+@command(pithos_cmds)
+class store_setpermissions(_store_container_command):
+ """Set sharing permissions """
+
+ def format_permition_dict(self, permissions):
read = False
write = False
- for perms in permitions:
+ for perms in permissions:
splstr = perms.split('=')
if 'read' == splstr[0]:
read = [user_or_group.strip() \
read = False
write = False
if not read and not write:
- raise CLIError(message='Usage:\tread=<groups,users> write=<groups,users>',
- importance=0)
- return (read,write)
-
- def main(self, container___path, *permitions):
- super(self.__class__, self).main(container___path, path_is_optional=False)
- (read, write) = self.format_permition_dict(permitions)
+ raiseCLIError(None,
+ 'Usage:\tread=<groups,users> write=<groups,users>')
+ return (read, write)
+
+ def main(self, container___path, *permissions):
+ super(self.__class__,
+ self).main(container___path, path_is_optional=False)
+ (read, write) = self.format_permition_dict(permissions)
try:
self.client.set_object_sharing(self.path,
read_permition=read, write_permition=write)
except ClientError as err:
raiseCLIError(err)
-@command()
-class store_delpermitions(_store_container_command):
- """Delete all sharing permitions"""
+
+@command(pithos_cmds)
+class store_delpermissions(_store_container_command):
+ """Delete all sharing permissions"""
def main(self, container___path):
- super(self.__class__, self).main(container___path, path_is_optional=False)
+ super(self.__class__,
+ self).main(container___path, path_is_optional=False)
try:
self.client.del_object_sharing(self.path)
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_info(_store_container_command):
"""Get information for account [, container [or object]]"""
-
+ def __init__(self, arguments={}):
+ super(self.__class__, self).__init__(arguments)
+ self.arguments['object_version'] =\
+ ValueArgument(parsed_name='--object-version',
+ help='show specific version \ (applies only for objects)')
+
def main(self, container____path__=None):
super(self.__class__, self).main(container____path__)
try:
elif self.path is None:
reply = self.client.get_container_info(self.container)
else:
- reply = self.client.get_object_info(self.path)
+ reply = self.client.get_object_info(self.path,
+ version=self.get_argument('object_version'))
except ClientError as err:
raiseCLIError(err)
print_dict(reply)
-@command()
+
+@command(pithos_cmds)
class store_meta(_store_container_command):
"""Get custom meta-content for account [, container [or object]]"""
- def update_parser(self, parser):
- super(self.__class__, self).update_parser(parser)
- parser.add_argument('-l', action='store_true', dest='detail', default=False,
- help='show detailed output')
- parser.add_argument('--until', action='store', dest='until', default=None,
- help='show metadata until that date')
- dateformat='%d/%m/%Y %H:%M:%S'
- parser.add_argument('--format', action='store', dest='format', default=dateformat,
- help='format to parse until date (default: "d/m/Y H:M:S")')
- parser.add_argument('--object_version', action='store', dest='object_version', default=None,
+ def __init__(self, arguments={}):
+ super(self.__class__, self).__init__(arguments)
+ self.arguments['detail'] =\
+ FlagArgument('show detailed output', '-l')
+ self.arguments['until'] =\
+ DateArgument('show metadata until then', '--until')
+ self.arguments['object_version'] =\
+ ValueArgument(parsed_name='--object-version',
help='show specific version \ (applies only for objects)')
- def getuntil(self, orelse=None):
- if hasattr(self.args, 'until'):
- import time
- until = getattr(self.args, 'until')
- if until is None:
- return None
- format = getattr(self.args, 'format')
- #except TypeError:
- try:
- t = time.strptime(until, format)
- except ValueError as err:
- raise CLIError(message='in --until: '+unicode(err), importance=1)
- return int(time.mktime(t))
- return orelse
-
- def main(self, container____path__ = None):
+ def main(self, container____path__=None):
super(self.__class__, self).main(container____path__)
- detail = getattr(self.args, 'detail')
+ detail = self.get_argument('detail')
try:
+ until = self.get_argument('until')
if self.container is None:
print(bold(self.client.account))
if detail:
- reply = self.client.get_account_info(until=self.getuntil())
+ reply = self.client.get_account_info(until=until)
else:
- reply = self.client.get_account_meta(until=self.getuntil())
+ reply = self.client.get_account_meta(until=until)
reply = pretty_keys(reply, '-')
elif self.path is None:
- print(bold(self.client.account+': '+self.container))
+ print(bold('%s: %s' % (self.client.account, self.container)))
if detail:
- reply = self.client.get_container_info(until = self.getuntil())
+ reply = self.client.get_container_info(until=until)
else:
- cmeta = self.client.get_container_meta(until=self.getuntil())
- ometa = self.client.get_container_object_meta(until=self.getuntil())
- reply = {'container-meta':pretty_keys(cmeta, '-'),
- 'object-meta':pretty_keys(ometa, '-')}
+ cmeta = self.client.get_container_meta(until=until)
+ ometa = self.client.get_container_object_meta(until=until)
+ reply = {'container-meta': pretty_keys(cmeta, '-'),
+ 'object-meta': pretty_keys(ometa, '-')}
else:
- print(bold(self.client.account+': '+self.container+':'+self.path))
- version=getattr(self.args, 'object_version')
+ print(bold('%s: %s:%s'\
+ % (self.client.account, self.container, self.path)))
+ version = self.get_argument('object_version')
if detail:
- reply = self.client.get_object_info(self.path, version = version)
+ reply = self.client.get_object_info(self.path,
+ version=version)
else:
- reply = self.client.get_object_meta(self.path, version=version)
+ reply = self.client.get_object_meta(self.path,
+ version=version)
reply = pretty_keys(pretty_keys(reply, '-'))
except ClientError as err:
raiseCLIError(err)
print_dict(reply)
-@command()
+
+@command(pithos_cmds)
class store_setmeta(_store_container_command):
"""Set a new metadatum for account [, container [or object]]"""
super(self.__class__, self).main(container____path__)
try:
metakey, metavalue = metakey___metaval.split(':')
- except ValueError:
- raise CLIError(message='Meta variables should be formated as metakey:metavalue',
- importance=1)
+ except ValueError as err:
+ raiseCLIError(err, 'Usage: metakey:metavalue', importance=1)
try:
if self.container is None:
- self.client.set_account_meta({metakey:metavalue})
+ self.client.set_account_meta({metakey: metavalue})
elif self.path is None:
- self.client.set_container_meta({metakey:metavalue})
+ self.client.set_container_meta({metakey: metavalue})
else:
- self.client.set_object_meta(self.path, {metakey:metavalue})
+ self.client.set_object_meta(self.path, {metakey: metavalue})
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_delmeta(_store_container_command):
"""Delete an existing metadatum of account [, container [or object]]"""
elif self.path is None:
self.client.del_container_meta(metakey)
else:
- self.client.del_object_meta(metakey, self.path)
+ self.client.del_object_meta(self.path, metakey)
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_quota(_store_account_command):
"""Get quota for account [or container]"""
- def main(self, container = None):
+ def main(self, container=None):
super(self.__class__, self).main()
try:
if container is None:
raiseCLIError(err)
print_dict(reply)
-@command()
+
+@command(pithos_cmds)
class store_setquota(_store_account_command):
"""Set new quota (in KB) for account [or container]"""
- def main(self, quota, container = None):
+ def main(self, quota, container=None):
super(self.__class__, self).main()
try:
if container is None:
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_versioning(_store_account_command):
"""Get versioning for account [or container ]"""
- def main(self, container = None):
+ def main(self, container=None):
super(self.__class__, self).main()
try:
if container is None:
raiseCLIError(err)
print_dict(reply)
-@command()
+
+@command(pithos_cmds)
class store_setversioning(_store_account_command):
"""Set new versioning (auto, none) for account [or container]"""
- def main(self, versioning, container = None):
+ def main(self, versioning, container=None):
super(self.__class__, self).main()
try:
if container is None:
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_group(_store_account_command):
"""Get user groups details for account"""
raiseCLIError(err)
print_dict(reply)
-@command()
+
+@command(pithos_cmds)
class store_setgroup(_store_account_command):
"""Create/update a new user group on account"""
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_delgroup(_store_account_command):
"""Delete a user group on an account"""
except ClientError as err:
raiseCLIError(err)
-@command()
+
+@command(pithos_cmds)
class store_sharers(_store_account_command):
"""List the accounts that share objects with default account"""
- def update_parser(self, parser):
- super(store_sharers, self).update_parser(parser)
- parser.add_argument('-l', action='store_true', dest='detail', default=False,
- help='show detailed output')
- parser.add_argument('-n', action='store', dest='limit', default=10000,
- help='show limited output')
- parser.add_argument('--marker', action='store', dest='marker', default=None,
- help='show output greater then marker')
+ def __init__(self, arguments={}):
+ super(self.__class__, self).__init__(arguments)
+ self.arguments['detail'] =\
+ FlagArgument('show detailed output', '-l')
+ self.arguments['limit'] =\
+ IntArgument('show limited output', '--n', default=1000)
+ self.arguments['marker'] =\
+ ValueArgument('show output greater then marker', '--marker')
def main(self):
super(self.__class__, self).main()
try:
- accounts = self.client.get_sharing_accounts(marker=getattr(self.args, 'marker'))
+ marker = self.get_argument('marker')
+ accounts = self.client.get_sharing_accounts(marker=marker)
except ClientError as err:
raiseCLIError(err)
for acc in accounts:
- stdout.write(bold(acc['name'])+' ')
- if getattr(self.args, 'detail'):
- print_dict(acc, exclude='name', ident=18)
- if not getattr(self.args, 'detail'):
+ stdout.write(bold(acc['name']) + ' ')
+ if self.get_argument('detail'):
+ print_dict(acc, exclude='name', ident=4)
+ if not self.get_argument('detail'):
print
-@command()
+
+@command(pithos_cmds)
class store_versions(_store_container_command):
"""Get the version list of an object"""
try:
versions = self.client.get_object_versionlist(self.path)
except ClientError as err:
- raise CLIError(err)
+ raiseCLIError(err)
- print('%s:%s versions'%(self.container,self.path))
+ print('%s:%s versions' % (self.container, self.path))
for vitem in versions:
t = localtime(float(vitem[1]))
vid = bold(unicode(vitem[0]))
- print('\t%s \t(%s)'%(vid, strftime('%d-%m-%Y %H:%M:%S', t)))
\ No newline at end of file
+ print('\t%s \t(%s)' % (vid, strftime('%d-%m-%Y %H:%M:%S', t)))