35 |
35 |
from kamaki.clients.utils import filter_in
|
36 |
36 |
from kamaki.cli.errors import CLIError, raiseCLIError
|
37 |
37 |
from kamaki.cli.utils import format_size, print_dict, pretty_keys, print_list
|
38 |
|
from kamaki.cli.argument import FlagArgument, ValueArgument
|
|
38 |
from kamaki.cli.argument import FlagArgument, ValueArgument, IntArgument
|
39 |
39 |
#set_api_description('store', 'Pithos+ storage commands')
|
40 |
40 |
API_DESCRIPTION = {'store':'Pithos+ storage commands'}
|
41 |
41 |
from kamaki.clients.pithos import PithosClient, ClientError
|
... | ... | |
43 |
43 |
from sys import stdout, exit
|
44 |
44 |
import signal
|
45 |
45 |
from time import localtime, strftime, strptime, mktime
|
|
46 |
from datetime import datetime as dtm
|
46 |
47 |
|
47 |
48 |
from progress.bar import IncrementalBar
|
48 |
49 |
|
... | ... | |
60 |
61 |
def value(self, newvalue):
|
61 |
62 |
self._value = newvalue
|
62 |
63 |
|
63 |
|
class UntilArgument(ValueArgument):
|
64 |
|
def __init__(self, caller_obj, help='', parsed_name=None, default=None):
|
65 |
|
super(UntilArgument, self).__init__(help, parsed_name, default)
|
66 |
|
self.caller_obj = caller_obj
|
67 |
|
|
68 |
|
@property
|
69 |
|
def value(self):
|
70 |
|
_value = getattr(self, '_value', self.default)
|
71 |
|
if _value is None:
|
72 |
|
return None
|
73 |
|
format = self.caller_obj.get_argument('format')
|
74 |
|
try:
|
75 |
|
t = strptime(_value, format)
|
76 |
|
except ValueError as err:
|
77 |
|
raise CLIError(message='in --until: '+unicode(err), importance=1)
|
78 |
|
return int(mktime(t))
|
79 |
|
@value.setter
|
80 |
|
def value(self, newvalue):
|
81 |
|
self._value = newvalue
|
82 |
|
|
83 |
64 |
class MetaArgument(ValueArgument):
|
84 |
65 |
@property
|
85 |
66 |
def value(self):
|
... | ... | |
114 |
95 |
yield
|
115 |
96 |
return progress_gen
|
116 |
97 |
|
|
98 |
class SharingArgument(ValueArgument):
|
|
99 |
@property
|
|
100 |
def value(self):
|
|
101 |
return getattr(self, '_value', self.default)
|
|
102 |
@value.setter
|
|
103 |
def value(self, newvalue):
|
|
104 |
perms = {}
|
|
105 |
try:
|
|
106 |
permlist = newvalue.split(' ')
|
|
107 |
except AttributeError:
|
|
108 |
return
|
|
109 |
for p in permlist:
|
|
110 |
try:
|
|
111 |
(key,val) = p.split('=')
|
|
112 |
except ValueError:
|
|
113 |
raise CLIError(message='Error in --sharing', details='Incorrect format', importance=1)
|
|
114 |
if key.lower() not in ('read', 'write'):
|
|
115 |
raise CLIError(message='Error in --sharing', details='Invalid permition key %s'%key, importance=1)
|
|
116 |
val_list = val.split(',')
|
|
117 |
if not perms.has_key(key):
|
|
118 |
perms[key]=[]
|
|
119 |
for item in val_list:
|
|
120 |
if item not in perms[key]:
|
|
121 |
perms[key].append(item)
|
|
122 |
self._value = perms
|
|
123 |
|
|
124 |
class RangeArgument(ValueArgument):
|
|
125 |
@property
|
|
126 |
def value(self):
|
|
127 |
return getattr(self, '_value', self.default)
|
|
128 |
@value.setter
|
|
129 |
def value(self, newvalue):
|
|
130 |
if newvalue is None:
|
|
131 |
self._value = self.default
|
|
132 |
return
|
|
133 |
(start, end) = newvalue.split('_')
|
|
134 |
(start, end) = (int(start), int(end))
|
|
135 |
self._value = '%s-%s'%(start, end)
|
|
136 |
|
|
137 |
class DateArgument(ValueArgument):
|
|
138 |
DATE_FORMATS = ["%a %b %d %H:%M:%S %Y",
|
|
139 |
"%A, %d-%b-%y %H:%M:%S GMT",
|
|
140 |
"%a, %d %b %Y %H:%M:%S GMT"]
|
|
141 |
|
|
142 |
INPUT_FORMATS = DATE_FORMATS + ["%d-%m-%Y", "%H:%M:%S %d-%m-%Y"]
|
|
143 |
|
|
144 |
@property
|
|
145 |
def value(self):
|
|
146 |
return getattr(self, '_value', self.default)
|
|
147 |
@value.setter
|
|
148 |
def value(self, newvalue):
|
|
149 |
if newvalue is None:
|
|
150 |
return
|
|
151 |
self._value = self.format_date(newvalue)
|
|
152 |
|
|
153 |
def format_date(self, datestr):
|
|
154 |
for format in self.INPUT_FORMATS:
|
|
155 |
try:
|
|
156 |
t = dtm.strptime(datestr, format)
|
|
157 |
except ValueError:
|
|
158 |
continue
|
|
159 |
self._value = t.strftime(self.DATE_FORMATS[0])
|
|
160 |
return
|
|
161 |
raise CLIError('Date Argument Error',
|
|
162 |
details='%s not a valid date. correct formats:\n\t%s'%(datestr, self.INPUT_FORMATS))
|
|
163 |
|
117 |
164 |
class _pithos_init(object):
|
118 |
165 |
def __init__(self, arguments={}):
|
119 |
166 |
self.arguments = arguments
|
... | ... | |
211 |
258 |
super(store_list, self).__init__(arguments)
|
212 |
259 |
self.arguments['detail'] = FlagArgument('show detailed output', '-l')
|
213 |
260 |
self.arguments['show_size'] = ValueArgument('print output in chunks of size N', '-N')
|
214 |
|
self.arguments['limit'] = ValueArgument('show limited output', '-n')
|
|
261 |
self.arguments['limit'] = IntArgument('show limited output', '-n')
|
215 |
262 |
self.arguments['marker'] = ValueArgument('show output greater that marker', '--marker')
|
216 |
263 |
self.arguments['prefix'] = ValueArgument('show output staritng with prefix', '--prefix')
|
217 |
264 |
self.arguments['delimiter'] = ValueArgument('show output up to delimiter', '--delimiter')
|
... | ... | |
222 |
269 |
'--if-modified-since')
|
223 |
270 |
self.arguments['if_unmodified_since'] = ValueArgument('show output not modified since then',
|
224 |
271 |
'--if-unmodified-since')
|
225 |
|
self.arguments['until'] = UntilArgument(self, 'show metadata until then', '--until')
|
|
272 |
self.arguments['until'] = DateArgument('show metadata until then', '--until')
|
226 |
273 |
self.arguments['format'] = ValueArgument('format to parse until data (default: d/m/Y H:M:S',
|
227 |
274 |
'--format')
|
228 |
275 |
self.arguments['shared'] = FlagArgument('show only shared', '--shared')
|
... | ... | |
332 |
379 |
super(self.__class__, self).__init__(arguments)
|
333 |
380 |
self.arguments['versioning'] = ValueArgument('set container versioning (auto/none)',
|
334 |
381 |
'--versioning')
|
335 |
|
self.arguments['quota'] = ValueArgument('set default container quota', '--quota')
|
|
382 |
self.arguments['quota'] = IntArgument('set default container quota', '--quota')
|
336 |
383 |
self.arguments['meta'] = MetaArgument('set container metadata', '---meta')
|
337 |
384 |
|
338 |
385 |
def main(self, container____directory__):
|
... | ... | |
381 |
428 |
"""Copy an object"""
|
382 |
429 |
|
383 |
430 |
def __init__(self, arguments={}):
|
384 |
|
super(self.__class__, self).__init(arguments)
|
|
431 |
super(self.__class__, self).__init__(arguments)
|
385 |
432 |
|
386 |
433 |
self.arguments['source_version']=ValueArgument('copy specific version', '--source-version')
|
387 |
|
self.arguments['public']=ValueArgument('make object publicly accessible', '--public')
|
|
434 |
self.arguments['public']=FlagArgument('make object publicly accessible', '--public')
|
388 |
435 |
self.arguments['content_type']=ValueArgument('change object\'s content type',
|
389 |
436 |
'--content-type')
|
390 |
437 |
self.arguments['delimiter']=DelimiterArgument(self, parsed_name='--delimiter',
|
... | ... | |
454 |
501 |
except ClientError as err:
|
455 |
502 |
raiseCLIError(err)
|
456 |
503 |
|
457 |
|
class SharingArgument(ValueArgument):
|
458 |
|
@property
|
459 |
|
def value(self):
|
460 |
|
return getattr(self, '_value', self.default)
|
461 |
|
@value.setter
|
462 |
|
def value(self, newvalue):
|
463 |
|
perms = {}
|
464 |
|
try:
|
465 |
|
permlist = newvalue.split(' ')
|
466 |
|
except AttributeError:
|
467 |
|
return
|
468 |
|
for p in permlist:
|
469 |
|
try:
|
470 |
|
(key,val) = p.split('=')
|
471 |
|
except ValueError:
|
472 |
|
raise CLIError(message='Error in --sharing', details='Incorrect format', importance=1)
|
473 |
|
if key.lower() not in ('read', 'write'):
|
474 |
|
raise CLIError(message='Error in --sharing', details='Invalid permition key %s'%key, importance=1)
|
475 |
|
val_list = val.split(',')
|
476 |
|
if not perms.has_key(key):
|
477 |
|
perms[key]=[]
|
478 |
|
for item in val_list:
|
479 |
|
if item not in perms[key]:
|
480 |
|
perms[key].append(item)
|
481 |
|
self._value = perms
|
482 |
|
|
483 |
504 |
@command()
|
484 |
505 |
class store_manifest(_store_container_command):
|
485 |
506 |
"""Create a remote file with uploaded parts by manifestation"""
|
... | ... | |
495 |
516 |
'--content-type')
|
496 |
517 |
self.arguments['sharing']=SharingArgument(parsed_name='--sharing',
|
497 |
518 |
help='define sharing object policy ( "read=user1,grp1,user2,... write=user1,grp2,...')
|
498 |
|
self.arguments['public']=ValueArgument('make object publicly accessible', '--public')
|
|
519 |
self.arguments['public']=FlagArgument('make object publicly accessible', '--public')
|
499 |
520 |
|
500 |
521 |
def main(self, container___path):
|
501 |
522 |
super(self.__class__, self).main(container___path, path_is_optional=False)
|
... | ... | |
512 |
533 |
class store_upload(_store_container_command):
|
513 |
534 |
"""Upload a file"""
|
514 |
535 |
|
515 |
|
def update_parser(self, parser):
|
516 |
|
super(self.__class__, self).update_parser(parser)
|
517 |
|
parser.add_argument('--use_hashes', action='store_true', dest='use_hashes', default=False,
|
518 |
|
help='provide hashmap file instead of data')
|
519 |
|
parser.add_argument('--unchunked', action='store_true', dest='unchunked', default=False,
|
520 |
|
help='avoid chunked transfer mode')
|
521 |
|
parser.add_argument('--etag', action='store', dest='etag', default=None,
|
522 |
|
help='check written data')
|
523 |
|
parser.add_argument('--content-encoding', action='store', dest='content_encoding',
|
524 |
|
default=None, help='provide the object MIME content type')
|
525 |
|
parser.add_argument('--content-disposition', action='store', dest='content_disposition',
|
526 |
|
default=None, help='provide the presentation style of the object')
|
527 |
|
parser.add_argument('--content-type', action='store', dest='content_type', default=None,
|
528 |
|
help='create object with specific content type')
|
529 |
|
parser.add_argument('--sharing', action='store', dest='sharing', default=None,
|
|
536 |
def __init__(self, arguments={}):
|
|
537 |
super(self.__class__, self).__init__(arguments)
|
|
538 |
self.arguments['use_hashes'] = FlagArgument('provide hashmap file instead of data',
|
|
539 |
'--use-hashes')
|
|
540 |
self.arguments['etag'] = ValueArgument('check written data', '--etag')
|
|
541 |
self.arguments['unchunked'] = FlagArgument('avoid chunked transfer mode', '--unchunked')
|
|
542 |
self.arguments['content_encoding']=ValueArgument('provide the object MIME content type',
|
|
543 |
'--content-encoding')
|
|
544 |
self.arguments['content_disposition'] = ValueArgument('provide the presentation style of the object',
|
|
545 |
'--content-disposition')
|
|
546 |
self.arguments['content_type']=ValueArgument('create object with specific content type',
|
|
547 |
'--content-type')
|
|
548 |
self.arguments['sharing']=SharingArgument(parsed_name='--sharing',
|
530 |
549 |
help='define sharing object policy ( "read=user1,grp1,user2,... write=user1,grp2,...')
|
531 |
|
parser.add_argument('--public', action='store_true', dest='public', default=False,
|
532 |
|
help='make object publicly accessible')
|
533 |
|
parser.add_argument('--with-pool-size', action='store', dest='poolsize', default=None,
|
534 |
|
help='Set the greenlet pool size (advanced)')
|
535 |
|
|
536 |
|
def getsharing(self, orelse={}):
|
537 |
|
permstr = getattr(self.args, 'sharing')
|
538 |
|
if permstr is None:
|
539 |
|
return orelse
|
540 |
|
perms = {}
|
541 |
|
for p in permstr.split(' '):
|
542 |
|
(key, val) = p.split('=')
|
543 |
|
if key.lower() not in ('read', 'write'):
|
544 |
|
raise CLIError(message='in --sharing: Invalid permition key', importance=1)
|
545 |
|
val_list = val.split(',')
|
546 |
|
if not perms.has_key(key):
|
547 |
|
perms[key]=[]
|
548 |
|
for item in val_list:
|
549 |
|
if item not in perms[key]:
|
550 |
|
perms[key].append(item)
|
551 |
|
return perms
|
|
550 |
self.arguments['public']=FlagArgument('make object publicly accessible', '--public')
|
|
551 |
self.arguments['poolsize']=IntArgument('set pool size', '--with-pool-size')
|
|
552 |
self.arguments['progress_bar'] = ProgressBarArgument('do not show progress bar',
|
|
553 |
'--no-progress-bar')
|
552 |
554 |
|
553 |
555 |
def main(self, local_path, container____path__):
|
554 |
556 |
super(self.__class__, self).main(container____path__)
|
555 |
557 |
remote_path = local_path if self.path is None else self.path
|
556 |
|
poolsize = getattr(self.args, 'poolsize')
|
|
558 |
poolsize = self.get_argument('poolsize')
|
557 |
559 |
if poolsize is not None:
|
558 |
|
self.POOL_SIZE = int(poolsize)
|
|
560 |
self.POOL_SIZE = poolsize
|
559 |
561 |
try:
|
560 |
562 |
with open(local_path) as f:
|
561 |
|
if getattr(self.args, 'unchunked'):
|
|
563 |
if self.get_argument('unchunked'):
|
562 |
564 |
self.client.upload_object_unchunked(remote_path, f,
|
563 |
|
etag=getattr(self.args, 'etag'), withHashFile=getattr(self.args, 'use_hashes'),
|
564 |
|
content_encoding=getattr(self.args, 'content_encoding'),
|
565 |
|
content_disposition=getattr(self.args, 'content_disposition'),
|
566 |
|
content_type=getattr(self.args, 'content_type'), sharing=self.getsharing(),
|
567 |
|
public=getattr(self.args, 'public'))
|
|
565 |
etag=self.get_argument('etag'), withHashFile=self.get_argument('use_hashes'),
|
|
566 |
content_encoding=self.get_argument('content_encoding'),
|
|
567 |
content_disposition=self.get_argument('content_disposition'),
|
|
568 |
content_type=self.get_argument('content_type'),
|
|
569 |
sharing=self.get_argument('sharing'), public=self.get_argument('public'))
|
568 |
570 |
else:
|
569 |
|
hash_cb = self.progress('Calculating block hashes')
|
570 |
|
upload_cb = self.progress('Uploading blocks')
|
|
571 |
hash_cb=self.arguments['progress_bar'].get_generator('Calculating block hashes')
|
|
572 |
upload_cb=self.arguments['progress_bar'].get_generator('Uploading')
|
571 |
573 |
self.client.upload_object(remote_path, f, hash_cb=hash_cb, upload_cb=upload_cb,
|
572 |
|
content_encoding=getattr(self.args, 'content_encoding'),
|
573 |
|
content_disposition=getattr(self.args, 'content_disposition'),
|
574 |
|
content_type=getattr(self.args, 'content_type'), sharing=self.getsharing(),
|
575 |
|
public=getattr(self.args, 'public'))
|
|
574 |
content_encoding=self.get_argument('content_encoding'),
|
|
575 |
content_disposition=self.get_argument('content_disposition'),
|
|
576 |
content_type=self.get_argument('content_type'),
|
|
577 |
sharing=self.get_argument('sharing'), public=self.get_argument('public'))
|
576 |
578 |
except ClientError as err:
|
577 |
579 |
raiseCLIError(err)
|
578 |
580 |
print 'Upload completed'
|
... | ... | |
581 |
583 |
class store_download(_store_container_command):
|
582 |
584 |
"""Download a file"""
|
583 |
585 |
|
584 |
|
def update_parser(self, parser):
|
585 |
|
super(self.__class__, self).update_parser(parser)
|
586 |
|
parser.add_argument('--no-progress-bar', action='store_true', dest='no_progress_bar',
|
587 |
|
default=False, help='Dont display progress bars')
|
588 |
|
parser.add_argument('--resume', action='store_true', dest='resume', default=False,
|
589 |
|
help='Resume a previous download instead of overwritting it')
|
590 |
|
parser.add_argument('--range', action='store', dest='range', default=None,
|
591 |
|
help='show range of data')
|
592 |
|
parser.add_argument('--if-match', action='store', dest='if_match', default=None,
|
593 |
|
help='show output if ETags match')
|
594 |
|
parser.add_argument('--if-none-match', action='store', dest='if_none_match', default=None,
|
595 |
|
help='show output if ETags don\'t match')
|
596 |
|
parser.add_argument('--if-modified-since', action='store', dest='if_modified_since',
|
597 |
|
default=None, help='show output if modified since then')
|
598 |
|
parser.add_argument('--if-unmodified-since', action='store', dest='if_unmodified_since',
|
599 |
|
default=None, help='show output if not modified since then')
|
600 |
|
parser.add_argument('--object-version', action='store', dest='object_version', default=None,
|
601 |
|
help='get the specific version')
|
602 |
|
parser.add_argument('--with-pool-size', action='store', dest='poolsize', default=None,
|
603 |
|
help='Set the greenlet pool size (advanced)')
|
|
586 |
def __init__(self, arguments={}):
|
|
587 |
super(self.__class__, self).__init__(arguments)
|
|
588 |
self.arguments['resume'] = FlagArgument(parsed_name='--resume',
|
|
589 |
help = 'Resume a previous download instead of overwritting it')
|
|
590 |
self.arguments['range'] = RangeArgument('show range of data', '--range')
|
|
591 |
self.arguments['if_match'] = ValueArgument('show output if ETags match', '--if-match')
|
|
592 |
self.arguments['if_none_match'] = ValueArgument('show output if ETags match',
|
|
593 |
'--if-none-match')
|
|
594 |
self.arguments['if_modified_since'] = DateArgument('show output modified since then',
|
|
595 |
'--if-modified-since')
|
|
596 |
self.arguments['if_unmodified_since'] = DateArgument('show output unmodified since then',
|
|
597 |
'--if-unmodified-since')
|
|
598 |
self.arguments['object_version'] = ValueArgument('get the specific version',
|
|
599 |
'--object-version')
|
|
600 |
self.arguments['poolsize']=IntArgument('set pool size', '--with-pool-size')
|
|
601 |
self.arguments['progress_bar'] = ProgressBarArgument('do not show progress bar',
|
|
602 |
'--no-progress-bar')
|
604 |
603 |
|
605 |
604 |
def main(self, container___path, local_path=None):
|
606 |
605 |
super(self.__class__, self).main(container___path, path_is_optional=False)
|
... | ... | |
611 |
610 |
out = stdout
|
612 |
611 |
else:
|
613 |
612 |
try:
|
614 |
|
if hasattr(self.args, 'resume') and getattr(self.args, 'resume'):
|
|
613 |
if self.get_argument('resume'):
|
615 |
614 |
out=open(local_path, 'rwb+')
|
616 |
615 |
else:
|
617 |
616 |
out=open(local_path, 'wb+')
|
618 |
617 |
except IOError as err:
|
619 |
618 |
raise CLIError(message='Cannot write to file %s - %s'%(local_path,unicode(err)),
|
620 |
619 |
importance=1)
|
621 |
|
download_cb = None if getattr(self.args, 'no_progress_bar') \
|
622 |
|
else self.progress('Downloading')
|
623 |
|
poolsize = getattr(self.args, 'poolsize')
|
|
620 |
download_cb = self.arguments['progress_bar'].get_generator('Downloading')
|
|
621 |
poolsize = self.get_argument('poolsize')
|
624 |
622 |
if poolsize is not None:
|
625 |
623 |
self.POOL_SIZE = int(poolsize)
|
626 |
624 |
|
627 |
625 |
try:
|
628 |
626 |
self.client.download_object(self.path, out, download_cb,
|
629 |
|
range=getattr(self.args, 'range'), version=getattr(self.args,'object_version'),
|
630 |
|
if_match=getattr(self.args, 'if_match'), resume=getattr(self.args, 'resume'),
|
631 |
|
if_none_match=getattr(self.args, 'if_none_match'),
|
632 |
|
if_modified_since=getattr(self.args, 'if_modified_since'),
|
633 |
|
if_unmodified_since=getattr(self.args, 'if_unmodified_since'))
|
|
627 |
range=self.get_argument('range'), version=self.get_argument('object_version'),
|
|
628 |
if_match=self.get_argument('if_match'), resume=self.get_argument('resume'),
|
|
629 |
if_none_match=self.get_argument('if_none_match'),
|
|
630 |
if_modified_since=self.get_argument('if_modified_since'),
|
|
631 |
if_unmodified_since=self.get_argument('if_unmodified_since'))
|
634 |
632 |
except ClientError as err:
|
635 |
633 |
raiseCLIError(err)
|
636 |
634 |
except KeyboardInterrupt:
|
... | ... | |
643 |
641 |
class store_hashmap(_store_container_command):
|
644 |
642 |
"""Get the hashmap of an object"""
|
645 |
643 |
|
646 |
|
def update_parser(self, parser):
|
647 |
|
super(self.__class__, self).update_parser(parser)
|
648 |
|
parser.add_argument('--if-match', action='store', dest='if_match', default=None,
|
649 |
|
help='show output if ETags match')
|
650 |
|
parser.add_argument('--if-none-match', action='store', dest='if_none_match', default=None,
|
651 |
|
help='show output if ETags dont match')
|
652 |
|
parser.add_argument('--if-modified-since', action='store', dest='if_modified_since',
|
653 |
|
default=None, help='show output if modified since then')
|
654 |
|
parser.add_argument('--if-unmodified-since', action='store', dest='if_unmodified_since',
|
655 |
|
default=None, help='show output if not modified since then')
|
656 |
|
parser.add_argument('--object-version', action='store', dest='object_version', default=None,
|
657 |
|
help='get the specific version')
|
|
644 |
def __init__(self, arguments={}):
|
|
645 |
super(self.__class__, self).__init__(arguments)
|
|
646 |
self.arguments['if_match'] = ValueArgument('show output if ETags match', '--if-match')
|
|
647 |
self.arguments['if_none_match'] = ValueArgument('show output if ETags match',
|
|
648 |
'--if-none-match')
|
|
649 |
self.arguments['if_modified_since'] = DateArgument('show output modified since then',
|
|
650 |
'--if-modified-since')
|
|
651 |
self.arguments['if_unmodified_since'] = DateArgument('show output unmodified since then',
|
|
652 |
'--if-unmodified-since')
|
|
653 |
self.arguments['object_version'] = ValueArgument('get the specific version',
|
|
654 |
'--object-version')
|
658 |
655 |
|
659 |
656 |
def main(self, container___path):
|
660 |
657 |
super(self.__class__, self).main(container___path, path_is_optional=False)
|
661 |
658 |
try:
|
662 |
659 |
data = self.client.get_object_hashmap(self.path,
|
663 |
|
version=getattr(self.args, 'object_version'),
|
664 |
|
if_match=getattr(self.args, 'if_match'),
|
665 |
|
if_none_match=getattr(self.args, 'if_none_match'),
|
666 |
|
if_modified_since=getattr(self.args, 'if_modified_since'),
|
667 |
|
if_unmodified_since=getattr(self.args, 'if_unmodified_since'))
|
|
660 |
version=self.arguments('object_version'),
|
|
661 |
if_match=self.arguments('if_match'),
|
|
662 |
if_none_match=self.arguments('if_none_match'),
|
|
663 |
if_modified_since=self.arguments('if_modified_since'),
|
|
664 |
if_unmodified_since=self.arguments('if_unmodified_since'))
|
668 |
665 |
except ClientError as err:
|
669 |
666 |
raiseCLIError(err)
|
670 |
667 |
print_dict(data)
|
... | ... | |
673 |
670 |
class store_delete(_store_container_command):
|
674 |
671 |
"""Delete a container [or an object]"""
|
675 |
672 |
|
676 |
|
def update_parser(self, parser):
|
677 |
|
super(self.__class__, self).update_parser(parser)
|
678 |
|
parser.add_argument('--until', action='store', dest='until', default=None,
|
679 |
|
help='remove history until that date')
|
680 |
|
parser.add_argument('--format', action='store', dest='format', default='%d/%m/%Y %H:%M:%S',
|
681 |
|
help='format to parse until date (default: d/m/Y H:M:S)')
|
682 |
|
parser.add_argument('--delimiter', action='store', dest='delimiter',
|
683 |
|
default=None,
|
684 |
|
help='mass delete objects with path staring with <object><delimiter>')
|
685 |
|
parser.add_argument('-r', action='store_true', dest='recursive', default=False,
|
686 |
|
help='empty dir or container and delete (if dir)')
|
687 |
|
|
688 |
|
def getuntil(self, orelse=None):
|
689 |
|
if hasattr(self.args, 'until'):
|
690 |
|
import time
|
691 |
|
until = getattr(self.args, 'until')
|
692 |
|
if until is None:
|
693 |
|
return None
|
694 |
|
format = getattr(self.args, 'format')
|
695 |
|
try:
|
696 |
|
t = time.strptime(until, format)
|
697 |
|
except ValueError as err:
|
698 |
|
raise CLIError(message='in --until: '+unicode(err), importance=1)
|
699 |
|
return int(time.mktime(t))
|
700 |
|
return orelse
|
701 |
|
|
702 |
|
def getdelimiter(self, orelse=None):
|
703 |
|
try:
|
704 |
|
dlm = getattr(self.args, 'delimiter')
|
705 |
|
if dlm is None:
|
706 |
|
return '/' if getattr(self.args, 'recursive') else orelse
|
707 |
|
except AttributeError:
|
708 |
|
return orelse
|
709 |
|
return dlm
|
|
673 |
def __init__(self, arguments={}):
|
|
674 |
super(self.__class__, self).__init__(arguments)
|
|
675 |
self.arguments['until'] = DateArgument('remove history until that date', '--until')
|
|
676 |
self.arguments['recursive'] = FlagArgument('empty dir or container and delete (if dir)',
|
|
677 |
'--recursive')
|
|
678 |
self.arguments['delimiter'] = DelimiterArgument(self, parsed_name='--delimiter',
|
|
679 |
help = 'mass delete objects with path staring with <object><delimiter>')
|
710 |
680 |
|
711 |
681 |
def main(self, container____path__):
|
712 |
682 |
super(self.__class__, self).main(container____path__)
|
713 |
683 |
try:
|
714 |
684 |
if self.path is None:
|
715 |
|
self.client.del_container(until=self.getuntil(), delimiter=self.getdelimiter())
|
|
685 |
self.client.del_container(until=self.get_argument('until'),
|
|
686 |
delimiter=self.get_argument('delimiter'))
|
716 |
687 |
else:
|
717 |
688 |
#self.client.delete_object(self.path)
|
718 |
|
self.client.del_object(self.path, until=self.getuntil(),
|
719 |
|
delimiter=self.getdelimiter())
|
|
689 |
self.client.del_object(self.path, until=self.get_argument('until'),
|
|
690 |
delimiter=self.get_argument('delimiter'))
|
720 |
691 |
except ClientError as err:
|
721 |
692 |
raiseCLIError(err)
|
722 |
693 |
|
... | ... | |
830 |
801 |
class store_meta(_store_container_command):
|
831 |
802 |
"""Get custom meta-content for account [, container [or object]]"""
|
832 |
803 |
|
833 |
|
def update_parser(self, parser):
|
834 |
|
super(self.__class__, self).update_parser(parser)
|
835 |
|
parser.add_argument('-l', action='store_true', dest='detail', default=False,
|
836 |
|
help='show detailed output')
|
837 |
|
parser.add_argument('--until', action='store', dest='until', default=None,
|
838 |
|
help='show metadata until that date')
|
839 |
|
dateformat='%d/%m/%Y %H:%M:%S'
|
840 |
|
parser.add_argument('--format', action='store', dest='format', default=dateformat,
|
841 |
|
help='format to parse until date (default: "d/m/Y H:M:S")')
|
842 |
|
parser.add_argument('--object_version', action='store', dest='object_version', default=None,
|
|
804 |
def __init__(self, arguments = {}):
|
|
805 |
super(self.__class__, self).__init__(arguments)
|
|
806 |
self.arguments['detail'] = FlagArgument('show detailed output', '-l')
|
|
807 |
self.arguments['until'] = DateArgument('show metadata until then', '--until')
|
|
808 |
self.arguments['object_version'] = ValueArgument(parsed_name='--object-version',
|
843 |
809 |
help='show specific version \ (applies only for objects)')
|
844 |
810 |
|
845 |
|
def getuntil(self, orelse=None):
|
846 |
|
if hasattr(self.args, 'until'):
|
847 |
|
import time
|
848 |
|
until = getattr(self.args, 'until')
|
849 |
|
if until is None:
|
850 |
|
return None
|
851 |
|
format = getattr(self.args, 'format')
|
852 |
|
#except TypeError:
|
853 |
|
try:
|
854 |
|
t = time.strptime(until, format)
|
855 |
|
except ValueError as err:
|
856 |
|
raise CLIError(message='in --until: '+unicode(err), importance=1)
|
857 |
|
return int(time.mktime(t))
|
858 |
|
return orelse
|
859 |
|
|
860 |
811 |
def main(self, container____path__ = None):
|
861 |
812 |
super(self.__class__, self).main(container____path__)
|
862 |
813 |
|
863 |
|
detail = getattr(self.args, 'detail')
|
|
814 |
detail = self.get_argument('detail')
|
864 |
815 |
try:
|
865 |
816 |
if self.container is None:
|
866 |
817 |
print(bold(self.client.account))
|
867 |
818 |
if detail:
|
868 |
|
reply = self.client.get_account_info(until=self.getuntil())
|
|
819 |
reply = self.client.get_account_info(until=self.get_argument('until'))
|
869 |
820 |
else:
|
870 |
|
reply = self.client.get_account_meta(until=self.getuntil())
|
|
821 |
reply = self.client.get_account_meta(until=self.get_argument('until'))
|
871 |
822 |
reply = pretty_keys(reply, '-')
|
872 |
823 |
elif self.path is None:
|
873 |
824 |
print(bold(self.client.account+': '+self.container))
|
874 |
825 |
if detail:
|
875 |
|
reply = self.client.get_container_info(until = self.getuntil())
|
|
826 |
reply = self.client.get_container_info(until = self.get_argument('until'))
|
876 |
827 |
else:
|
877 |
|
cmeta = self.client.get_container_meta(until=self.getuntil())
|
878 |
|
ometa = self.client.get_container_object_meta(until=self.getuntil())
|
|
828 |
cmeta = self.client.get_container_meta(until=self.get_argument('until'))
|
|
829 |
ometa = self.client.get_container_object_meta(until=self.get_argument('until'))
|
879 |
830 |
reply = {'container-meta':pretty_keys(cmeta, '-'),
|
880 |
831 |
'object-meta':pretty_keys(ometa, '-')}
|
881 |
832 |
else:
|
882 |
833 |
print(bold(self.client.account+': '+self.container+':'+self.path))
|
883 |
|
version=getattr(self.args, 'object_version')
|
|
834 |
version=self.get_argument('object_version')
|
884 |
835 |
if detail:
|
885 |
836 |
reply = self.client.get_object_info(self.path, version = version)
|
886 |
837 |
else:
|
... | ... | |
1025 |
976 |
class store_sharers(_store_account_command):
|
1026 |
977 |
"""List the accounts that share objects with default account"""
|
1027 |
978 |
|
1028 |
|
def update_parser(self, parser):
|
1029 |
|
super(store_sharers, self).update_parser(parser)
|
1030 |
|
parser.add_argument('-l', action='store_true', dest='detail', default=False,
|
1031 |
|
help='show detailed output')
|
1032 |
|
parser.add_argument('-n', action='store', dest='limit', default=10000,
|
1033 |
|
help='show limited output')
|
1034 |
|
parser.add_argument('--marker', action='store', dest='marker', default=None,
|
1035 |
|
help='show output greater then marker')
|
|
979 |
def __init__(self, arguments = {}):
|
|
980 |
super(self.__class__, self).__init__(arguments)
|
|
981 |
self.arguments['detail'] = FlagArgument('show detailed output', '-l')
|
|
982 |
self.arguments['limit'] = IntArgument('show limited output', '--n', default=1000)
|
|
983 |
self.arguments['marker'] = ValueArgument('show output greater then marker', '--marker')
|
1036 |
984 |
|
1037 |
985 |
def main(self):
|
1038 |
986 |
super(self.__class__, self).main()
|
1039 |
987 |
try:
|
1040 |
|
accounts = self.client.get_sharing_accounts(marker=getattr(self.args, 'marker'))
|
|
988 |
accounts = self.client.get_sharing_accounts(marker=self.get_argument('marker'))
|
1041 |
989 |
except ClientError as err:
|
1042 |
990 |
raiseCLIError(err)
|
1043 |
991 |
|
1044 |
992 |
for acc in accounts:
|
1045 |
993 |
stdout.write(bold(acc['name'])+' ')
|
1046 |
|
if getattr(self.args, 'detail'):
|
|
994 |
if self.get_argument('detail'):
|
1047 |
995 |
print_dict(acc, exclude='name', ident=18)
|
1048 |
|
if not getattr(self.args, 'detail'):
|
|
996 |
if not self.get_argument('detail'):
|
1049 |
997 |
print
|
1050 |
998 |
|
1051 |
999 |
@command()
|