Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / commands / pithos_cli.py @ 7147e1ca

History | View | Annotate | Download (75.2 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 234954d1 Stavros Sachtouris
from kamaki.cli import command
35 d486baec Stavros Sachtouris
from kamaki.cli.command_tree import CommandTree
36 447c9568 Stavros Sachtouris
from kamaki.cli.errors import raiseCLIError, CLISyntaxError
37 7147e1ca Stavros Sachtouris
from kamaki.cli.utils import (
38 7147e1ca Stavros Sachtouris
    format_size,
39 7147e1ca Stavros Sachtouris
    print_dict,
40 7147e1ca Stavros Sachtouris
    pretty_keys,
41 7147e1ca Stavros Sachtouris
    page_hold,
42 7147e1ca Stavros Sachtouris
    ask_user)
43 e3d4d442 Stavros Sachtouris
from kamaki.cli.argument import FlagArgument, ValueArgument, IntArgument
44 04d01cd4 Stavros Sachtouris
from kamaki.cli.argument import KeyValueArgument, DateArgument
45 fd1f1d96 Stavros Sachtouris
from kamaki.cli.argument import ProgressBarArgument
46 0b9269d8 Stavros Sachtouris
from kamaki.cli.commands import _command_init
47 7493ccb6 Stavros Sachtouris
from kamaki.clients.pithos import PithosClient, ClientError
48 67cea04c Stavros Sachtouris
from kamaki.cli.utils import bold
49 1e29b9f6 Stavros Sachtouris
from sys import stdout
50 234954d1 Stavros Sachtouris
from time import localtime, strftime
51 451a7992 Stavros Sachtouris
from logging import getLogger
52 8fa6ef6a Stavros Sachtouris
from os import path
53 7493ccb6 Stavros Sachtouris
54 451a7992 Stavros Sachtouris
kloger = getLogger('kamaki')
55 234954d1 Stavros Sachtouris
56 d486baec Stavros Sachtouris
pithos_cmds = CommandTree('store', 'Pithos+ storage commands')
57 d486baec Stavros Sachtouris
_commands = [pithos_cmds]
58 234954d1 Stavros Sachtouris
59 7493ccb6 Stavros Sachtouris
60 1e29b9f6 Stavros Sachtouris
about_directories = [
61 1e29b9f6 Stavros Sachtouris
    'Kamaki hanldes directories the same way as OOS Storage and Pithos+:',
62 1e29b9f6 Stavros Sachtouris
    'A directory is an object with type "application/directory"',
63 1e29b9f6 Stavros Sachtouris
    'An object with path dir/name can exist even if dir does not exist or',
64 1e29b9f6 Stavros Sachtouris
    'even if dir is a non directory object. Users can modify dir without',
65 1e29b9f6 Stavros Sachtouris
    'affecting the dir/name object in any way.']
66 1e29b9f6 Stavros Sachtouris
67 1e29b9f6 Stavros Sachtouris
68 234954d1 Stavros Sachtouris
# Argument functionality
69 234954d1 Stavros Sachtouris
70 35f78d77 Stavros Sachtouris
def raise_connection_errors(e):
71 72952f4f Stavros Sachtouris
    if e.status in range(200) + [403, 401]:
72 35f78d77 Stavros Sachtouris
        raiseCLIError(e, details=[
73 35f78d77 Stavros Sachtouris
            'Please check the service url and the authentication information',
74 35f78d77 Stavros Sachtouris
            ' ',
75 35f78d77 Stavros Sachtouris
            '  to get the service url: /config get store.url',
76 35f78d77 Stavros Sachtouris
            '  to set the service url: /config set store.url <url>',
77 35f78d77 Stavros Sachtouris
            ' ',
78 35f78d77 Stavros Sachtouris
            '  to get user the account: /config get store.account',
79 35f78d77 Stavros Sachtouris
            '           or              /config get account',
80 35f78d77 Stavros Sachtouris
            '  to set the user account: /config set store.account <account>',
81 35f78d77 Stavros Sachtouris
            ' ',
82 35f78d77 Stavros Sachtouris
            '  to get authentication token: /config get token',
83 35f78d77 Stavros Sachtouris
            '  to set authentication token: /config set token <token>'
84 35f78d77 Stavros Sachtouris
            ])
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 776eee69 Stavros Sachtouris
            '-                  /store setquota <limit in KB> <container>'
92 776eee69 Stavros Sachtouris
            ])
93 35f78d77 Stavros Sachtouris
94 234954d1 Stavros Sachtouris
95 aaca2ef4 Stavros Sachtouris
def check_range(start, end):
96 aaca2ef4 Stavros Sachtouris
    """
97 aaca2ef4 Stavros Sachtouris
    :param start: (int)
98 aaca2ef4 Stavros Sachtouris

99 aaca2ef4 Stavros Sachtouris
    :param end: (int)
100 aaca2ef4 Stavros Sachtouris

101 aaca2ef4 Stavros Sachtouris
    :returns: (int(start), int(end))
102 aaca2ef4 Stavros Sachtouris

103 aaca2ef4 Stavros Sachtouris
    :raises CLIError - Invalid start/end value in range
104 aaca2ef4 Stavros Sachtouris
    :raises CLIError - Invalid range
105 aaca2ef4 Stavros Sachtouris
    """
106 aaca2ef4 Stavros Sachtouris
    try:
107 aaca2ef4 Stavros Sachtouris
        start = int(start)
108 aaca2ef4 Stavros Sachtouris
    except ValueError as e:
109 aaca2ef4 Stavros Sachtouris
        raiseCLIError(e, 'Invalid start value %s in range' % start)
110 aaca2ef4 Stavros Sachtouris
    try:
111 aaca2ef4 Stavros Sachtouris
        end = int(end)
112 aaca2ef4 Stavros Sachtouris
    except ValueError as e:
113 aaca2ef4 Stavros Sachtouris
        raiseCLIError(e, 'Invalid end value %s in range' % end)
114 aaca2ef4 Stavros Sachtouris
    if start > end:
115 aaca2ef4 Stavros Sachtouris
        raiseCLIError('Invalid range %s-%s' % (start, end))
116 aaca2ef4 Stavros Sachtouris
    return (start, end)
117 aaca2ef4 Stavros Sachtouris
118 aaca2ef4 Stavros Sachtouris
119 efdee310 Stavros Sachtouris
class DelimiterArgument(ValueArgument):
120 befed235 Stavros Sachtouris
    """
121 befed235 Stavros Sachtouris
    :value type: string
122 befed235 Stavros Sachtouris
    :value returns: given string or /
123 03d661d8 Stavros Sachtouris
    """
124 03d661d8 Stavros Sachtouris
125 efdee310 Stavros Sachtouris
    def __init__(self, caller_obj, help='', parsed_name=None, default=None):
126 efdee310 Stavros Sachtouris
        super(DelimiterArgument, self).__init__(help, parsed_name, default)
127 efdee310 Stavros Sachtouris
        self.caller_obj = caller_obj
128 efdee310 Stavros Sachtouris
129 234954d1 Stavros Sachtouris
    @property
130 efdee310 Stavros Sachtouris
    def value(self):
131 2fe2672e Stavros Sachtouris
        if self.caller_obj['recursive']:
132 efdee310 Stavros Sachtouris
            return '/'
133 efdee310 Stavros Sachtouris
        return getattr(self, '_value', self.default)
134 234954d1 Stavros Sachtouris
135 234954d1 Stavros Sachtouris
    @value.setter
136 efdee310 Stavros Sachtouris
    def value(self, newvalue):
137 efdee310 Stavros Sachtouris
        self._value = newvalue
138 efdee310 Stavros Sachtouris
139 234954d1 Stavros Sachtouris
140 befed235 Stavros Sachtouris
class SharingArgument(ValueArgument):
141 befed235 Stavros Sachtouris
    """Set sharing (read and/or write) groups
142 439826ec Stavros Sachtouris
    .
143 befed235 Stavros Sachtouris
    :value type: "read=term1,term2,... write=term1,term2,..."
144 439826ec Stavros Sachtouris
    .
145 befed235 Stavros Sachtouris
    :value returns: {'read':['term1', 'term2', ...],
146 439826ec Stavros Sachtouris
    .   'write':['term1', 'term2', ...]}
147 befed235 Stavros Sachtouris
    """
148 234954d1 Stavros Sachtouris
149 234954d1 Stavros Sachtouris
    @property
150 e3d4d442 Stavros Sachtouris
    def value(self):
151 e3d4d442 Stavros Sachtouris
        return getattr(self, '_value', self.default)
152 234954d1 Stavros Sachtouris
153 e3d4d442 Stavros Sachtouris
    @value.setter
154 e3d4d442 Stavros Sachtouris
    def value(self, newvalue):
155 e3d4d442 Stavros Sachtouris
        perms = {}
156 e3d4d442 Stavros Sachtouris
        try:
157 e3d4d442 Stavros Sachtouris
            permlist = newvalue.split(' ')
158 e3d4d442 Stavros Sachtouris
        except AttributeError:
159 e3d4d442 Stavros Sachtouris
            return
160 e3d4d442 Stavros Sachtouris
        for p in permlist:
161 e3d4d442 Stavros Sachtouris
            try:
162 234954d1 Stavros Sachtouris
                (key, val) = p.split('=')
163 83ba5545 Stavros Sachtouris
            except ValueError as err:
164 43ee6ae1 Stavros Sachtouris
                raiseCLIError(err, 'Error in --sharing',
165 234954d1 Stavros Sachtouris
                    details='Incorrect format',
166 234954d1 Stavros Sachtouris
                    importance=1)
167 e3d4d442 Stavros Sachtouris
            if key.lower() not in ('read', 'write'):
168 43ee6ae1 Stavros Sachtouris
                raiseCLIError(err, 'Error in --sharing',
169 83ba5545 Stavros Sachtouris
                    details='Invalid permission key %s' % key,
170 234954d1 Stavros Sachtouris
                    importance=1)
171 e3d4d442 Stavros Sachtouris
            val_list = val.split(',')
172 234954d1 Stavros Sachtouris
            if not key in perms:
173 234954d1 Stavros Sachtouris
                perms[key] = []
174 e3d4d442 Stavros Sachtouris
            for item in val_list:
175 e3d4d442 Stavros Sachtouris
                if item not in perms[key]:
176 e3d4d442 Stavros Sachtouris
                    perms[key].append(item)
177 e3d4d442 Stavros Sachtouris
        self._value = perms
178 e3d4d442 Stavros Sachtouris
179 234954d1 Stavros Sachtouris
180 e3d4d442 Stavros Sachtouris
class RangeArgument(ValueArgument):
181 befed235 Stavros Sachtouris
    """
182 439826ec Stavros Sachtouris
    :value type: string of the form <start>-<end> where <start> and <end> are
183 439826ec Stavros Sachtouris
        integers
184 befed235 Stavros Sachtouris
    :value returns: the input string, after type checking <start> and <end>
185 befed235 Stavros Sachtouris
    """
186 befed235 Stavros Sachtouris
187 234954d1 Stavros Sachtouris
    @property
188 e3d4d442 Stavros Sachtouris
    def value(self):
189 e3d4d442 Stavros Sachtouris
        return getattr(self, '_value', self.default)
190 234954d1 Stavros Sachtouris
191 e3d4d442 Stavros Sachtouris
    @value.setter
192 e3d4d442 Stavros Sachtouris
    def value(self, newvalue):
193 e3d4d442 Stavros Sachtouris
        if newvalue is None:
194 e3d4d442 Stavros Sachtouris
            self._value = self.default
195 e3d4d442 Stavros Sachtouris
            return
196 9ceec15a Stavros Sachtouris
        (start, end) = newvalue.split('-')
197 e3d4d442 Stavros Sachtouris
        (start, end) = (int(start), int(end))
198 234954d1 Stavros Sachtouris
        self._value = '%s-%s' % (start, end)
199 234954d1 Stavros Sachtouris
200 234954d1 Stavros Sachtouris
# Command specs
201 234954d1 Stavros Sachtouris
202 e3d4d442 Stavros Sachtouris
203 5eae854d Stavros Sachtouris
class _pithos_init(_command_init):
204 befed235 Stavros Sachtouris
    """Initialize a pithos+ kamaki client"""
205 befed235 Stavros Sachtouris
206 7493ccb6 Stavros Sachtouris
    def main(self):
207 234954d1 Stavros Sachtouris
        self.token = self.config.get('store', 'token')\
208 234954d1 Stavros Sachtouris
            or self.config.get('global', 'token')
209 234954d1 Stavros Sachtouris
        self.base_url = self.config.get('store', 'url')\
210 234954d1 Stavros Sachtouris
            or self.config.get('global', 'url')
211 234954d1 Stavros Sachtouris
        self.account = self.config.get('store', 'account')\
212 234954d1 Stavros Sachtouris
            or self.config.get('global', 'account')
213 234954d1 Stavros Sachtouris
        self.container = self.config.get('store', 'container')\
214 234954d1 Stavros Sachtouris
            or self.config.get('global', 'container')
215 234954d1 Stavros Sachtouris
        self.client = PithosClient(base_url=self.base_url,
216 234954d1 Stavros Sachtouris
            token=self.token,
217 234954d1 Stavros Sachtouris
            account=self.account,
218 7493ccb6 Stavros Sachtouris
            container=self.container)
219 7493ccb6 Stavros Sachtouris
220 234954d1 Stavros Sachtouris
221 7493ccb6 Stavros Sachtouris
class _store_account_command(_pithos_init):
222 7493ccb6 Stavros Sachtouris
    """Base class for account level storage commands"""
223 7493ccb6 Stavros Sachtouris
224 c41a86b2 Stavros Sachtouris
    def __init__(self, arguments={}):
225 c41a86b2 Stavros Sachtouris
        super(_store_account_command, self).__init__(arguments)
226 439826ec Stavros Sachtouris
        self['account'] = ValueArgument(
227 47ae7577 Stavros Sachtouris
            'Set user account (not permanent)',
228 47ae7577 Stavros Sachtouris
            '--account')
229 7493ccb6 Stavros Sachtouris
230 7493ccb6 Stavros Sachtouris
    def main(self):
231 7493ccb6 Stavros Sachtouris
        super(_store_account_command, self).main()
232 47ae7577 Stavros Sachtouris
        if self['account']:
233 47ae7577 Stavros Sachtouris
            self.client.account = self['account']
234 7493ccb6 Stavros Sachtouris
235 234954d1 Stavros Sachtouris
236 7493ccb6 Stavros Sachtouris
class _store_container_command(_store_account_command):
237 7493ccb6 Stavros Sachtouris
    """Base class for container level storage commands"""
238 7493ccb6 Stavros Sachtouris
239 439826ec Stavros Sachtouris
    generic_err_details = ['To specify a container:',
240 2d7ce81e Stavros Sachtouris
    '  1. Set store.container variable (permanent)',
241 2d7ce81e Stavros Sachtouris
    '     /config set store.container <container>',
242 2d7ce81e Stavros Sachtouris
    '  2. --container=<container> (temporary, overrides 1)',
243 439826ec Stavros Sachtouris
    '  3. Use the container:path format (temporary, overrides all)']
244 776eee69 Stavros Sachtouris
245 47ae7577 Stavros Sachtouris
    container = None
246 47ae7577 Stavros Sachtouris
    path = None
247 2d7ce81e Stavros Sachtouris
248 c41a86b2 Stavros Sachtouris
    def __init__(self, arguments={}):
249 c41a86b2 Stavros Sachtouris
        super(_store_container_command, self).__init__(arguments)
250 439826ec Stavros Sachtouris
        self['container'] = ValueArgument(
251 47ae7577 Stavros Sachtouris
            'Set container to work with (temporary)',
252 47ae7577 Stavros Sachtouris
            '--container')
253 7493ccb6 Stavros Sachtouris
254 234954d1 Stavros Sachtouris
    def extract_container_and_path(self,
255 234954d1 Stavros Sachtouris
        container_with_path,
256 234954d1 Stavros Sachtouris
        path_is_optional=True):
257 83ba5545 Stavros Sachtouris
        try:
258 83ba5545 Stavros Sachtouris
            assert isinstance(container_with_path, str)
259 83ba5545 Stavros Sachtouris
        except AssertionError as err:
260 83ba5545 Stavros Sachtouris
            raiseCLIError(err)
261 447c9568 Stavros Sachtouris
262 447c9568 Stavros Sachtouris
        cont, sep, path = container_with_path.partition(':')
263 447c9568 Stavros Sachtouris
264 447c9568 Stavros Sachtouris
        if sep:
265 447c9568 Stavros Sachtouris
            if not cont:
266 c1558584 Stavros Sachtouris
                raiseCLIError(CLISyntaxError('Container is missing\n',
267 2d7ce81e Stavros Sachtouris
                    details=self.generic_err_details))
268 47ae7577 Stavros Sachtouris
            alt_cont = self['container']
269 447c9568 Stavros Sachtouris
            if alt_cont and cont != alt_cont:
270 c1558584 Stavros Sachtouris
                raiseCLIError(CLISyntaxError(
271 447c9568 Stavros Sachtouris
                    'Conflict: 2 containers (%s, %s)' % (cont, alt_cont),
272 47ae7577 Stavros Sachtouris
                    details=self.generic_err_details)
273 47ae7577 Stavros Sachtouris
                )
274 447c9568 Stavros Sachtouris
            self.container = cont
275 447c9568 Stavros Sachtouris
            if not path:
276 c1558584 Stavros Sachtouris
                raiseCLIError(CLISyntaxError(
277 447c9568 Stavros Sachtouris
                    'Path is missing for object in container %s' % cont,
278 47ae7577 Stavros Sachtouris
                    details=self.generic_err_details)
279 47ae7577 Stavros Sachtouris
                )
280 447c9568 Stavros Sachtouris
            self.path = path
281 447c9568 Stavros Sachtouris
        else:
282 47ae7577 Stavros Sachtouris
            alt_cont = self['container'] or self.client.container
283 447c9568 Stavros Sachtouris
            if alt_cont:
284 447c9568 Stavros Sachtouris
                self.container = alt_cont
285 447c9568 Stavros Sachtouris
                self.path = cont
286 447c9568 Stavros Sachtouris
            elif path_is_optional:
287 447c9568 Stavros Sachtouris
                self.container = cont
288 7493ccb6 Stavros Sachtouris
                self.path = None
289 7493ccb6 Stavros Sachtouris
            else:
290 447c9568 Stavros Sachtouris
                self.container = cont
291 447c9568 Stavros Sachtouris
                raiseCLIError(CLISyntaxError(
292 c1558584 Stavros Sachtouris
                    'Both container and path are required',
293 47ae7577 Stavros Sachtouris
                    details=self.generic_err_details)
294 47ae7577 Stavros Sachtouris
                )
295 7493ccb6 Stavros Sachtouris
296 7493ccb6 Stavros Sachtouris
    def main(self, container_with_path=None, path_is_optional=True):
297 7493ccb6 Stavros Sachtouris
        super(_store_container_command, self).main()
298 7493ccb6 Stavros Sachtouris
        if container_with_path is not None:
299 47ae7577 Stavros Sachtouris
            self.extract_container_and_path(
300 47ae7577 Stavros Sachtouris
                container_with_path,
301 234954d1 Stavros Sachtouris
                path_is_optional)
302 7493ccb6 Stavros Sachtouris
            self.client.container = self.container
303 47ae7577 Stavros Sachtouris
        elif self['container']:
304 47ae7577 Stavros Sachtouris
            self.client.container = self['container']
305 7493ccb6 Stavros Sachtouris
        self.container = self.client.container
306 7493ccb6 Stavros Sachtouris
307 7493ccb6 Stavros Sachtouris
308 d486baec Stavros Sachtouris
@command(pithos_cmds)
309 7493ccb6 Stavros Sachtouris
class store_list(_store_container_command):
310 7493ccb6 Stavros Sachtouris
    """List containers, object trees or objects in a directory
311 2703cceb Stavros Sachtouris
    Use with:
312 2703cceb Stavros Sachtouris
    1 no parameters : containers in set account
313 2703cceb Stavros Sachtouris
    2. one parameter (container) or --container : contents of container
314 2703cceb Stavros Sachtouris
    3. <container>:<prefix> or --container=<container> <prefix>: objects in
315 439826ec Stavros Sachtouris
    .   container starting with prefix
316 7493ccb6 Stavros Sachtouris
    """
317 7493ccb6 Stavros Sachtouris
318 47ae7577 Stavros Sachtouris
    arguments = dict(
319 47ae7577 Stavros Sachtouris
        detail=FlagArgument('show detailed output', '-l'),
320 439826ec Stavros Sachtouris
        limit=IntArgument('limit the number of listed items', '-n'),
321 47ae7577 Stavros Sachtouris
        marker=ValueArgument('show output greater that marker', '--marker'),
322 439826ec Stavros Sachtouris
        prefix=ValueArgument('show output starting with prefix', '--prefix'),
323 47ae7577 Stavros Sachtouris
        delimiter=ValueArgument('show output up to delimiter', '--delimiter'),
324 47ae7577 Stavros Sachtouris
        path=ValueArgument(
325 47ae7577 Stavros Sachtouris
            'show output starting with prefix up to /',
326 47ae7577 Stavros Sachtouris
            '--path'),
327 47ae7577 Stavros Sachtouris
        meta=ValueArgument(
328 47ae7577 Stavros Sachtouris
            'show output with specified meta keys',
329 47ae7577 Stavros Sachtouris
            '--meta',
330 47ae7577 Stavros Sachtouris
            default=[]),
331 47ae7577 Stavros Sachtouris
        if_modified_since=ValueArgument(
332 47ae7577 Stavros Sachtouris
            'show output modified since then',
333 47ae7577 Stavros Sachtouris
            '--if-modified-since'),
334 47ae7577 Stavros Sachtouris
        if_unmodified_since=ValueArgument(
335 47ae7577 Stavros Sachtouris
            'show output not modified since then',
336 47ae7577 Stavros Sachtouris
            '--if-unmodified-since'),
337 47ae7577 Stavros Sachtouris
        until=DateArgument('show metadata until then', '--until'),
338 47ae7577 Stavros Sachtouris
        format=ValueArgument(
339 47ae7577 Stavros Sachtouris
            'format to parse until data (default: d/m/Y H:M:S )',
340 47ae7577 Stavros Sachtouris
            '--format'),
341 47ae7577 Stavros Sachtouris
        shared=FlagArgument('show only shared', '--shared'),
342 47ae7577 Stavros Sachtouris
        public=FlagArgument('show only public', '--public'),
343 439826ec Stavros Sachtouris
        more=FlagArgument(
344 439826ec Stavros Sachtouris
            'output results in pages (-n to set items per page, default 10)',
345 eb18b8a7 Stavros Sachtouris
            '--more'),
346 eb18b8a7 Stavros Sachtouris
        exact_match=FlagArgument(
347 eb18b8a7 Stavros Sachtouris
            'Show only objects that match exactly with path',
348 eb18b8a7 Stavros Sachtouris
            '--exact-match')
349 47ae7577 Stavros Sachtouris
    )
350 c41a86b2 Stavros Sachtouris
351 7493ccb6 Stavros Sachtouris
    def print_objects(self, object_list):
352 439826ec Stavros Sachtouris
        limit = int(self['limit']) if self['limit'] > 0 else len(object_list)
353 234954d1 Stavros Sachtouris
        for index, obj in enumerate(object_list):
354 eb18b8a7 Stavros Sachtouris
            if (self['exact_match'] and self.path and\
355 eb18b8a7 Stavros Sachtouris
                obj['name'] != self.path) or 'content_type' not in obj:
356 7493ccb6 Stavros Sachtouris
                continue
357 7493ccb6 Stavros Sachtouris
            pretty_obj = obj.copy()
358 7493ccb6 Stavros Sachtouris
            index += 1
359 234954d1 Stavros Sachtouris
            empty_space = ' ' * (len(str(len(object_list))) - len(str(index)))
360 7493ccb6 Stavros Sachtouris
            if obj['content_type'] == 'application/directory':
361 7493ccb6 Stavros Sachtouris
                isDir = True
362 7493ccb6 Stavros Sachtouris
                size = 'D'
363 7493ccb6 Stavros Sachtouris
            else:
364 7493ccb6 Stavros Sachtouris
                isDir = False
365 7493ccb6 Stavros Sachtouris
                size = format_size(obj['bytes'])
366 234954d1 Stavros Sachtouris
                pretty_obj['bytes'] = '%s (%s)' % (obj['bytes'], size)
367 7493ccb6 Stavros Sachtouris
            oname = bold(obj['name'])
368 47ae7577 Stavros Sachtouris
            if self['detail']:
369 234954d1 Stavros Sachtouris
                print('%s%s. %s' % (empty_space, index, oname))
370 7493ccb6 Stavros Sachtouris
                print_dict(pretty_keys(pretty_obj), exclude=('name'))
371 7493ccb6 Stavros Sachtouris
                print
372 7493ccb6 Stavros Sachtouris
            else:
373 234954d1 Stavros Sachtouris
                oname = '%s%s. %6s %s' % (empty_space, index, size, oname)
374 7493ccb6 Stavros Sachtouris
                oname += '/' if isDir else ''
375 7493ccb6 Stavros Sachtouris
                print(oname)
376 439826ec Stavros Sachtouris
            if self['more']:
377 439826ec Stavros Sachtouris
                page_hold(index, limit, len(object_list))
378 7493ccb6 Stavros Sachtouris
379 7493ccb6 Stavros Sachtouris
    def print_containers(self, container_list):
380 439826ec Stavros Sachtouris
        limit = int(self['limit']) if self['limit'] > 0\
381 439826ec Stavros Sachtouris
            else len(container_list)
382 234954d1 Stavros Sachtouris
        for index, container in enumerate(container_list):
383 234954d1 Stavros Sachtouris
            if 'bytes' in container:
384 234954d1 Stavros Sachtouris
                size = format_size(container['bytes'])
385 234954d1 Stavros Sachtouris
            cname = '%s. %s' % (index + 1, bold(container['name']))
386 47ae7577 Stavros Sachtouris
            if self['detail']:
387 7493ccb6 Stavros Sachtouris
                print(cname)
388 7493ccb6 Stavros Sachtouris
                pretty_c = container.copy()
389 234954d1 Stavros Sachtouris
                if 'bytes' in container:
390 234954d1 Stavros Sachtouris
                    pretty_c['bytes'] = '%s (%s)' % (container['bytes'], size)
391 7493ccb6 Stavros Sachtouris
                print_dict(pretty_keys(pretty_c), exclude=('name'))
392 7493ccb6 Stavros Sachtouris
                print
393 7493ccb6 Stavros Sachtouris
            else:
394 234954d1 Stavros Sachtouris
                if 'count' in container and 'bytes' in container:
395 234954d1 Stavros Sachtouris
                    print('%s (%s, %s objects)'\
396 234954d1 Stavros Sachtouris
                    % (cname, size, container['count']))
397 7493ccb6 Stavros Sachtouris
                else:
398 7493ccb6 Stavros Sachtouris
                    print(cname)
399 439826ec Stavros Sachtouris
            if self['more']:
400 439826ec Stavros Sachtouris
                page_hold(index + 1, limit, len(container_list))
401 7493ccb6 Stavros Sachtouris
402 7493ccb6 Stavros Sachtouris
    def main(self, container____path__=None):
403 7493ccb6 Stavros Sachtouris
        super(self.__class__, self).main(container____path__)
404 7493ccb6 Stavros Sachtouris
        try:
405 7493ccb6 Stavros Sachtouris
            if self.container is None:
406 47ae7577 Stavros Sachtouris
                r = self.client.account_get(
407 439826ec Stavros Sachtouris
                    limit=False if self['more'] else self['limit'],
408 47ae7577 Stavros Sachtouris
                    marker=self['marker'],
409 47ae7577 Stavros Sachtouris
                    if_modified_since=self['if_modified_since'],
410 47ae7577 Stavros Sachtouris
                    if_unmodified_since=self['if_unmodified_since'],
411 47ae7577 Stavros Sachtouris
                    until=self['until'],
412 47ae7577 Stavros Sachtouris
                    show_only_shared=self['shared'])
413 7493ccb6 Stavros Sachtouris
                self.print_containers(r.json)
414 7493ccb6 Stavros Sachtouris
            else:
415 eb18b8a7 Stavros Sachtouris
                prefix = self.path if self.path else self['prefix']
416 47ae7577 Stavros Sachtouris
                r = self.client.container_get(
417 439826ec Stavros Sachtouris
                    limit=False if self['more'] else self['limit'],
418 47ae7577 Stavros Sachtouris
                    marker=self['marker'],
419 2d7ce81e Stavros Sachtouris
                    prefix=prefix,
420 47ae7577 Stavros Sachtouris
                    delimiter=self['delimiter'],
421 47ae7577 Stavros Sachtouris
                    path=self['path'],
422 47ae7577 Stavros Sachtouris
                    if_modified_since=self['if_modified_since'],
423 47ae7577 Stavros Sachtouris
                    if_unmodified_since=self['if_unmodified_since'],
424 47ae7577 Stavros Sachtouris
                    until=self['until'],
425 47ae7577 Stavros Sachtouris
                    meta=self['meta'],
426 47ae7577 Stavros Sachtouris
                    show_only_shared=self['shared'])
427 7493ccb6 Stavros Sachtouris
                self.print_objects(r.json)
428 7493ccb6 Stavros Sachtouris
        except ClientError as err:
429 c8e17a67 Stavros Sachtouris
            if err.status == 404:
430 439826ec Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
431 47ae7577 Stavros Sachtouris
                    raiseCLIError(
432 47ae7577 Stavros Sachtouris
                        err,
433 47ae7577 Stavros Sachtouris
                        'No container %s in account %s'\
434 c8e17a67 Stavros Sachtouris
                        % (self.container, self.account),
435 c8e17a67 Stavros Sachtouris
                        details=self.generic_err_details)
436 439826ec Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
437 47ae7577 Stavros Sachtouris
                    raiseCLIError(
438 47ae7577 Stavros Sachtouris
                        err,
439 47ae7577 Stavros Sachtouris
                        'No object %s in %s\'s container %s'\
440 c8e17a67 Stavros Sachtouris
                        % (self.path, self.account, self.container),
441 c8e17a67 Stavros Sachtouris
                        details=self.generic_err_details)
442 35f78d77 Stavros Sachtouris
            raise_connection_errors(err)
443 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
444 439826ec Stavros Sachtouris
        except Exception as e:
445 439826ec Stavros Sachtouris
            raiseCLIError(e)
446 7493ccb6 Stavros Sachtouris
447 234954d1 Stavros Sachtouris
448 d486baec Stavros Sachtouris
@command(pithos_cmds)
449 7493ccb6 Stavros Sachtouris
class store_mkdir(_store_container_command):
450 f5d9bc54 Stavros Sachtouris
    """Create a directory"""
451 1e29b9f6 Stavros Sachtouris
452 1e29b9f6 Stavros Sachtouris
    __doc__ += '\n. '.join(about_directories)
453 7493ccb6 Stavros Sachtouris
454 7493ccb6 Stavros Sachtouris
    def main(self, container___directory):
455 234954d1 Stavros Sachtouris
        super(self.__class__,
456 234954d1 Stavros Sachtouris
            self).main(container___directory, path_is_optional=False)
457 7493ccb6 Stavros Sachtouris
        try:
458 7493ccb6 Stavros Sachtouris
            self.client.create_directory(self.path)
459 7493ccb6 Stavros Sachtouris
        except ClientError as err:
460 1e29b9f6 Stavros Sachtouris
            if err.status == 404:
461 1e29b9f6 Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
462 1e29b9f6 Stavros Sachtouris
                    raiseCLIError(
463 1e29b9f6 Stavros Sachtouris
                        err,
464 1e29b9f6 Stavros Sachtouris
                        'No container %s in account %s'\
465 1e29b9f6 Stavros Sachtouris
                        % (self.container, self.account),
466 1e29b9f6 Stavros Sachtouris
                        details=self.generic_err_details)
467 8fa6ef6a Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
468 8fa6ef6a Stavros Sachtouris
                    raiseCLIError(
469 8fa6ef6a Stavros Sachtouris
                        err,
470 8fa6ef6a Stavros Sachtouris
                        'No object %s in container %s'\
471 8fa6ef6a Stavros Sachtouris
                        % (self.path, self.container),
472 8fa6ef6a Stavros Sachtouris
                        details=self.generic_err_details)
473 35f78d77 Stavros Sachtouris
            raise_connection_errors(err)
474 1e29b9f6 Stavros Sachtouris
            raiseCLIError(err)
475 1e29b9f6 Stavros Sachtouris
        except Exception as err:
476 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
477 7493ccb6 Stavros Sachtouris
478 234954d1 Stavros Sachtouris
479 d486baec Stavros Sachtouris
@command(pithos_cmds)
480 1e29b9f6 Stavros Sachtouris
class store_touch(_store_container_command):
481 1e29b9f6 Stavros Sachtouris
    """Create an empty object (file)
482 1e29b9f6 Stavros Sachtouris
    If object exists, this command will reset it to 0 length
483 1e29b9f6 Stavros Sachtouris
    """
484 1e29b9f6 Stavros Sachtouris
485 1e29b9f6 Stavros Sachtouris
    arguments = dict(
486 1e29b9f6 Stavros Sachtouris
        content_type=ValueArgument(
487 1e29b9f6 Stavros Sachtouris
            'Set content type (default: application/octet-stream)',
488 1e29b9f6 Stavros Sachtouris
            '--content-type',
489 1e29b9f6 Stavros Sachtouris
            default='application/octet-stream')
490 1e29b9f6 Stavros Sachtouris
    )
491 1e29b9f6 Stavros Sachtouris
492 1e29b9f6 Stavros Sachtouris
    def main(self, container___path):
493 1e29b9f6 Stavros Sachtouris
        super(store_touch, self).main(container___path)
494 1e29b9f6 Stavros Sachtouris
        try:
495 1e29b9f6 Stavros Sachtouris
            self.client.create_object(self.path, self['content_type'])
496 1e29b9f6 Stavros Sachtouris
        except ClientError as err:
497 1e29b9f6 Stavros Sachtouris
            if err.status == 404:
498 1e29b9f6 Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
499 1e29b9f6 Stavros Sachtouris
                    raiseCLIError(
500 1e29b9f6 Stavros Sachtouris
                        err,
501 1e29b9f6 Stavros Sachtouris
                        'No container %s in account %s'\
502 1e29b9f6 Stavros Sachtouris
                        % (self.container, self.account),
503 1e29b9f6 Stavros Sachtouris
                        details=self.generic_err_details)
504 8fa6ef6a Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
505 8fa6ef6a Stavros Sachtouris
                    raiseCLIError(
506 8fa6ef6a Stavros Sachtouris
                        err,
507 8fa6ef6a Stavros Sachtouris
                        'No object %s in container %s'\
508 8fa6ef6a Stavros Sachtouris
                        % (self.path, self.container),
509 8fa6ef6a Stavros Sachtouris
                        details=self.generic_err_details)
510 35f78d77 Stavros Sachtouris
            raise_connection_errors(err)
511 1e29b9f6 Stavros Sachtouris
            raiseCLIError(err)
512 1e29b9f6 Stavros Sachtouris
        except Exception as err:
513 1e29b9f6 Stavros Sachtouris
            raiseCLIError(err)
514 1e29b9f6 Stavros Sachtouris
515 1e29b9f6 Stavros Sachtouris
516 1e29b9f6 Stavros Sachtouris
@command(pithos_cmds)
517 72952f4f Stavros Sachtouris
class store_create(_store_container_command):
518 1e29b9f6 Stavros Sachtouris
    """Create a container"""
519 7493ccb6 Stavros Sachtouris
520 2fe2672e Stavros Sachtouris
    arguments = dict(
521 2fe2672e Stavros Sachtouris
        versioning=ValueArgument(
522 2fe2672e Stavros Sachtouris
            'set container versioning (auto/none)',
523 2fe2672e Stavros Sachtouris
            '--versioning'),
524 2fe2672e Stavros Sachtouris
        quota=IntArgument('set default container quota', '--quota'),
525 2fe2672e Stavros Sachtouris
        meta=KeyValueArgument(
526 2fe2672e Stavros Sachtouris
            'set container metadata (can be repeated)',
527 2fe2672e Stavros Sachtouris
            '--meta')
528 2fe2672e Stavros Sachtouris
    )
529 7493ccb6 Stavros Sachtouris
530 1e29b9f6 Stavros Sachtouris
    def main(self, container):
531 1e29b9f6 Stavros Sachtouris
        super(self.__class__, self).main(container)
532 7493ccb6 Stavros Sachtouris
        try:
533 1e29b9f6 Stavros Sachtouris
            self.client.container_put(quota=self['quota'],
534 1e29b9f6 Stavros Sachtouris
                versioning=self['versioning'],
535 1e29b9f6 Stavros Sachtouris
                metadata=self['meta'])
536 7493ccb6 Stavros Sachtouris
        except ClientError as err:
537 1e29b9f6 Stavros Sachtouris
            if err.status == 404:
538 1e29b9f6 Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
539 1e29b9f6 Stavros Sachtouris
                    raiseCLIError(
540 1e29b9f6 Stavros Sachtouris
                        err,
541 1e29b9f6 Stavros Sachtouris
                        'No container %s in account %s'\
542 1e29b9f6 Stavros Sachtouris
                        % (self.container, self.account),
543 1e29b9f6 Stavros Sachtouris
                        details=self.generic_err_details)
544 8fa6ef6a Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
545 8fa6ef6a Stavros Sachtouris
                    raiseCLIError(
546 8fa6ef6a Stavros Sachtouris
                        err,
547 8fa6ef6a Stavros Sachtouris
                        'No object %s in container %s'\
548 8fa6ef6a Stavros Sachtouris
                        % (self.path, self.container),
549 8fa6ef6a Stavros Sachtouris
                        details=self.generic_err_details)
550 35f78d77 Stavros Sachtouris
            raise_connection_errors(err)
551 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
552 1e29b9f6 Stavros Sachtouris
        except Exception as e:
553 1e29b9f6 Stavros Sachtouris
            raiseCLIError(e)
554 7493ccb6 Stavros Sachtouris
555 234954d1 Stavros Sachtouris
556 d486baec Stavros Sachtouris
@command(pithos_cmds)
557 7493ccb6 Stavros Sachtouris
class store_copy(_store_container_command):
558 38b55954 Stavros Sachtouris
    """Copy objects from container to (another) container
559 38b55954 Stavros Sachtouris
    Semantics:
560 8249ee0f Stavros Sachtouris
    copy cont:path path2
561 8249ee0f Stavros Sachtouris
    .   will copy all <obj> prefixed with path, as path2<obj>
562 7a423d97 Stavros Sachtouris
    .   or as path2 if path corresponds to just one whole object
563 8249ee0f Stavros Sachtouris
    copy cont:path cont2:
564 8249ee0f Stavros Sachtouris
    .   will copy all <obj> prefixed with path to container cont2
565 8249ee0f Stavros Sachtouris
    copy cont:path [cont2:]path2 --exact-match
566 7a423d97 Stavros Sachtouris
    .   will copy at most one <obj> as a new object named path2,
567 7a423d97 Stavros Sachtouris
    .   provided path corresponds to a whole object path
568 8249ee0f Stavros Sachtouris
    copy cont:path [cont2:]path2 --replace
569 8249ee0f Stavros Sachtouris
    .   will copy all <obj> prefixed with path, replacing path with path2
570 8249ee0f Stavros Sachtouris
    where <obj> is a full file or directory object path.
571 2fe2672e Stavros Sachtouris
    Use options:
572 795bf206 Stavros Sachtouris
    1. <container1>:<path1> [container2:]<path2> : if container2 is not given,
573 795bf206 Stavros Sachtouris
    destination is container1:path2
574 795bf206 Stavros Sachtouris
    2. <container>:<path1> <path2> : make a copy in the same container
575 8249ee0f Stavros Sachtouris
    3. Can use --container= instead of <container1>
576 2fe2672e Stavros Sachtouris
    """
577 2fe2672e Stavros Sachtouris
578 2fe2672e Stavros Sachtouris
    arguments = dict(
579 2fe2672e Stavros Sachtouris
        source_version=ValueArgument(
580 2fe2672e Stavros Sachtouris
            'copy specific version',
581 2fe2672e Stavros Sachtouris
            '--source-version'),
582 2fe2672e Stavros Sachtouris
        public=ValueArgument('make object publicly accessible', '--public'),
583 2fe2672e Stavros Sachtouris
        content_type=ValueArgument(
584 2fe2672e Stavros Sachtouris
            'change object\'s content type',
585 2fe2672e Stavros Sachtouris
            '--content-type'),
586 2fe2672e Stavros Sachtouris
        recursive=FlagArgument(
587 2fe2672e Stavros Sachtouris
            'mass copy with delimiter /',
588 35f78d77 Stavros Sachtouris
            ('-r', '--recursive')),
589 eb18b8a7 Stavros Sachtouris
        exact_match=FlagArgument(
590 eb18b8a7 Stavros Sachtouris
            'Copy only the object that fully matches path',
591 38b55954 Stavros Sachtouris
            '--exact-match'),
592 38b55954 Stavros Sachtouris
        replace=FlagArgument('Replace src. path with dst. path', '--replace')
593 2fe2672e Stavros Sachtouris
    )
594 7493ccb6 Stavros Sachtouris
595 7a423d97 Stavros Sachtouris
    def _objlist(self, dst_path):
596 eb18b8a7 Stavros Sachtouris
        if self['exact_match']:
597 aaca2ef4 Stavros Sachtouris
            return [(dst_path if dst_path else self.path, self.path)]
598 eb18b8a7 Stavros Sachtouris
        r = self.client.container_get(prefix=self.path)
599 7a423d97 Stavros Sachtouris
        if len(r.json) == 1:
600 7a423d97 Stavros Sachtouris
            obj = r.json[0]
601 7a423d97 Stavros Sachtouris
            return [(obj['name'], dst_path if dst_path else obj['name'])]
602 7a423d97 Stavros Sachtouris
        return [(obj['name'], '%s%s' % (
603 7a423d97 Stavros Sachtouris
                    dst_path,
604 7a423d97 Stavros Sachtouris
                    obj['name'][len(self.path) if self['replace'] else 0:])
605 7a423d97 Stavros Sachtouris
                ) for obj in r.json]
606 efdee310 Stavros Sachtouris
607 eb18b8a7 Stavros Sachtouris
    def main(self, source_container___path, destination_container___path):
608 234954d1 Stavros Sachtouris
        super(self.__class__,
609 234954d1 Stavros Sachtouris
            self).main(source_container___path, path_is_optional=False)
610 7493ccb6 Stavros Sachtouris
        try:
611 eb18b8a7 Stavros Sachtouris
            dst = destination_container___path.split(':')
612 795bf206 Stavros Sachtouris
            (dst_cont, dst_path) = (dst[0], dst[1])\
613 795bf206 Stavros Sachtouris
            if len(dst) > 1 else (None, dst[0])
614 7a423d97 Stavros Sachtouris
            for src_object, dst_object in self._objlist(dst_path):
615 eb18b8a7 Stavros Sachtouris
                self.client.copy_object(src_container=self.container,
616 eb18b8a7 Stavros Sachtouris
                    src_object=src_object,
617 eb18b8a7 Stavros Sachtouris
                    dst_container=dst_cont if dst_cont else self.container,
618 7a423d97 Stavros Sachtouris
                    dst_object=dst_object,
619 eb18b8a7 Stavros Sachtouris
                    source_version=self['source_version'],
620 eb18b8a7 Stavros Sachtouris
                    public=self['public'],
621 eb18b8a7 Stavros Sachtouris
                    content_type=self['content_type'])
622 7493ccb6 Stavros Sachtouris
        except ClientError as err:
623 35f78d77 Stavros Sachtouris
            if err.status == 404:
624 72952f4f Stavros Sachtouris
                if 'object' in ('%s' % err).lower():
625 72952f4f Stavros Sachtouris
                    raiseCLIError(
626 72952f4f Stavros Sachtouris
                        err,
627 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
628 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
629 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
630 72952f4f Stavros Sachtouris
                elif 'container' in ('%s' % err).lower():
631 795bf206 Stavros Sachtouris
                    cont_msg = '(either %s or %s)' % (
632 795bf206 Stavros Sachtouris
                        self.container,
633 795bf206 Stavros Sachtouris
                        dst_cont
634 795bf206 Stavros Sachtouris
                    ) if dst_cont else self.container
635 35f78d77 Stavros Sachtouris
                    raiseCLIError(
636 35f78d77 Stavros Sachtouris
                        err,
637 35f78d77 Stavros Sachtouris
                        'No container %s in account %s'\
638 795bf206 Stavros Sachtouris
                        % (cont_msg, self.account),
639 35f78d77 Stavros Sachtouris
                        details=self.generic_err_details)
640 35f78d77 Stavros Sachtouris
            raise_connection_errors(err)
641 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
642 35f78d77 Stavros Sachtouris
        except Exception as e:
643 35f78d77 Stavros Sachtouris
            raiseCLIError(e)
644 7493ccb6 Stavros Sachtouris
645 234954d1 Stavros Sachtouris
646 d486baec Stavros Sachtouris
@command(pithos_cmds)
647 7493ccb6 Stavros Sachtouris
class store_move(_store_container_command):
648 38b55954 Stavros Sachtouris
    """Move/rename objects
649 8249ee0f Stavros Sachtouris
    Semantics:
650 8249ee0f Stavros Sachtouris
    move cont:path path2
651 8249ee0f Stavros Sachtouris
    .   will move all <obj> prefixed with path, as path2<obj>
652 7a423d97 Stavros Sachtouris
    .   or as path2 if path corresponds to just one whole object
653 8249ee0f Stavros Sachtouris
    move cont:path cont2:
654 8249ee0f Stavros Sachtouris
    .   will move all <obj> prefixed with path to container cont2
655 8249ee0f Stavros Sachtouris
    move cont:path [cont2:]path2 --exact-match
656 7a423d97 Stavros Sachtouris
    .   will move at most one <obj> as a new object named path2,
657 7a423d97 Stavros Sachtouris
    .   provided path corresponds to a whole object path
658 8249ee0f Stavros Sachtouris
    move cont:path [cont2:]path2 --replace
659 7a423d97 Stavros Sachtouris
    .   will move all <obj> prefixed with path, replacing path with path2
660 8249ee0f Stavros Sachtouris
    where <obj> is a full file or directory object path.
661 2fe2672e Stavros Sachtouris
    Use options:
662 795bf206 Stavros Sachtouris
    1. <container1>:<path1> [container2:]<path2> : if container2 not given,
663 795bf206 Stavros Sachtouris
    destination is container1:path2
664 795bf206 Stavros Sachtouris
    2. <container>:<path1> path2 : rename
665 8249ee0f Stavros Sachtouris
    3. Can use --container= instead of <container1>
666 2fe2672e Stavros Sachtouris
    """
667 2fe2672e Stavros Sachtouris
668 2fe2672e Stavros Sachtouris
    arguments = dict(
669 2fe2672e Stavros Sachtouris
        source_version=ValueArgument('specify version', '--source-version'),
670 2fe2672e Stavros Sachtouris
        public=FlagArgument('make object publicly accessible', '--public'),
671 2fe2672e Stavros Sachtouris
        content_type=ValueArgument('modify content type', '--content-type'),
672 38b55954 Stavros Sachtouris
        recursive=FlagArgument('up to delimiter /', ('-r', '--recursive')),
673 38b55954 Stavros Sachtouris
        exact_match=FlagArgument(
674 38b55954 Stavros Sachtouris
            'Copy only the object that fully matches path',
675 8249ee0f Stavros Sachtouris
            '--exact-match'),
676 8249ee0f Stavros Sachtouris
        replace=FlagArgument('Replace src. path with dst. path', '--replace')
677 2fe2672e Stavros Sachtouris
    )
678 7493ccb6 Stavros Sachtouris
679 7a423d97 Stavros Sachtouris
    def _objlist(self, dst_path):
680 8249ee0f Stavros Sachtouris
        if self['exact_match']:
681 aaca2ef4 Stavros Sachtouris
            return [(dst_path if dst_path else self.path, self.path)]
682 8249ee0f Stavros Sachtouris
        r = self.client.container_get(prefix=self.path)
683 7a423d97 Stavros Sachtouris
        if len(r.json) == 1:
684 7a423d97 Stavros Sachtouris
            obj = r.json[0]
685 7a423d97 Stavros Sachtouris
            return [(obj['name'], dst_path if dst_path else obj['name'])]
686 7a423d97 Stavros Sachtouris
        return [(obj['name'], '%s%s' % (
687 7a423d97 Stavros Sachtouris
                    dst_path,
688 7a423d97 Stavros Sachtouris
                    obj['name'][len(self.path) if self['replace'] else 0:])
689 7a423d97 Stavros Sachtouris
                ) for obj in r.json]
690 7493ccb6 Stavros Sachtouris
691 7493ccb6 Stavros Sachtouris
    def main(self, source_container___path, destination_container____path__):
692 234954d1 Stavros Sachtouris
        super(self.__class__,
693 234954d1 Stavros Sachtouris
            self).main(source_container___path, path_is_optional=False)
694 7493ccb6 Stavros Sachtouris
        try:
695 7493ccb6 Stavros Sachtouris
            dst = destination_container____path__.split(':')
696 795bf206 Stavros Sachtouris
            (dst_cont, dst_path) = (dst[0], dst[1])\
697 795bf206 Stavros Sachtouris
            if len(dst) > 1 else (None, dst[0])
698 7a423d97 Stavros Sachtouris
            for src_object, dst_object in self._objlist(dst_path):
699 8249ee0f Stavros Sachtouris
                self.client.move_object(
700 8249ee0f Stavros Sachtouris
                    src_container=self.container,
701 8249ee0f Stavros Sachtouris
                    src_object=src_object,
702 8249ee0f Stavros Sachtouris
                    dst_container=dst_cont if dst_cont else self.container,
703 7a423d97 Stavros Sachtouris
                    dst_object=dst_object,
704 8249ee0f Stavros Sachtouris
                    source_version=self['source_version'],
705 8249ee0f Stavros Sachtouris
                    public=self['public'],
706 8249ee0f Stavros Sachtouris
                    content_type=self['content_type'])
707 7493ccb6 Stavros Sachtouris
        except ClientError as err:
708 795bf206 Stavros Sachtouris
            if err.status == 404:
709 72952f4f Stavros Sachtouris
                if 'object' in ('%s' % err).lower():
710 72952f4f Stavros Sachtouris
                    raiseCLIError(
711 72952f4f Stavros Sachtouris
                        err,
712 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
713 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
714 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
715 72952f4f Stavros Sachtouris
                elif 'container' in ('%s' % err).lower():
716 795bf206 Stavros Sachtouris
                    cont_msg = '(either %s or %s)' % (
717 795bf206 Stavros Sachtouris
                        self.container,
718 795bf206 Stavros Sachtouris
                        dst_cont
719 795bf206 Stavros Sachtouris
                    ) if dst_cont else self.container
720 795bf206 Stavros Sachtouris
                    raiseCLIError(
721 795bf206 Stavros Sachtouris
                        err,
722 795bf206 Stavros Sachtouris
                        'No container %s in account %s'\
723 795bf206 Stavros Sachtouris
                        % (cont_msg, self.account),
724 795bf206 Stavros Sachtouris
                        details=self.generic_err_details)
725 795bf206 Stavros Sachtouris
            raise_connection_errors(err)
726 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
727 795bf206 Stavros Sachtouris
        except Exception as e:
728 795bf206 Stavros Sachtouris
            raiseCLIError(e)
729 7493ccb6 Stavros Sachtouris
730 234954d1 Stavros Sachtouris
731 d486baec Stavros Sachtouris
@command(pithos_cmds)
732 7493ccb6 Stavros Sachtouris
class store_append(_store_container_command):
733 aaca2ef4 Stavros Sachtouris
    """Append local file to (existing) remote object
734 aaca2ef4 Stavros Sachtouris
    The remote object should exist.
735 aaca2ef4 Stavros Sachtouris
    If the remote object is a directory, it is transformed into a file.
736 aaca2ef4 Stavros Sachtouris
    In the later case, objects under the directory remain intact.
737 aaca2ef4 Stavros Sachtouris
    """
738 7493ccb6 Stavros Sachtouris
739 2fe2672e Stavros Sachtouris
    arguments = dict(
740 2fe2672e Stavros Sachtouris
        progress_bar=ProgressBarArgument(
741 2fe2672e Stavros Sachtouris
            'do not show progress bar',
742 2fe2672e Stavros Sachtouris
            '--no-progress-bar',
743 2fe2672e Stavros Sachtouris
            default=False)
744 2fe2672e Stavros Sachtouris
    )
745 486f7af1 Stavros Sachtouris
746 7493ccb6 Stavros Sachtouris
    def main(self, local_path, container___path):
747 aaca2ef4 Stavros Sachtouris
        super(self.__class__, self).main(
748 aaca2ef4 Stavros Sachtouris
            container___path,
749 aaca2ef4 Stavros Sachtouris
            path_is_optional=False)
750 aaca2ef4 Stavros Sachtouris
        progress_bar = self.arguments['progress_bar']
751 aaca2ef4 Stavros Sachtouris
        try:
752 aaca2ef4 Stavros Sachtouris
            upload_cb = progress_bar.get_generator('Appending blocks')
753 aaca2ef4 Stavros Sachtouris
        except Exception:
754 aaca2ef4 Stavros Sachtouris
            upload_cb = None
755 7493ccb6 Stavros Sachtouris
        try:
756 e876ac62 Stavros Sachtouris
            f = open(local_path, 'rb')
757 96ec49f2 Stavros Sachtouris
            self.client.append_object(self.path, f, upload_cb)
758 7493ccb6 Stavros Sachtouris
        except ClientError as err:
759 852a22e7 Stavros Sachtouris
            progress_bar.finish()
760 96ec49f2 Stavros Sachtouris
            if err.status == 404:
761 96ec49f2 Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
762 96ec49f2 Stavros Sachtouris
                    raiseCLIError(
763 96ec49f2 Stavros Sachtouris
                        err,
764 96ec49f2 Stavros Sachtouris
                        'No container %s in account %s'\
765 96ec49f2 Stavros Sachtouris
                        % (self.container, self.account),
766 96ec49f2 Stavros Sachtouris
                        details=self.generic_err_details)
767 8fa6ef6a Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
768 8fa6ef6a Stavros Sachtouris
                    raiseCLIError(
769 8fa6ef6a Stavros Sachtouris
                        err,
770 8fa6ef6a Stavros Sachtouris
                        'No object %s in container %s'\
771 8fa6ef6a Stavros Sachtouris
                        % (self.path, self.container),
772 8fa6ef6a Stavros Sachtouris
                        details=self.generic_err_details)
773 96ec49f2 Stavros Sachtouris
            raise_connection_errors(err)
774 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
775 96ec49f2 Stavros Sachtouris
        except Exception as e:
776 96ec49f2 Stavros Sachtouris
            progress_bar.finish()
777 96ec49f2 Stavros Sachtouris
            raiseCLIError(e)
778 852a22e7 Stavros Sachtouris
        finally:
779 852a22e7 Stavros Sachtouris
            progress_bar.finish()
780 7493ccb6 Stavros Sachtouris
781 234954d1 Stavros Sachtouris
782 d486baec Stavros Sachtouris
@command(pithos_cmds)
783 7493ccb6 Stavros Sachtouris
class store_truncate(_store_container_command):
784 aaca2ef4 Stavros Sachtouris
    """Truncate remote file up to a size (default is 0)"""
785 7493ccb6 Stavros Sachtouris
786 7493ccb6 Stavros Sachtouris
    def main(self, container___path, size=0):
787 8fa6ef6a Stavros Sachtouris
        super(self.__class__, self).main(container___path)
788 7493ccb6 Stavros Sachtouris
        try:
789 7493ccb6 Stavros Sachtouris
            self.client.truncate_object(self.path, size)
790 7493ccb6 Stavros Sachtouris
        except ClientError as err:
791 8fa6ef6a Stavros Sachtouris
            if err.status == 404:
792 8fa6ef6a Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
793 8fa6ef6a Stavros Sachtouris
                    raiseCLIError(
794 8fa6ef6a Stavros Sachtouris
                        err,
795 8fa6ef6a Stavros Sachtouris
                        'No container %s in account %s'\
796 8fa6ef6a Stavros Sachtouris
                        % (self.container, self.account),
797 8fa6ef6a Stavros Sachtouris
                        details=self.generic_err_details)
798 8fa6ef6a Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
799 8fa6ef6a Stavros Sachtouris
                    raiseCLIError(
800 8fa6ef6a Stavros Sachtouris
                        err,
801 8fa6ef6a Stavros Sachtouris
                        'No object %s in container %s'\
802 8fa6ef6a Stavros Sachtouris
                        % (self.path, self.container),
803 8fa6ef6a Stavros Sachtouris
                        details=self.generic_err_details)
804 8fa6ef6a Stavros Sachtouris
            if err.status == 400 and\
805 8fa6ef6a Stavros Sachtouris
                'object length is smaller than range length'\
806 8fa6ef6a Stavros Sachtouris
                in ('%s' % err).lower():
807 8fa6ef6a Stavros Sachtouris
                raiseCLIError(err, 'Object %s:%s <= %sb' % (
808 8fa6ef6a Stavros Sachtouris
                    self.container,
809 8fa6ef6a Stavros Sachtouris
                    self.path,
810 8fa6ef6a Stavros Sachtouris
                    size))
811 8fa6ef6a Stavros Sachtouris
            raise_connection_errors(err)
812 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
813 8fa6ef6a Stavros Sachtouris
        except Exception as e:
814 8fa6ef6a Stavros Sachtouris
            raiseCLIError(e)
815 7493ccb6 Stavros Sachtouris
816 234954d1 Stavros Sachtouris
817 d486baec Stavros Sachtouris
@command(pithos_cmds)
818 7493ccb6 Stavros Sachtouris
class store_overwrite(_store_container_command):
819 aaca2ef4 Stavros Sachtouris
    """Overwrite part (from start to end) of a remote file
820 aaca2ef4 Stavros Sachtouris
    overwrite local-path container 10 20
821 aaca2ef4 Stavros Sachtouris
    .   will overwrite bytes from 10 to 20 of a remote file with the same name
822 aaca2ef4 Stavros Sachtouris
    .   as local-path basename
823 aaca2ef4 Stavros Sachtouris
    overwrite local-path container:path 10 20
824 aaca2ef4 Stavros Sachtouris
    .   will overwrite as above, but the remote file is named path
825 aaca2ef4 Stavros Sachtouris
    """
826 7493ccb6 Stavros Sachtouris
827 2fe2672e Stavros Sachtouris
    arguments = dict(
828 2fe2672e Stavros Sachtouris
        progress_bar=ProgressBarArgument(
829 2fe2672e Stavros Sachtouris
            'do not show progress bar',
830 439826ec Stavros Sachtouris
            '--no-progress-bar',
831 2fe2672e Stavros Sachtouris
            default=False)
832 2fe2672e Stavros Sachtouris
    )
833 486f7af1 Stavros Sachtouris
834 aaca2ef4 Stavros Sachtouris
    def main(self, local_path, container____path__, start, end):
835 aaca2ef4 Stavros Sachtouris
        (start, end) = check_range(start, end)
836 aaca2ef4 Stavros Sachtouris
        super(self.__class__, self).main(container____path__)
837 7493ccb6 Stavros Sachtouris
        try:
838 8fa6ef6a Stavros Sachtouris
            f = open(local_path, 'rb')
839 aaca2ef4 Stavros Sachtouris
            f.seek(0, 2)
840 aaca2ef4 Stavros Sachtouris
            f_size = f.tell()
841 aaca2ef4 Stavros Sachtouris
            f.seek(start, 0)
842 aaca2ef4 Stavros Sachtouris
        except Exception as e:
843 aaca2ef4 Stavros Sachtouris
            raiseCLIError(e)
844 aaca2ef4 Stavros Sachtouris
        progress_bar = self.arguments['progress_bar']
845 aaca2ef4 Stavros Sachtouris
        try:
846 aaca2ef4 Stavros Sachtouris
            upload_cb = progress_bar.get_generator(
847 aaca2ef4 Stavros Sachtouris
                'Overwriting %s blocks' % end - start)
848 aaca2ef4 Stavros Sachtouris
        except Exception:
849 aaca2ef4 Stavros Sachtouris
            upload_cb = None
850 aaca2ef4 Stavros Sachtouris
        try:
851 8fa6ef6a Stavros Sachtouris
            self.path = self.path if self.path else path.basename(local_path)
852 8fa6ef6a Stavros Sachtouris
            self.client.overwrite_object(
853 8fa6ef6a Stavros Sachtouris
                obj=self.path,
854 234954d1 Stavros Sachtouris
                start=start,
855 234954d1 Stavros Sachtouris
                end=end,
856 234954d1 Stavros Sachtouris
                source_file=f,
857 234954d1 Stavros Sachtouris
                upload_cb=upload_cb)
858 7493ccb6 Stavros Sachtouris
        except ClientError as err:
859 852a22e7 Stavros Sachtouris
            progress_bar.finish()
860 aaca2ef4 Stavros Sachtouris
            if (err.status == 400 and\
861 aaca2ef4 Stavros Sachtouris
            'content length does not match range' in ('%s' % err).lower()) or\
862 aaca2ef4 Stavros Sachtouris
            err.status == 416:
863 aaca2ef4 Stavros Sachtouris
                raiseCLIError(err, details=[
864 aaca2ef4 Stavros Sachtouris
                    'Content size: %s' % f_size,
865 aaca2ef4 Stavros Sachtouris
                    'Range: %s-%s (size: %s)' % (start, end, end - start)])
866 aaca2ef4 Stavros Sachtouris
            elif err.status == 404:
867 8fa6ef6a Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
868 8fa6ef6a Stavros Sachtouris
                    raiseCLIError(
869 8fa6ef6a Stavros Sachtouris
                        err,
870 8fa6ef6a Stavros Sachtouris
                        'No container %s in account %s'\
871 8fa6ef6a Stavros Sachtouris
                        % (self.container, self.account),
872 8fa6ef6a Stavros Sachtouris
                        details=self.generic_err_details)
873 8fa6ef6a Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
874 8fa6ef6a Stavros Sachtouris
                    raiseCLIError(
875 8fa6ef6a Stavros Sachtouris
                        err,
876 8fa6ef6a Stavros Sachtouris
                        'No object %s in container %s'\
877 8fa6ef6a Stavros Sachtouris
                        % (self.path, self.container),
878 8fa6ef6a Stavros Sachtouris
                        details=self.generic_err_details)
879 8fa6ef6a Stavros Sachtouris
            raise_connection_errors(err)
880 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
881 8fa6ef6a Stavros Sachtouris
        except Exception as e:
882 8fa6ef6a Stavros Sachtouris
            progress_bar.finish()
883 8fa6ef6a Stavros Sachtouris
            raiseCLIError(e)
884 852a22e7 Stavros Sachtouris
        finally:
885 852a22e7 Stavros Sachtouris
            progress_bar.finish()
886 7493ccb6 Stavros Sachtouris
887 234954d1 Stavros Sachtouris
888 d486baec Stavros Sachtouris
@command(pithos_cmds)
889 486f7af1 Stavros Sachtouris
class store_manifest(_store_container_command):
890 8fa6ef6a Stavros Sachtouris
    """Create a remote file of uploaded parts by manifestation
891 35b52b0e Stavros Sachtouris
    Remains functional for compatibility with OOS Storage. Users are advised
892 35b52b0e Stavros Sachtouris
    to use the upload command instead.
893 35b52b0e Stavros Sachtouris
    Manifestation is a compliant process for uploading large files. The files
894 35b52b0e Stavros Sachtouris
    have to be chunked in smalled files and uploaded as <prefix><increment>
895 35b52b0e Stavros Sachtouris
    where increment is 1, 2, ...
896 35b52b0e Stavros Sachtouris
    Finally, the manifest command glues partial files together in one file
897 35b52b0e Stavros Sachtouris
    named <prefix>
898 35b52b0e Stavros Sachtouris
    The upload command is faster, easier and more intuitive than manifest
899 8fa6ef6a Stavros Sachtouris
    """
900 486f7af1 Stavros Sachtouris
901 2fe2672e Stavros Sachtouris
    arguments = dict(
902 2fe2672e Stavros Sachtouris
        etag=ValueArgument('check written data', '--etag'),
903 2fe2672e Stavros Sachtouris
        content_encoding=ValueArgument(
904 2fe2672e Stavros Sachtouris
            'set MIME content type',
905 2fe2672e Stavros Sachtouris
            '--content-encoding'),
906 2fe2672e Stavros Sachtouris
        content_disposition=ValueArgument(
907 2fe2672e Stavros Sachtouris
            'the presentation style of the object',
908 2fe2672e Stavros Sachtouris
            '--content-disposition'),
909 8fa6ef6a Stavros Sachtouris
        content_type=ValueArgument(
910 8fa6ef6a Stavros Sachtouris
            'specify content type',
911 8fa6ef6a Stavros Sachtouris
            '--content-type',
912 8fa6ef6a Stavros Sachtouris
            default='application/octet-stream'),
913 2fe2672e Stavros Sachtouris
        sharing=SharingArgument(
914 2fe2672e Stavros Sachtouris
            'define object sharing policy \n' +\
915 2fe2672e Stavros Sachtouris
            '    ( "read=user1,grp1,user2,... write=user1,grp2,..." )',
916 2fe2672e Stavros Sachtouris
            '--sharing'),
917 2fe2672e Stavros Sachtouris
        public=FlagArgument('make object publicly accessible', '--public')
918 2fe2672e Stavros Sachtouris
    )
919 234954d1 Stavros Sachtouris
920 7493ccb6 Stavros Sachtouris
    def main(self, container___path):
921 234954d1 Stavros Sachtouris
        super(self.__class__,
922 234954d1 Stavros Sachtouris
            self).main(container___path, path_is_optional=False)
923 7493ccb6 Stavros Sachtouris
        try:
924 2fe2672e Stavros Sachtouris
            self.client.create_object_by_manifestation(
925 2fe2672e Stavros Sachtouris
                self.path,
926 2fe2672e Stavros Sachtouris
                content_encoding=self['content_encoding'],
927 2fe2672e Stavros Sachtouris
                content_disposition=self['content_disposition'],
928 2fe2672e Stavros Sachtouris
                content_type=self['content_type'],
929 2fe2672e Stavros Sachtouris
                sharing=self['sharing'],
930 2fe2672e Stavros Sachtouris
                public=self['public'])
931 7493ccb6 Stavros Sachtouris
        except ClientError as err:
932 8fa6ef6a Stavros Sachtouris
            if err.status == 404:
933 8fa6ef6a Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
934 8fa6ef6a Stavros Sachtouris
                    raiseCLIError(
935 8fa6ef6a Stavros Sachtouris
                        err,
936 8fa6ef6a Stavros Sachtouris
                        'No container %s in account %s'\
937 8fa6ef6a Stavros Sachtouris
                        % (self.container, self.account),
938 8fa6ef6a Stavros Sachtouris
                        details=self.generic_err_details)
939 8fa6ef6a Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
940 8fa6ef6a Stavros Sachtouris
                    raiseCLIError(
941 8fa6ef6a Stavros Sachtouris
                        err,
942 8fa6ef6a Stavros Sachtouris
                        'No object %s in container %s'\
943 8fa6ef6a Stavros Sachtouris
                        % (self.path, self.container),
944 8fa6ef6a Stavros Sachtouris
                        details=self.generic_err_details)
945 8fa6ef6a Stavros Sachtouris
            raise_connection_errors(err)
946 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
947 8fa6ef6a Stavros Sachtouris
        except Exception as e:
948 8fa6ef6a Stavros Sachtouris
            raiseCLIError(e)
949 7493ccb6 Stavros Sachtouris
950 234954d1 Stavros Sachtouris
951 d486baec Stavros Sachtouris
@command(pithos_cmds)
952 7493ccb6 Stavros Sachtouris
class store_upload(_store_container_command):
953 7493ccb6 Stavros Sachtouris
    """Upload a file"""
954 7493ccb6 Stavros Sachtouris
955 2fe2672e Stavros Sachtouris
    arguments = dict(
956 2fe2672e Stavros Sachtouris
        use_hashes=FlagArgument(
957 2fe2672e Stavros Sachtouris
            'provide hashmap file instead of data',
958 2fe2672e Stavros Sachtouris
            '--use-hashes'),
959 2fe2672e Stavros Sachtouris
        etag=ValueArgument('check written data', '--etag'),
960 2fe2672e Stavros Sachtouris
        unchunked=FlagArgument('avoid chunked transfer mode', '--unchunked'),
961 2fe2672e Stavros Sachtouris
        content_encoding=ValueArgument(
962 2fe2672e Stavros Sachtouris
            'set MIME content type',
963 2fe2672e Stavros Sachtouris
            '--content-encoding'),
964 2fe2672e Stavros Sachtouris
        content_disposition=ValueArgument(
965 2fe2672e Stavros Sachtouris
            'specify objects presentation style',
966 2fe2672e Stavros Sachtouris
            '--content-disposition'),
967 2fe2672e Stavros Sachtouris
        content_type=ValueArgument('specify content type', '--content-type'),
968 2fe2672e Stavros Sachtouris
        sharing=SharingArgument(
969 2fe2672e Stavros Sachtouris
            help='define sharing object policy \n' +\
970 2fe2672e Stavros Sachtouris
            '( "read=user1,grp1,user2,... write=user1,grp2,... )',
971 2fe2672e Stavros Sachtouris
            parsed_name='--sharing'),
972 2fe2672e Stavros Sachtouris
        public=FlagArgument('make object publicly accessible', '--public'),
973 2fe2672e Stavros Sachtouris
        poolsize=IntArgument('set pool size', '--with-pool-size'),
974 2fe2672e Stavros Sachtouris
        progress_bar=ProgressBarArgument(
975 2fe2672e Stavros Sachtouris
            'do not show progress bar',
976 2fe2672e Stavros Sachtouris
            '--no-progress-bar',
977 706fc940 Stavros Sachtouris
            default=False),
978 706fc940 Stavros Sachtouris
        overwrite=FlagArgument('Force overwrite, if object exists', '-f')
979 2fe2672e Stavros Sachtouris
    )
980 7493ccb6 Stavros Sachtouris
981 706fc940 Stavros Sachtouris
    def _remote_path(self, remote_path, local_path=''):
982 706fc940 Stavros Sachtouris
        if self['overwrite']:
983 706fc940 Stavros Sachtouris
            return remote_path
984 706fc940 Stavros Sachtouris
        try:
985 706fc940 Stavros Sachtouris
            r = self.client.get_object_info(remote_path)
986 706fc940 Stavros Sachtouris
        except ClientError as ce:
987 706fc940 Stavros Sachtouris
            if ce.status == 404:
988 706fc940 Stavros Sachtouris
                return remote_path
989 1f315e7b Stavros Sachtouris
            raise ce
990 706fc940 Stavros Sachtouris
        ctype = r.get('content-type', '')
991 706fc940 Stavros Sachtouris
        if 'application/directory' == ctype.lower():
992 706fc940 Stavros Sachtouris
            ret = '%s/%s' % (remote_path, local_path)
993 706fc940 Stavros Sachtouris
            return self._remote_path(ret) if local_path else ret
994 706fc940 Stavros Sachtouris
        raiseCLIError(
995 706fc940 Stavros Sachtouris
            'Object %s already exists' % remote_path,
996 706fc940 Stavros Sachtouris
            importance=1,
997 3e7d1e0e Stavros Sachtouris
            details=['use -f to overwrite or resume'])
998 706fc940 Stavros Sachtouris
999 1f315e7b Stavros Sachtouris
    def main(self, local_path, container____path__=None):
1000 7493ccb6 Stavros Sachtouris
        super(self.__class__, self).main(container____path__)
1001 707c1a4a Stavros Sachtouris
        remote_path = self.path if self.path else path.basename(local_path)
1002 2fe2672e Stavros Sachtouris
        poolsize = self['poolsize']
1003 72952f4f Stavros Sachtouris
        if poolsize > 0:
1004 cccff590 Stavros Sachtouris
            self.client.POOL_SIZE = int(poolsize)
1005 72952f4f Stavros Sachtouris
        params = dict(
1006 72952f4f Stavros Sachtouris
            content_encoding=self['content_encoding'],
1007 2fe2672e Stavros Sachtouris
            content_type=self['content_type'],
1008 2fe2672e Stavros Sachtouris
            content_disposition=self['content_disposition'],
1009 2fe2672e Stavros Sachtouris
            sharing=self['sharing'],
1010 2fe2672e Stavros Sachtouris
            public=self['public'])
1011 7493ccb6 Stavros Sachtouris
        try:
1012 852a22e7 Stavros Sachtouris
            progress_bar = self.arguments['progress_bar']
1013 852a22e7 Stavros Sachtouris
            hash_bar = progress_bar.clone()
1014 1f315e7b Stavros Sachtouris
            remote_path = self._remote_path(remote_path, local_path)
1015 72952f4f Stavros Sachtouris
            with open(path.abspath(local_path), 'rb') as f:
1016 2fe2672e Stavros Sachtouris
                if self['unchunked']:
1017 2fe2672e Stavros Sachtouris
                    self.client.upload_object_unchunked(
1018 2fe2672e Stavros Sachtouris
                        remote_path,
1019 2fe2672e Stavros Sachtouris
                        f,
1020 2fe2672e Stavros Sachtouris
                        etag=self['etag'],
1021 2fe2672e Stavros Sachtouris
                        withHashFile=self['use_hashes'],
1022 2fe2672e Stavros Sachtouris
                        **params)
1023 7493ccb6 Stavros Sachtouris
                else:
1024 2fe2672e Stavros Sachtouris
                    hash_cb = hash_bar.get_generator(
1025 234954d1 Stavros Sachtouris
                        'Calculating block hashes')
1026 234954d1 Stavros Sachtouris
                    upload_cb = progress_bar.get_generator('Uploading')
1027 2fe2672e Stavros Sachtouris
                    self.client.upload_object(
1028 2fe2672e Stavros Sachtouris
                        remote_path,
1029 2fe2672e Stavros Sachtouris
                        f,
1030 852a22e7 Stavros Sachtouris
                        hash_cb=hash_cb,
1031 852a22e7 Stavros Sachtouris
                        upload_cb=upload_cb,
1032 852a22e7 Stavros Sachtouris
                        **params)
1033 852a22e7 Stavros Sachtouris
                    progress_bar.finish()
1034 852a22e7 Stavros Sachtouris
                    hash_bar.finish()
1035 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1036 706fc940 Stavros Sachtouris
            try:
1037 706fc940 Stavros Sachtouris
                progress_bar.finish()
1038 706fc940 Stavros Sachtouris
                hash_bar.finish()
1039 706fc940 Stavros Sachtouris
            except Exception:
1040 706fc940 Stavros Sachtouris
                pass
1041 72952f4f Stavros Sachtouris
            if err.status == 404:
1042 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1043 72952f4f Stavros Sachtouris
                    raiseCLIError(
1044 72952f4f Stavros Sachtouris
                        err,
1045 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1046 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1047 7644c38e Stavros Sachtouris
                        details=[self.generic_err_details])
1048 7644c38e Stavros Sachtouris
            elif err.status == 800:
1049 7644c38e Stavros Sachtouris
                raiseCLIError(err, details=[
1050 7644c38e Stavros Sachtouris
                    'Possible cause: temporary server failure',
1051 7644c38e Stavros Sachtouris
                    'Try to re-upload the file',
1052 7644c38e Stavros Sachtouris
                    'For more error details, try kamaki store upload -d'])
1053 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1054 745d938b Stavros Sachtouris
            raiseCLIError(err, 'Failed to upload to %s' % container____path__)
1055 436f2ce1 Stavros Sachtouris
        except IOError as err:
1056 706fc940 Stavros Sachtouris
            try:
1057 706fc940 Stavros Sachtouris
                progress_bar.finish()
1058 706fc940 Stavros Sachtouris
                hash_bar.finish()
1059 706fc940 Stavros Sachtouris
            except Exception:
1060 706fc940 Stavros Sachtouris
                pass
1061 43ee6ae1 Stavros Sachtouris
            raiseCLIError(err, 'Failed to read form file %s' % local_path, 2)
1062 72952f4f Stavros Sachtouris
        except Exception as e:
1063 706fc940 Stavros Sachtouris
            try:
1064 706fc940 Stavros Sachtouris
                progress_bar.finish()
1065 706fc940 Stavros Sachtouris
                hash_bar.finish()
1066 706fc940 Stavros Sachtouris
            except Exception:
1067 706fc940 Stavros Sachtouris
                pass
1068 72952f4f Stavros Sachtouris
            raiseCLIError(e)
1069 f364f960 Stavros Sachtouris
        print 'Upload completed'
1070 7493ccb6 Stavros Sachtouris
1071 234954d1 Stavros Sachtouris
1072 d486baec Stavros Sachtouris
@command(pithos_cmds)
1073 9ceec15a Stavros Sachtouris
class store_cat(_store_container_command):
1074 72952f4f Stavros Sachtouris
    """Print remote file contents to console"""
1075 9ceec15a Stavros Sachtouris
1076 2fe2672e Stavros Sachtouris
    arguments = dict(
1077 2fe2672e Stavros Sachtouris
        range=RangeArgument('show range of data', '--range'),
1078 2fe2672e Stavros Sachtouris
        if_match=ValueArgument('show output if ETags match', '--if-match'),
1079 2fe2672e Stavros Sachtouris
        if_none_match=ValueArgument(
1080 2fe2672e Stavros Sachtouris
            'show output if ETags match',
1081 2fe2672e Stavros Sachtouris
            '--if-none-match'),
1082 2fe2672e Stavros Sachtouris
        if_modified_since=DateArgument(
1083 2fe2672e Stavros Sachtouris
            'show output modified since then',
1084 2fe2672e Stavros Sachtouris
            '--if-modified-since'),
1085 2fe2672e Stavros Sachtouris
        if_unmodified_since=DateArgument(
1086 2fe2672e Stavros Sachtouris
            'show output unmodified since then',
1087 2fe2672e Stavros Sachtouris
            '--if-unmodified-since'),
1088 2fe2672e Stavros Sachtouris
        object_version=ValueArgument(
1089 2fe2672e Stavros Sachtouris
            'get the specific version',
1090 2fe2672e Stavros Sachtouris
            '--object-version')
1091 2fe2672e Stavros Sachtouris
    )
1092 2fe2672e Stavros Sachtouris
1093 9ceec15a Stavros Sachtouris
    def main(self, container___path):
1094 1f315e7b Stavros Sachtouris
        super(self.__class__, self).main(
1095 1f315e7b Stavros Sachtouris
            container___path,
1096 1f315e7b Stavros Sachtouris
            path_is_optional=False)
1097 0238c167 Stavros Sachtouris
        try:
1098 0238c167 Stavros Sachtouris
            self.client.download_object(self.path, stdout,
1099 2fe2672e Stavros Sachtouris
            range=self['range'],
1100 2fe2672e Stavros Sachtouris
            version=self['object_version'],
1101 2fe2672e Stavros Sachtouris
            if_match=self['if_match'],
1102 2fe2672e Stavros Sachtouris
            if_none_match=self['if_none_match'],
1103 2fe2672e Stavros Sachtouris
            if_modified_since=self['if_modified_since'],
1104 2fe2672e Stavros Sachtouris
            if_unmodified_since=self['if_unmodified_since'])
1105 0238c167 Stavros Sachtouris
        except ClientError as err:
1106 72952f4f Stavros Sachtouris
            if err.status == 404:
1107 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1108 72952f4f Stavros Sachtouris
                    raiseCLIError(
1109 72952f4f Stavros Sachtouris
                        err,
1110 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1111 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1112 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1113 72952f4f Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
1114 72952f4f Stavros Sachtouris
                    raiseCLIError(
1115 72952f4f Stavros Sachtouris
                        err,
1116 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
1117 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
1118 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1119 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1120 0238c167 Stavros Sachtouris
            raiseCLIError(err)
1121 72952f4f Stavros Sachtouris
        except Exception as e:
1122 72952f4f Stavros Sachtouris
            raiseCLIError(e)
1123 9ceec15a Stavros Sachtouris
1124 234954d1 Stavros Sachtouris
1125 d486baec Stavros Sachtouris
@command(pithos_cmds)
1126 7493ccb6 Stavros Sachtouris
class store_download(_store_container_command):
1127 72952f4f Stavros Sachtouris
    """Download remote object as local file"""
1128 7493ccb6 Stavros Sachtouris
1129 2fe2672e Stavros Sachtouris
    arguments = dict(
1130 2fe2672e Stavros Sachtouris
        resume=FlagArgument('Resume instead of overwrite', '--resume'),
1131 2fe2672e Stavros Sachtouris
        range=RangeArgument('show range of data', '--range'),
1132 2fe2672e Stavros Sachtouris
        if_match=ValueArgument('show output if ETags match', '--if-match'),
1133 2fe2672e Stavros Sachtouris
        if_none_match=ValueArgument(
1134 2fe2672e Stavros Sachtouris
            'show output if ETags match',
1135 2fe2672e Stavros Sachtouris
            '--if-none-match'),
1136 2fe2672e Stavros Sachtouris
        if_modified_since=DateArgument(
1137 2fe2672e Stavros Sachtouris
            'show output modified since then',
1138 2fe2672e Stavros Sachtouris
            '--if-modified-since'),
1139 2fe2672e Stavros Sachtouris
        if_unmodified_since=DateArgument(
1140 2fe2672e Stavros Sachtouris
            'show output unmodified since then',
1141 2fe2672e Stavros Sachtouris
            '--if-unmodified-since'),
1142 2fe2672e Stavros Sachtouris
        object_version=ValueArgument(
1143 2fe2672e Stavros Sachtouris
            'get the specific version',
1144 2fe2672e Stavros Sachtouris
            '--object-version'),
1145 2fe2672e Stavros Sachtouris
        poolsize=IntArgument('set pool size', '--with-pool-size'),
1146 2fe2672e Stavros Sachtouris
        progress_bar=ProgressBarArgument(
1147 2fe2672e Stavros Sachtouris
            'do not show progress bar',
1148 2fe2672e Stavros Sachtouris
            '--no-progress-bar',
1149 2fe2672e Stavros Sachtouris
            default=False)
1150 2fe2672e Stavros Sachtouris
    )
1151 7493ccb6 Stavros Sachtouris
1152 1f315e7b Stavros Sachtouris
    def _output_stream(self, local_path):
1153 1f315e7b Stavros Sachtouris
        if local_path is None:
1154 1f315e7b Stavros Sachtouris
            return stdout
1155 1f315e7b Stavros Sachtouris
        try:
1156 1f315e7b Stavros Sachtouris
            return open(
1157 1f315e7b Stavros Sachtouris
                path.abspath(local_path),
1158 1f315e7b Stavros Sachtouris
                'rwb+' if self['resume'] else 'wb+')
1159 1f315e7b Stavros Sachtouris
        except IOError as err:
1160 1f315e7b Stavros Sachtouris
            raiseCLIError(err, 'Cannot write to file %s' % local_path, 1)
1161 1f315e7b Stavros Sachtouris
1162 1f315e7b Stavros Sachtouris
    def main(self, container___path, local_path=None):
1163 72952f4f Stavros Sachtouris
        super(self.__class__, self).main(
1164 72952f4f Stavros Sachtouris
            container___path,
1165 72952f4f Stavros Sachtouris
            path_is_optional=False)
1166 7493ccb6 Stavros Sachtouris
1167 1f315e7b Stavros Sachtouris
        out = self._output_stream(local_path)
1168 2fe2672e Stavros Sachtouris
        poolsize = self['poolsize']
1169 624ee36f Stavros Sachtouris
        if poolsize is not None:
1170 cccff590 Stavros Sachtouris
            self.client.POOL_SIZE = int(poolsize)
1171 b1713259 Stavros Sachtouris
1172 7493ccb6 Stavros Sachtouris
        try:
1173 852a22e7 Stavros Sachtouris
            progress_bar = self.arguments['progress_bar']
1174 852a22e7 Stavros Sachtouris
            download_cb = progress_bar.get_generator('Downloading')
1175 1f315e7b Stavros Sachtouris
            self.client.download_object(
1176 1f315e7b Stavros Sachtouris
                self.path,
1177 1f315e7b Stavros Sachtouris
                out,
1178 234954d1 Stavros Sachtouris
                download_cb=download_cb,
1179 2fe2672e Stavros Sachtouris
                range=self['range'],
1180 2fe2672e Stavros Sachtouris
                version=self['object_version'],
1181 2fe2672e Stavros Sachtouris
                if_match=self['if_match'],
1182 2fe2672e Stavros Sachtouris
                resume=self['resume'],
1183 2fe2672e Stavros Sachtouris
                if_none_match=self['if_none_match'],
1184 2fe2672e Stavros Sachtouris
                if_modified_since=self['if_modified_since'],
1185 2fe2672e Stavros Sachtouris
                if_unmodified_since=self['if_unmodified_since'])
1186 852a22e7 Stavros Sachtouris
            progress_bar.finish()
1187 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1188 852a22e7 Stavros Sachtouris
            progress_bar.finish()
1189 72952f4f Stavros Sachtouris
            if err.status == 404:
1190 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1191 72952f4f Stavros Sachtouris
                    raiseCLIError(
1192 72952f4f Stavros Sachtouris
                        err,
1193 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1194 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1195 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1196 72952f4f Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
1197 72952f4f Stavros Sachtouris
                    raiseCLIError(
1198 72952f4f Stavros Sachtouris
                        err,
1199 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
1200 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
1201 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1202 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1203 72952f4f Stavros Sachtouris
            raiseCLIError(err, '"%s" not accessible' % container___path)
1204 72952f4f Stavros Sachtouris
        except IOError as err:
1205 1f315e7b Stavros Sachtouris
            try:
1206 1f315e7b Stavros Sachtouris
                progress_bar.finish()
1207 1f315e7b Stavros Sachtouris
            except Exception:
1208 1f315e7b Stavros Sachtouris
                pass
1209 72952f4f Stavros Sachtouris
            raiseCLIError(err, 'Failed to write on file %s' % local_path, 2)
1210 7493ccb6 Stavros Sachtouris
        except KeyboardInterrupt:
1211 f27ed9a0 Stavros Sachtouris
            from threading import enumerate as activethreads
1212 f27ed9a0 Stavros Sachtouris
            stdout.write('\nFinishing active threads ')
1213 f27ed9a0 Stavros Sachtouris
            for thread in activethreads():
1214 f27ed9a0 Stavros Sachtouris
                stdout.flush()
1215 f27ed9a0 Stavros Sachtouris
                try:
1216 f27ed9a0 Stavros Sachtouris
                    thread.join()
1217 f27ed9a0 Stavros Sachtouris
                    stdout.write('.')
1218 f27ed9a0 Stavros Sachtouris
                except RuntimeError:
1219 f27ed9a0 Stavros Sachtouris
                    continue
1220 1f315e7b Stavros Sachtouris
            try:
1221 1f315e7b Stavros Sachtouris
                progress_bar.finish()
1222 1f315e7b Stavros Sachtouris
            except Exception:
1223 1f315e7b Stavros Sachtouris
                pass
1224 7493ccb6 Stavros Sachtouris
            print('\ndownload canceled by user')
1225 7493ccb6 Stavros Sachtouris
            if local_path is not None:
1226 624ee36f Stavros Sachtouris
                print('to resume, re-run with --resume')
1227 852a22e7 Stavros Sachtouris
        except Exception as e:
1228 1f315e7b Stavros Sachtouris
            try:
1229 1f315e7b Stavros Sachtouris
                progress_bar.finish()
1230 1f315e7b Stavros Sachtouris
            except Exception:
1231 1f315e7b Stavros Sachtouris
                pass
1232 83ba5545 Stavros Sachtouris
            raiseCLIError(e)
1233 7493ccb6 Stavros Sachtouris
        print
1234 7493ccb6 Stavros Sachtouris
1235 234954d1 Stavros Sachtouris
1236 d486baec Stavros Sachtouris
@command(pithos_cmds)
1237 7493ccb6 Stavros Sachtouris
class store_hashmap(_store_container_command):
1238 72952f4f Stavros Sachtouris
    """Get the hash-map of an object"""
1239 7493ccb6 Stavros Sachtouris
1240 2fe2672e Stavros Sachtouris
    arguments = dict(
1241 2fe2672e Stavros Sachtouris
        if_match=ValueArgument('show output if ETags match', '--if-match'),
1242 2fe2672e Stavros Sachtouris
        if_none_match=ValueArgument(
1243 2fe2672e Stavros Sachtouris
            'show output if ETags match',
1244 2fe2672e Stavros Sachtouris
            '--if-none-match'),
1245 2fe2672e Stavros Sachtouris
        if_modified_since=DateArgument(
1246 2fe2672e Stavros Sachtouris
            'show output modified since then',
1247 2fe2672e Stavros Sachtouris
            '--if-modified-since'),
1248 2fe2672e Stavros Sachtouris
        if_unmodified_since=DateArgument(
1249 2fe2672e Stavros Sachtouris
            'show output unmodified since then',
1250 2fe2672e Stavros Sachtouris
            '--if-unmodified-since'),
1251 2fe2672e Stavros Sachtouris
        object_version=ValueArgument(
1252 2fe2672e Stavros Sachtouris
            'get the specific version',
1253 2fe2672e Stavros Sachtouris
            '--object-version')
1254 2fe2672e Stavros Sachtouris
    )
1255 7493ccb6 Stavros Sachtouris
1256 7493ccb6 Stavros Sachtouris
    def main(self, container___path):
1257 72952f4f Stavros Sachtouris
        super(self.__class__, self).main(
1258 72952f4f Stavros Sachtouris
            container___path,
1259 72952f4f Stavros Sachtouris
            path_is_optional=False)
1260 7493ccb6 Stavros Sachtouris
        try:
1261 2fe2672e Stavros Sachtouris
            data = self.client.get_object_hashmap(
1262 2fe2672e Stavros Sachtouris
                self.path,
1263 2fe2672e Stavros Sachtouris
                version=self['object_version'],
1264 2fe2672e Stavros Sachtouris
                if_match=self['if_match'],
1265 2fe2672e Stavros Sachtouris
                if_none_match=self['if_none_match'],
1266 2fe2672e Stavros Sachtouris
                if_modified_since=self['if_modified_since'],
1267 2fe2672e Stavros Sachtouris
                if_unmodified_since=self['if_unmodified_since'])
1268 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1269 72952f4f Stavros Sachtouris
            if err.status == 404:
1270 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1271 72952f4f Stavros Sachtouris
                    raiseCLIError(
1272 72952f4f Stavros Sachtouris
                        err,
1273 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1274 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1275 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1276 72952f4f Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
1277 72952f4f Stavros Sachtouris
                    raiseCLIError(
1278 72952f4f Stavros Sachtouris
                        err,
1279 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
1280 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
1281 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1282 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1283 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1284 72952f4f Stavros Sachtouris
        except Exception as e:
1285 72952f4f Stavros Sachtouris
            raiseCLIError(e)
1286 7493ccb6 Stavros Sachtouris
        print_dict(data)
1287 7493ccb6 Stavros Sachtouris
1288 234954d1 Stavros Sachtouris
1289 d486baec Stavros Sachtouris
@command(pithos_cmds)
1290 7493ccb6 Stavros Sachtouris
class store_delete(_store_container_command):
1291 72952f4f Stavros Sachtouris
    """Delete a container [or an object]
1292 72952f4f Stavros Sachtouris
    How to delete a non-empty container:
1293 72952f4f Stavros Sachtouris
    - empty the container:  /store delete -r <container>
1294 72952f4f Stavros Sachtouris
    - delete it:            /store delete <container>
1295 72952f4f Stavros Sachtouris
    .
1296 72952f4f Stavros Sachtouris
    Semantics of directory deletion:
1297 72952f4f Stavros Sachtouris
    .a preserve the contents: /store delete <container>:<directory>
1298 72952f4f Stavros Sachtouris
    .    objects of the form dir/filename can exist with a dir object
1299 72952f4f Stavros Sachtouris
    .b delete contents:       /store delete -r <container>:<directory>
1300 72952f4f Stavros Sachtouris
    .    all dir/* objects are affected, even if dir does not exist
1301 72952f4f Stavros Sachtouris
    .
1302 72952f4f Stavros Sachtouris
    To restore a deleted object OBJ in a container CONT:
1303 72952f4f Stavros Sachtouris
    - get object versions: /store versions CONT:OBJ
1304 72952f4f Stavros Sachtouris
    .   and choose the version to be restored
1305 72952f4f Stavros Sachtouris
    - restore the object:  /store copy --source-version=<version> CONT:OBJ OBJ
1306 72952f4f Stavros Sachtouris
    """
1307 7493ccb6 Stavros Sachtouris
1308 2fe2672e Stavros Sachtouris
    arguments = dict(
1309 439826ec Stavros Sachtouris
        until=DateArgument('remove history until that date', '--until'),
1310 7147e1ca Stavros Sachtouris
        yes=FlagArgument('Do not prompt for permission', '--yes'),
1311 2fe2672e Stavros Sachtouris
        recursive=FlagArgument(
1312 234954d1 Stavros Sachtouris
            'empty dir or container and delete (if dir)',
1313 234954d1 Stavros Sachtouris
            ('-r', '--recursive'))
1314 2fe2672e Stavros Sachtouris
    )
1315 2fe2672e Stavros Sachtouris
1316 2fe2672e Stavros Sachtouris
    def __init__(self, arguments={}):
1317 2fe2672e Stavros Sachtouris
        super(self.__class__, self).__init__(arguments)
1318 439826ec Stavros Sachtouris
        self['delimiter'] = DelimiterArgument(
1319 2fe2672e Stavros Sachtouris
            self,
1320 234954d1 Stavros Sachtouris
            parsed_name='--delimiter',
1321 234954d1 Stavros Sachtouris
            help='delete objects prefixed with <object><delimiter>')
1322 7493ccb6 Stavros Sachtouris
1323 7493ccb6 Stavros Sachtouris
    def main(self, container____path__):
1324 7493ccb6 Stavros Sachtouris
        super(self.__class__, self).main(container____path__)
1325 7493ccb6 Stavros Sachtouris
        try:
1326 7147e1ca Stavros Sachtouris
            if (not self.path):
1327 7147e1ca Stavros Sachtouris
                if self['yes'] or ask_user(
1328 7147e1ca Stavros Sachtouris
                    'Delete container %s ?' % self.container):
1329 7147e1ca Stavros Sachtouris
                    self.client.del_container(
1330 7147e1ca Stavros Sachtouris
                        until=self['until'],
1331 7147e1ca Stavros Sachtouris
                        delimiter=self['delimiter'])
1332 7493ccb6 Stavros Sachtouris
            else:
1333 7147e1ca Stavros Sachtouris
                if self['yes'] or ask_user(
1334 7147e1ca Stavros Sachtouris
                    'Delete %s:%s ?' % (self.container, self.path)):
1335 7147e1ca Stavros Sachtouris
                    self.client.del_object(
1336 7147e1ca Stavros Sachtouris
                        self.path,
1337 7147e1ca Stavros Sachtouris
                        until=self['until'],
1338 7147e1ca Stavros Sachtouris
                        delimiter=self['delimiter'])
1339 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1340 72952f4f Stavros Sachtouris
            if err.status == 404:
1341 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1342 72952f4f Stavros Sachtouris
                    raiseCLIError(
1343 72952f4f Stavros Sachtouris
                        err,
1344 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1345 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1346 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1347 72952f4f Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
1348 72952f4f Stavros Sachtouris
                    raiseCLIError(
1349 72952f4f Stavros Sachtouris
                        err,
1350 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
1351 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
1352 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1353 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1354 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1355 72952f4f Stavros Sachtouris
        except Exception as e:
1356 72952f4f Stavros Sachtouris
            raiseCLIError(e)
1357 7493ccb6 Stavros Sachtouris
1358 234954d1 Stavros Sachtouris
1359 d486baec Stavros Sachtouris
@command(pithos_cmds)
1360 7493ccb6 Stavros Sachtouris
class store_purge(_store_container_command):
1361 72952f4f Stavros Sachtouris
    """Delete a container and release related data blocks
1362 72952f4f Stavros Sachtouris
    Non-empty containers can not purged.
1363 72952f4f Stavros Sachtouris
    To purge a container with content:
1364 439826ec Stavros Sachtouris
    .   /store delete -r <container>
1365 72952f4f Stavros Sachtouris
    .      objects are deleted, but data blocks remain on server
1366 72952f4f Stavros Sachtouris
    .   /store purge <container>
1367 72952f4f Stavros Sachtouris
    .      container and data blocks are released and deleted
1368 2fe2672e Stavros Sachtouris
    """
1369 234954d1 Stavros Sachtouris
1370 7147e1ca Stavros Sachtouris
    arguments = dict(
1371 7147e1ca Stavros Sachtouris
        yes=FlagArgument('Do not prompt for permission', '--yes'),
1372 7147e1ca Stavros Sachtouris
    )
1373 7147e1ca Stavros Sachtouris
1374 7493ccb6 Stavros Sachtouris
    def main(self, container):
1375 ebdecdc7 Stavros Sachtouris
        super(self.__class__, self).main(container)
1376 7493ccb6 Stavros Sachtouris
        try:
1377 7147e1ca Stavros Sachtouris
            if self['yes'] or ask_user(
1378 7147e1ca Stavros Sachtouris
                'Purge container %s?' % self.container):
1379 7147e1ca Stavros Sachtouris
                self.client.purge_container()
1380 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1381 72952f4f Stavros Sachtouris
            if err.status == 404:
1382 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1383 72952f4f Stavros Sachtouris
                    raiseCLIError(
1384 72952f4f Stavros Sachtouris
                        err,
1385 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1386 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1387 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1388 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1389 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1390 72952f4f Stavros Sachtouris
        except Exception as e:
1391 72952f4f Stavros Sachtouris
            raiseCLIError(e)
1392 7493ccb6 Stavros Sachtouris
1393 234954d1 Stavros Sachtouris
1394 d486baec Stavros Sachtouris
@command(pithos_cmds)
1395 7493ccb6 Stavros Sachtouris
class store_publish(_store_container_command):
1396 2fe2672e Stavros Sachtouris
    """Publish the object and print the public url"""
1397 7493ccb6 Stavros Sachtouris
1398 7493ccb6 Stavros Sachtouris
    def main(self, container___path):
1399 72952f4f Stavros Sachtouris
        super(self.__class__, self).main(
1400 72952f4f Stavros Sachtouris
            container___path,
1401 72952f4f Stavros Sachtouris
            path_is_optional=False)
1402 7493ccb6 Stavros Sachtouris
        try:
1403 5260a313 Stavros Sachtouris
            url = self.client.publish_object(self.path)
1404 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1405 72952f4f Stavros Sachtouris
            if err.status == 404:
1406 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1407 72952f4f Stavros Sachtouris
                    raiseCLIError(
1408 72952f4f Stavros Sachtouris
                        err,
1409 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1410 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1411 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1412 72952f4f Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
1413 72952f4f Stavros Sachtouris
                    raiseCLIError(
1414 72952f4f Stavros Sachtouris
                        err,
1415 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
1416 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
1417 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1418 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1419 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1420 72952f4f Stavros Sachtouris
        except Exception as e:
1421 72952f4f Stavros Sachtouris
            raiseCLIError(e)
1422 5260a313 Stavros Sachtouris
        print(url)
1423 7493ccb6 Stavros Sachtouris
1424 234954d1 Stavros Sachtouris
1425 d486baec Stavros Sachtouris
@command(pithos_cmds)
1426 7493ccb6 Stavros Sachtouris
class store_unpublish(_store_container_command):
1427 7493ccb6 Stavros Sachtouris
    """Unpublish an object"""
1428 7493ccb6 Stavros Sachtouris
1429 7493ccb6 Stavros Sachtouris
    def main(self, container___path):
1430 72952f4f Stavros Sachtouris
        super(self.__class__, self).main(
1431 72952f4f Stavros Sachtouris
            container___path,
1432 72952f4f Stavros Sachtouris
            path_is_optional=False)
1433 7493ccb6 Stavros Sachtouris
        try:
1434 7493ccb6 Stavros Sachtouris
            self.client.unpublish_object(self.path)
1435 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1436 72952f4f Stavros Sachtouris
            if err.status == 404:
1437 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1438 72952f4f Stavros Sachtouris
                    raiseCLIError(
1439 72952f4f Stavros Sachtouris
                        err,
1440 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1441 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1442 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1443 72952f4f Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
1444 72952f4f Stavros Sachtouris
                    raiseCLIError(
1445 72952f4f Stavros Sachtouris
                        err,
1446 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
1447 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
1448 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1449 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1450 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1451 72952f4f Stavros Sachtouris
        except Exception as e:
1452 72952f4f Stavros Sachtouris
            raiseCLIError(e)
1453 7493ccb6 Stavros Sachtouris
1454 234954d1 Stavros Sachtouris
1455 d486baec Stavros Sachtouris
@command(pithos_cmds)
1456 3dabe5d2 Stavros Sachtouris
class store_permissions(_store_container_command):
1457 72952f4f Stavros Sachtouris
    """Get read and write permissions of an object
1458 72952f4f Stavros Sachtouris
    Permissions are lists of users and user groups. There is read and write
1459 72952f4f Stavros Sachtouris
    permissions. Users and groups with write permission have also read
1460 72952f4f Stavros Sachtouris
    permission.
1461 72952f4f Stavros Sachtouris
    """
1462 7493ccb6 Stavros Sachtouris
1463 7493ccb6 Stavros Sachtouris
    def main(self, container___path):
1464 72952f4f Stavros Sachtouris
        super(self.__class__, self).main(
1465 72952f4f Stavros Sachtouris
            container___path,
1466 72952f4f Stavros Sachtouris
            path_is_optional=False)
1467 7493ccb6 Stavros Sachtouris
        try:
1468 7493ccb6 Stavros Sachtouris
            reply = self.client.get_object_sharing(self.path)
1469 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1470 72952f4f Stavros Sachtouris
            if err.status == 404:
1471 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1472 72952f4f Stavros Sachtouris
                    raiseCLIError(
1473 72952f4f Stavros Sachtouris
                        err,
1474 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1475 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1476 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1477 72952f4f Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
1478 72952f4f Stavros Sachtouris
                    raiseCLIError(
1479 72952f4f Stavros Sachtouris
                        err,
1480 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
1481 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
1482 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1483 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1484 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1485 72952f4f Stavros Sachtouris
        except Exception as e:
1486 72952f4f Stavros Sachtouris
            raiseCLIError(e)
1487 72952f4f Stavros Sachtouris
        print_dict(reply)
1488 7493ccb6 Stavros Sachtouris
1489 234954d1 Stavros Sachtouris
1490 d486baec Stavros Sachtouris
@command(pithos_cmds)
1491 3dabe5d2 Stavros Sachtouris
class store_setpermissions(_store_container_command):
1492 72952f4f Stavros Sachtouris
    """Set permissions for an object
1493 72952f4f Stavros Sachtouris
    New permissions overwrite existing permissions.
1494 72952f4f Stavros Sachtouris
    Permission format:
1495 72952f4f Stavros Sachtouris
    -   read=<username>[,usergroup[,...]]
1496 72952f4f Stavros Sachtouris
    -   write=<username>[,usegroup[,...]]
1497 72952f4f Stavros Sachtouris
    E.g. to give read permissions for file F to users A and B and write for C:
1498 72952f4f Stavros Sachtouris
    .       /store setpermissions F read=A,B write=C
1499 72952f4f Stavros Sachtouris
    """
1500 7493ccb6 Stavros Sachtouris
1501 3dabe5d2 Stavros Sachtouris
    def format_permition_dict(self, permissions):
1502 7493ccb6 Stavros Sachtouris
        read = False
1503 7493ccb6 Stavros Sachtouris
        write = False
1504 3dabe5d2 Stavros Sachtouris
        for perms in permissions:
1505 7493ccb6 Stavros Sachtouris
            splstr = perms.split('=')
1506 7493ccb6 Stavros Sachtouris
            if 'read' == splstr[0]:
1507 7493ccb6 Stavros Sachtouris
                read = [user_or_group.strip() \
1508 7493ccb6 Stavros Sachtouris
                for user_or_group in splstr[1].split(',')]
1509 7493ccb6 Stavros Sachtouris
            elif 'write' == splstr[0]:
1510 7493ccb6 Stavros Sachtouris
                write = [user_or_group.strip() \
1511 7493ccb6 Stavros Sachtouris
                for user_or_group in splstr[1].split(',')]
1512 7493ccb6 Stavros Sachtouris
            else:
1513 7493ccb6 Stavros Sachtouris
                read = False
1514 7493ccb6 Stavros Sachtouris
                write = False
1515 7493ccb6 Stavros Sachtouris
        if not read and not write:
1516 43ee6ae1 Stavros Sachtouris
            raiseCLIError(None,
1517 43ee6ae1 Stavros Sachtouris
            'Usage:\tread=<groups,users> write=<groups,users>')
1518 234954d1 Stavros Sachtouris
        return (read, write)
1519 7493ccb6 Stavros Sachtouris
1520 3dabe5d2 Stavros Sachtouris
    def main(self, container___path, *permissions):
1521 234954d1 Stavros Sachtouris
        super(self.__class__,
1522 234954d1 Stavros Sachtouris
            self).main(container___path, path_is_optional=False)
1523 3dabe5d2 Stavros Sachtouris
        (read, write) = self.format_permition_dict(permissions)
1524 7493ccb6 Stavros Sachtouris
        try:
1525 7493ccb6 Stavros Sachtouris
            self.client.set_object_sharing(self.path,
1526 7493ccb6 Stavros Sachtouris
                read_permition=read, write_permition=write)
1527 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1528 72952f4f Stavros Sachtouris
            if err.status == 404:
1529 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1530 72952f4f Stavros Sachtouris
                    raiseCLIError(
1531 72952f4f Stavros Sachtouris
                        err,
1532 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1533 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1534 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1535 72952f4f Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
1536 72952f4f Stavros Sachtouris
                    raiseCLIError(
1537 72952f4f Stavros Sachtouris
                        err,
1538 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
1539 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
1540 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1541 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1542 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1543 72952f4f Stavros Sachtouris
        except Exception as e:
1544 72952f4f Stavros Sachtouris
            raiseCLIError(e)
1545 7493ccb6 Stavros Sachtouris
1546 234954d1 Stavros Sachtouris
1547 d486baec Stavros Sachtouris
@command(pithos_cmds)
1548 3dabe5d2 Stavros Sachtouris
class store_delpermissions(_store_container_command):
1549 72952f4f Stavros Sachtouris
    """Delete all permissions set on object
1550 72952f4f Stavros Sachtouris
    To modify permissions, use /store setpermssions
1551 72952f4f Stavros Sachtouris
    """
1552 7493ccb6 Stavros Sachtouris
1553 7493ccb6 Stavros Sachtouris
    def main(self, container___path):
1554 234954d1 Stavros Sachtouris
        super(self.__class__,
1555 234954d1 Stavros Sachtouris
            self).main(container___path, path_is_optional=False)
1556 7493ccb6 Stavros Sachtouris
        try:
1557 7493ccb6 Stavros Sachtouris
            self.client.del_object_sharing(self.path)
1558 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1559 72952f4f Stavros Sachtouris
            if err.status == 404:
1560 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1561 72952f4f Stavros Sachtouris
                    raiseCLIError(
1562 72952f4f Stavros Sachtouris
                        err,
1563 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1564 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1565 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1566 72952f4f Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
1567 72952f4f Stavros Sachtouris
                    raiseCLIError(
1568 72952f4f Stavros Sachtouris
                        err,
1569 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
1570 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
1571 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1572 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1573 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1574 72952f4f Stavros Sachtouris
        except Exception as e:
1575 72952f4f Stavros Sachtouris
            raiseCLIError(e)
1576 7493ccb6 Stavros Sachtouris
1577 234954d1 Stavros Sachtouris
1578 d486baec Stavros Sachtouris
@command(pithos_cmds)
1579 7493ccb6 Stavros Sachtouris
class store_info(_store_container_command):
1580 72952f4f Stavros Sachtouris
    """Get detailed information for user account, containers or objects
1581 72952f4f Stavros Sachtouris
    to get account info:    /store info
1582 72952f4f Stavros Sachtouris
    to get container info:  /store info <container>
1583 72952f4f Stavros Sachtouris
    to get object info:     /store info <container>:<path>
1584 72952f4f Stavros Sachtouris
    """
1585 7493ccb6 Stavros Sachtouris
1586 2fe2672e Stavros Sachtouris
    arguments = dict(
1587 2fe2672e Stavros Sachtouris
        object_version=ValueArgument(
1588 2fe2672e Stavros Sachtouris
            'show specific version \ (applies only for objects)',
1589 2fe2672e Stavros Sachtouris
            '--object-version')
1590 2fe2672e Stavros Sachtouris
    )
1591 6ac7f90f Stavros Sachtouris
1592 7493ccb6 Stavros Sachtouris
    def main(self, container____path__=None):
1593 7493ccb6 Stavros Sachtouris
        super(self.__class__, self).main(container____path__)
1594 7493ccb6 Stavros Sachtouris
        try:
1595 7493ccb6 Stavros Sachtouris
            if self.container is None:
1596 7493ccb6 Stavros Sachtouris
                reply = self.client.get_account_info()
1597 7493ccb6 Stavros Sachtouris
            elif self.path is None:
1598 7493ccb6 Stavros Sachtouris
                reply = self.client.get_container_info(self.container)
1599 7493ccb6 Stavros Sachtouris
            else:
1600 2fe2672e Stavros Sachtouris
                reply = self.client.get_object_info(
1601 2fe2672e Stavros Sachtouris
                    self.path,
1602 2fe2672e Stavros Sachtouris
                    version=self['object_version'])
1603 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1604 72952f4f Stavros Sachtouris
            if err.status == 404:
1605 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1606 72952f4f Stavros Sachtouris
                    raiseCLIError(
1607 72952f4f Stavros Sachtouris
                        err,
1608 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1609 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1610 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1611 72952f4f Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
1612 72952f4f Stavros Sachtouris
                    raiseCLIError(
1613 72952f4f Stavros Sachtouris
                        err,
1614 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
1615 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
1616 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1617 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1618 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1619 72952f4f Stavros Sachtouris
        except Exception as e:
1620 72952f4f Stavros Sachtouris
            raiseCLIError(e)
1621 7493ccb6 Stavros Sachtouris
        print_dict(reply)
1622 7493ccb6 Stavros Sachtouris
1623 234954d1 Stavros Sachtouris
1624 d486baec Stavros Sachtouris
@command(pithos_cmds)
1625 7493ccb6 Stavros Sachtouris
class store_meta(_store_container_command):
1626 72952f4f Stavros Sachtouris
    """Get metadata for account, containers or objects"""
1627 7493ccb6 Stavros Sachtouris
1628 2fe2672e Stavros Sachtouris
    arguments = dict(
1629 2fe2672e Stavros Sachtouris
        detail=FlagArgument('show detailed output', '-l'),
1630 2fe2672e Stavros Sachtouris
        until=DateArgument('show metadata until then', '--until'),
1631 2fe2672e Stavros Sachtouris
        object_version=ValueArgument(
1632 2fe2672e Stavros Sachtouris
            'show specific version \ (applies only for objects)',
1633 2fe2672e Stavros Sachtouris
            '--object-version')
1634 2fe2672e Stavros Sachtouris
    )
1635 7493ccb6 Stavros Sachtouris
1636 234954d1 Stavros Sachtouris
    def main(self, container____path__=None):
1637 7493ccb6 Stavros Sachtouris
        super(self.__class__, self).main(container____path__)
1638 7493ccb6 Stavros Sachtouris
1639 2fe2672e Stavros Sachtouris
        detail = self['detail']
1640 7493ccb6 Stavros Sachtouris
        try:
1641 2fe2672e Stavros Sachtouris
            until = self['until']
1642 7493ccb6 Stavros Sachtouris
            if self.container is None:
1643 7493ccb6 Stavros Sachtouris
                if detail:
1644 234954d1 Stavros Sachtouris
                    reply = self.client.get_account_info(until=until)
1645 7493ccb6 Stavros Sachtouris
                else:
1646 234954d1 Stavros Sachtouris
                    reply = self.client.get_account_meta(until=until)
1647 7493ccb6 Stavros Sachtouris
                    reply = pretty_keys(reply, '-')
1648 72952f4f Stavros Sachtouris
                if reply:
1649 72952f4f Stavros Sachtouris
                    print(bold(self.client.account))
1650 7493ccb6 Stavros Sachtouris
            elif self.path is None:
1651 7493ccb6 Stavros Sachtouris
                if detail:
1652 234954d1 Stavros Sachtouris
                    reply = self.client.get_container_info(until=until)
1653 7493ccb6 Stavros Sachtouris
                else:
1654 234954d1 Stavros Sachtouris
                    cmeta = self.client.get_container_meta(until=until)
1655 234954d1 Stavros Sachtouris
                    ometa = self.client.get_container_object_meta(until=until)
1656 72952f4f Stavros Sachtouris
                    reply = {}
1657 72952f4f Stavros Sachtouris
                    if cmeta:
1658 72952f4f Stavros Sachtouris
                        reply['container-meta'] = pretty_keys(cmeta, '-')
1659 72952f4f Stavros Sachtouris
                    if ometa:
1660 72952f4f Stavros Sachtouris
                        reply['object-meta'] = pretty_keys(ometa, '-')
1661 7493ccb6 Stavros Sachtouris
            else:
1662 7493ccb6 Stavros Sachtouris
                if detail:
1663 234954d1 Stavros Sachtouris
                    reply = self.client.get_object_info(self.path,
1664 72952f4f Stavros Sachtouris
                        version=self['object_version'])
1665 7493ccb6 Stavros Sachtouris
                else:
1666 234954d1 Stavros Sachtouris
                    reply = self.client.get_object_meta(self.path,
1667 72952f4f Stavros Sachtouris
                        version=self['object_version'])
1668 72952f4f Stavros Sachtouris
                if reply:
1669 7493ccb6 Stavros Sachtouris
                    reply = pretty_keys(pretty_keys(reply, '-'))
1670 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1671 72952f4f Stavros Sachtouris
            if err.status == 404:
1672 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1673 72952f4f Stavros Sachtouris
                    raiseCLIError(
1674 72952f4f Stavros Sachtouris
                        err,
1675 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1676 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1677 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1678 72952f4f Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
1679 72952f4f Stavros Sachtouris
                    raiseCLIError(
1680 72952f4f Stavros Sachtouris
                        err,
1681 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
1682 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
1683 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1684 72952f4f Stavros Sachtouris
                else:
1685 72952f4f Stavros Sachtouris
                    raiseCLIError(err, details=self.generic_err_details)
1686 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1687 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1688 72952f4f Stavros Sachtouris
        except Exception as e:
1689 72952f4f Stavros Sachtouris
            raiseCLIError(e)
1690 72952f4f Stavros Sachtouris
        if reply:
1691 72952f4f Stavros Sachtouris
            print_dict(reply)
1692 7493ccb6 Stavros Sachtouris
1693 234954d1 Stavros Sachtouris
1694 d486baec Stavros Sachtouris
@command(pithos_cmds)
1695 7493ccb6 Stavros Sachtouris
class store_setmeta(_store_container_command):
1696 72952f4f Stavros Sachtouris
    """Set a piece of metadata for account, container or object
1697 72952f4f Stavros Sachtouris
    Metadata are formed as key:value pairs
1698 72952f4f Stavros Sachtouris
    """
1699 7493ccb6 Stavros Sachtouris
1700 7493ccb6 Stavros Sachtouris
    def main(self, metakey___metaval, container____path__=None):
1701 7493ccb6 Stavros Sachtouris
        super(self.__class__, self).main(container____path__)
1702 7493ccb6 Stavros Sachtouris
        try:
1703 7493ccb6 Stavros Sachtouris
            metakey, metavalue = metakey___metaval.split(':')
1704 83ba5545 Stavros Sachtouris
        except ValueError as err:
1705 72952f4f Stavros Sachtouris
            raiseCLIError(err,
1706 72952f4f Stavros Sachtouris
                'Cannot parse %s as a key:value pair' % metakey___metaval,
1707 72952f4f Stavros Sachtouris
                details=['Syntax:',
1708 72952f4f Stavros Sachtouris
                    '   store setmeta metakey:metavalue [cont[:path]]'
1709 72952f4f Stavros Sachtouris
                ],
1710 72952f4f Stavros Sachtouris
                importance=1,
1711 72952f4f Stavros Sachtouris
                )
1712 7493ccb6 Stavros Sachtouris
        try:
1713 7493ccb6 Stavros Sachtouris
            if self.container is None:
1714 234954d1 Stavros Sachtouris
                self.client.set_account_meta({metakey: metavalue})
1715 7493ccb6 Stavros Sachtouris
            elif self.path is None:
1716 234954d1 Stavros Sachtouris
                self.client.set_container_meta({metakey: metavalue})
1717 7493ccb6 Stavros Sachtouris
            else:
1718 234954d1 Stavros Sachtouris
                self.client.set_object_meta(self.path, {metakey: metavalue})
1719 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1720 72952f4f Stavros Sachtouris
            if err.status == 404:
1721 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1722 72952f4f Stavros Sachtouris
                    raiseCLIError(
1723 72952f4f Stavros Sachtouris
                        err,
1724 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1725 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1726 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1727 72952f4f Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
1728 72952f4f Stavros Sachtouris
                    raiseCLIError(
1729 72952f4f Stavros Sachtouris
                        err,
1730 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
1731 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
1732 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1733 72952f4f Stavros Sachtouris
                else:
1734 72952f4f Stavros Sachtouris
                    raiseCLIError(err, details=self.generic_err_details)
1735 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1736 72952f4f Stavros Sachtouris
            raiseCLIError(err)
1737 72952f4f Stavros Sachtouris
        except Exception as err:
1738 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1739 7493ccb6 Stavros Sachtouris
1740 234954d1 Stavros Sachtouris
1741 d486baec Stavros Sachtouris
@command(pithos_cmds)
1742 7493ccb6 Stavros Sachtouris
class store_delmeta(_store_container_command):
1743 72952f4f Stavros Sachtouris
    """Delete metadata with given key from account, container or object
1744 72952f4f Stavros Sachtouris
    Metadata are formed as key:value objects
1745 72952f4f Stavros Sachtouris
    - to get metadata of current account:     /store meta
1746 72952f4f Stavros Sachtouris
    - to get metadata of a container:         /store meta <container>
1747 72952f4f Stavros Sachtouris
    - to get metadata of an object:           /store meta <container>:<path>
1748 72952f4f Stavros Sachtouris
    """
1749 7493ccb6 Stavros Sachtouris
1750 7493ccb6 Stavros Sachtouris
    def main(self, metakey, container____path__=None):
1751 7493ccb6 Stavros Sachtouris
        super(self.__class__, self).main(container____path__)
1752 7493ccb6 Stavros Sachtouris
        try:
1753 7493ccb6 Stavros Sachtouris
            if self.container is None:
1754 7493ccb6 Stavros Sachtouris
                self.client.del_account_meta(metakey)
1755 7493ccb6 Stavros Sachtouris
            elif self.path is None:
1756 7493ccb6 Stavros Sachtouris
                self.client.del_container_meta(metakey)
1757 7493ccb6 Stavros Sachtouris
            else:
1758 bc223d91 Stavros Sachtouris
                self.client.del_object_meta(self.path, metakey)
1759 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1760 72952f4f Stavros Sachtouris
            if err.status == 404:
1761 72952f4f Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1762 72952f4f Stavros Sachtouris
                    raiseCLIError(
1763 72952f4f Stavros Sachtouris
                        err,
1764 72952f4f Stavros Sachtouris
                        'No container %s in account %s'\
1765 72952f4f Stavros Sachtouris
                        % (self.container, self.account),
1766 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1767 72952f4f Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
1768 72952f4f Stavros Sachtouris
                    raiseCLIError(
1769 72952f4f Stavros Sachtouris
                        err,
1770 72952f4f Stavros Sachtouris
                        'No object %s in container %s'\
1771 72952f4f Stavros Sachtouris
                        % (self.path, self.container),
1772 72952f4f Stavros Sachtouris
                        details=self.generic_err_details)
1773 72952f4f Stavros Sachtouris
                else:
1774 72952f4f Stavros Sachtouris
                    raiseCLIError(err, details=self.generic_err_details)
1775 72952f4f Stavros Sachtouris
            raise_connection_errors(err)
1776 72952f4f Stavros Sachtouris
            raiseCLIError(err)
1777 72952f4f Stavros Sachtouris
        except Exception as err:
1778 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1779 7493ccb6 Stavros Sachtouris
1780 234954d1 Stavros Sachtouris
1781 d486baec Stavros Sachtouris
@command(pithos_cmds)
1782 7493ccb6 Stavros Sachtouris
class store_quota(_store_account_command):
1783 776eee69 Stavros Sachtouris
    """Get quota (in KB) for account or container"""
1784 7493ccb6 Stavros Sachtouris
1785 234954d1 Stavros Sachtouris
    def main(self, container=None):
1786 7493ccb6 Stavros Sachtouris
        super(self.__class__, self).main()
1787 7493ccb6 Stavros Sachtouris
        try:
1788 7493ccb6 Stavros Sachtouris
            if container is None:
1789 7493ccb6 Stavros Sachtouris
                reply = self.client.get_account_quota()
1790 7493ccb6 Stavros Sachtouris
            else:
1791 7493ccb6 Stavros Sachtouris
                reply = self.client.get_container_quota(container)
1792 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1793 776eee69 Stavros Sachtouris
            if err.status == 404:
1794 776eee69 Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1795 776eee69 Stavros Sachtouris
                    raiseCLIError(err,
1796 776eee69 Stavros Sachtouris
                        'No container %s in account %s'\
1797 776eee69 Stavros Sachtouris
                        % (container, self.account))
1798 776eee69 Stavros Sachtouris
            raise_connection_errors(err)
1799 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1800 776eee69 Stavros Sachtouris
        except Exception as err:
1801 776eee69 Stavros Sachtouris
            raiseCLIError(err)
1802 776eee69 Stavros Sachtouris
        print_dict(pretty_keys(reply, '-'))
1803 7493ccb6 Stavros Sachtouris
1804 234954d1 Stavros Sachtouris
1805 d486baec Stavros Sachtouris
@command(pithos_cmds)
1806 7493ccb6 Stavros Sachtouris
class store_setquota(_store_account_command):
1807 776eee69 Stavros Sachtouris
    """Set new quota (in KB) for account or container"""
1808 7493ccb6 Stavros Sachtouris
1809 234954d1 Stavros Sachtouris
    def main(self, quota, container=None):
1810 7493ccb6 Stavros Sachtouris
        super(self.__class__, self).main()
1811 7493ccb6 Stavros Sachtouris
        try:
1812 7493ccb6 Stavros Sachtouris
            if container is None:
1813 7493ccb6 Stavros Sachtouris
                self.client.set_account_quota(quota)
1814 7493ccb6 Stavros Sachtouris
            else:
1815 7493ccb6 Stavros Sachtouris
                self.client.container = container
1816 7493ccb6 Stavros Sachtouris
                self.client.set_container_quota(quota)
1817 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1818 776eee69 Stavros Sachtouris
            if err.status == 404:
1819 776eee69 Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1820 776eee69 Stavros Sachtouris
                    raiseCLIError(err,
1821 776eee69 Stavros Sachtouris
                        'No container %s in account %s'\
1822 776eee69 Stavros Sachtouris
                        % (container, self.account))
1823 776eee69 Stavros Sachtouris
            raise_connection_errors(err)
1824 776eee69 Stavros Sachtouris
            raiseCLIError(err)
1825 776eee69 Stavros Sachtouris
        except Exception as err:
1826 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1827 7493ccb6 Stavros Sachtouris
1828 234954d1 Stavros Sachtouris
1829 d486baec Stavros Sachtouris
@command(pithos_cmds)
1830 7493ccb6 Stavros Sachtouris
class store_versioning(_store_account_command):
1831 776eee69 Stavros Sachtouris
    """Get  versioning for account or container"""
1832 7493ccb6 Stavros Sachtouris
1833 234954d1 Stavros Sachtouris
    def main(self, container=None):
1834 7493ccb6 Stavros Sachtouris
        super(self.__class__, self).main()
1835 7493ccb6 Stavros Sachtouris
        try:
1836 7493ccb6 Stavros Sachtouris
            if container is None:
1837 7493ccb6 Stavros Sachtouris
                reply = self.client.get_account_versioning()
1838 7493ccb6 Stavros Sachtouris
            else:
1839 7493ccb6 Stavros Sachtouris
                reply = self.client.get_container_versioning(container)
1840 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1841 776eee69 Stavros Sachtouris
            if err.status == 404:
1842 776eee69 Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1843 776eee69 Stavros Sachtouris
                    raiseCLIError(
1844 776eee69 Stavros Sachtouris
                        err,
1845 776eee69 Stavros Sachtouris
                        'No container %s in account %s'\
1846 776eee69 Stavros Sachtouris
                        % (self.container, self.account),
1847 776eee69 Stavros Sachtouris
                        details=self.generic_err_details)
1848 776eee69 Stavros Sachtouris
                else:
1849 776eee69 Stavros Sachtouris
                    raiseCLIError(err, details=self.generic_err_details)
1850 776eee69 Stavros Sachtouris
            raise_connection_errors(err)
1851 776eee69 Stavros Sachtouris
            raiseCLIError(err)
1852 776eee69 Stavros Sachtouris
        except Exception as err:
1853 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1854 7493ccb6 Stavros Sachtouris
        print_dict(reply)
1855 7493ccb6 Stavros Sachtouris
1856 234954d1 Stavros Sachtouris
1857 d486baec Stavros Sachtouris
@command(pithos_cmds)
1858 7493ccb6 Stavros Sachtouris
class store_setversioning(_store_account_command):
1859 776eee69 Stavros Sachtouris
    """Set versioning mode (auto, none) for account or container"""
1860 7493ccb6 Stavros Sachtouris
1861 234954d1 Stavros Sachtouris
    def main(self, versioning, container=None):
1862 7493ccb6 Stavros Sachtouris
        super(self.__class__, self).main()
1863 7493ccb6 Stavros Sachtouris
        try:
1864 7493ccb6 Stavros Sachtouris
            if container is None:
1865 7493ccb6 Stavros Sachtouris
                self.client.set_account_versioning(versioning)
1866 7493ccb6 Stavros Sachtouris
            else:
1867 7493ccb6 Stavros Sachtouris
                self.client.container = container
1868 7493ccb6 Stavros Sachtouris
                self.client.set_container_versioning(versioning)
1869 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1870 776eee69 Stavros Sachtouris
            if err.status == 404:
1871 776eee69 Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1872 776eee69 Stavros Sachtouris
                    raiseCLIError(
1873 776eee69 Stavros Sachtouris
                        err,
1874 776eee69 Stavros Sachtouris
                        'No container %s in account %s'\
1875 776eee69 Stavros Sachtouris
                        % (self.container, self.account),
1876 776eee69 Stavros Sachtouris
                        details=self.generic_err_details)
1877 776eee69 Stavros Sachtouris
                else:
1878 776eee69 Stavros Sachtouris
                    raiseCLIError(err, details=self.generic_err_details)
1879 776eee69 Stavros Sachtouris
            raise_connection_errors(err)
1880 776eee69 Stavros Sachtouris
            raiseCLIError(err)
1881 776eee69 Stavros Sachtouris
        except Exception as err:
1882 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1883 7493ccb6 Stavros Sachtouris
1884 234954d1 Stavros Sachtouris
1885 d486baec Stavros Sachtouris
@command(pithos_cmds)
1886 7493ccb6 Stavros Sachtouris
class store_group(_store_account_command):
1887 4fcc38a2 Stavros Sachtouris
    """Get groups and group members"""
1888 7493ccb6 Stavros Sachtouris
1889 7493ccb6 Stavros Sachtouris
    def main(self):
1890 7493ccb6 Stavros Sachtouris
        super(self.__class__, self).main()
1891 7493ccb6 Stavros Sachtouris
        try:
1892 7493ccb6 Stavros Sachtouris
            reply = self.client.get_account_group()
1893 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1894 4fcc38a2 Stavros Sachtouris
            raise_connection_errors(err)
1895 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1896 4fcc38a2 Stavros Sachtouris
        except Exception as err:
1897 4fcc38a2 Stavros Sachtouris
            raiseCLIError(err)
1898 4fcc38a2 Stavros Sachtouris
        print_dict(pretty_keys(reply, '-'))
1899 7493ccb6 Stavros Sachtouris
1900 234954d1 Stavros Sachtouris
1901 d486baec Stavros Sachtouris
@command(pithos_cmds)
1902 7493ccb6 Stavros Sachtouris
class store_setgroup(_store_account_command):
1903 4fcc38a2 Stavros Sachtouris
    """Set a user group"""
1904 7493ccb6 Stavros Sachtouris
1905 7493ccb6 Stavros Sachtouris
    def main(self, groupname, *users):
1906 7493ccb6 Stavros Sachtouris
        super(self.__class__, self).main()
1907 7493ccb6 Stavros Sachtouris
        try:
1908 7493ccb6 Stavros Sachtouris
            self.client.set_account_group(groupname, users)
1909 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1910 4fcc38a2 Stavros Sachtouris
            raise_connection_errors(err)
1911 4fcc38a2 Stavros Sachtouris
            raiseCLIError(err)
1912 4fcc38a2 Stavros Sachtouris
        except Exception as err:
1913 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1914 7493ccb6 Stavros Sachtouris
1915 234954d1 Stavros Sachtouris
1916 d486baec Stavros Sachtouris
@command(pithos_cmds)
1917 7493ccb6 Stavros Sachtouris
class store_delgroup(_store_account_command):
1918 4fcc38a2 Stavros Sachtouris
    """Delete a user group"""
1919 7493ccb6 Stavros Sachtouris
1920 7493ccb6 Stavros Sachtouris
    def main(self, groupname):
1921 7493ccb6 Stavros Sachtouris
        super(self.__class__, self).main()
1922 7493ccb6 Stavros Sachtouris
        try:
1923 7493ccb6 Stavros Sachtouris
            self.client.del_account_group(groupname)
1924 7493ccb6 Stavros Sachtouris
        except ClientError as err:
1925 4fcc38a2 Stavros Sachtouris
            raise_connection_errors(err)
1926 4fcc38a2 Stavros Sachtouris
            raiseCLIError(err)
1927 4fcc38a2 Stavros Sachtouris
        except Exception as err:
1928 7493ccb6 Stavros Sachtouris
            raiseCLIError(err)
1929 a23f6ffe Stavros Sachtouris
1930 234954d1 Stavros Sachtouris
1931 d486baec Stavros Sachtouris
@command(pithos_cmds)
1932 a23f6ffe Stavros Sachtouris
class store_sharers(_store_account_command):
1933 4fcc38a2 Stavros Sachtouris
    """List the accounts that share objects with current user"""
1934 a23f6ffe Stavros Sachtouris
1935 2fe2672e Stavros Sachtouris
    arguments = dict(
1936 2fe2672e Stavros Sachtouris
        detail=FlagArgument('show detailed output', '-l'),
1937 2fe2672e Stavros Sachtouris
        marker=ValueArgument('show output greater then marker', '--marker')
1938 2fe2672e Stavros Sachtouris
    )
1939 a23f6ffe Stavros Sachtouris
1940 a23f6ffe Stavros Sachtouris
    def main(self):
1941 a23f6ffe Stavros Sachtouris
        super(self.__class__, self).main()
1942 a23f6ffe Stavros Sachtouris
        try:
1943 2fe2672e Stavros Sachtouris
            marker = self['marker']
1944 234954d1 Stavros Sachtouris
            accounts = self.client.get_sharing_accounts(marker=marker)
1945 a23f6ffe Stavros Sachtouris
        except ClientError as err:
1946 4fcc38a2 Stavros Sachtouris
            raise_connection_errors(err)
1947 4fcc38a2 Stavros Sachtouris
            raiseCLIError(err)
1948 4fcc38a2 Stavros Sachtouris
        except Exception as err:
1949 a23f6ffe Stavros Sachtouris
            raiseCLIError(err)
1950 a23f6ffe Stavros Sachtouris
1951 a23f6ffe Stavros Sachtouris
        for acc in accounts:
1952 234954d1 Stavros Sachtouris
            stdout.write(bold(acc['name']) + ' ')
1953 2fe2672e Stavros Sachtouris
            if self['detail']:
1954 4fcc38a2 Stavros Sachtouris
                print_dict(acc, exclude='name')
1955 2fe2672e Stavros Sachtouris
        if not self['detail']:
1956 a23f6ffe Stavros Sachtouris
            print
1957 38dc5d2f Stavros Sachtouris
1958 234954d1 Stavros Sachtouris
1959 d486baec Stavros Sachtouris
@command(pithos_cmds)
1960 38dc5d2f Stavros Sachtouris
class store_versions(_store_container_command):
1961 4fcc38a2 Stavros Sachtouris
    """Get the list of object versions
1962 4fcc38a2 Stavros Sachtouris
    Deleted objects may still have versions that can be used to restore it and
1963 4fcc38a2 Stavros Sachtouris
    get information about its previous state.
1964 4fcc38a2 Stavros Sachtouris
    The version number can be used in a number of other commands, like info,
1965 4fcc38a2 Stavros Sachtouris
    copy, move, meta. See these commands for more information, e.g.
1966 4fcc38a2 Stavros Sachtouris
    /store info -h
1967 4fcc38a2 Stavros Sachtouris
    """
1968 38dc5d2f Stavros Sachtouris
1969 38dc5d2f Stavros Sachtouris
    def main(self, container___path):
1970 38dc5d2f Stavros Sachtouris
        super(store_versions, self).main(container___path)
1971 38dc5d2f Stavros Sachtouris
        try:
1972 38dc5d2f Stavros Sachtouris
            versions = self.client.get_object_versionlist(self.path)
1973 4fcc38a2 Stavros Sachtouris
1974 4fcc38a2 Stavros Sachtouris
            for vitem in versions:
1975 4fcc38a2 Stavros Sachtouris
                t = localtime(float(vitem[1]))
1976 4fcc38a2 Stavros Sachtouris
                vid = bold(unicode(vitem[0]))
1977 4fcc38a2 Stavros Sachtouris
                print('\t%s \t(%s)' % (vid, strftime('%d-%m-%Y %H:%M:%S', t)))
1978 38dc5d2f Stavros Sachtouris
        except ClientError as err:
1979 4fcc38a2 Stavros Sachtouris
            if err.status == 404:
1980 4fcc38a2 Stavros Sachtouris
                if 'container' in ('%s' % err).lower():
1981 4fcc38a2 Stavros Sachtouris
                    raiseCLIError(
1982 4fcc38a2 Stavros Sachtouris
                        err,
1983 4fcc38a2 Stavros Sachtouris
                        'No container %s in account %s'\
1984 4fcc38a2 Stavros Sachtouris
                        % (self.container, self.account),
1985 4fcc38a2 Stavros Sachtouris
                        details=self.generic_err_details)
1986 4fcc38a2 Stavros Sachtouris
                elif 'object' in ('%s' % err).lower():
1987 4fcc38a2 Stavros Sachtouris
                    raiseCLIError(
1988 4fcc38a2 Stavros Sachtouris
                        err,
1989 4fcc38a2 Stavros Sachtouris
                        'No object %s in container %s'\
1990 4fcc38a2 Stavros Sachtouris
                        % (self.path, self.container),
1991 4fcc38a2 Stavros Sachtouris
                        details=self.generic_err_details)
1992 4fcc38a2 Stavros Sachtouris
                else:
1993 4fcc38a2 Stavros Sachtouris
                    raiseCLIError(err, details=self.generic_err_details)
1994 4fcc38a2 Stavros Sachtouris
            raise_connection_errors(err)
1995 4fcc38a2 Stavros Sachtouris
            raiseCLIError(err)
1996 4fcc38a2 Stavros Sachtouris
        except Exception as err:
1997 83ba5545 Stavros Sachtouris
            raiseCLIError(err)