Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / commands / pithos_cli.py @ 2005b18e

History | View | Annotate | Download (60.5 kB)

1 7493ccb6 Stavros Sachtouris
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 7493ccb6 Stavros Sachtouris
#
3 7493ccb6 Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
4 7493ccb6 Stavros Sachtouris
# without modification, are permitted provided that the following
5 7493ccb6 Stavros Sachtouris
# conditions are met:
6 7493ccb6 Stavros Sachtouris
#
7 7493ccb6 Stavros Sachtouris
#   1. Redistributions of source code must retain the above
8 7493ccb6 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
9 7493ccb6 Stavros Sachtouris
#      disclaimer.
10 7493ccb6 Stavros Sachtouris
#
11 7493ccb6 Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
12 7493ccb6 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
13 7493ccb6 Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
14 7493ccb6 Stavros Sachtouris
#      provided with the distribution.
15 7493ccb6 Stavros Sachtouris
#
16 7493ccb6 Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 7493ccb6 Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 7493ccb6 Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 7493ccb6 Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 7493ccb6 Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 7493ccb6 Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 7493ccb6 Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 7493ccb6 Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 7493ccb6 Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 7493ccb6 Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 7493ccb6 Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 7493ccb6 Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
28 7493ccb6 Stavros Sachtouris
#
29 7493ccb6 Stavros Sachtouris
# The views and conclusions contained in the software and
30 7493ccb6 Stavros Sachtouris
# documentation are those of the authors and should not be
31 7493ccb6 Stavros Sachtouris
# interpreted as representing official policies, either expressed
32 7493ccb6 Stavros Sachtouris
# or implied, of GRNET S.A.command
33 7493ccb6 Stavros Sachtouris
34 1395c40e Stavros Sachtouris
from sys import stdout
35 1395c40e Stavros Sachtouris
from time import localtime, strftime
36 1395c40e Stavros Sachtouris
from logging import getLogger
37 f6c09d14 Stavros Sachtouris
from os import path, makedirs
38 1395c40e Stavros Sachtouris
39 234954d1 Stavros Sachtouris
from kamaki.cli import command
40 d486baec Stavros Sachtouris
from kamaki.cli.command_tree import CommandTree
41 447c9568 Stavros Sachtouris
from kamaki.cli.errors import raiseCLIError, CLISyntaxError
42 7147e1ca Stavros Sachtouris
from kamaki.cli.utils import (
43 7147e1ca Stavros Sachtouris
    format_size,
44 001200c3 Stavros Sachtouris
    to_bytes,
45 7147e1ca Stavros Sachtouris
    print_dict,
46 b4cf92b8 Stavros Sachtouris
    print_items,
47 7147e1ca Stavros Sachtouris
    pretty_keys,
48 7147e1ca Stavros Sachtouris
    page_hold,
49 b4cf92b8 Stavros Sachtouris
    bold,
50 7147e1ca Stavros Sachtouris
    ask_user)
51 e3d4d442 Stavros Sachtouris
from kamaki.cli.argument import FlagArgument, ValueArgument, IntArgument
52 04d01cd4 Stavros Sachtouris
from kamaki.cli.argument import KeyValueArgument, DateArgument
53 fd1f1d96 Stavros Sachtouris
from kamaki.cli.argument import ProgressBarArgument
54 1395c40e Stavros Sachtouris
from kamaki.cli.commands import _command_init, errors
55 7493ccb6 Stavros Sachtouris
from kamaki.clients.pithos import PithosClient, ClientError
56 1f5debf7 Stavros Sachtouris
from kamaki.clients.astakos import AstakosClient
57 1395c40e Stavros Sachtouris
58 7493ccb6 Stavros Sachtouris
59 451a7992 Stavros Sachtouris
kloger = getLogger('kamaki')
60 234954d1 Stavros Sachtouris
61 d486baec Stavros Sachtouris
pithos_cmds = CommandTree('store', 'Pithos+ storage commands')
62 d486baec Stavros Sachtouris
_commands = [pithos_cmds]
63 234954d1 Stavros Sachtouris
64 7493ccb6 Stavros Sachtouris
65 1e29b9f6 Stavros Sachtouris
about_directories = [
66 1e29b9f6 Stavros Sachtouris
    'Kamaki hanldes directories the same way as OOS Storage and Pithos+:',
67 1e29b9f6 Stavros Sachtouris
    'A directory is an object with type "application/directory"',
68 1e29b9f6 Stavros Sachtouris
    'An object with path dir/name can exist even if dir does not exist or',
69 1e29b9f6 Stavros Sachtouris
    'even if dir is a non directory object. Users can modify dir without',
70 1e29b9f6 Stavros Sachtouris
    'affecting the dir/name object in any way.']
71 1e29b9f6 Stavros Sachtouris
72 1e29b9f6 Stavros Sachtouris
73 234954d1 Stavros Sachtouris
# Argument functionality
74 234954d1 Stavros Sachtouris
75 35f78d77 Stavros Sachtouris
def raise_connection_errors(e):
76 72952f4f Stavros Sachtouris
    if e.status in range(200) + [403, 401]:
77 35f78d77 Stavros Sachtouris
        raiseCLIError(e, details=[
78 35f78d77 Stavros Sachtouris
            'Please check the service url and the authentication information',
79 35f78d77 Stavros Sachtouris
            ' ',
80 35f78d77 Stavros Sachtouris
            '  to get the service url: /config get store.url',
81 35f78d77 Stavros Sachtouris
            '  to set the service url: /config set store.url <url>',
82 35f78d77 Stavros Sachtouris
            ' ',
83 35f78d77 Stavros Sachtouris
            '  to get authentication token: /config get token',
84 de73876b Stavros Sachtouris
            '  to set authentication token: /config set token <token>'])
85 776eee69 Stavros Sachtouris
    elif e.status == 413:
86 776eee69 Stavros Sachtouris
        raiseCLIError(e, details=[
87 776eee69 Stavros Sachtouris
            'Get quotas:',
88 776eee69 Stavros Sachtouris
            '- total quota:      /store quota',
89 776eee69 Stavros Sachtouris
            '- container quota:  /store quota <container>',
90 776eee69 Stavros Sachtouris
            'Users shall set a higher container quota, if available:',
91 de73876b Stavros Sachtouris
            '-                  /store setquota <quota>[unit] <container>'])
92 35f78d77 Stavros Sachtouris
93 234954d1 Stavros Sachtouris
94 efdee310 Stavros Sachtouris
class DelimiterArgument(ValueArgument):
95 befed235 Stavros Sachtouris
    """
96 befed235 Stavros Sachtouris
    :value type: string
97 befed235 Stavros Sachtouris
    :value returns: given string or /
98 03d661d8 Stavros Sachtouris
    """
99 03d661d8 Stavros Sachtouris
100 efdee310 Stavros Sachtouris
    def __init__(self, caller_obj, help='', parsed_name=None, default=None):
101 efdee310 Stavros Sachtouris
        super(DelimiterArgument, self).__init__(help, parsed_name, default)
102 efdee310 Stavros Sachtouris
        self.caller_obj = caller_obj
103 efdee310 Stavros Sachtouris
104 234954d1 Stavros Sachtouris
    @property
105 efdee310 Stavros Sachtouris
    def value(self):
106 2fe2672e Stavros Sachtouris
        if self.caller_obj['recursive']:
107 efdee310 Stavros Sachtouris
            return '/'
108 efdee310 Stavros Sachtouris
        return getattr(self, '_value', self.default)
109 234954d1 Stavros Sachtouris
110 234954d1 Stavros Sachtouris
    @value.setter
111 efdee310 Stavros Sachtouris
    def value(self, newvalue):
112 efdee310 Stavros Sachtouris
        self._value = newvalue
113 efdee310 Stavros Sachtouris
114 234954d1 Stavros Sachtouris
115 befed235 Stavros Sachtouris
class SharingArgument(ValueArgument):
116 befed235 Stavros Sachtouris
    """Set sharing (read and/or write) groups
117 439826ec Stavros Sachtouris
    .
118 befed235 Stavros Sachtouris
    :value type: "read=term1,term2,... write=term1,term2,..."
119 439826ec Stavros Sachtouris
    .
120 befed235 Stavros Sachtouris
    :value returns: {'read':['term1', 'term2', ...],
121 439826ec Stavros Sachtouris
    .   'write':['term1', 'term2', ...]}
122 befed235 Stavros Sachtouris
    """
123 234954d1 Stavros Sachtouris
124 234954d1 Stavros Sachtouris
    @property
125 e3d4d442 Stavros Sachtouris
    def value(self):
126 e3d4d442 Stavros Sachtouris
        return getattr(self, '_value', self.default)
127 234954d1 Stavros Sachtouris
128 e3d4d442 Stavros Sachtouris
    @value.setter
129 e3d4d442 Stavros Sachtouris
    def value(self, newvalue):
130 e3d4d442 Stavros Sachtouris
        perms = {}
131 e3d4d442 Stavros Sachtouris
        try:
132 e3d4d442 Stavros Sachtouris
            permlist = newvalue.split(' ')
133 e3d4d442 Stavros Sachtouris
        except AttributeError:
134 e3d4d442 Stavros Sachtouris
            return
135 e3d4d442 Stavros Sachtouris
        for p in permlist:
136 e3d4d442 Stavros Sachtouris
            try:
137 234954d1 Stavros Sachtouris
                (key, val) = p.split('=')
138 83ba5545 Stavros Sachtouris
            except ValueError as err:
139 24ff0a35 Stavros Sachtouris
                raiseCLIError(
140 24ff0a35 Stavros Sachtouris
                    err,
141 24ff0a35 Stavros Sachtouris
                    'Error in --sharing',
142 234954d1 Stavros Sachtouris
                    details='Incorrect format',
143 234954d1 Stavros Sachtouris
                    importance=1)
144 e3d4d442 Stavros Sachtouris
            if key.lower() not in ('read', 'write'):
145 de73876b Stavros Sachtouris
                msg = 'Error in --sharing'
146 de73876b Stavros Sachtouris
                raiseCLIError(err, msg, importance=1, details=[
147 de73876b Stavros Sachtouris
                    'Invalid permission key %s' % key])
148 e3d4d442 Stavros Sachtouris
            val_list = val.split(',')
149 234954d1 Stavros Sachtouris
            if not key in perms:
150 234954d1 Stavros Sachtouris
                perms[key] = []
151 e3d4d442 Stavros Sachtouris
            for item in val_list:
152 e3d4d442 Stavros Sachtouris
                if item not in perms[key]:
153 e3d4d442 Stavros Sachtouris
                    perms[key].append(item)
154 e3d4d442 Stavros Sachtouris
        self._value = perms
155 e3d4d442 Stavros Sachtouris
156 234954d1 Stavros Sachtouris
157 e3d4d442 Stavros Sachtouris
class RangeArgument(ValueArgument):
158 befed235 Stavros Sachtouris
    """
159 439826ec Stavros Sachtouris
    :value type: string of the form <start>-<end> where <start> and <end> are
160 439826ec Stavros Sachtouris
        integers
161 befed235 Stavros Sachtouris
    :value returns: the input string, after type checking <start> and <end>
162 befed235 Stavros Sachtouris
    """
163 befed235 Stavros Sachtouris
164 234954d1 Stavros Sachtouris
    @property
165 e3d4d442 Stavros Sachtouris
    def value(self):
166 e3d4d442 Stavros Sachtouris
        return getattr(self, '_value', self.default)
167 234954d1 Stavros Sachtouris
168 e3d4d442 Stavros Sachtouris
    @value.setter
169 e3d4d442 Stavros Sachtouris
    def value(self, newvalue):
170 e3d4d442 Stavros Sachtouris
        if newvalue is None:
171 e3d4d442 Stavros Sachtouris
            self._value = self.default
172 e3d4d442 Stavros Sachtouris
            return
173 9ceec15a Stavros Sachtouris
        (start, end) = newvalue.split('-')
174 e3d4d442 Stavros Sachtouris
        (start, end) = (int(start), int(end))
175 234954d1 Stavros Sachtouris
        self._value = '%s-%s' % (start, end)
176 234954d1 Stavros Sachtouris
177 234954d1 Stavros Sachtouris
# Command specs
178 234954d1 Stavros Sachtouris
179 e3d4d442 Stavros Sachtouris
180 5eae854d Stavros Sachtouris
class _pithos_init(_command_init):
181 befed235 Stavros Sachtouris
    """Initialize a pithos+ kamaki client"""
182 befed235 Stavros Sachtouris
183 1395c40e Stavros Sachtouris
    @errors.generic.all
184 1395c40e Stavros Sachtouris
    def _run(self):
185 234954d1 Stavros Sachtouris
        self.token = self.config.get('store', 'token')\
186 234954d1 Stavros Sachtouris
            or self.config.get('global', 'token')
187 234954d1 Stavros Sachtouris
        self.base_url = self.config.get('store', 'url')\
188 234954d1 Stavros Sachtouris
            or self.config.get('global', 'url')
189 1f5debf7 Stavros Sachtouris
        self._set_account()
190 234954d1 Stavros Sachtouris
        self.container = self.config.get('store', 'container')\
191 234954d1 Stavros Sachtouris
            or self.config.get('global', 'container')
192 de73876b Stavros Sachtouris
        self.client = PithosClient(
193 de73876b Stavros Sachtouris
            base_url=self.base_url,
194 234954d1 Stavros Sachtouris
            token=self.token,
195 234954d1 Stavros Sachtouris
            account=self.account,
196 7493ccb6 Stavros Sachtouris
            container=self.container)
197 7493ccb6 Stavros Sachtouris
198 1395c40e Stavros Sachtouris
    def main(self):
199 1395c40e Stavros Sachtouris
        self._run()
200 1395c40e Stavros Sachtouris
201 1f5debf7 Stavros Sachtouris
    def _set_account(self):
202 1f5debf7 Stavros Sachtouris
        astakos = AstakosClient(self.config.get('astakos', 'url'), self.token)
203 7ae842c2 Stavros Sachtouris
        self.account = self['account'] or astakos.term('uuid')
204 7ae842c2 Stavros Sachtouris
205 7ae842c2 Stavros Sachtouris
        """Backwards compatibility"""
206 7ae842c2 Stavros Sachtouris
        self.account = self.account\
207 7ae842c2 Stavros Sachtouris
            or self.config.get('store', 'account')\
208 7ae842c2 Stavros Sachtouris
            or self.config.get('global', 'account')
209 1f5debf7 Stavros Sachtouris
210 234954d1 Stavros Sachtouris
211 7493ccb6 Stavros Sachtouris
class _store_account_command(_pithos_init):
212 7493ccb6 Stavros Sachtouris
    """Base class for account level storage commands"""
213 7493ccb6 Stavros Sachtouris
214 c41a86b2 Stavros Sachtouris
    def __init__(self, arguments={}):
215 c41a86b2 Stavros Sachtouris
        super(_store_account_command, self).__init__(arguments)
216 439826ec Stavros Sachtouris
        self['account'] = ValueArgument(
217 47ae7577 Stavros Sachtouris
            'Set user account (not permanent)',
218 47ae7577 Stavros Sachtouris
            '--account')
219 7493ccb6 Stavros Sachtouris
220 1395c40e Stavros Sachtouris
    def _run(self):
221 1395c40e Stavros Sachtouris
        super(_store_account_command, self)._run()
222 47ae7577 Stavros Sachtouris
        if self['account']:
223 47ae7577 Stavros Sachtouris
            self.client.account = self['account']
224 7493ccb6 Stavros Sachtouris
225 1395c40e Stavros Sachtouris
    @errors.generic.all
226 1395c40e Stavros Sachtouris
    def main(self):
227 1395c40e Stavros Sachtouris
        self._run()
228 1395c40e Stavros Sachtouris
229 234954d1 Stavros Sachtouris
230 7493ccb6 Stavros Sachtouris
class _store_container_command(_store_account_command):
231 7493ccb6 Stavros Sachtouris
    """Base class for container level storage commands"""
232 7493ccb6 Stavros Sachtouris
233 47ae7577 Stavros Sachtouris
    container = None
234 47ae7577 Stavros Sachtouris
    path = None
235 2d7ce81e Stavros Sachtouris
236 c41a86b2 Stavros Sachtouris
    def __init__(self, arguments={}):
237 c41a86b2 Stavros Sachtouris
        super(_store_container_command, self).__init__(arguments)
238 439826ec Stavros Sachtouris
        self['container'] = ValueArgument(
239 47ae7577 Stavros Sachtouris
            'Set container to work with (temporary)',
240 47ae7577 Stavros Sachtouris
            '--container')
241 7493ccb6 Stavros Sachtouris
242 1395c40e Stavros Sachtouris
    @errors.generic.all
243 1395c40e Stavros Sachtouris
    def _dest_container_path(self, dest_container_path):
244 e423eb63 Stavros Sachtouris
        if self['destination_container']:
245 e423eb63 Stavros Sachtouris
            return (self['destination_container'], dest_container_path)
246 1395c40e Stavros Sachtouris
        dst = dest_container_path.split(':')
247 1395c40e Stavros Sachtouris
        return (dst[0], dst[1]) if len(dst) > 1 else (None, dst[0])
248 1395c40e Stavros Sachtouris
249 de73876b Stavros Sachtouris
    def extract_container_and_path(
250 24ff0a35 Stavros Sachtouris
            self,
251 24ff0a35 Stavros Sachtouris
            container_with_path,
252 24ff0a35 Stavros Sachtouris
            path_is_optional=True):
253 1395c40e Stavros Sachtouris
        """Contains all heuristics for deciding what should be used as
254 1395c40e Stavros Sachtouris
        container or path. Options are:
255 1395c40e Stavros Sachtouris
        * user string of the form container:path
256 1395c40e Stavros Sachtouris
        * self.container, self.path variables set by super constructor, or
257 1395c40e Stavros Sachtouris
        explicitly by the caller application
258 1395c40e Stavros Sachtouris
        Error handling is explicit as these error cases happen only here
259 1395c40e Stavros Sachtouris
        """
260 83ba5545 Stavros Sachtouris
        try:
261 83ba5545 Stavros Sachtouris
            assert isinstance(container_with_path, str)
262 83ba5545 Stavros Sachtouris
        except AssertionError as err:
263 edab7ba7 Stavros Sachtouris
            if self['container'] and path_is_optional:
264 edab7ba7 Stavros Sachtouris
                self.container = self['container']
265 edab7ba7 Stavros Sachtouris
                self.client.container = self['container']
266 edab7ba7 Stavros Sachtouris
                return
267 83ba5545 Stavros Sachtouris
            raiseCLIError(err)
268 447c9568 Stavros Sachtouris
269 1395c40e Stavros Sachtouris
        user_cont, sep, userpath = container_with_path.partition(':')
270 447c9568 Stavros Sachtouris
271 447c9568 Stavros Sachtouris
        if sep:
272 1395c40e Stavros Sachtouris
            if not user_cont:
273 2005b18e Stavros Sachtouris
                raiseCLIError(CLISyntaxError(
274 2005b18e Stavros Sachtouris
                    'Container is missing\n',
275 1395c40e Stavros Sachtouris
                    details=errors.pithos.container_howto))
276 47ae7577 Stavros Sachtouris
            alt_cont = self['container']
277 1395c40e Stavros Sachtouris
            if alt_cont and user_cont != alt_cont:
278 c1558584 Stavros Sachtouris
                raiseCLIError(CLISyntaxError(
279 1395c40e Stavros Sachtouris
                    'Conflict: 2 containers (%s, %s)' % (user_cont, alt_cont),
280 1395c40e Stavros Sachtouris
                    details=errors.pithos.container_howto)
281 47ae7577 Stavros Sachtouris
                )
282 1395c40e Stavros Sachtouris
            self.container = user_cont
283 1395c40e Stavros Sachtouris
            if not userpath:
284 c1558584 Stavros Sachtouris
                raiseCLIError(CLISyntaxError(
285 1395c40e Stavros Sachtouris
                    'Path is missing for object in container %s' % user_cont,
286 1395c40e Stavros Sachtouris
                    details=errors.pithos.container_howto)
287 47ae7577 Stavros Sachtouris
                )
288 1395c40e Stavros Sachtouris
            self.path = userpath
289 447c9568 Stavros Sachtouris
        else:
290 47ae7577 Stavros Sachtouris
            alt_cont = self['container'] or self.client.container
291 447c9568 Stavros Sachtouris
            if alt_cont:
292 447c9568 Stavros Sachtouris
                self.container = alt_cont
293 1395c40e Stavros Sachtouris
                self.path = user_cont
294 447c9568 Stavros Sachtouris
            elif path_is_optional:
295 1395c40e Stavros Sachtouris
                self.container = user_cont
296 7493ccb6 Stavros Sachtouris
                self.path = None
297 7493ccb6 Stavros Sachtouris
            else:
298 1395c40e Stavros Sachtouris
                self.container = user_cont
299 447c9568 Stavros Sachtouris
                raiseCLIError(CLISyntaxError(
300 c1558584 Stavros Sachtouris
                    'Both container and path are required',
301 1395c40e Stavros Sachtouris
                    details=errors.pithos.container_howto)
302 47ae7577 Stavros Sachtouris
                )
303 7493ccb6 Stavros Sachtouris
304 1395c40e Stavros Sachtouris
    @errors.generic.all
305 1395c40e Stavros Sachtouris
    def _run(self, container_with_path=None, path_is_optional=True):
306 1395c40e Stavros Sachtouris
        super(_store_container_command, self)._run()
307 edab7ba7 Stavros Sachtouris
        if self['container']:
308 edab7ba7 Stavros Sachtouris
            self.client.container = self['container']
309 edab7ba7 Stavros Sachtouris
            if container_with_path:
310 edab7ba7 Stavros Sachtouris
                self.path = container_with_path
311 edab7ba7 Stavros Sachtouris
            elif not path_is_optional:
312 edab7ba7 Stavros Sachtouris
                raise CLISyntaxError(
313 edab7ba7 Stavros Sachtouris
                    'Both container and path are required',
314 edab7ba7 Stavros Sachtouris
                    details=errors.pithos.container_howto)
315 edab7ba7 Stavros Sachtouris
        elif container_with_path:
316 47ae7577 Stavros Sachtouris
            self.extract_container_and_path(
317 47ae7577 Stavros Sachtouris
                container_with_path,
318 234954d1 Stavros Sachtouris
                path_is_optional)
319 7493ccb6 Stavros Sachtouris
            self.client.container = self.container
320 7493ccb6 Stavros Sachtouris
        self.container = self.client.container
321 7493ccb6 Stavros Sachtouris
322 1395c40e Stavros Sachtouris
    def main(self, container_with_path=None, path_is_optional=True):
323 1395c40e Stavros Sachtouris
        self._run(container_with_path, path_is_optional)
324 1395c40e Stavros Sachtouris
325 7493ccb6 Stavros Sachtouris
326 d486baec Stavros Sachtouris
@command(pithos_cmds)
327 7493ccb6 Stavros Sachtouris
class store_list(_store_container_command):
328 7493ccb6 Stavros Sachtouris
    """List containers, object trees or objects in a directory
329 2703cceb Stavros Sachtouris
    Use with:
330 7ae842c2 Stavros Sachtouris
    1 no parameters : containers in current account
331 2703cceb Stavros Sachtouris
    2. one parameter (container) or --container : contents of container
332 2703cceb Stavros Sachtouris
    3. <container>:<prefix> or --container=<container> <prefix>: objects in
333 439826ec Stavros Sachtouris
    .   container starting with prefix
334 7493ccb6 Stavros Sachtouris
    """
335 7493ccb6 Stavros Sachtouris
336 47ae7577 Stavros Sachtouris
    arguments = dict(
337 47ae7577 Stavros Sachtouris
        detail=FlagArgument('show detailed output', '-l'),
338 439826ec Stavros Sachtouris
        limit=IntArgument('limit the number of listed items', '-n'),
339 47ae7577 Stavros Sachtouris
        marker=ValueArgument('show output greater that marker', '--marker'),
340 439826ec Stavros Sachtouris
        prefix=ValueArgument('show output starting with prefix', '--prefix'),
341 47ae7577 Stavros Sachtouris
        delimiter=ValueArgument('show output up to delimiter', '--delimiter'),
342 47ae7577 Stavros Sachtouris
        path=ValueArgument(
343 47ae7577 Stavros Sachtouris
            'show output starting with prefix up to /',
344 47ae7577 Stavros Sachtouris
            '--path'),
345 47ae7577 Stavros Sachtouris
        meta=ValueArgument(
346 47ae7577 Stavros Sachtouris
            'show output with specified meta keys',
347 47ae7577 Stavros Sachtouris
            '--meta',
348 47ae7577 Stavros Sachtouris
            default=[]),
349 47ae7577 Stavros Sachtouris
        if_modified_since=ValueArgument(
350 47ae7577 Stavros Sachtouris
            'show output modified since then',
351 47ae7577 Stavros Sachtouris
            '--if-modified-since'),
352 47ae7577 Stavros Sachtouris
        if_unmodified_since=ValueArgument(
353 47ae7577 Stavros Sachtouris
            'show output not modified since then',
354 47ae7577 Stavros Sachtouris
            '--if-unmodified-since'),
355 47ae7577 Stavros Sachtouris
        until=DateArgument('show metadata until then', '--until'),
356 47ae7577 Stavros Sachtouris
        format=ValueArgument(
357 47ae7577 Stavros Sachtouris
            'format to parse until data (default: d/m/Y H:M:S )',
358 47ae7577 Stavros Sachtouris
            '--format'),
359 47ae7577 Stavros Sachtouris
        shared=FlagArgument('show only shared', '--shared'),
360 47ae7577 Stavros Sachtouris
        public=FlagArgument('show only public', '--public'),
361 439826ec Stavros Sachtouris
        more=FlagArgument(
362 439826ec Stavros Sachtouris
            'output results in pages (-n to set items per page, default 10)',
363 eb18b8a7 Stavros Sachtouris
            '--more'),
364 eb18b8a7 Stavros Sachtouris
        exact_match=FlagArgument(
365 eb18b8a7 Stavros Sachtouris
            'Show only objects that match exactly with path',
366 eb18b8a7 Stavros Sachtouris
            '--exact-match')
367 47ae7577 Stavros Sachtouris
    )
368 c41a86b2 Stavros Sachtouris
369 7493ccb6 Stavros Sachtouris
    def print_objects(self, object_list):
370 439826ec Stavros Sachtouris
        limit = int(self['limit']) if self['limit'] > 0 else len(object_list)
371 234954d1 Stavros Sachtouris
        for index, obj in enumerate(object_list):
372 24ff0a35 Stavros Sachtouris
            if self['exact_match'] and self.path and not (
373 2005b18e Stavros Sachtouris
                    obj['name'] == self.path or 'content_type' in obj):
374 2005b18e Stavros Sachtouris
                continue
375 7493ccb6 Stavros Sachtouris
            pretty_obj = obj.copy()
376 7493ccb6 Stavros Sachtouris
            index += 1
377 234954d1 Stavros Sachtouris
            empty_space = ' ' * (len(str(len(object_list))) - len(str(index)))
378 7493ccb6 Stavros Sachtouris
            if obj['content_type'] == 'application/directory':
379 7493ccb6 Stavros Sachtouris
                isDir = True
380 7493ccb6 Stavros Sachtouris
                size = 'D'
381 7493ccb6 Stavros Sachtouris
            else:
382 7493ccb6 Stavros Sachtouris
                isDir = False
383 7493ccb6 Stavros Sachtouris
                size = format_size(obj['bytes'])
384 234954d1 Stavros Sachtouris
                pretty_obj['bytes'] = '%s (%s)' % (obj['bytes'], size)
385 7493ccb6 Stavros Sachtouris
            oname = bold(obj['name'])
386 47ae7577 Stavros Sachtouris
            if self['detail']:
387 234954d1 Stavros Sachtouris
                print('%s%s. %s' % (empty_space, index, oname))
388 7493ccb6 Stavros Sachtouris
                print_dict(pretty_keys(pretty_obj), exclude=('name'))
389 7493ccb6 Stavros Sachtouris
                print
390 7493ccb6 Stavros Sachtouris
            else:
391 234954d1 Stavros Sachtouris
                oname = '%s%s. %6s %s' % (empty_space, index, size, oname)
392 7493ccb6 Stavros Sachtouris
                oname += '/' if isDir else ''
393 7493ccb6 Stavros Sachtouris
                print(oname)
394 439826ec Stavros Sachtouris
            if self['more']:
395 439826ec Stavros Sachtouris
                page_hold(index, limit, len(object_list))
396 7493ccb6 Stavros Sachtouris
397 7493ccb6 Stavros Sachtouris
    def print_containers(self, container_list):
398 439826ec Stavros Sachtouris
        limit = int(self['limit']) if self['limit'] > 0\
399 439826ec Stavros Sachtouris
            else len(container_list)
400 234954d1 Stavros Sachtouris
        for index, container in enumerate(container_list):
401 234954d1 Stavros Sachtouris
            if 'bytes' in container:
402 234954d1 Stavros Sachtouris
                size = format_size(container['bytes'])
403 234954d1 Stavros Sachtouris
            cname = '%s. %s' % (index + 1, bold(container['name']))
404 47ae7577 Stavros Sachtouris
            if self['detail']:
405 7493ccb6 Stavros Sachtouris
                print(cname)
406 7493ccb6 Stavros Sachtouris
                pretty_c = container.copy()
407 234954d1 Stavros Sachtouris
                if 'bytes' in container:
408 234954d1 Stavros Sachtouris
                    pretty_c['bytes'] = '%s (%s)' % (container['bytes'], size)
409 7493ccb6 Stavros Sachtouris
                print_dict(pretty_keys(pretty_c), exclude=('name'))
410 7493ccb6 Stavros Sachtouris
                print
411 7493ccb6 Stavros Sachtouris
            else:
412 234954d1 Stavros Sachtouris
                if 'count' in container and 'bytes' in container:
413 de73876b Stavros Sachtouris
                    print('%s (%s, %s objects)' % (
414 de73876b Stavros Sachtouris
                        cname,
415 de73876b Stavros Sachtouris
                        size,
416 de73876b Stavros Sachtouris
                        container['count']))
417 7493ccb6 Stavros Sachtouris
                else:
418 7493ccb6 Stavros Sachtouris
                    print(cname)
419 439826ec Stavros Sachtouris
            if self['more']:
420 439826ec Stavros Sachtouris
                page_hold(index + 1, limit, len(container_list))
421 7493ccb6 Stavros Sachtouris
422 1395c40e Stavros Sachtouris
    @errors.generic.all
423 1395c40e Stavros Sachtouris
    @errors.pithos.connection
424 1395c40e Stavros Sachtouris
    @errors.pithos.object_path
425 1395c40e Stavros Sachtouris
    @errors.pithos.container
426 1395c40e Stavros Sachtouris
    def _run(self):
427 1395c40e Stavros Sachtouris
        if self.container is None:
428 1395c40e Stavros Sachtouris
            r = self.client.account_get(
429 1395c40e Stavros Sachtouris
                limit=False if self['more'] else self['limit'],
430 1395c40e Stavros Sachtouris
                marker=self['marker'],
431 1395c40e Stavros Sachtouris
                if_modified_since=self['if_modified_since'],
432 1395c40e Stavros Sachtouris
                if_unmodified_since=self['if_unmodified_since'],
433 1395c40e Stavros Sachtouris
                until=self['until'],
434 1395c40e Stavros Sachtouris
                show_only_shared=self['shared'])
435 1395c40e Stavros Sachtouris
            self.print_containers(r.json)
436 1395c40e Stavros Sachtouris
        else:
437 52edad0a Stavros Sachtouris
            prefix = self.path or self['prefix']
438 1395c40e Stavros Sachtouris
            r = self.client.container_get(
439 1395c40e Stavros Sachtouris
                limit=False if self['more'] else self['limit'],
440 1395c40e Stavros Sachtouris
                marker=self['marker'],
441 1395c40e Stavros Sachtouris
                prefix=prefix,
442 1395c40e Stavros Sachtouris
                delimiter=self['delimiter'],
443 1395c40e Stavros Sachtouris
                path=self['path'],
444 1395c40e Stavros Sachtouris
                if_modified_since=self['if_modified_since'],
445 1395c40e Stavros Sachtouris
                if_unmodified_since=self['if_unmodified_since'],
446 1395c40e Stavros Sachtouris
                until=self['until'],
447 1395c40e Stavros Sachtouris
                meta=self['meta'],
448 1395c40e Stavros Sachtouris
                show_only_shared=self['shared'])
449 1395c40e Stavros Sachtouris
            self.print_objects(r.json)
450 1395c40e Stavros Sachtouris
451 7493ccb6 Stavros Sachtouris
    def main(self, container____path__=None):
452 1395c40e Stavros Sachtouris
        super(self.__class__, self)._run(container____path__)
453 1395c40e Stavros Sachtouris
        self._run()
454 7493ccb6 Stavros Sachtouris
455 234954d1 Stavros Sachtouris
456 d486baec Stavros Sachtouris
@command(pithos_cmds)
457 7493ccb6 Stavros Sachtouris
class store_mkdir(_store_container_command):
458 f5d9bc54 Stavros Sachtouris
    """Create a directory"""
459 1e29b9f6 Stavros Sachtouris
460 1e29b9f6 Stavros Sachtouris
    __doc__ += '\n. '.join(about_directories)
461 7493ccb6 Stavros Sachtouris
462 1395c40e Stavros Sachtouris
    @errors.generic.all
463 1395c40e Stavros Sachtouris
    @errors.pithos.connection
464 1395c40e Stavros Sachtouris
    @errors.pithos.container
465 1395c40e Stavros Sachtouris
    def _run(self):
466 1395c40e Stavros Sachtouris
        self.client.create_directory(self.path)
467 1395c40e Stavros Sachtouris
468 7493ccb6 Stavros Sachtouris
    def main(self, container___directory):
469 1395c40e Stavros Sachtouris
        super(self.__class__, self)._run(
470 1395c40e Stavros Sachtouris
            container___directory,
471 1395c40e Stavros Sachtouris
            path_is_optional=False)
472 1395c40e Stavros Sachtouris
        self._run()
473 7493ccb6 Stavros Sachtouris
474 234954d1 Stavros Sachtouris
475 d486baec Stavros Sachtouris
@command(pithos_cmds)
476 1e29b9f6 Stavros Sachtouris
class store_touch(_store_container_command):
477 1e29b9f6 Stavros Sachtouris
    """Create an empty object (file)
478 1e29b9f6 Stavros Sachtouris
    If object exists, this command will reset it to 0 length
479 1e29b9f6 Stavros Sachtouris
    """
480 1e29b9f6 Stavros Sachtouris
481 1e29b9f6 Stavros Sachtouris
    arguments = dict(
482 1e29b9f6 Stavros Sachtouris
        content_type=ValueArgument(
483 1e29b9f6 Stavros Sachtouris
            'Set content type (default: application/octet-stream)',
484 1e29b9f6 Stavros Sachtouris
            '--content-type',
485 1e29b9f6 Stavros Sachtouris
            default='application/octet-stream')
486 1e29b9f6 Stavros Sachtouris
    )
487 1e29b9f6 Stavros Sachtouris
488 1395c40e Stavros Sachtouris
    @errors.generic.all
489 1395c40e Stavros Sachtouris
    @errors.pithos.connection
490 1395c40e Stavros Sachtouris
    @errors.pithos.container
491 1395c40e Stavros Sachtouris
    def _run(self):
492 1395c40e Stavros Sachtouris
        self.client.create_object(self.path, self['content_type'])
493 1395c40e Stavros Sachtouris
494 1e29b9f6 Stavros Sachtouris
    def main(self, container___path):
495 52edad0a Stavros Sachtouris
        super(store_touch, self)._run(
496 52edad0a Stavros Sachtouris
            container___path,
497 52edad0a Stavros Sachtouris
            path_is_optional=False)
498 1395c40e Stavros Sachtouris
        self._run()
499 1e29b9f6 Stavros Sachtouris
500 1e29b9f6 Stavros Sachtouris
501 1e29b9f6 Stavros Sachtouris
@command(pithos_cmds)
502 72952f4f Stavros Sachtouris
class store_create(_store_container_command):
503 1e29b9f6 Stavros Sachtouris
    """Create a container"""
504 7493ccb6 Stavros Sachtouris
505 2fe2672e Stavros Sachtouris
    arguments = dict(
506 2fe2672e Stavros Sachtouris
        versioning=ValueArgument(
507 2fe2672e Stavros Sachtouris
            'set container versioning (auto/none)',
508 2fe2672e Stavros Sachtouris
            '--versioning'),
509 2fe2672e Stavros Sachtouris
        quota=IntArgument('set default container quota', '--quota'),
510 2fe2672e Stavros Sachtouris
        meta=KeyValueArgument(
511 2fe2672e Stavros Sachtouris
            'set container metadata (can be repeated)',
512 2fe2672e Stavros Sachtouris
            '--meta')
513 2fe2672e Stavros Sachtouris
    )
514 7493ccb6 Stavros Sachtouris
515 1395c40e Stavros Sachtouris
    @errors.generic.all
516 1395c40e Stavros Sachtouris
    @errors.pithos.connection
517 1395c40e Stavros Sachtouris
    @errors.pithos.container
518 1395c40e Stavros Sachtouris
    def _run(self):
519 de73876b Stavros Sachtouris
        self.client.container_put(
520 de73876b Stavros Sachtouris
            quota=self['quota'],
521 1395c40e Stavros Sachtouris
            versioning=self['versioning'],
522 1395c40e Stavros Sachtouris
            metadata=self['meta'])
523 1395c40e Stavros Sachtouris
524 edab7ba7 Stavros Sachtouris
    def main(self, container=None):
525 1395c40e Stavros Sachtouris
        super(self.__class__, self)._run(container)
526 edab7ba7 Stavros Sachtouris
        if container and self.container != container:
527 1395c40e Stavros Sachtouris
            raiseCLIError('Invalid container name %s' % container, details=[
528 edab7ba7 Stavros Sachtouris
                'Did you mean "%s" ?' % self.container,
529 52edad0a Stavros Sachtouris
                'Use --container for names containing :'])
530 1395c40e Stavros Sachtouris
        self._run()
531 7493ccb6 Stavros Sachtouris
532 234954d1 Stavros Sachtouris
533 d486baec Stavros Sachtouris
@command(pithos_cmds)
534 7493ccb6 Stavros Sachtouris
class store_copy(_store_container_command):
535 38b55954 Stavros Sachtouris
    """Copy objects from container to (another) container
536 38b55954 Stavros Sachtouris
    Semantics:
537 8249ee0f Stavros Sachtouris
    copy cont:path path2
538 8249ee0f Stavros Sachtouris
    .   will copy all <obj> prefixed with path, as path2<obj>
539 7a423d97 Stavros Sachtouris
    .   or as path2 if path corresponds to just one whole object
540 8249ee0f Stavros Sachtouris
    copy cont:path cont2:
541 8249ee0f Stavros Sachtouris
    .   will copy all <obj> prefixed with path to container cont2
542 8249ee0f Stavros Sachtouris
    copy cont:path [cont2:]path2 --exact-match
543 7a423d97 Stavros Sachtouris
    .   will copy at most one <obj> as a new object named path2,
544 7a423d97 Stavros Sachtouris
    .   provided path corresponds to a whole object path
545 8249ee0f Stavros Sachtouris
    copy cont:path [cont2:]path2 --replace
546 8249ee0f Stavros Sachtouris
    .   will copy all <obj> prefixed with path, replacing path with path2
547 8249ee0f Stavros Sachtouris
    where <obj> is a full file or directory object path.
548 2fe2672e Stavros Sachtouris
    Use options:
549 795bf206 Stavros Sachtouris
    1. <container1>:<path1> [container2:]<path2> : if container2 is not given,
550 795bf206 Stavros Sachtouris
    destination is container1:path2
551 795bf206 Stavros Sachtouris
    2. <container>:<path1> <path2> : make a copy in the same container
552 8249ee0f Stavros Sachtouris
    3. Can use --container= instead of <container1>
553 2fe2672e Stavros Sachtouris
    """
554 2fe2672e Stavros Sachtouris
555 2fe2672e Stavros Sachtouris
    arguments = dict(
556 e423eb63 Stavros Sachtouris
        destination_container=ValueArgument(
557 e423eb63 Stavros Sachtouris
            'use it if destination container name contains a : character',
558 e423eb63 Stavros Sachtouris
            '--dst-container'),
559 2fe2672e Stavros Sachtouris
        source_version=ValueArgument(
560 2fe2672e Stavros Sachtouris
            'copy specific version',
561 2fe2672e Stavros Sachtouris
            '--source-version'),
562 2fe2672e Stavros Sachtouris
        public=ValueArgument('make object publicly accessible', '--public'),
563 2fe2672e Stavros Sachtouris
        content_type=ValueArgument(
564 2fe2672e Stavros Sachtouris
            'change object\'s content type',
565 2fe2672e Stavros Sachtouris
            '--content-type'),
566 2fe2672e Stavros Sachtouris
        recursive=FlagArgument(
567 2fe2672e Stavros Sachtouris
            'mass copy with delimiter /',
568 35f78d77 Stavros Sachtouris
            ('-r', '--recursive')),
569 eb18b8a7 Stavros Sachtouris
        exact_match=FlagArgument(
570 eb18b8a7 Stavros Sachtouris
            'Copy only the object that fully matches path',
571 38b55954 Stavros Sachtouris
            '--exact-match'),
572 38b55954 Stavros Sachtouris
        replace=FlagArgument('Replace src. path with dst. path', '--replace')
573 2fe2672e Stavros Sachtouris
    )
574 7493ccb6 Stavros Sachtouris
575 7a423d97 Stavros Sachtouris
    def _objlist(self, dst_path):
576 eb18b8a7 Stavros Sachtouris
        if self['exact_match']:
577 52edad0a Stavros Sachtouris
            return [(dst_path or self.path, self.path)]
578 eb18b8a7 Stavros Sachtouris
        r = self.client.container_get(prefix=self.path)
579 7a423d97 Stavros Sachtouris
        if len(r.json) == 1:
580 7a423d97 Stavros Sachtouris
            obj = r.json[0]
581 52edad0a Stavros Sachtouris
            return [(obj['name'], dst_path or obj['name'])]
582 24ff0a35 Stavros Sachtouris
        start = len(self.path) if self['replace'] else 0
583 24ff0a35 Stavros Sachtouris
        return [(obj['name'], '%s%s' % (
584 24ff0a35 Stavros Sachtouris
            dst_path,
585 24ff0a35 Stavros Sachtouris
            obj['name'][start:])) for obj in r.json]
586 efdee310 Stavros Sachtouris
587 1395c40e Stavros Sachtouris
    @errors.generic.all
588 1395c40e Stavros Sachtouris
    @errors.pithos.connection
589 1395c40e Stavros Sachtouris
    @errors.pithos.container
590 1395c40e Stavros Sachtouris
    def _run(self, dst_cont, dst_path):
591 1395c40e Stavros Sachtouris
        no_source_object = True
592 1395c40e Stavros Sachtouris
        for src_object, dst_object in self._objlist(dst_path):
593 1395c40e Stavros Sachtouris
            no_source_object = False
594 1395c40e Stavros Sachtouris
            self.client.copy_object(
595 1395c40e Stavros Sachtouris
                src_container=self.container,
596 1395c40e Stavros Sachtouris
                src_object=src_object,
597 52edad0a Stavros Sachtouris
                dst_container=dst_cont or self.container,
598 1395c40e Stavros Sachtouris
                dst_object=dst_object,
599 1395c40e Stavros Sachtouris
                source_version=self['source_version'],
600 1395c40e Stavros Sachtouris
                public=self['public'],
601 1395c40e Stavros Sachtouris
                content_type=self['content_type'])
602 1395c40e Stavros Sachtouris
        if no_source_object:
603 1395c40e Stavros Sachtouris
            raiseCLIError('No object %s in container %s' % (
604 1395c40e Stavros Sachtouris
                self.path,
605 1395c40e Stavros Sachtouris
                self.container))
606 1395c40e Stavros Sachtouris
607 de73876b Stavros Sachtouris
    def main(
608 24ff0a35 Stavros Sachtouris
            self,
609 24ff0a35 Stavros Sachtouris
            source_container___path,
610 24ff0a35 Stavros Sachtouris
            destination_container___path=None):
611 1395c40e Stavros Sachtouris
        super(self.__class__, self)._run(
612 1395c40e Stavros Sachtouris
            source_container___path,
613 1395c40e Stavros Sachtouris
            path_is_optional=False)
614 1395c40e Stavros Sachtouris
        (dst_cont, dst_path) = self._dest_container_path(
615 0e4ee6d1 Stavros Sachtouris
            destination_container___path)
616 e423eb63 Stavros Sachtouris
        self._run(dst_cont=dst_cont, dst_path=dst_path or '')
617 7493ccb6 Stavros Sachtouris
618 234954d1 Stavros Sachtouris
619 d486baec Stavros Sachtouris
@command(pithos_cmds)
620 7493ccb6 Stavros Sachtouris
class store_move(_store_container_command):
621 38b55954 Stavros Sachtouris
    """Move/rename objects
622 8249ee0f Stavros Sachtouris
    Semantics:
623 8249ee0f Stavros Sachtouris
    move cont:path path2
624 8249ee0f Stavros Sachtouris
    .   will move all <obj> prefixed with path, as path2<obj>
625 7a423d97 Stavros Sachtouris
    .   or as path2 if path corresponds to just one whole object
626 8249ee0f Stavros Sachtouris
    move cont:path cont2:
627 8249ee0f Stavros Sachtouris
    .   will move all <obj> prefixed with path to container cont2
628 8249ee0f Stavros Sachtouris
    move cont:path [cont2:]path2 --exact-match
629 7a423d97 Stavros Sachtouris
    .   will move at most one <obj> as a new object named path2,
630 7a423d97 Stavros Sachtouris
    .   provided path corresponds to a whole object path
631 8249ee0f Stavros Sachtouris
    move cont:path [cont2:]path2 --replace
632 7a423d97 Stavros Sachtouris
    .   will move all <obj> prefixed with path, replacing path with path2
633 8249ee0f Stavros Sachtouris
    where <obj> is a full file or directory object path.
634 2fe2672e Stavros Sachtouris
    Use options:
635 795bf206 Stavros Sachtouris
    1. <container1>:<path1> [container2:]<path2> : if container2 not given,
636 795bf206 Stavros Sachtouris
    destination is container1:path2
637 795bf206 Stavros Sachtouris
    2. <container>:<path1> path2 : rename
638 8249ee0f Stavros Sachtouris
    3. Can use --container= instead of <container1>
639 2fe2672e Stavros Sachtouris
    """
640 2fe2672e Stavros Sachtouris
641 2fe2672e Stavros Sachtouris
    arguments = dict(
642 0e4ee6d1 Stavros Sachtouris
        destination_container=ValueArgument(
643 0e4ee6d1 Stavros Sachtouris
            'use it if destination container name contains a : character',
644 0e4ee6d1 Stavros Sachtouris
            '--dst-container'),
645 2fe2672e Stavros Sachtouris
        source_version=ValueArgument('specify version', '--source-version'),
646 2fe2672e Stavros Sachtouris
        public=FlagArgument('make object publicly accessible', '--public'),
647 2fe2672e Stavros Sachtouris
        content_type=ValueArgument('modify content type', '--content-type'),
648 38b55954 Stavros Sachtouris
        recursive=FlagArgument('up to delimiter /', ('-r', '--recursive')),
649 38b55954 Stavros Sachtouris
        exact_match=FlagArgument(
650 38b55954 Stavros Sachtouris
            'Copy only the object that fully matches path',
651 8249ee0f Stavros Sachtouris
            '--exact-match'),
652 8249ee0f Stavros Sachtouris
        replace=FlagArgument('Replace src. path with dst. path', '--replace')
653 2fe2672e Stavros Sachtouris
    )
654 7493ccb6 Stavros Sachtouris
655 7a423d97 Stavros Sachtouris
    def _objlist(self, dst_path):
656 8249ee0f Stavros Sachtouris
        if self['exact_match']:
657 52edad0a Stavros Sachtouris
            return [(dst_path or self.path, self.path)]
658 8249ee0f Stavros Sachtouris
        r = self.client.container_get(prefix=self.path)
659 7a423d97 Stavros Sachtouris
        if len(r.json) == 1:
660 7a423d97 Stavros Sachtouris
            obj = r.json[0]
661 52edad0a Stavros Sachtouris
            return [(obj['name'], dst_path or obj['name'])]
662 de73876b Stavros Sachtouris
        return [(
663 de73876b Stavros Sachtouris
            obj['name'],
664 de73876b Stavros Sachtouris
            '%s%s' % (
665 de73876b Stavros Sachtouris
                dst_path,
666 de73876b Stavros Sachtouris
                obj['name'][len(self.path) if self['replace'] else 0:]
667 de73876b Stavros Sachtouris
            )) for obj in r.json]
668 7493ccb6 Stavros Sachtouris
669 1395c40e Stavros Sachtouris
    @errors.generic.all
670 1395c40e Stavros Sachtouris
    @errors.pithos.connection
671 1395c40e Stavros Sachtouris
    @errors.pithos.container
672 1395c40e Stavros Sachtouris
    def _run(self, dst_cont, dst_path):
673 1395c40e Stavros Sachtouris
        no_source_object = True
674 1395c40e Stavros Sachtouris
        for src_object, dst_object in self._objlist(dst_path):
675 1395c40e Stavros Sachtouris
            no_source_object = False
676 1395c40e Stavros Sachtouris
            self.client.move_object(
677 1395c40e Stavros Sachtouris
                src_container=self.container,
678 1395c40e Stavros Sachtouris
                src_object=src_object,
679 52edad0a Stavros Sachtouris
                dst_container=dst_cont or self.container,
680 1395c40e Stavros Sachtouris
                dst_object=dst_object,
681 1395c40e Stavros Sachtouris
                source_version=self['source_version'],
682 1395c40e Stavros Sachtouris
                public=self['public'],
683 1395c40e Stavros Sachtouris
                content_type=self['content_type'])
684 1395c40e Stavros Sachtouris
        if no_source_object:
685 1395c40e Stavros Sachtouris
            raiseCLIError('No object %s in container %s' % (
686 1395c40e Stavros Sachtouris
                self.path,
687 1395c40e Stavros Sachtouris
                self.container))
688 1395c40e Stavros Sachtouris
689 de73876b Stavros Sachtouris
    def main(
690 24ff0a35 Stavros Sachtouris
            self,
691 24ff0a35 Stavros Sachtouris
            source_container___path,
692 24ff0a35 Stavros Sachtouris
            destination_container___path=None):
693 1395c40e Stavros Sachtouris
        super(self.__class__, self)._run(
694 1395c40e Stavros Sachtouris
            source_container___path,
695 1395c40e Stavros Sachtouris
            path_is_optional=False)
696 1395c40e Stavros Sachtouris
        (dst_cont, dst_path) = self._dest_container_path(
697 1395c40e Stavros Sachtouris
            destination_container___path)
698 0e4ee6d1 Stavros Sachtouris
        self._run(dst_cont=dst_cont, dst_path=dst_path or '')
699 7493ccb6 Stavros Sachtouris
700 234954d1 Stavros Sachtouris
701 d486baec Stavros Sachtouris
@command(pithos_cmds)
702 7493ccb6 Stavros Sachtouris
class store_append(_store_container_command):
703 aaca2ef4 Stavros Sachtouris
    """Append local file to (existing) remote object
704 aaca2ef4 Stavros Sachtouris
    The remote object should exist.
705 aaca2ef4 Stavros Sachtouris
    If the remote object is a directory, it is transformed into a file.
706 aaca2ef4 Stavros Sachtouris
    In the later case, objects under the directory remain intact.
707 aaca2ef4 Stavros Sachtouris
    """
708 7493ccb6 Stavros Sachtouris
709 2fe2672e Stavros Sachtouris
    arguments = dict(
710 2fe2672e Stavros Sachtouris
        progress_bar=ProgressBarArgument(
711 2fe2672e Stavros Sachtouris
            'do not show progress bar',
712 2fe2672e Stavros Sachtouris
            '--no-progress-bar',
713 2fe2672e Stavros Sachtouris
            default=False)
714 2fe2672e Stavros Sachtouris
    )
715 486f7af1 Stavros Sachtouris
716 ca092af4 Stavros Sachtouris
    @errors.generic.all
717 ca092af4 Stavros Sachtouris
    @errors.pithos.connection
718 ca092af4 Stavros Sachtouris
    @errors.pithos.container
719 ca092af4 Stavros Sachtouris
    @errors.pithos.object_path
720 ca092af4 Stavros Sachtouris
    def _run(self, local_path):
721 ca092af4 Stavros Sachtouris
        (progress_bar, upload_cb) = self._safe_progress_bar('Appending')
722 7493ccb6 Stavros Sachtouris
        try:
723 e876ac62 Stavros Sachtouris
            f = open(local_path, 'rb')
724 96ec49f2 Stavros Sachtouris
            self.client.append_object(self.path, f, upload_cb)
725 ca092af4 Stavros Sachtouris
        except Exception:
726 ca092af4 Stavros Sachtouris
            self._safe_progress_bar_finish(progress_bar)
727 ca092af4 Stavros Sachtouris
            raise
728 852a22e7 Stavros Sachtouris
        finally:
729 ca092af4 Stavros Sachtouris
            self._safe_progress_bar_finish(progress_bar)
730 ca092af4 Stavros Sachtouris
731 ca092af4 Stavros Sachtouris
    def main(self, local_path, container___path):
732 ca092af4 Stavros Sachtouris
        super(self.__class__, self)._run(
733 ca092af4 Stavros Sachtouris
            container___path,
734 ca092af4 Stavros Sachtouris
            path_is_optional=False)
735 ca092af4 Stavros Sachtouris
        self._run(local_path)
736 7493ccb6 Stavros Sachtouris
737 234954d1 Stavros Sachtouris
738 d486baec Stavros Sachtouris
@command(pithos_cmds)
739 7493ccb6 Stavros Sachtouris
class store_truncate(_store_container_command):
740 aaca2ef4 Stavros Sachtouris
    """Truncate remote file up to a size (default is 0)"""
741 7493ccb6 Stavros Sachtouris
742 ca092af4 Stavros Sachtouris
    @errors.generic.all
743 ca092af4 Stavros Sachtouris
    @errors.pithos.connection
744 ca092af4 Stavros Sachtouris
    @errors.pithos.container
745 ca092af4 Stavros Sachtouris
    @errors.pithos.object_path
746 ca092af4 Stavros Sachtouris
    @errors.pithos.object_size
747 ca092af4 Stavros Sachtouris
    def _run(self, size=0):
748 ca092af4 Stavros Sachtouris
        self.client.truncate_object(self.path, size)
749 ca092af4 Stavros Sachtouris
750 7493ccb6 Stavros Sachtouris
    def main(self, container___path, size=0):
751 ca092af4 Stavros Sachtouris
        super(self.__class__, self)._run(container___path)
752 ca092af4 Stavros Sachtouris
        self._run(size=size)
753 7493ccb6 Stavros Sachtouris
754 234954d1 Stavros Sachtouris
755 d486baec Stavros Sachtouris
@command(pithos_cmds)
756 7493ccb6 Stavros Sachtouris
class store_overwrite(_store_container_command):
757 aaca2ef4 Stavros Sachtouris
    """Overwrite part (from start to end) of a remote file
758 aaca2ef4 Stavros Sachtouris
    overwrite local-path container 10 20
759 aaca2ef4 Stavros Sachtouris
    .   will overwrite bytes from 10 to 20 of a remote file with the same name
760 aaca2ef4 Stavros Sachtouris
    .   as local-path basename
761 aaca2ef4 Stavros Sachtouris
    overwrite local-path container:path 10 20
762 aaca2ef4 Stavros Sachtouris
    .   will overwrite as above, but the remote file is named path
763 aaca2ef4 Stavros Sachtouris
    """
764 7493ccb6 Stavros Sachtouris
765 2fe2672e Stavros Sachtouris
    arguments = dict(
766 2fe2672e Stavros Sachtouris
        progress_bar=ProgressBarArgument(
767 2fe2672e Stavros Sachtouris
            'do not show progress bar',
768 439826ec Stavros Sachtouris
            '--no-progress-bar',
769 2fe2672e Stavros Sachtouris
            default=False)
770 2fe2672e Stavros Sachtouris
    )
771 486f7af1 Stavros Sachtouris
772 ca092af4 Stavros Sachtouris
    def _open_file(self, local_path, start):
773 ca092af4 Stavros Sachtouris
        f = open(path.abspath(local_path), 'rb')
774 ca092af4 Stavros Sachtouris
        f.seek(0, 2)
775 ca092af4 Stavros Sachtouris
        f_size = f.tell()
776 ca092af4 Stavros Sachtouris
        f.seek(start, 0)
777 ca092af4 Stavros Sachtouris
        return (f, f_size)
778 ca092af4 Stavros Sachtouris
779 ca092af4 Stavros Sachtouris
    @errors.generic.all
780 ca092af4 Stavros Sachtouris
    @errors.pithos.connection
781 ca092af4 Stavros Sachtouris
    @errors.pithos.container
782 ca092af4 Stavros Sachtouris
    @errors.pithos.object_path
783 ca092af4 Stavros Sachtouris
    @errors.pithos.object_size
784 ca092af4 Stavros Sachtouris
    def _run(self, local_path, start, end):
785 ca092af4 Stavros Sachtouris
        (start, end) = (int(start), int(end))
786 ca092af4 Stavros Sachtouris
        (f, f_size) = self._open_file(local_path, start)
787 ca092af4 Stavros Sachtouris
        (progress_bar, upload_cb) = self._safe_progress_bar(
788 ca092af4 Stavros Sachtouris
            'Overwrite %s bytes' % (end - start))
789 aaca2ef4 Stavros Sachtouris
        try:
790 8fa6ef6a Stavros Sachtouris
            self.client.overwrite_object(
791 8fa6ef6a Stavros Sachtouris
                obj=self.path,
792 234954d1 Stavros Sachtouris
                start=start,
793 234954d1 Stavros Sachtouris
                end=end,
794 234954d1 Stavros Sachtouris
                source_file=f,
795 234954d1 Stavros Sachtouris
                upload_cb=upload_cb)
796 ca092af4 Stavros Sachtouris
        except Exception:
797 ca092af4 Stavros Sachtouris
            self._safe_progress_bar_finish(progress_bar)
798 ca092af4 Stavros Sachtouris
            raise
799 852a22e7 Stavros Sachtouris
        finally:
800 ca092af4 Stavros Sachtouris
            self._safe_progress_bar_finish(progress_bar)
801 ca092af4 Stavros Sachtouris
802 52edad0a Stavros Sachtouris
    def main(self, local_path, container___path, start, end):
803 52edad0a Stavros Sachtouris
        super(self.__class__, self)._run(
804 52edad0a Stavros Sachtouris
            container___path,
805 52edad0a Stavros Sachtouris
            path_is_optional=None)
806 52edad0a Stavros Sachtouris
        self.path = self.path or path.basename(local_path)
807 ca092af4 Stavros Sachtouris
        self._run(local_path=local_path, start=start, end=end)
808 7493ccb6 Stavros Sachtouris
809 234954d1 Stavros Sachtouris
810 d486baec Stavros Sachtouris
@command(pithos_cmds)
811 486f7af1 Stavros Sachtouris
class store_manifest(_store_container_command):
812 8fa6ef6a Stavros Sachtouris
    """Create a remote file of uploaded parts by manifestation
813 35b52b0e Stavros Sachtouris
    Remains functional for compatibility with OOS Storage. Users are advised
814 35b52b0e Stavros Sachtouris
    to use the upload command instead.
815 35b52b0e Stavros Sachtouris
    Manifestation is a compliant process for uploading large files. The files
816 35b52b0e Stavros Sachtouris
    have to be chunked in smalled files and uploaded as <prefix><increment>
817 35b52b0e Stavros Sachtouris
    where increment is 1, 2, ...
818 35b52b0e Stavros Sachtouris
    Finally, the manifest command glues partial files together in one file
819 35b52b0e Stavros Sachtouris
    named <prefix>
820 35b52b0e Stavros Sachtouris
    The upload command is faster, easier and more intuitive than manifest
821 8fa6ef6a Stavros Sachtouris
    """
822 486f7af1 Stavros Sachtouris
823 2fe2672e Stavros Sachtouris
    arguments = dict(
824 2fe2672e Stavros Sachtouris
        etag=ValueArgument('check written data', '--etag'),
825 2fe2672e Stavros Sachtouris
        content_encoding=ValueArgument(
826 2fe2672e Stavros Sachtouris
            'set MIME content type',
827 2fe2672e Stavros Sachtouris
            '--content-encoding'),
828 2fe2672e Stavros Sachtouris
        content_disposition=ValueArgument(
829 2fe2672e Stavros Sachtouris
            'the presentation style of the object',
830 2fe2672e Stavros Sachtouris
            '--content-disposition'),
831 8fa6ef6a Stavros Sachtouris
        content_type=ValueArgument(
832 8fa6ef6a Stavros Sachtouris
            'specify content type',
833 8fa6ef6a Stavros Sachtouris
            '--content-type',
834 8fa6ef6a Stavros Sachtouris
            default='application/octet-stream'),
835 2fe2672e Stavros Sachtouris
        sharing=SharingArgument(
836 de73876b Stavros Sachtouris
            '\n'.join([
837 de73876b Stavros Sachtouris
                'define object sharing policy',
838 de73876b Stavros Sachtouris
                '    ( "read=user1,grp1,user2,... write=user1,grp2,..." )']),
839 2fe2672e Stavros Sachtouris
            '--sharing'),
840 2fe2672e Stavros Sachtouris
        public=FlagArgument('make object publicly accessible', '--public')
841 2fe2672e Stavros Sachtouris
    )
842 234954d1 Stavros Sachtouris
843 68858765 Stavros Sachtouris
    @errors.generic.all
844 68858765 Stavros Sachtouris
    @errors.pithos.connection
845 68858765 Stavros Sachtouris
    @errors.pithos.container
846 68858765 Stavros Sachtouris
    @errors.pithos.object_path
847 68858765 Stavros Sachtouris
    def _run(self):
848 68858765 Stavros Sachtouris
        self.client.create_object_by_manifestation(
849 68858765 Stavros Sachtouris
            self.path,
850 68858765 Stavros Sachtouris
            content_encoding=self['content_encoding'],
851 68858765 Stavros Sachtouris
            content_disposition=self['content_disposition'],
852 68858765 Stavros Sachtouris
            content_type=self['content_type'],
853 68858765 Stavros Sachtouris
            sharing=self['sharing'],
854 68858765 Stavros Sachtouris
            public=self['public'])
855 68858765 Stavros Sachtouris
856 7493ccb6 Stavros Sachtouris
    def main(self, container___path):
857 68858765 Stavros Sachtouris
        super(self.__class__, self)._run(
858 68858765 Stavros Sachtouris
            container___path,
859 68858765 Stavros Sachtouris
            path_is_optional=False)
860 68858765 Stavros Sachtouris
        self.run()
861 7493ccb6 Stavros Sachtouris
862 234954d1 Stavros Sachtouris
863 d486baec Stavros Sachtouris
@command(pithos_cmds)
864 7493ccb6 Stavros Sachtouris
class store_upload(_store_container_command):
865 7493ccb6 Stavros Sachtouris
    """Upload a file"""
866 7493ccb6 Stavros Sachtouris
867 2fe2672e Stavros Sachtouris
    arguments = dict(
868 2fe2672e Stavros Sachtouris
        use_hashes=FlagArgument(
869 2fe2672e Stavros Sachtouris
            'provide hashmap file instead of data',
870 2fe2672e Stavros Sachtouris
            '--use-hashes'),
871 2fe2672e Stavros Sachtouris
        etag=ValueArgument('check written data', '--etag'),
872 2fe2672e Stavros Sachtouris
        unchunked=FlagArgument('avoid chunked transfer mode', '--unchunked'),
873 2fe2672e Stavros Sachtouris
        content_encoding=ValueArgument(
874 2fe2672e Stavros Sachtouris
            'set MIME content type',
875 2fe2672e Stavros Sachtouris
            '--content-encoding'),
876 2fe2672e Stavros Sachtouris
        content_disposition=ValueArgument(
877 2fe2672e Stavros Sachtouris
            'specify objects presentation style',
878 2fe2672e Stavros Sachtouris
            '--content-disposition'),
879 2fe2672e Stavros Sachtouris
        content_type=ValueArgument('specify content type', '--content-type'),
880 2fe2672e Stavros Sachtouris
        sharing=SharingArgument(
881 de73876b Stavros Sachtouris
            help='\n'.join([
882 de73876b Stavros Sachtouris
                'define sharing object policy',
883 de73876b Stavros Sachtouris
                '( "read=user1,grp1,user2,... write=user1,grp2,... )']),
884 2fe2672e Stavros Sachtouris
            parsed_name='--sharing'),
885 2fe2672e Stavros Sachtouris
        public=FlagArgument('make object publicly accessible', '--public'),
886 2fe2672e Stavros Sachtouris
        poolsize=IntArgument('set pool size', '--with-pool-size'),
887 2fe2672e Stavros Sachtouris
        progress_bar=ProgressBarArgument(
888 2fe2672e Stavros Sachtouris
            'do not show progress bar',
889 2fe2672e Stavros Sachtouris
            '--no-progress-bar',
890 706fc940 Stavros Sachtouris
            default=False),
891 706fc940 Stavros Sachtouris
        overwrite=FlagArgument('Force overwrite, if object exists', '-f')
892 2fe2672e Stavros Sachtouris
    )
893 7493ccb6 Stavros Sachtouris
894 706fc940 Stavros Sachtouris
    def _remote_path(self, remote_path, local_path=''):
895 706fc940 Stavros Sachtouris
        if self['overwrite']:
896 706fc940 Stavros Sachtouris
            return remote_path
897 706fc940 Stavros Sachtouris
        try:
898 706fc940 Stavros Sachtouris
            r = self.client.get_object_info(remote_path)
899 706fc940 Stavros Sachtouris
        except ClientError as ce:
900 706fc940 Stavros Sachtouris
            if ce.status == 404:
901 706fc940 Stavros Sachtouris
                return remote_path
902 1f315e7b Stavros Sachtouris
            raise ce
903 706fc940 Stavros Sachtouris
        ctype = r.get('content-type', '')
904 706fc940 Stavros Sachtouris
        if 'application/directory' == ctype.lower():
905 706fc940 Stavros Sachtouris
            ret = '%s/%s' % (remote_path, local_path)
906 706fc940 Stavros Sachtouris
            return self._remote_path(ret) if local_path else ret
907 706fc940 Stavros Sachtouris
        raiseCLIError(
908 706fc940 Stavros Sachtouris
            'Object %s already exists' % remote_path,
909 706fc940 Stavros Sachtouris
            importance=1,
910 3e7d1e0e Stavros Sachtouris
            details=['use -f to overwrite or resume'])
911 706fc940 Stavros Sachtouris
912 68858765 Stavros Sachtouris
    @errors.generic.all
913 68858765 Stavros Sachtouris
    @errors.pithos.connection
914 68858765 Stavros Sachtouris
    @errors.pithos.container
915 68858765 Stavros Sachtouris
    @errors.pithos.object_path
916 68858765 Stavros Sachtouris
    @errors.pithos.local_path
917 68858765 Stavros Sachtouris
    def _run(self, local_path, remote_path):
918 2fe2672e Stavros Sachtouris
        poolsize = self['poolsize']
919 72952f4f Stavros Sachtouris
        if poolsize > 0:
920 cccff590 Stavros Sachtouris
            self.client.POOL_SIZE = int(poolsize)
921 72952f4f Stavros Sachtouris
        params = dict(
922 72952f4f Stavros Sachtouris
            content_encoding=self['content_encoding'],
923 2fe2672e Stavros Sachtouris
            content_type=self['content_type'],
924 2fe2672e Stavros Sachtouris
            content_disposition=self['content_disposition'],
925 2fe2672e Stavros Sachtouris
            sharing=self['sharing'],
926 2fe2672e Stavros Sachtouris
            public=self['public'])
927 68858765 Stavros Sachtouris
        remote_path = self._remote_path(remote_path, local_path)
928 68858765 Stavros Sachtouris
        with open(path.abspath(local_path), 'rb') as f:
929 68858765 Stavros Sachtouris
            if self['unchunked']:
930 68858765 Stavros Sachtouris
                self.client.upload_object_unchunked(
931 68858765 Stavros Sachtouris
                    remote_path,
932 68858765 Stavros Sachtouris
                    f,
933 68858765 Stavros Sachtouris
                    etag=self['etag'],
934 68858765 Stavros Sachtouris
                    withHashFile=self['use_hashes'],
935 68858765 Stavros Sachtouris
                    **params)
936 68858765 Stavros Sachtouris
            else:
937 68858765 Stavros Sachtouris
                try:
938 68858765 Stavros Sachtouris
                    (progress_bar, upload_cb) = self._safe_progress_bar(
939 68858765 Stavros Sachtouris
                        'Uploading')
940 68858765 Stavros Sachtouris
                    if progress_bar:
941 68858765 Stavros Sachtouris
                        hash_bar = progress_bar.clone()
942 68858765 Stavros Sachtouris
                        hash_cb = hash_bar.get_generator(
943 de73876b Stavros Sachtouris
                            'Calculating block hashes'
944 de73876b Stavros Sachtouris
                        )
945 68858765 Stavros Sachtouris
                    else:
946 68858765 Stavros Sachtouris
                        hash_cb = None
947 2fe2672e Stavros Sachtouris
                    self.client.upload_object(
948 2fe2672e Stavros Sachtouris
                        remote_path,
949 2fe2672e Stavros Sachtouris
                        f,
950 852a22e7 Stavros Sachtouris
                        hash_cb=hash_cb,
951 852a22e7 Stavros Sachtouris
                        upload_cb=upload_cb,
952 852a22e7 Stavros Sachtouris
                        **params)
953 68858765 Stavros Sachtouris
                except Exception:
954 68858765 Stavros Sachtouris
                    self._safe_progress_bar_finish(progress_bar)
955 68858765 Stavros Sachtouris
                    raise
956 68858765 Stavros Sachtouris
                finally:
957 68858765 Stavros Sachtouris
                    self._safe_progress_bar_finish(progress_bar)
958 f364f960 Stavros Sachtouris
        print 'Upload completed'
959 7493ccb6 Stavros Sachtouris
960 68858765 Stavros Sachtouris
    def main(self, local_path, container____path__=None):
961 68858765 Stavros Sachtouris
        super(self.__class__, self)._run(container____path__)
962 52edad0a Stavros Sachtouris
        remote_path = self.path or path.basename(local_path)
963 68858765 Stavros Sachtouris
        self._run(local_path=local_path, remote_path=remote_path)
964 68858765 Stavros Sachtouris
965 234954d1 Stavros Sachtouris
966 d486baec Stavros Sachtouris
@command(pithos_cmds)
967 9ceec15a Stavros Sachtouris
class store_cat(_store_container_command):
968 72952f4f Stavros Sachtouris
    """Print remote file contents to console"""
969 9ceec15a Stavros Sachtouris
970 2fe2672e Stavros Sachtouris
    arguments = dict(
971 2fe2672e Stavros Sachtouris
        range=RangeArgument('show range of data', '--range'),
972 2fe2672e Stavros Sachtouris
        if_match=ValueArgument('show output if ETags match', '--if-match'),
973 2fe2672e Stavros Sachtouris
        if_none_match=ValueArgument(
974 2fe2672e Stavros Sachtouris
            'show output if ETags match',
975 2fe2672e Stavros Sachtouris
            '--if-none-match'),
976 2fe2672e Stavros Sachtouris
        if_modified_since=DateArgument(
977 2fe2672e Stavros Sachtouris
            'show output modified since then',
978 2fe2672e Stavros Sachtouris
            '--if-modified-since'),
979 2fe2672e Stavros Sachtouris
        if_unmodified_since=DateArgument(
980 2fe2672e Stavros Sachtouris
            'show output unmodified since then',
981 2fe2672e Stavros Sachtouris
            '--if-unmodified-since'),
982 2fe2672e Stavros Sachtouris
        object_version=ValueArgument(
983 2fe2672e Stavros Sachtouris
            'get the specific version',
984 2fe2672e Stavros Sachtouris
            '--object-version')
985 2fe2672e Stavros Sachtouris
    )
986 2fe2672e Stavros Sachtouris
987 68858765 Stavros Sachtouris
    @errors.generic.all
988 68858765 Stavros Sachtouris
    @errors.pithos.connection
989 68858765 Stavros Sachtouris
    @errors.pithos.container
990 68858765 Stavros Sachtouris
    @errors.pithos.object_path
991 68858765 Stavros Sachtouris
    def _run(self):
992 68858765 Stavros Sachtouris
        self.client.download_object(
993 68858765 Stavros Sachtouris
            self.path,
994 68858765 Stavros Sachtouris
            stdout,
995 2fe2672e Stavros Sachtouris
            range=self['range'],
996 2fe2672e Stavros Sachtouris
            version=self['object_version'],
997 2fe2672e Stavros Sachtouris
            if_match=self['if_match'],
998 2fe2672e Stavros Sachtouris
            if_none_match=self['if_none_match'],
999 2fe2672e Stavros Sachtouris
            if_modified_since=self['if_modified_since'],
1000 2fe2672e Stavros Sachtouris
            if_unmodified_since=self['if_unmodified_since'])
1001 68858765 Stavros Sachtouris
1002 68858765 Stavros Sachtouris
    def main(self, container___path):
1003 68858765 Stavros Sachtouris
        super(self.__class__, self)._run(
1004 68858765 Stavros Sachtouris
            container___path,
1005 68858765 Stavros Sachtouris
            path_is_optional=False)
1006 68858765 Stavros Sachtouris
        self._run()
1007 9ceec15a Stavros Sachtouris
1008 234954d1 Stavros Sachtouris
1009 d486baec Stavros Sachtouris
@command(pithos_cmds)
1010 7493ccb6 Stavros Sachtouris
class store_download(_store_container_command):
1011 ae99b37d Stavros Sachtouris
    """Download remote object as local file
1012 ae99b37d Stavros Sachtouris
    If local destination is a directory:
1013 cdc4247b Stavros Sachtouris
    *   download <container>:<path> <local dir> -r
1014 ae99b37d Stavros Sachtouris
    will download all files on <container> prefixed as <path>,
1015 ae99b37d Stavros Sachtouris
    to <local dir>/<full path>
1016 ae99b37d Stavros Sachtouris
    *   download <container>:<path> <local dir> --exact-match
1017 ae99b37d Stavros Sachtouris
    will download only one file, exactly matching <path>
1018 f6c09d14 Stavros Sachtouris
    ATTENTION: to download cont:dir1/dir2/file there must exist objects
1019 f6c09d14 Stavros Sachtouris
    cont:dir1 and cont:dir1/dir2 of type application/directory
1020 f6c09d14 Stavros Sachtouris
    To create directory objects, use /store mkdir
1021 ae99b37d Stavros Sachtouris
    """
1022 7493ccb6 Stavros Sachtouris
1023 2fe2672e Stavros Sachtouris
    arguments = dict(
1024 2fe2672e Stavros Sachtouris
        resume=FlagArgument('Resume instead of overwrite', '--resume'),
1025 2fe2672e Stavros Sachtouris
        range=RangeArgument('show range of data', '--range'),
1026 2fe2672e Stavros Sachtouris
        if_match=ValueArgument('show output if ETags match', '--if-match'),
1027 2fe2672e Stavros Sachtouris
        if_none_match=ValueArgument(
1028 2fe2672e Stavros Sachtouris
            'show output if ETags match',
1029 2fe2672e Stavros Sachtouris
            '--if-none-match'),
1030 2fe2672e Stavros Sachtouris
        if_modified_since=DateArgument(
1031 2fe2672e Stavros Sachtouris
            'show output modified since then',
1032 2fe2672e Stavros Sachtouris
            '--if-modified-since'),
1033 2fe2672e Stavros Sachtouris
        if_unmodified_since=DateArgument(
1034 2fe2672e Stavros Sachtouris
            'show output unmodified since then',
1035 2fe2672e Stavros Sachtouris
            '--if-unmodified-since'),
1036 2fe2672e Stavros Sachtouris
        object_version=ValueArgument(
1037 2fe2672e Stavros Sachtouris
            'get the specific version',
1038 2fe2672e Stavros Sachtouris
            '--object-version'),
1039 2fe2672e Stavros Sachtouris
        poolsize=IntArgument('set pool size', '--with-pool-size'),
1040 2fe2672e Stavros Sachtouris
        progress_bar=ProgressBarArgument(
1041 2fe2672e Stavros Sachtouris
            'do not show progress bar',
1042 2fe2672e Stavros Sachtouris
            '--no-progress-bar',
1043 ae99b37d Stavros Sachtouris
            default=False),
1044 f6c09d14 Stavros Sachtouris
        recursive=FlagArgument(
1045 f6c09d14 Stavros Sachtouris
            'Download a remote directory and all its contents',
1046 24ff0a35 Stavros Sachtouris
            '-r, --recursive')
1047 2fe2672e Stavros Sachtouris
    )
1048 7493ccb6 Stavros Sachtouris
1049 f6c09d14 Stavros Sachtouris
    def _is_dir(self, remote_dict):
1050 f6c09d14 Stavros Sachtouris
        return 'application/directory' == remote_dict.get('content_type', '')
1051 f6c09d14 Stavros Sachtouris
1052 f6c09d14 Stavros Sachtouris
    def _outputs(self, local_path):
1053 1f315e7b Stavros Sachtouris
        if local_path is None:
1054 f6c09d14 Stavros Sachtouris
            return [(None, self.path)]
1055 ae99b37d Stavros Sachtouris
        outpath = path.abspath(local_path)
1056 f6c09d14 Stavros Sachtouris
        if not (path.exists(outpath) or path.isdir(outpath)):
1057 f6c09d14 Stavros Sachtouris
            return [(outpath, self.path)]
1058 f6c09d14 Stavros Sachtouris
        elif self['recursive']:
1059 f6c09d14 Stavros Sachtouris
            remotes = self.client.container_get(
1060 f6c09d14 Stavros Sachtouris
                prefix=self.path,
1061 f6c09d14 Stavros Sachtouris
                if_modified_since=self['if_modified_since'],
1062 f6c09d14 Stavros Sachtouris
                if_unmodified_since=self['if_unmodified_since'])
1063 f6c09d14 Stavros Sachtouris
            return [(
1064 f6c09d14 Stavros Sachtouris
                '%s/%s' % (outpath, remote['name']),
1065 de73876b Stavros Sachtouris
                None if self._is_dir(remote) else remote['name']
1066 de73876b Stavros Sachtouris
            ) for remote in remotes.json]
1067 f6c09d14 Stavros Sachtouris
        raiseCLIError('Illegal destination location %s' % local_path)
1068 7493ccb6 Stavros Sachtouris
1069 68858765 Stavros Sachtouris
    @errors.generic.all
1070 68858765 Stavros Sachtouris
    @errors.pithos.connection
1071 68858765 Stavros Sachtouris
    @errors.pithos.container
1072 68858765 Stavros Sachtouris
    @errors.pithos.object_path
1073 68858765 Stavros Sachtouris
    @errors.pithos.local_path
1074 68858765 Stavros Sachtouris
    def _run(self, local_path):
1075 f6c09d14 Stavros Sachtouris
        outputs = self._outputs(local_path)
1076 2fe2672e Stavros Sachtouris
        poolsize = self['poolsize']
1077 68858765 Stavros Sachtouris
        if poolsize:
1078 cccff590 Stavros Sachtouris
            self.client.POOL_SIZE = int(poolsize)
1079 f6c09d14 Stavros Sachtouris
        if not outputs:
1080 ae99b37d Stavros Sachtouris
            raiseCLIError('No objects prefixed as %s on container %s' % (
1081 1f315e7b Stavros Sachtouris
                self.path,
1082 ae99b37d Stavros Sachtouris
                self.container))
1083 f6c09d14 Stavros Sachtouris
        progress_bar = None
1084 ae99b37d Stavros Sachtouris
        try:
1085 f6c09d14 Stavros Sachtouris
            for lpath, rpath in sorted(outputs):
1086 f6c09d14 Stavros Sachtouris
                if not rpath:
1087 f6c09d14 Stavros Sachtouris
                    if not path.isdir(lpath):
1088 f6c09d14 Stavros Sachtouris
                        print('Create directory %s' % lpath)
1089 f6c09d14 Stavros Sachtouris
                        makedirs(lpath)
1090 f6c09d14 Stavros Sachtouris
                    continue
1091 b9ca5b73 Stavros Sachtouris
                wmode = 'rwb+' if path.exists(lpath) and self['resume']\
1092 b9ca5b73 Stavros Sachtouris
                    else 'wb+'
1093 f6c09d14 Stavros Sachtouris
                print('\nFrom %s:%s to %s' % (
1094 ae99b37d Stavros Sachtouris
                    self.container,
1095 ae99b37d Stavros Sachtouris
                    rpath,
1096 f6c09d14 Stavros Sachtouris
                    lpath))
1097 ae99b37d Stavros Sachtouris
                (progress_bar,
1098 ae99b37d Stavros Sachtouris
                    download_cb) = self._safe_progress_bar('Downloading')
1099 ae99b37d Stavros Sachtouris
                self.client.download_object(
1100 ae99b37d Stavros Sachtouris
                    rpath,
1101 f6c09d14 Stavros Sachtouris
                    open(lpath, wmode) if lpath else stdout,
1102 ae99b37d Stavros Sachtouris
                    download_cb=download_cb,
1103 ae99b37d Stavros Sachtouris
                    range=self['range'],
1104 ae99b37d Stavros Sachtouris
                    version=self['object_version'],
1105 ae99b37d Stavros Sachtouris
                    if_match=self['if_match'],
1106 ae99b37d Stavros Sachtouris
                    resume=self['resume'],
1107 ae99b37d Stavros Sachtouris
                    if_none_match=self['if_none_match'],
1108 ae99b37d Stavros Sachtouris
                    if_modified_since=self['if_modified_since'],
1109 ae99b37d Stavros Sachtouris
                    if_unmodified_since=self['if_unmodified_since'])
1110 7493ccb6 Stavros Sachtouris
        except KeyboardInterrupt:
1111 f27ed9a0 Stavros Sachtouris
            from threading import enumerate as activethreads
1112 f27ed9a0 Stavros Sachtouris
            stdout.write('\nFinishing active threads ')
1113 f27ed9a0 Stavros Sachtouris
            for thread in activethreads():
1114 f27ed9a0 Stavros Sachtouris
                stdout.flush()
1115 f27ed9a0 Stavros Sachtouris
                try:
1116 f27ed9a0 Stavros Sachtouris
                    thread.join()
1117 f27ed9a0 Stavros Sachtouris
                    stdout.write('.')
1118 f27ed9a0 Stavros Sachtouris
                except RuntimeError:
1119 f27ed9a0 Stavros Sachtouris
                    continue
1120 7493ccb6 Stavros Sachtouris
            print('\ndownload canceled by user')
1121 7493ccb6 Stavros Sachtouris
            if local_path is not None:
1122 624ee36f Stavros Sachtouris
                print('to resume, re-run with --resume')
1123 68858765 Stavros Sachtouris
        except Exception:
1124 68858765 Stavros Sachtouris
            self._safe_progress_bar_finish(progress_bar)
1125 68858765 Stavros Sachtouris
            raise
1126 68858765 Stavros Sachtouris
        finally:
1127 68858765 Stavros Sachtouris
            self._safe_progress_bar_finish(progress_bar)
1128 68858765 Stavros Sachtouris
1129 68858765 Stavros Sachtouris
    def main(self, container___path, local_path=None):
1130 68858765 Stavros Sachtouris
        super(self.__class__, self)._run(
1131 68858765 Stavros Sachtouris
            container___path,
1132 68858765 Stavros Sachtouris
            path_is_optional=False)
1133 68858765 Stavros Sachtouris
        self._run(local_path=local_path)
1134 7493ccb6 Stavros Sachtouris
1135 234954d1 Stavros Sachtouris
1136 d486baec Stavros Sachtouris
@command(pithos_cmds)
1137 7493ccb6 Stavros Sachtouris
class store_hashmap(_store_container_command):
1138 72952f4f Stavros Sachtouris
    """Get the hash-map of an object"""
1139 7493ccb6 Stavros Sachtouris
1140 2fe2672e Stavros Sachtouris
    arguments = dict(
1141 2fe2672e Stavros Sachtouris
        if_match=ValueArgument('show output if ETags match', '--if-match'),
1142 2fe2672e Stavros Sachtouris
        if_none_match=ValueArgument(
1143 2fe2672e Stavros Sachtouris
            'show output if ETags match',
1144 2fe2672e Stavros Sachtouris
            '--if-none-match'),
1145 2fe2672e Stavros Sachtouris
        if_modified_since=DateArgument(
1146 2fe2672e Stavros Sachtouris
            'show output modified since then',
1147 2fe2672e Stavros Sachtouris
            '--if-modified-since'),
1148 2fe2672e Stavros Sachtouris
        if_unmodified_since=DateArgument(
1149 2fe2672e Stavros Sachtouris
            'show output unmodified since then',
1150 2fe2672e Stavros Sachtouris
            '--if-unmodified-since'),
1151 2fe2672e Stavros Sachtouris
        object_version=ValueArgument(
1152 2fe2672e Stavros Sachtouris
            'get the specific version',
1153 2fe2672e Stavros Sachtouris
            '--object-version')
1154 2fe2672e Stavros Sachtouris
    )
1155 7493ccb6 Stavros Sachtouris
1156 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1157 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1158 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1159 b4cf92b8 Stavros Sachtouris
    @errors.pithos.object_path
1160 b4cf92b8 Stavros Sachtouris
    def _run(self):
1161 b4cf92b8 Stavros Sachtouris
        data = self.client.get_object_hashmap(
1162 b4cf92b8 Stavros Sachtouris
            self.path,
1163 b4cf92b8 Stavros Sachtouris
            version=self['object_version'],
1164 b4cf92b8 Stavros Sachtouris
            if_match=self['if_match'],
1165 b4cf92b8 Stavros Sachtouris
            if_none_match=self['if_none_match'],
1166 b4cf92b8 Stavros Sachtouris
            if_modified_since=self['if_modified_since'],
1167 b4cf92b8 Stavros Sachtouris
            if_unmodified_since=self['if_unmodified_since'])
1168 b4cf92b8 Stavros Sachtouris
        print_dict(data)
1169 b4cf92b8 Stavros Sachtouris
1170 7493ccb6 Stavros Sachtouris
    def main(self, container___path):
1171 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run(
1172 72952f4f Stavros Sachtouris
            container___path,
1173 72952f4f Stavros Sachtouris
            path_is_optional=False)
1174 b4cf92b8 Stavros Sachtouris
        self._run()
1175 7493ccb6 Stavros Sachtouris
1176 234954d1 Stavros Sachtouris
1177 d486baec Stavros Sachtouris
@command(pithos_cmds)
1178 7493ccb6 Stavros Sachtouris
class store_delete(_store_container_command):
1179 72952f4f Stavros Sachtouris
    """Delete a container [or an object]
1180 72952f4f Stavros Sachtouris
    How to delete a non-empty container:
1181 72952f4f Stavros Sachtouris
    - empty the container:  /store delete -r <container>
1182 72952f4f Stavros Sachtouris
    - delete it:            /store delete <container>
1183 72952f4f Stavros Sachtouris
    .
1184 72952f4f Stavros Sachtouris
    Semantics of directory deletion:
1185 72952f4f Stavros Sachtouris
    .a preserve the contents: /store delete <container>:<directory>
1186 72952f4f Stavros Sachtouris
    .    objects of the form dir/filename can exist with a dir object
1187 72952f4f Stavros Sachtouris
    .b delete contents:       /store delete -r <container>:<directory>
1188 72952f4f Stavros Sachtouris
    .    all dir/* objects are affected, even if dir does not exist
1189 72952f4f Stavros Sachtouris
    .
1190 72952f4f Stavros Sachtouris
    To restore a deleted object OBJ in a container CONT:
1191 72952f4f Stavros Sachtouris
    - get object versions: /store versions CONT:OBJ
1192 72952f4f Stavros Sachtouris
    .   and choose the version to be restored
1193 72952f4f Stavros Sachtouris
    - restore the object:  /store copy --source-version=<version> CONT:OBJ OBJ
1194 72952f4f Stavros Sachtouris
    """
1195 7493ccb6 Stavros Sachtouris
1196 2fe2672e Stavros Sachtouris
    arguments = dict(
1197 439826ec Stavros Sachtouris
        until=DateArgument('remove history until that date', '--until'),
1198 7147e1ca Stavros Sachtouris
        yes=FlagArgument('Do not prompt for permission', '--yes'),
1199 2fe2672e Stavros Sachtouris
        recursive=FlagArgument(
1200 234954d1 Stavros Sachtouris
            'empty dir or container and delete (if dir)',
1201 234954d1 Stavros Sachtouris
            ('-r', '--recursive'))
1202 2fe2672e Stavros Sachtouris
    )
1203 2fe2672e Stavros Sachtouris
1204 2fe2672e Stavros Sachtouris
    def __init__(self, arguments={}):
1205 2fe2672e Stavros Sachtouris
        super(self.__class__, self).__init__(arguments)
1206 439826ec Stavros Sachtouris
        self['delimiter'] = DelimiterArgument(
1207 2fe2672e Stavros Sachtouris
            self,
1208 234954d1 Stavros Sachtouris
            parsed_name='--delimiter',
1209 234954d1 Stavros Sachtouris
            help='delete objects prefixed with <object><delimiter>')
1210 7493ccb6 Stavros Sachtouris
1211 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1212 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1213 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1214 b4cf92b8 Stavros Sachtouris
    @errors.pithos.object_path
1215 b4cf92b8 Stavros Sachtouris
    def _run(self):
1216 b4cf92b8 Stavros Sachtouris
        if self.path:
1217 24ff0a35 Stavros Sachtouris
            if self['yes'] or ask_user(
1218 24ff0a35 Stavros Sachtouris
                    'Delete %s:%s ?' % (self.container, self.path)):
1219 b4cf92b8 Stavros Sachtouris
                self.client.del_object(
1220 b4cf92b8 Stavros Sachtouris
                    self.path,
1221 b4cf92b8 Stavros Sachtouris
                    until=self['until'],
1222 b4cf92b8 Stavros Sachtouris
                    delimiter=self['delimiter'])
1223 7493ccb6 Stavros Sachtouris
            else:
1224 b4cf92b8 Stavros Sachtouris
                print('Aborted')
1225 b4cf92b8 Stavros Sachtouris
        else:
1226 24ff0a35 Stavros Sachtouris
            if self['recursive']:
1227 de73876b Stavros Sachtouris
                ask_msg = 'Delete container contents'
1228 de73876b Stavros Sachtouris
            else:
1229 de73876b Stavros Sachtouris
                ask_msg = 'Delete container'
1230 b4cf92b8 Stavros Sachtouris
            if self['yes'] or ask_user('%s %s ?' % (ask_msg, self.container)):
1231 b4cf92b8 Stavros Sachtouris
                self.client.del_container(
1232 b4cf92b8 Stavros Sachtouris
                    until=self['until'],
1233 b4cf92b8 Stavros Sachtouris
                    delimiter=self['delimiter'])
1234 b4cf92b8 Stavros Sachtouris
            else:
1235 b4cf92b8 Stavros Sachtouris
                print('Aborted')
1236 b4cf92b8 Stavros Sachtouris
1237 edab7ba7 Stavros Sachtouris
    def main(self, container____path__=None):
1238 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run(container____path__)
1239 b4cf92b8 Stavros Sachtouris
        self._run()
1240 7493ccb6 Stavros Sachtouris
1241 234954d1 Stavros Sachtouris
1242 d486baec Stavros Sachtouris
@command(pithos_cmds)
1243 7493ccb6 Stavros Sachtouris
class store_purge(_store_container_command):
1244 72952f4f Stavros Sachtouris
    """Delete a container and release related data blocks
1245 72952f4f Stavros Sachtouris
    Non-empty containers can not purged.
1246 72952f4f Stavros Sachtouris
    To purge a container with content:
1247 439826ec Stavros Sachtouris
    .   /store delete -r <container>
1248 72952f4f Stavros Sachtouris
    .      objects are deleted, but data blocks remain on server
1249 72952f4f Stavros Sachtouris
    .   /store purge <container>
1250 72952f4f Stavros Sachtouris
    .      container and data blocks are released and deleted
1251 2fe2672e Stavros Sachtouris
    """
1252 234954d1 Stavros Sachtouris
1253 7147e1ca Stavros Sachtouris
    arguments = dict(
1254 7147e1ca Stavros Sachtouris
        yes=FlagArgument('Do not prompt for permission', '--yes'),
1255 7147e1ca Stavros Sachtouris
    )
1256 7147e1ca Stavros Sachtouris
1257 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1258 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1259 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1260 b4cf92b8 Stavros Sachtouris
    def _run(self):
1261 b4cf92b8 Stavros Sachtouris
        if self['yes'] or ask_user('Purge container %s?' % self.container):
1262 7147e1ca Stavros Sachtouris
                self.client.purge_container()
1263 b4cf92b8 Stavros Sachtouris
        else:
1264 b4cf92b8 Stavros Sachtouris
            print('Aborted')
1265 b4cf92b8 Stavros Sachtouris
1266 52edad0a Stavros Sachtouris
    def main(self, container=None):
1267 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run(container)
1268 52edad0a Stavros Sachtouris
        if container and self.container != container:
1269 52edad0a Stavros Sachtouris
            raiseCLIError('Invalid container name %s' % container, details=[
1270 52edad0a Stavros Sachtouris
                'Did you mean "%s" ?' % self.container,
1271 52edad0a Stavros Sachtouris
                'Use --container for names containing :'])
1272 b4cf92b8 Stavros Sachtouris
        self._run()
1273 7493ccb6 Stavros Sachtouris
1274 234954d1 Stavros Sachtouris
1275 d486baec Stavros Sachtouris
@command(pithos_cmds)
1276 7493ccb6 Stavros Sachtouris
class store_publish(_store_container_command):
1277 2fe2672e Stavros Sachtouris
    """Publish the object and print the public url"""
1278 7493ccb6 Stavros Sachtouris
1279 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1280 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1281 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1282 b4cf92b8 Stavros Sachtouris
    @errors.pithos.object_path
1283 b4cf92b8 Stavros Sachtouris
    def _run(self):
1284 b4cf92b8 Stavros Sachtouris
        url = self.client.publish_object(self.path)
1285 b4cf92b8 Stavros Sachtouris
        print(url)
1286 b4cf92b8 Stavros Sachtouris
1287 7493ccb6 Stavros Sachtouris
    def main(self, container___path):
1288 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run(
1289 72952f4f Stavros Sachtouris
            container___path,
1290 72952f4f Stavros Sachtouris
            path_is_optional=False)
1291 b4cf92b8 Stavros Sachtouris
        self._run()
1292 7493ccb6 Stavros Sachtouris
1293 234954d1 Stavros Sachtouris
1294 d486baec Stavros Sachtouris
@command(pithos_cmds)
1295 7493ccb6 Stavros Sachtouris
class store_unpublish(_store_container_command):
1296 7493ccb6 Stavros Sachtouris
    """Unpublish an object"""
1297 7493ccb6 Stavros Sachtouris
1298 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1299 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1300 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1301 b4cf92b8 Stavros Sachtouris
    @errors.pithos.object_path
1302 b4cf92b8 Stavros Sachtouris
    def _run(self):
1303 b4cf92b8 Stavros Sachtouris
            self.client.unpublish_object(self.path)
1304 b4cf92b8 Stavros Sachtouris
1305 7493ccb6 Stavros Sachtouris
    def main(self, container___path):
1306 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run(
1307 72952f4f Stavros Sachtouris
            container___path,
1308 72952f4f Stavros Sachtouris
            path_is_optional=False)
1309 b4cf92b8 Stavros Sachtouris
        self._run()
1310 7493ccb6 Stavros Sachtouris
1311 234954d1 Stavros Sachtouris
1312 d486baec Stavros Sachtouris
@command(pithos_cmds)
1313 3dabe5d2 Stavros Sachtouris
class store_permissions(_store_container_command):
1314 72952f4f Stavros Sachtouris
    """Get read and write permissions of an object
1315 72952f4f Stavros Sachtouris
    Permissions are lists of users and user groups. There is read and write
1316 72952f4f Stavros Sachtouris
    permissions. Users and groups with write permission have also read
1317 72952f4f Stavros Sachtouris
    permission.
1318 72952f4f Stavros Sachtouris
    """
1319 7493ccb6 Stavros Sachtouris
1320 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1321 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1322 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1323 b4cf92b8 Stavros Sachtouris
    @errors.pithos.object_path
1324 b4cf92b8 Stavros Sachtouris
    def _run(self):
1325 b4cf92b8 Stavros Sachtouris
        r = self.client.get_object_sharing(self.path)
1326 b4cf92b8 Stavros Sachtouris
        print_dict(r)
1327 b4cf92b8 Stavros Sachtouris
1328 7493ccb6 Stavros Sachtouris
    def main(self, container___path):
1329 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run(
1330 72952f4f Stavros Sachtouris
            container___path,
1331 72952f4f Stavros Sachtouris
            path_is_optional=False)
1332 b4cf92b8 Stavros Sachtouris
        self._run()
1333 7493ccb6 Stavros Sachtouris
1334 234954d1 Stavros Sachtouris
1335 d486baec Stavros Sachtouris
@command(pithos_cmds)
1336 3dabe5d2 Stavros Sachtouris
class store_setpermissions(_store_container_command):
1337 72952f4f Stavros Sachtouris
    """Set permissions for an object
1338 72952f4f Stavros Sachtouris
    New permissions overwrite existing permissions.
1339 72952f4f Stavros Sachtouris
    Permission format:
1340 72952f4f Stavros Sachtouris
    -   read=<username>[,usergroup[,...]]
1341 72952f4f Stavros Sachtouris
    -   write=<username>[,usegroup[,...]]
1342 72952f4f Stavros Sachtouris
    E.g. to give read permissions for file F to users A and B and write for C:
1343 72952f4f Stavros Sachtouris
    .       /store setpermissions F read=A,B write=C
1344 72952f4f Stavros Sachtouris
    """
1345 7493ccb6 Stavros Sachtouris
1346 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1347 3dabe5d2 Stavros Sachtouris
    def format_permition_dict(self, permissions):
1348 7493ccb6 Stavros Sachtouris
        read = False
1349 7493ccb6 Stavros Sachtouris
        write = False
1350 3dabe5d2 Stavros Sachtouris
        for perms in permissions:
1351 7493ccb6 Stavros Sachtouris
            splstr = perms.split('=')
1352 7493ccb6 Stavros Sachtouris
            if 'read' == splstr[0]:
1353 24ff0a35 Stavros Sachtouris
                read = [ug.strip() for ug in splstr[1].split(',')]
1354 7493ccb6 Stavros Sachtouris
            elif 'write' == splstr[0]:
1355 24ff0a35 Stavros Sachtouris
                write = [ug.strip() for ug in splstr[1].split(',')]
1356 7493ccb6 Stavros Sachtouris
            else:
1357 24ff0a35 Stavros Sachtouris
                msg = 'Usage:\tread=<groups,users> write=<groups,users>'
1358 24ff0a35 Stavros Sachtouris
                raiseCLIError(None, msg)
1359 234954d1 Stavros Sachtouris
        return (read, write)
1360 7493ccb6 Stavros Sachtouris
1361 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1362 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1363 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1364 b4cf92b8 Stavros Sachtouris
    @errors.pithos.object_path
1365 b4cf92b8 Stavros Sachtouris
    def _run(self, read, write):
1366 b4cf92b8 Stavros Sachtouris
        self.client.set_object_sharing(
1367 b4cf92b8 Stavros Sachtouris
            self.path,
1368 b4cf92b8 Stavros Sachtouris
            read_permition=read,
1369 b4cf92b8 Stavros Sachtouris
            write_permition=write)
1370 b4cf92b8 Stavros Sachtouris
1371 3dabe5d2 Stavros Sachtouris
    def main(self, container___path, *permissions):
1372 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run(
1373 b4cf92b8 Stavros Sachtouris
            container___path,
1374 b4cf92b8 Stavros Sachtouris
            path_is_optional=False)
1375 3dabe5d2 Stavros Sachtouris
        (read, write) = self.format_permition_dict(permissions)
1376 b4cf92b8 Stavros Sachtouris
        self._run(read, write)
1377 7493ccb6 Stavros Sachtouris
1378 234954d1 Stavros Sachtouris
1379 d486baec Stavros Sachtouris
@command(pithos_cmds)
1380 3dabe5d2 Stavros Sachtouris
class store_delpermissions(_store_container_command):
1381 72952f4f Stavros Sachtouris
    """Delete all permissions set on object
1382 72952f4f Stavros Sachtouris
    To modify permissions, use /store setpermssions
1383 72952f4f Stavros Sachtouris
    """
1384 7493ccb6 Stavros Sachtouris
1385 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1386 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1387 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1388 b4cf92b8 Stavros Sachtouris
    @errors.pithos.object_path
1389 b4cf92b8 Stavros Sachtouris
    def _run(self):
1390 b4cf92b8 Stavros Sachtouris
        self.client.del_object_sharing(self.path)
1391 b4cf92b8 Stavros Sachtouris
1392 7493ccb6 Stavros Sachtouris
    def main(self, container___path):
1393 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run(
1394 b4cf92b8 Stavros Sachtouris
            container___path,
1395 b4cf92b8 Stavros Sachtouris
            path_is_optional=False)
1396 b4cf92b8 Stavros Sachtouris
        self._run()
1397 7493ccb6 Stavros Sachtouris
1398 234954d1 Stavros Sachtouris
1399 d486baec Stavros Sachtouris
@command(pithos_cmds)
1400 7493ccb6 Stavros Sachtouris
class store_info(_store_container_command):
1401 72952f4f Stavros Sachtouris
    """Get detailed information for user account, containers or objects
1402 72952f4f Stavros Sachtouris
    to get account info:    /store info
1403 72952f4f Stavros Sachtouris
    to get container info:  /store info <container>
1404 72952f4f Stavros Sachtouris
    to get object info:     /store info <container>:<path>
1405 72952f4f Stavros Sachtouris
    """
1406 7493ccb6 Stavros Sachtouris
1407 2fe2672e Stavros Sachtouris
    arguments = dict(
1408 2fe2672e Stavros Sachtouris
        object_version=ValueArgument(
1409 2fe2672e Stavros Sachtouris
            'show specific version \ (applies only for objects)',
1410 2fe2672e Stavros Sachtouris
            '--object-version')
1411 2fe2672e Stavros Sachtouris
    )
1412 6ac7f90f Stavros Sachtouris
1413 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1414 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1415 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1416 b4cf92b8 Stavros Sachtouris
    @errors.pithos.object_path
1417 b4cf92b8 Stavros Sachtouris
    def _run(self):
1418 b4cf92b8 Stavros Sachtouris
        if self.container is None:
1419 b4cf92b8 Stavros Sachtouris
            r = self.client.get_account_info()
1420 b4cf92b8 Stavros Sachtouris
        elif self.path is None:
1421 b4cf92b8 Stavros Sachtouris
            r = self.client.get_container_info(self.container)
1422 b4cf92b8 Stavros Sachtouris
        else:
1423 b4cf92b8 Stavros Sachtouris
            r = self.client.get_object_info(
1424 b4cf92b8 Stavros Sachtouris
                self.path,
1425 b4cf92b8 Stavros Sachtouris
                version=self['object_version'])
1426 b4cf92b8 Stavros Sachtouris
        print_dict(r)
1427 b4cf92b8 Stavros Sachtouris
1428 7493ccb6 Stavros Sachtouris
    def main(self, container____path__=None):
1429 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run(container____path__)
1430 b4cf92b8 Stavros Sachtouris
        self._run()
1431 7493ccb6 Stavros Sachtouris
1432 234954d1 Stavros Sachtouris
1433 d486baec Stavros Sachtouris
@command(pithos_cmds)
1434 7493ccb6 Stavros Sachtouris
class store_meta(_store_container_command):
1435 72952f4f Stavros Sachtouris
    """Get metadata for account, containers or objects"""
1436 7493ccb6 Stavros Sachtouris
1437 2fe2672e Stavros Sachtouris
    arguments = dict(
1438 2fe2672e Stavros Sachtouris
        detail=FlagArgument('show detailed output', '-l'),
1439 2fe2672e Stavros Sachtouris
        until=DateArgument('show metadata until then', '--until'),
1440 2fe2672e Stavros Sachtouris
        object_version=ValueArgument(
1441 2fe2672e Stavros Sachtouris
            'show specific version \ (applies only for objects)',
1442 2fe2672e Stavros Sachtouris
            '--object-version')
1443 2fe2672e Stavros Sachtouris
    )
1444 7493ccb6 Stavros Sachtouris
1445 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1446 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1447 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1448 b4cf92b8 Stavros Sachtouris
    @errors.pithos.object_path
1449 b4cf92b8 Stavros Sachtouris
    def _run(self):
1450 b4cf92b8 Stavros Sachtouris
        until = self['until']
1451 b4cf92b8 Stavros Sachtouris
        if self.container is None:
1452 b4cf92b8 Stavros Sachtouris
            if self['detail']:
1453 b4cf92b8 Stavros Sachtouris
                r = self.client.get_account_info(until=until)
1454 7493ccb6 Stavros Sachtouris
            else:
1455 b4cf92b8 Stavros Sachtouris
                r = self.client.get_account_meta(until=until)
1456 b4cf92b8 Stavros Sachtouris
                r = pretty_keys(r, '-')
1457 b4cf92b8 Stavros Sachtouris
            if r:
1458 b4cf92b8 Stavros Sachtouris
                print(bold(self.client.account))
1459 b4cf92b8 Stavros Sachtouris
        elif self.path is None:
1460 b4cf92b8 Stavros Sachtouris
            if self['detail']:
1461 b4cf92b8 Stavros Sachtouris
                r = self.client.get_container_info(until=until)
1462 b4cf92b8 Stavros Sachtouris
            else:
1463 b4cf92b8 Stavros Sachtouris
                cmeta = self.client.get_container_meta(until=until)
1464 b4cf92b8 Stavros Sachtouris
                ometa = self.client.get_container_object_meta(until=until)
1465 b4cf92b8 Stavros Sachtouris
                r = {}
1466 b4cf92b8 Stavros Sachtouris
                if cmeta:
1467 b4cf92b8 Stavros Sachtouris
                    r['container-meta'] = pretty_keys(cmeta, '-')
1468 b4cf92b8 Stavros Sachtouris
                if ometa:
1469 b4cf92b8 Stavros Sachtouris
                    r['object-meta'] = pretty_keys(ometa, '-')
1470 b4cf92b8 Stavros Sachtouris
        else:
1471 b4cf92b8 Stavros Sachtouris
            if self['detail']:
1472 de73876b Stavros Sachtouris
                r = self.client.get_object_info(
1473 de73876b Stavros Sachtouris
                    self.path,
1474 b4cf92b8 Stavros Sachtouris
                    version=self['object_version'])
1475 b4cf92b8 Stavros Sachtouris
            else:
1476 de73876b Stavros Sachtouris
                r = self.client.get_object_meta(
1477 de73876b Stavros Sachtouris
                    self.path,
1478 b4cf92b8 Stavros Sachtouris
                    version=self['object_version'])
1479 b4cf92b8 Stavros Sachtouris
            if r:
1480 b4cf92b8 Stavros Sachtouris
                r = pretty_keys(pretty_keys(r, '-'))
1481 b4cf92b8 Stavros Sachtouris
        if r:
1482 b4cf92b8 Stavros Sachtouris
            print_dict(r)
1483 b4cf92b8 Stavros Sachtouris
1484 b4cf92b8 Stavros Sachtouris
    def main(self, container____path__=None):
1485 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run(container____path__)
1486 b4cf92b8 Stavros Sachtouris
        self._run()
1487 7493ccb6 Stavros Sachtouris
1488 234954d1 Stavros Sachtouris
1489 d486baec Stavros Sachtouris
@command(pithos_cmds)
1490 7493ccb6 Stavros Sachtouris
class store_setmeta(_store_container_command):
1491 72952f4f Stavros Sachtouris
    """Set a piece of metadata for account, container or object
1492 72952f4f Stavros Sachtouris
    Metadata are formed as key:value pairs
1493 72952f4f Stavros Sachtouris
    """
1494 7493ccb6 Stavros Sachtouris
1495 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1496 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1497 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1498 b4cf92b8 Stavros Sachtouris
    @errors.pithos.object_path
1499 b4cf92b8 Stavros Sachtouris
    def _run(self, metakey, metaval):
1500 b4cf92b8 Stavros Sachtouris
        if not self.container:
1501 b4cf92b8 Stavros Sachtouris
            self.client.set_account_meta({metakey: metaval})
1502 b4cf92b8 Stavros Sachtouris
        elif not self.path:
1503 b4cf92b8 Stavros Sachtouris
            self.client.set_container_meta({metakey: metaval})
1504 b4cf92b8 Stavros Sachtouris
        else:
1505 b4cf92b8 Stavros Sachtouris
            self.client.set_object_meta(self.path, {metakey: metaval})
1506 b4cf92b8 Stavros Sachtouris
1507 b4cf92b8 Stavros Sachtouris
    def main(self, metakey, metaval, container____path__=None):
1508 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run(container____path__)
1509 b4cf92b8 Stavros Sachtouris
        self._run(metakey=metakey, metaval=metaval)
1510 7493ccb6 Stavros Sachtouris
1511 234954d1 Stavros Sachtouris
1512 d486baec Stavros Sachtouris
@command(pithos_cmds)
1513 7493ccb6 Stavros Sachtouris
class store_delmeta(_store_container_command):
1514 72952f4f Stavros Sachtouris
    """Delete metadata with given key from account, container or object
1515 72952f4f Stavros Sachtouris
    Metadata are formed as key:value objects
1516 72952f4f Stavros Sachtouris
    - to get metadata of current account:     /store meta
1517 72952f4f Stavros Sachtouris
    - to get metadata of a container:         /store meta <container>
1518 72952f4f Stavros Sachtouris
    - to get metadata of an object:           /store meta <container>:<path>
1519 72952f4f Stavros Sachtouris
    """
1520 7493ccb6 Stavros Sachtouris
1521 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1522 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1523 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1524 b4cf92b8 Stavros Sachtouris
    @errors.pithos.object_path
1525 b4cf92b8 Stavros Sachtouris
    def _run(self, metakey):
1526 b4cf92b8 Stavros Sachtouris
        if self.container is None:
1527 b4cf92b8 Stavros Sachtouris
            self.client.del_account_meta(metakey)
1528 b4cf92b8 Stavros Sachtouris
        elif self.path is None:
1529 b4cf92b8 Stavros Sachtouris
            self.client.del_container_meta(metakey)
1530 b4cf92b8 Stavros Sachtouris
        else:
1531 b4cf92b8 Stavros Sachtouris
            self.client.del_object_meta(self.path, metakey)
1532 b4cf92b8 Stavros Sachtouris
1533 7493ccb6 Stavros Sachtouris
    def main(self, metakey, container____path__=None):
1534 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run(container____path__)
1535 b4cf92b8 Stavros Sachtouris
        self._run(metakey)
1536 7493ccb6 Stavros Sachtouris
1537 234954d1 Stavros Sachtouris
1538 d486baec Stavros Sachtouris
@command(pithos_cmds)
1539 7493ccb6 Stavros Sachtouris
class store_quota(_store_account_command):
1540 001200c3 Stavros Sachtouris
    """Get quota for account or container"""
1541 001200c3 Stavros Sachtouris
1542 001200c3 Stavros Sachtouris
    arguments = dict(
1543 001200c3 Stavros Sachtouris
        in_bytes=FlagArgument('Show result in bytes', ('-b', '--bytes'))
1544 de73876b Stavros Sachtouris
    )
1545 7493ccb6 Stavros Sachtouris
1546 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1547 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1548 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1549 b4cf92b8 Stavros Sachtouris
    def _run(self):
1550 52edad0a Stavros Sachtouris
        if self.container:
1551 b4cf92b8 Stavros Sachtouris
            reply = self.client.get_container_quota(self.container)
1552 52edad0a Stavros Sachtouris
        else:
1553 52edad0a Stavros Sachtouris
            reply = self.client.get_account_quota()
1554 001200c3 Stavros Sachtouris
        if not self['in_bytes']:
1555 001200c3 Stavros Sachtouris
            for k in reply:
1556 001200c3 Stavros Sachtouris
                reply[k] = format_size(reply[k])
1557 776eee69 Stavros Sachtouris
        print_dict(pretty_keys(reply, '-'))
1558 7493ccb6 Stavros Sachtouris
1559 b4cf92b8 Stavros Sachtouris
    def main(self, container=None):
1560 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run()
1561 b4cf92b8 Stavros Sachtouris
        self.container = container
1562 b4cf92b8 Stavros Sachtouris
        self._run()
1563 b4cf92b8 Stavros Sachtouris
1564 234954d1 Stavros Sachtouris
1565 d486baec Stavros Sachtouris
@command(pithos_cmds)
1566 7493ccb6 Stavros Sachtouris
class store_setquota(_store_account_command):
1567 001200c3 Stavros Sachtouris
    """Set new quota for account or container
1568 001200c3 Stavros Sachtouris
    By default, quota is set in bytes
1569 001200c3 Stavros Sachtouris
    Users may specify a different unit, e.g:
1570 001200c3 Stavros Sachtouris
    /store setquota 2.3GB mycontainer
1571 001200c3 Stavros Sachtouris
    Accepted units: B, KiB (1024 B), KB (1000 B), MiB, MB, GiB, GB, TiB, TB
1572 001200c3 Stavros Sachtouris
    """
1573 001200c3 Stavros Sachtouris
1574 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1575 001200c3 Stavros Sachtouris
    def _calculate_quota(self, user_input):
1576 001200c3 Stavros Sachtouris
        quota = 0
1577 001200c3 Stavros Sachtouris
        try:
1578 001200c3 Stavros Sachtouris
            quota = int(user_input)
1579 001200c3 Stavros Sachtouris
        except ValueError:
1580 001200c3 Stavros Sachtouris
            index = 0
1581 001200c3 Stavros Sachtouris
            digits = [str(num) for num in range(0, 10)] + ['.']
1582 001200c3 Stavros Sachtouris
            while user_input[index] in digits:
1583 001200c3 Stavros Sachtouris
                index += 1
1584 001200c3 Stavros Sachtouris
            quota = user_input[:index]
1585 001200c3 Stavros Sachtouris
            format = user_input[index:]
1586 001200c3 Stavros Sachtouris
            try:
1587 001200c3 Stavros Sachtouris
                return to_bytes(quota, format)
1588 001200c3 Stavros Sachtouris
            except Exception as qe:
1589 de73876b Stavros Sachtouris
                msg = 'Failed to convert %s to bytes' % user_input,
1590 de73876b Stavros Sachtouris
                raiseCLIError(qe, msg, details=[
1591 de73876b Stavros Sachtouris
                    'Syntax: setquota <quota>[format] [container]',
1592 de73876b Stavros Sachtouris
                    'e.g.: setquota 2.3GB mycontainer',
1593 de73876b Stavros Sachtouris
                    'Acceptable formats:',
1594 de73876b Stavros Sachtouris
                    '(*1024): B, KiB, MiB, GiB, TiB',
1595 de73876b Stavros Sachtouris
                    '(*1000): B, KB, MB, GB, TB'])
1596 001200c3 Stavros Sachtouris
        return quota
1597 7493ccb6 Stavros Sachtouris
1598 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1599 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1600 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1601 b4cf92b8 Stavros Sachtouris
    def _run(self, quota):
1602 b4cf92b8 Stavros Sachtouris
        if self.container:
1603 b4cf92b8 Stavros Sachtouris
            self.client.container = self.container
1604 b4cf92b8 Stavros Sachtouris
            self.client.set_container_quota(quota)
1605 b4cf92b8 Stavros Sachtouris
        else:
1606 b4cf92b8 Stavros Sachtouris
            self.client.set_account_quota(quota)
1607 b4cf92b8 Stavros Sachtouris
1608 234954d1 Stavros Sachtouris
    def main(self, quota, container=None):
1609 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run()
1610 001200c3 Stavros Sachtouris
        quota = self._calculate_quota(quota)
1611 b4cf92b8 Stavros Sachtouris
        self.container = container
1612 b4cf92b8 Stavros Sachtouris
        self._run(quota)
1613 7493ccb6 Stavros Sachtouris
1614 234954d1 Stavros Sachtouris
1615 d486baec Stavros Sachtouris
@command(pithos_cmds)
1616 7493ccb6 Stavros Sachtouris
class store_versioning(_store_account_command):
1617 776eee69 Stavros Sachtouris
    """Get  versioning for account or container"""
1618 7493ccb6 Stavros Sachtouris
1619 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1620 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1621 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1622 b4cf92b8 Stavros Sachtouris
    def _run(self):
1623 52edad0a Stavros Sachtouris
        if self.container:
1624 b4cf92b8 Stavros Sachtouris
            r = self.client.get_container_versioning(self.container)
1625 52edad0a Stavros Sachtouris
        else:
1626 52edad0a Stavros Sachtouris
            r = self.client.get_account_versioning()
1627 b4cf92b8 Stavros Sachtouris
        print_dict(r)
1628 b4cf92b8 Stavros Sachtouris
1629 234954d1 Stavros Sachtouris
    def main(self, container=None):
1630 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run()
1631 b4cf92b8 Stavros Sachtouris
        self.container = container
1632 b4cf92b8 Stavros Sachtouris
        self._run()
1633 7493ccb6 Stavros Sachtouris
1634 234954d1 Stavros Sachtouris
1635 d486baec Stavros Sachtouris
@command(pithos_cmds)
1636 7493ccb6 Stavros Sachtouris
class store_setversioning(_store_account_command):
1637 776eee69 Stavros Sachtouris
    """Set versioning mode (auto, none) for account or container"""
1638 7493ccb6 Stavros Sachtouris
1639 b4cf92b8 Stavros Sachtouris
    def _check_versioning(self, versioning):
1640 b4cf92b8 Stavros Sachtouris
        if versioning and versioning.lower() in ('auto', 'none'):
1641 b4cf92b8 Stavros Sachtouris
            return versioning.lower()
1642 b4cf92b8 Stavros Sachtouris
        raiseCLIError('Invalid versioning %s' % versioning, details=[
1643 b4cf92b8 Stavros Sachtouris
            'Versioning can be auto or none'])
1644 b4cf92b8 Stavros Sachtouris
1645 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1646 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1647 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1648 b4cf92b8 Stavros Sachtouris
    def _run(self, versioning):
1649 52edad0a Stavros Sachtouris
        if self.container:
1650 b4cf92b8 Stavros Sachtouris
            self.client.container = self.container
1651 b4cf92b8 Stavros Sachtouris
            self.client.set_container_versioning(versioning)
1652 52edad0a Stavros Sachtouris
        else:
1653 52edad0a Stavros Sachtouris
            self.client.set_account_versioning(versioning)
1654 b4cf92b8 Stavros Sachtouris
1655 234954d1 Stavros Sachtouris
    def main(self, versioning, container=None):
1656 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run()
1657 b4cf92b8 Stavros Sachtouris
        self._run(self._check_versioning(versioning))
1658 7493ccb6 Stavros Sachtouris
1659 234954d1 Stavros Sachtouris
1660 d486baec Stavros Sachtouris
@command(pithos_cmds)
1661 7493ccb6 Stavros Sachtouris
class store_group(_store_account_command):
1662 4fcc38a2 Stavros Sachtouris
    """Get groups and group members"""
1663 7493ccb6 Stavros Sachtouris
1664 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1665 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1666 b4cf92b8 Stavros Sachtouris
    def _run(self):
1667 b4cf92b8 Stavros Sachtouris
        r = self.client.get_account_group()
1668 b4cf92b8 Stavros Sachtouris
        print_dict(pretty_keys(r, '-'))
1669 b4cf92b8 Stavros Sachtouris
1670 7493ccb6 Stavros Sachtouris
    def main(self):
1671 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run()
1672 b4cf92b8 Stavros Sachtouris
        self._run()
1673 7493ccb6 Stavros Sachtouris
1674 234954d1 Stavros Sachtouris
1675 d486baec Stavros Sachtouris
@command(pithos_cmds)
1676 7493ccb6 Stavros Sachtouris
class store_setgroup(_store_account_command):
1677 4fcc38a2 Stavros Sachtouris
    """Set a user group"""
1678 7493ccb6 Stavros Sachtouris
1679 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1680 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1681 b4cf92b8 Stavros Sachtouris
    def _run(self, groupname, *users):
1682 b4cf92b8 Stavros Sachtouris
        self.client.set_account_group(groupname, users)
1683 b4cf92b8 Stavros Sachtouris
1684 7493ccb6 Stavros Sachtouris
    def main(self, groupname, *users):
1685 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run()
1686 b4cf92b8 Stavros Sachtouris
        if users:
1687 b4cf92b8 Stavros Sachtouris
            self._run(groupname, *users)
1688 b4cf92b8 Stavros Sachtouris
        else:
1689 b4cf92b8 Stavros Sachtouris
            raiseCLIError('No users to add in group %s' % groupname)
1690 7493ccb6 Stavros Sachtouris
1691 234954d1 Stavros Sachtouris
1692 d486baec Stavros Sachtouris
@command(pithos_cmds)
1693 7493ccb6 Stavros Sachtouris
class store_delgroup(_store_account_command):
1694 4fcc38a2 Stavros Sachtouris
    """Delete a user group"""
1695 7493ccb6 Stavros Sachtouris
1696 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1697 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1698 b4cf92b8 Stavros Sachtouris
    def _run(self, groupname):
1699 b4cf92b8 Stavros Sachtouris
        self.client.del_account_group(groupname)
1700 b4cf92b8 Stavros Sachtouris
1701 7493ccb6 Stavros Sachtouris
    def main(self, groupname):
1702 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run()
1703 b4cf92b8 Stavros Sachtouris
        self._run(groupname)
1704 a23f6ffe Stavros Sachtouris
1705 234954d1 Stavros Sachtouris
1706 d486baec Stavros Sachtouris
@command(pithos_cmds)
1707 a23f6ffe Stavros Sachtouris
class store_sharers(_store_account_command):
1708 4fcc38a2 Stavros Sachtouris
    """List the accounts that share objects with current user"""
1709 a23f6ffe Stavros Sachtouris
1710 2fe2672e Stavros Sachtouris
    arguments = dict(
1711 2fe2672e Stavros Sachtouris
        detail=FlagArgument('show detailed output', '-l'),
1712 2fe2672e Stavros Sachtouris
        marker=ValueArgument('show output greater then marker', '--marker')
1713 2fe2672e Stavros Sachtouris
    )
1714 a23f6ffe Stavros Sachtouris
1715 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1716 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1717 b4cf92b8 Stavros Sachtouris
    def _run(self):
1718 b4cf92b8 Stavros Sachtouris
        accounts = self.client.get_sharing_accounts(marker=self['marker'])
1719 24ff0a35 Stavros Sachtouris
        if self['detail']:
1720 24ff0a35 Stavros Sachtouris
            print_items(accounts)
1721 24ff0a35 Stavros Sachtouris
        else:
1722 24ff0a35 Stavros Sachtouris
            print_items([acc['name'] for acc in accounts])
1723 a23f6ffe Stavros Sachtouris
1724 b4cf92b8 Stavros Sachtouris
    def main(self):
1725 b4cf92b8 Stavros Sachtouris
        super(self.__class__, self)._run()
1726 b4cf92b8 Stavros Sachtouris
        self._run()
1727 38dc5d2f Stavros Sachtouris
1728 234954d1 Stavros Sachtouris
1729 d486baec Stavros Sachtouris
@command(pithos_cmds)
1730 38dc5d2f Stavros Sachtouris
class store_versions(_store_container_command):
1731 4fcc38a2 Stavros Sachtouris
    """Get the list of object versions
1732 4fcc38a2 Stavros Sachtouris
    Deleted objects may still have versions that can be used to restore it and
1733 4fcc38a2 Stavros Sachtouris
    get information about its previous state.
1734 4fcc38a2 Stavros Sachtouris
    The version number can be used in a number of other commands, like info,
1735 4fcc38a2 Stavros Sachtouris
    copy, move, meta. See these commands for more information, e.g.
1736 4fcc38a2 Stavros Sachtouris
    /store info -h
1737 4fcc38a2 Stavros Sachtouris
    """
1738 38dc5d2f Stavros Sachtouris
1739 b4cf92b8 Stavros Sachtouris
    @errors.generic.all
1740 b4cf92b8 Stavros Sachtouris
    @errors.pithos.connection
1741 b4cf92b8 Stavros Sachtouris
    @errors.pithos.container
1742 b4cf92b8 Stavros Sachtouris
    @errors.pithos.object_path
1743 b4cf92b8 Stavros Sachtouris
    def _run(self):
1744 b4cf92b8 Stavros Sachtouris
        versions = self.client.get_object_versionlist(self.path)
1745 24ff0a35 Stavros Sachtouris
        print_items([dict(id=vitem[0], created=strftime(
1746 24ff0a35 Stavros Sachtouris
            '%d-%m-%Y %H:%M:%S',
1747 24ff0a35 Stavros Sachtouris
            localtime(float(vitem[1])))) for vitem in versions])
1748 b4cf92b8 Stavros Sachtouris
1749 38dc5d2f Stavros Sachtouris
    def main(self, container___path):
1750 b4cf92b8 Stavros Sachtouris
        super(store_versions, self)._run(
1751 b4cf92b8 Stavros Sachtouris
            container___path,
1752 b4cf92b8 Stavros Sachtouris
            path_is_optional=False)
1753 b4cf92b8 Stavros Sachtouris
        self._run()