Statistics
| Branch: | Tag: | Revision:

root / snf-pithos-tools / pithos / tools / sh.py @ f4fbb0fa

History | View | Annotate | Download (33 kB)

1 cfac048c Giorgos Verigakis
#!/usr/bin/env python
2 cfac048c Giorgos Verigakis
3 2e662088 Antony Chazapis
# Copyright 2011-2012 GRNET S.A. All rights reserved.
4 2715ade4 Sofia Papagiannaki
#
5 a4c10cbc Sofia Papagiannaki
# Redistribution and use in source and binary forms, with or
6 a4c10cbc Sofia Papagiannaki
# without modification, are permitted provided that the following
7 a4c10cbc Sofia Papagiannaki
# conditions are met:
8 2715ade4 Sofia Papagiannaki
#
9 a4c10cbc Sofia Papagiannaki
#   1. Redistributions of source code must retain the above
10 a4c10cbc Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
11 a4c10cbc Sofia Papagiannaki
#      disclaimer.
12 2715ade4 Sofia Papagiannaki
#
13 a4c10cbc Sofia Papagiannaki
#   2. Redistributions in binary form must reproduce the above
14 a4c10cbc Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
15 a4c10cbc Sofia Papagiannaki
#      disclaimer in the documentation and/or other materials
16 a4c10cbc Sofia Papagiannaki
#      provided with the distribution.
17 2715ade4 Sofia Papagiannaki
#
18 a4c10cbc Sofia Papagiannaki
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 a4c10cbc Sofia Papagiannaki
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 a4c10cbc Sofia Papagiannaki
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 a4c10cbc Sofia Papagiannaki
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 a4c10cbc Sofia Papagiannaki
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 a4c10cbc Sofia Papagiannaki
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 a4c10cbc Sofia Papagiannaki
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 a4c10cbc Sofia Papagiannaki
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 a4c10cbc Sofia Papagiannaki
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 a4c10cbc Sofia Papagiannaki
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 a4c10cbc Sofia Papagiannaki
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 a4c10cbc Sofia Papagiannaki
# POSSIBILITY OF SUCH DAMAGE.
30 2715ade4 Sofia Papagiannaki
#
31 a4c10cbc Sofia Papagiannaki
# The views and conclusions contained in the software and
32 a4c10cbc Sofia Papagiannaki
# documentation are those of the authors and should not be
33 a4c10cbc Sofia Papagiannaki
# interpreted as representing official policies, either expressed
34 a4c10cbc Sofia Papagiannaki
# or implied, of GRNET S.A.
35 a4c10cbc Sofia Papagiannaki
36 cfac048c Giorgos Verigakis
from getpass import getuser
37 cfac048c Giorgos Verigakis
from optparse import OptionParser
38 bcb7c5a8 Sofia Papagiannaki
from os import environ
39 f07c5a53 Sofia Papagiannaki
from sys import argv, exit, stdin, stdout
40 d2d5c360 Sofia Papagiannaki
from datetime import datetime
41 5a96180b Antony Chazapis
42 6e147ecc Antony Chazapis
from pithos.tools.lib.client import Pithos_Client, Fault
43 6e147ecc Antony Chazapis
from pithos.tools.lib.util import get_user, get_auth, get_url
44 6e147ecc Antony Chazapis
from pithos.tools.lib.transfer import upload, download
45 cfac048c Giorgos Verigakis
46 cfac048c Giorgos Verigakis
import json
47 cfac048c Giorgos Verigakis
import logging
48 f07c5a53 Sofia Papagiannaki
import types
49 d2d5c360 Sofia Papagiannaki
import re
50 d2d5c360 Sofia Papagiannaki
import time as _time
51 bcb7c5a8 Sofia Papagiannaki
import os
52 cfac048c Giorgos Verigakis
53 cfac048c Giorgos Verigakis
_cli_commands = {}
54 cfac048c Giorgos Verigakis
55 2715ade4 Sofia Papagiannaki
56 cfac048c Giorgos Verigakis
def cli_command(*args):
57 cfac048c Giorgos Verigakis
    def decorator(cls):
58 cfac048c Giorgos Verigakis
        cls.commands = args
59 cfac048c Giorgos Verigakis
        for name in args:
60 cfac048c Giorgos Verigakis
            _cli_commands[name] = cls
61 cfac048c Giorgos Verigakis
        return cls
62 cfac048c Giorgos Verigakis
    return decorator
63 cfac048c Giorgos Verigakis
64 2715ade4 Sofia Papagiannaki
65 cfac048c Giorgos Verigakis
def class_for_cli_command(name):
66 cfac048c Giorgos Verigakis
    return _cli_commands[name]
67 cfac048c Giorgos Verigakis
68 2715ade4 Sofia Papagiannaki
69 cfac048c Giorgos Verigakis
class Command(object):
70 10998c60 Sofia Papagiannaki
    syntax = ''
71 2715ade4 Sofia Papagiannaki
72 a2defd86 Sofia Papagiannaki
    def __init__(self, name, argv):
73 a2defd86 Sofia Papagiannaki
        parser = OptionParser('%%prog %s [options] %s' % (name, self.syntax))
74 96738a78 Sofia Papagiannaki
        parser.add_option('--url', dest='url', metavar='URL',
75 2a0d6ae0 Sofia Papagiannaki
                          default=get_url(), help='server URL (currently: %s)' % get_url())
76 2a0d6ae0 Sofia Papagiannaki
        parser.add_option('--user', dest='user', metavar='USER',
77 a5149fd0 Sofia Papagiannaki
                          default=get_user(),
78 2a0d6ae0 Sofia Papagiannaki
                          help='account USER (currently: %s)' % get_user())
79 2a0d6ae0 Sofia Papagiannaki
        parser.add_option('--token', dest='token', metavar='TOKEN',
80 a5149fd0 Sofia Papagiannaki
                          default=get_auth(),
81 2a0d6ae0 Sofia Papagiannaki
                          help='account TOKEN (currently: %s)' % get_auth())
82 f07c5a53 Sofia Papagiannaki
        parser.add_option('-v', action='store_true', dest='verbose',
83 2a0d6ae0 Sofia Papagiannaki
                          default=False, help='verbose output')
84 f07c5a53 Sofia Papagiannaki
        parser.add_option('-d', action='store_true', dest='debug',
85 2a0d6ae0 Sofia Papagiannaki
                          default=False, help='debug output')
86 cfac048c Giorgos Verigakis
        self.add_options(parser)
87 cfac048c Giorgos Verigakis
        options, args = parser.parse_args(argv)
88 2715ade4 Sofia Papagiannaki
89 cfac048c Giorgos Verigakis
        # Add options to self
90 cfac048c Giorgos Verigakis
        for opt in parser.option_list:
91 cfac048c Giorgos Verigakis
            key = opt.dest
92 cfac048c Giorgos Verigakis
            if key:
93 cfac048c Giorgos Verigakis
                val = getattr(options, key)
94 cfac048c Giorgos Verigakis
                setattr(self, key, val)
95 2715ade4 Sofia Papagiannaki
96 2715ade4 Sofia Papagiannaki
        self.client = Pithos_Client(
97 2715ade4 Sofia Papagiannaki
            self.url, self.token, self.user, self.verbose,
98 2715ade4 Sofia Papagiannaki
            self.debug)
99 2715ade4 Sofia Papagiannaki
100 cfac048c Giorgos Verigakis
        self.parser = parser
101 cfac048c Giorgos Verigakis
        self.args = args
102 2715ade4 Sofia Papagiannaki
103 25c3841c Sofia Papagiannaki
    def _build_args(self, attrs):
104 25c3841c Sofia Papagiannaki
        args = {}
105 25c3841c Sofia Papagiannaki
        for a in [a for a in attrs if getattr(self, a)]:
106 25c3841c Sofia Papagiannaki
            args[a] = getattr(self, a)
107 25c3841c Sofia Papagiannaki
        return args
108 25c3841c Sofia Papagiannaki
109 cfac048c Giorgos Verigakis
    def add_options(self, parser):
110 cfac048c Giorgos Verigakis
        pass
111 2715ade4 Sofia Papagiannaki
112 cfac048c Giorgos Verigakis
    def execute(self, *args):
113 cfac048c Giorgos Verigakis
        pass
114 cfac048c Giorgos Verigakis
115 2715ade4 Sofia Papagiannaki
116 cfac048c Giorgos Verigakis
@cli_command('list', 'ls')
117 cfac048c Giorgos Verigakis
class List(Command):
118 f07c5a53 Sofia Papagiannaki
    syntax = '[<container>[/<object>]]'
119 cfac048c Giorgos Verigakis
    description = 'list containers or objects'
120 2715ade4 Sofia Papagiannaki
121 cfac048c Giorgos Verigakis
    def add_options(self, parser):
122 3f5b02c7 Sofia Papagiannaki
        parser.add_option('-l', action='store_true', dest='detail',
123 3f5b02c7 Sofia Papagiannaki
                          default=False, help='show detailed output')
124 3f5b02c7 Sofia Papagiannaki
        parser.add_option('-n', action='store', type='int', dest='limit',
125 25c3841c Sofia Papagiannaki
                          default=10000, help='show limited output')
126 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--marker', action='store', type='str',
127 3f5b02c7 Sofia Papagiannaki
                          dest='marker', default=None,
128 3f5b02c7 Sofia Papagiannaki
                          help='show output greater then marker')
129 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--prefix', action='store', type='str',
130 3f5b02c7 Sofia Papagiannaki
                          dest='prefix', default=None,
131 3f5b02c7 Sofia Papagiannaki
                          help='show output starting with prefix')
132 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--delimiter', action='store', type='str',
133 3f5b02c7 Sofia Papagiannaki
                          dest='delimiter', default=None,
134 3f5b02c7 Sofia Papagiannaki
                          help='show output up to the delimiter')
135 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--path', action='store', type='str',
136 3f5b02c7 Sofia Papagiannaki
                          dest='path', default=None,
137 3f5b02c7 Sofia Papagiannaki
                          help='show output starting with prefix up to /')
138 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--meta', action='store', type='str',
139 3f5b02c7 Sofia Papagiannaki
                          dest='meta', default=None,
140 3f5b02c7 Sofia Papagiannaki
                          help='show output having the specified meta keys')
141 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--if-modified-since', action='store', type='str',
142 3f5b02c7 Sofia Papagiannaki
                          dest='if_modified_since', default=None,
143 3f5b02c7 Sofia Papagiannaki
                          help='show output if modified since then')
144 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--if-unmodified-since', action='store', type='str',
145 3f5b02c7 Sofia Papagiannaki
                          dest='if_unmodified_since', default=None,
146 3f5b02c7 Sofia Papagiannaki
                          help='show output if not modified since then')
147 d2d5c360 Sofia Papagiannaki
        parser.add_option('--until', action='store', dest='until',
148 f0eacc2c Sofia Papagiannaki
                          default=None, help='show metadata until that date')
149 d2d5c360 Sofia Papagiannaki
        parser.add_option('--format', action='store', dest='format',
150 e46b2bcf Sofia Papagiannaki
                          default='%d/%m/%Y %H:%M:%S', help='format to parse until date (default: %d/%m/%Y %H:%M:%S)')
151 5ddd6bcb Sofia Papagiannaki
        parser.add_option('--shared', action='store_true', dest='shared',
152 5ddd6bcb Sofia Papagiannaki
                          default=False, help='show only shared')
153 5ddd6bcb Sofia Papagiannaki
        parser.add_option('--public', action='store_true', dest='public',
154 5ddd6bcb Sofia Papagiannaki
                          default=False, help='show only public')
155 2715ade4 Sofia Papagiannaki
156 cfac048c Giorgos Verigakis
    def execute(self, container=None):
157 cfac048c Giorgos Verigakis
        if container:
158 cfac048c Giorgos Verigakis
            self.list_objects(container)
159 cfac048c Giorgos Verigakis
        else:
160 cfac048c Giorgos Verigakis
            self.list_containers()
161 2715ade4 Sofia Papagiannaki
162 cfac048c Giorgos Verigakis
    def list_containers(self):
163 f0eacc2c Sofia Papagiannaki
        attrs = ['limit', 'marker', 'if_modified_since',
164 5ddd6bcb Sofia Papagiannaki
                 'if_unmodified_since', 'shared', 'public']
165 25c3841c Sofia Papagiannaki
        args = self._build_args(attrs)
166 f0eacc2c Sofia Papagiannaki
        args['format'] = 'json' if self.detail else 'text'
167 2715ade4 Sofia Papagiannaki
168 f0eacc2c Sofia Papagiannaki
        if getattr(self, 'until'):
169 d2d5c360 Sofia Papagiannaki
            t = _time.strptime(self.until, self.format)
170 25c3841c Sofia Papagiannaki
            args['until'] = int(_time.mktime(t))
171 2715ade4 Sofia Papagiannaki
172 25c3841c Sofia Papagiannaki
        l = self.client.list_containers(**args)
173 f07c5a53 Sofia Papagiannaki
        print_list(l)
174 2715ade4 Sofia Papagiannaki
175 cfac048c Giorgos Verigakis
    def list_objects(self, container):
176 bcb7c5a8 Sofia Papagiannaki
        #prepate params
177 bcb7c5a8 Sofia Papagiannaki
        params = {}
178 f0eacc2c Sofia Papagiannaki
        attrs = ['limit', 'marker', 'prefix', 'delimiter', 'path',
179 5ddd6bcb Sofia Papagiannaki
                 'meta', 'if_modified_since', 'if_unmodified_since',
180 5ddd6bcb Sofia Papagiannaki
                 'shared', 'public']
181 25c3841c Sofia Papagiannaki
        args = self._build_args(attrs)
182 f0eacc2c Sofia Papagiannaki
        args['format'] = 'json' if self.detail else 'text'
183 2715ade4 Sofia Papagiannaki
184 bcb7c5a8 Sofia Papagiannaki
        if self.until:
185 bcb7c5a8 Sofia Papagiannaki
            t = _time.strptime(self.until, self.format)
186 25c3841c Sofia Papagiannaki
            args['until'] = int(_time.mktime(t))
187 2715ade4 Sofia Papagiannaki
188 d2d5c360 Sofia Papagiannaki
        container, sep, object = container.partition('/')
189 d2d5c360 Sofia Papagiannaki
        if object:
190 d2d5c360 Sofia Papagiannaki
            return
191 2715ade4 Sofia Papagiannaki
192 a4c10cbc Sofia Papagiannaki
        detail = 'json'
193 a2defd86 Sofia Papagiannaki
        #if request with meta quering disable trash filtering
194 a2defd86 Sofia Papagiannaki
        show_trashed = True if self.meta else False
195 25c3841c Sofia Papagiannaki
        l = self.client.list_objects(container, **args)
196 a4c10cbc Sofia Papagiannaki
        print_list(l, detail=self.detail)
197 cfac048c Giorgos Verigakis
198 2715ade4 Sofia Papagiannaki
199 cfac048c Giorgos Verigakis
@cli_command('meta')
200 cfac048c Giorgos Verigakis
class Meta(Command):
201 cfac048c Giorgos Verigakis
    syntax = '[<container>[/<object>]]'
202 f63cf249 Sofia Papagiannaki
    description = 'get account/container/object metadata'
203 2715ade4 Sofia Papagiannaki
204 0ea1dcc4 Sofia Papagiannaki
    def add_options(self, parser):
205 0ea1dcc4 Sofia Papagiannaki
        parser.add_option('-r', action='store_true', dest='restricted',
206 0ea1dcc4 Sofia Papagiannaki
                          default=False, help='show only user defined metadata')
207 d2d5c360 Sofia Papagiannaki
        parser.add_option('--until', action='store', dest='until',
208 f0eacc2c Sofia Papagiannaki
                          default=None, help='show metadata until that date')
209 d2d5c360 Sofia Papagiannaki
        parser.add_option('--format', action='store', dest='format',
210 e46b2bcf Sofia Papagiannaki
                          default='%d/%m/%Y %H:%M:%S', help='format to parse until date (default: %d/%m/%Y %H:%M:%S)')
211 e3fd7f91 Sofia Papagiannaki
        parser.add_option('--version', action='store', dest='version',
212 e3fd7f91 Sofia Papagiannaki
                          default=None, help='show specific version \
213 e3fd7f91 Sofia Papagiannaki
                                  (applies only for objects)')
214 2715ade4 Sofia Papagiannaki
215 cfac048c Giorgos Verigakis
    def execute(self, path=''):
216 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
217 f546c15e Antony Chazapis
        args = {'restricted': self.restricted}
218 f0eacc2c Sofia Papagiannaki
        if getattr(self, 'until'):
219 d2d5c360 Sofia Papagiannaki
            t = _time.strptime(self.until, self.format)
220 25c3841c Sofia Papagiannaki
            args['until'] = int(_time.mktime(t))
221 2715ade4 Sofia Papagiannaki
222 cfac048c Giorgos Verigakis
        if object:
223 0ea1dcc4 Sofia Papagiannaki
            meta = self.client.retrieve_object_metadata(container, object,
224 8fe01d72 Sofia Papagiannaki
                                                        self.restricted,
225 8fe01d72 Sofia Papagiannaki
                                                        self.version)
226 cfac048c Giorgos Verigakis
        elif container:
227 25c3841c Sofia Papagiannaki
            meta = self.client.retrieve_container_metadata(container, **args)
228 cfac048c Giorgos Verigakis
        else:
229 25c3841c Sofia Papagiannaki
            meta = self.client.retrieve_account_metadata(**args)
230 2715ade4 Sofia Papagiannaki
        if meta is None:
231 f07c5a53 Sofia Papagiannaki
            print 'Entity does not exist'
232 f07c5a53 Sofia Papagiannaki
        else:
233 f07c5a53 Sofia Papagiannaki
            print_dict(meta, header=None)
234 cfac048c Giorgos Verigakis
235 2715ade4 Sofia Papagiannaki
236 cfac048c Giorgos Verigakis
@cli_command('create')
237 cfac048c Giorgos Verigakis
class CreateContainer(Command):
238 f07c5a53 Sofia Papagiannaki
    syntax = '<container> [key=val] [...]'
239 cfac048c Giorgos Verigakis
    description = 'create a container'
240 2715ade4 Sofia Papagiannaki
241 5a8dc30c Sofia Papagiannaki
    def add_options(self, parser):
242 93abb8b2 Antony Chazapis
        parser.add_option('--versioning', action='store', dest='versioning',
243 5a8dc30c Sofia Papagiannaki
                          default=None, help='set container versioning (auto/none)')
244 93abb8b2 Antony Chazapis
        parser.add_option('--quota', action='store', dest='quota',
245 5a8dc30c Sofia Papagiannaki
                          default=None, help='set default container quota')
246 2715ade4 Sofia Papagiannaki
247 f07c5a53 Sofia Papagiannaki
    def execute(self, container, *args):
248 bcb7c5a8 Sofia Papagiannaki
        meta = {}
249 f07c5a53 Sofia Papagiannaki
        for arg in args:
250 f07c5a53 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
251 bcb7c5a8 Sofia Papagiannaki
            meta[key] = val
252 93abb8b2 Antony Chazapis
        policy = {}
253 93abb8b2 Antony Chazapis
        if getattr(self, 'versioning'):
254 93abb8b2 Antony Chazapis
            policy['versioning'] = self.versioning
255 93abb8b2 Antony Chazapis
        if getattr(self, 'quota'):
256 93abb8b2 Antony Chazapis
            policy['quota'] = self.quota
257 2715ade4 Sofia Papagiannaki
        ret = self.client.create_container(
258 2715ade4 Sofia Papagiannaki
            container, meta=meta, policies=policy)
259 cfac048c Giorgos Verigakis
        if not ret:
260 cfac048c Giorgos Verigakis
            print 'Container already exists'
261 cfac048c Giorgos Verigakis
262 2715ade4 Sofia Papagiannaki
263 cfac048c Giorgos Verigakis
@cli_command('delete', 'rm')
264 cfac048c Giorgos Verigakis
class Delete(Command):
265 cfac048c Giorgos Verigakis
    syntax = '<container>[/<object>]'
266 cfac048c Giorgos Verigakis
    description = 'delete a container or an object'
267 2715ade4 Sofia Papagiannaki
268 25c3841c Sofia Papagiannaki
    def add_options(self, parser):
269 25c3841c Sofia Papagiannaki
        parser.add_option('--until', action='store', dest='until',
270 f0eacc2c Sofia Papagiannaki
                          default=None, help='remove history until that date')
271 25c3841c Sofia Papagiannaki
        parser.add_option('--format', action='store', dest='format',
272 e46b2bcf Sofia Papagiannaki
                          default='%d/%m/%Y %H:%M:%S', help='format to parse until date (default: %d/%m/%Y %H:%M:%S)')
273 db117cac Sofia Papagiannaki
        parser.add_option('--delimiter', action='store', type='str',
274 db117cac Sofia Papagiannaki
                          dest='delimiter', default=None,
275 db117cac Sofia Papagiannaki
                          help='mass delete objects with path staring with <src object> + delimiter')
276 db117cac Sofia Papagiannaki
        parser.add_option('-r', action='store_true',
277 db117cac Sofia Papagiannaki
                          dest='recursive', default=False,
278 db117cac Sofia Papagiannaki
                          help='mass delimiter objects with delimiter /')
279 2715ade4 Sofia Papagiannaki
280 cfac048c Giorgos Verigakis
    def execute(self, path):
281 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
282 f0eacc2c Sofia Papagiannaki
        until = None
283 f0eacc2c Sofia Papagiannaki
        if getattr(self, 'until'):
284 25c3841c Sofia Papagiannaki
            t = _time.strptime(self.until, self.format)
285 25c3841c Sofia Papagiannaki
            until = int(_time.mktime(t))
286 2715ade4 Sofia Papagiannaki
287 e46b2bcf Sofia Papagiannaki
        kwargs = {}
288 e46b2bcf Sofia Papagiannaki
        if self.delimiter:
289 e46b2bcf Sofia Papagiannaki
            kwargs['delimiter'] = self.delimiter
290 e46b2bcf Sofia Papagiannaki
        elif self.recursive:
291 e46b2bcf Sofia Papagiannaki
            kwargs['delimiter'] = '/'
292 2715ade4 Sofia Papagiannaki
293 cfac048c Giorgos Verigakis
        if object:
294 db117cac Sofia Papagiannaki
            self.client.delete_object(container, object, until, **kwargs)
295 cfac048c Giorgos Verigakis
        else:
296 e46b2bcf Sofia Papagiannaki
            self.client.delete_container(container, until, **kwargs)
297 cfac048c Giorgos Verigakis
298 2715ade4 Sofia Papagiannaki
299 cfac048c Giorgos Verigakis
@cli_command('get')
300 cfac048c Giorgos Verigakis
class GetObject(Command):
301 cfac048c Giorgos Verigakis
    syntax = '<container>/<object>'
302 cfac048c Giorgos Verigakis
    description = 'get the data of an object'
303 2715ade4 Sofia Papagiannaki
304 f07c5a53 Sofia Papagiannaki
    def add_options(self, parser):
305 f07c5a53 Sofia Papagiannaki
        parser.add_option('-l', action='store_true', dest='detail',
306 f07c5a53 Sofia Papagiannaki
                          default=False, help='show detailed output')
307 f07c5a53 Sofia Papagiannaki
        parser.add_option('--range', action='store', dest='range',
308 f07c5a53 Sofia Papagiannaki
                          default=None, help='show range of data')
309 25c3841c Sofia Papagiannaki
        parser.add_option('--if-range', action='store', dest='if_range',
310 b44d602e Sofia Papagiannaki
                          default=None, help='show range of data')
311 25c3841c Sofia Papagiannaki
        parser.add_option('--if-match', action='store', dest='if_match',
312 f07c5a53 Sofia Papagiannaki
                          default=None, help='show output if ETags match')
313 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-none-match', action='store',
314 25c3841c Sofia Papagiannaki
                          dest='if_none_match', default=None,
315 f07c5a53 Sofia Papagiannaki
                          help='show output if ETags don\'t match')
316 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-modified-since', action='store', type='str',
317 25c3841c Sofia Papagiannaki
                          dest='if_modified_since', default=None,
318 f07c5a53 Sofia Papagiannaki
                          help='show output if modified since then')
319 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-unmodified-since', action='store', type='str',
320 25c3841c Sofia Papagiannaki
                          dest='if_unmodified_since', default=None,
321 f07c5a53 Sofia Papagiannaki
                          help='show output if not modified since then')
322 bcb7c5a8 Sofia Papagiannaki
        parser.add_option('-o', action='store', type='str',
323 f07c5a53 Sofia Papagiannaki
                          dest='file', default=None,
324 f07c5a53 Sofia Papagiannaki
                          help='save output in file')
325 8fe01d72 Sofia Papagiannaki
        parser.add_option('--version', action='store', type='str',
326 ad71a0ce Sofia Papagiannaki
                          dest='version', default=None,
327 085a31d7 Sofia Papagiannaki
                          help='get the specific \
328 8fe01d72 Sofia Papagiannaki
                               version')
329 085a31d7 Sofia Papagiannaki
        parser.add_option('--versionlist', action='store_true',
330 085a31d7 Sofia Papagiannaki
                          dest='versionlist', default=False,
331 085a31d7 Sofia Papagiannaki
                          help='get the full object version list')
332 f9e723fd Sofia Papagiannaki
        parser.add_option('--hashmap', action='store_true',
333 f9e723fd Sofia Papagiannaki
                          dest='hashmap', default=False,
334 f9e723fd Sofia Papagiannaki
                          help='get the object hashmap instead')
335 2715ade4 Sofia Papagiannaki
336 cfac048c Giorgos Verigakis
    def execute(self, path):
337 f0eacc2c Sofia Papagiannaki
        attrs = ['if_match', 'if_none_match', 'if_modified_since',
338 f9e723fd Sofia Papagiannaki
                 'if_unmodified_since', 'hashmap']
339 25c3841c Sofia Papagiannaki
        args = self._build_args(attrs)
340 f0eacc2c Sofia Papagiannaki
        args['format'] = 'json' if self.detail else 'text'
341 f07c5a53 Sofia Papagiannaki
        if self.range:
342 f546c15e Antony Chazapis
            args['range'] = 'bytes=%s' % self.range
343 25c3841c Sofia Papagiannaki
        if getattr(self, 'if_range'):
344 25c3841c Sofia Papagiannaki
            args['if-range'] = 'If-Range:%s' % getattr(self, 'if_range')
345 2715ade4 Sofia Papagiannaki
346 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
347 25c3841c Sofia Papagiannaki
        data = None
348 085a31d7 Sofia Papagiannaki
        if self.versionlist:
349 25c3841c Sofia Papagiannaki
            if 'detail' in args.keys():
350 25c3841c Sofia Papagiannaki
                args.pop('detail')
351 7f769d34 Sofia Papagiannaki
            args.pop('format')
352 11999722 Sofia Papagiannaki
            self.detail = True
353 2715ade4 Sofia Papagiannaki
            data = self.client.retrieve_object_versionlist(
354 2715ade4 Sofia Papagiannaki
                container, object, **args)
355 25c3841c Sofia Papagiannaki
        elif self.version:
356 25c3841c Sofia Papagiannaki
            data = self.client.retrieve_object_version(container, object,
357 25c3841c Sofia Papagiannaki
                                                       self.version, **args)
358 f9e723fd Sofia Papagiannaki
        elif self.hashmap:
359 f9e723fd Sofia Papagiannaki
            if 'detail' in args.keys():
360 f9e723fd Sofia Papagiannaki
                args.pop('detail')
361 f9e723fd Sofia Papagiannaki
            args.pop('format')
362 f9e723fd Sofia Papagiannaki
            self.detail = True
363 2715ade4 Sofia Papagiannaki
            data = self.client.retrieve_object_hashmap(
364 2715ade4 Sofia Papagiannaki
                container, object, **args)
365 25c3841c Sofia Papagiannaki
        else:
366 2715ade4 Sofia Papagiannaki
            data = self.client.retrieve_object(container, object, **args)
367 2715ade4 Sofia Papagiannaki
368 af6d3b5d Antony Chazapis
        f = open(self.file, 'w') if self.file else stdout
369 2715ade4 Sofia Papagiannaki
        if self.detail or isinstance(data, types.DictionaryType):
370 085a31d7 Sofia Papagiannaki
            if self.versionlist:
371 8fe01d72 Sofia Papagiannaki
                print_versions(data, f=f)
372 f07c5a53 Sofia Papagiannaki
            else:
373 8fe01d72 Sofia Papagiannaki
                print_dict(data, f=f)
374 f07c5a53 Sofia Papagiannaki
        else:
375 8fe01d72 Sofia Papagiannaki
            f.write(data)
376 8fe01d72 Sofia Papagiannaki
        f.close()
377 cfac048c Giorgos Verigakis
378 2715ade4 Sofia Papagiannaki
379 f7ab99df Sofia Papagiannaki
@cli_command('mkdir')
380 f7ab99df Sofia Papagiannaki
class PutMarker(Command):
381 f7ab99df Sofia Papagiannaki
    syntax = '<container>/<directory marker>'
382 f7ab99df Sofia Papagiannaki
    description = 'create a directory marker'
383 2715ade4 Sofia Papagiannaki
384 f7ab99df Sofia Papagiannaki
    def execute(self, path):
385 f7ab99df Sofia Papagiannaki
        container, sep, object = path.partition('/')
386 f7ab99df Sofia Papagiannaki
        self.client.create_directory_marker(container, object)
387 f7ab99df Sofia Papagiannaki
388 2715ade4 Sofia Papagiannaki
389 cfac048c Giorgos Verigakis
@cli_command('put')
390 cfac048c Giorgos Verigakis
class PutObject(Command):
391 f63cf249 Sofia Papagiannaki
    syntax = '<container>/<object> [key=val] [...]'
392 f89e3cf4 Sofia Papagiannaki
    description = 'create/override object'
393 2715ade4 Sofia Papagiannaki
394 f07c5a53 Sofia Papagiannaki
    def add_options(self, parser):
395 2715ade4 Sofia Papagiannaki
        parser.add_option(
396 2715ade4 Sofia Papagiannaki
            '--use_hashes', action='store_true', dest='use_hashes',
397 2715ade4 Sofia Papagiannaki
            default=False, help='provide hashmap instead of data')
398 f07c5a53 Sofia Papagiannaki
        parser.add_option('--chunked', action='store_true', dest='chunked',
399 f07c5a53 Sofia Papagiannaki
                          default=False, help='set chunked transfer mode')
400 f07c5a53 Sofia Papagiannaki
        parser.add_option('--etag', action='store', dest='etag',
401 f07c5a53 Sofia Papagiannaki
                          default=None, help='check written data')
402 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-encoding', action='store',
403 25c3841c Sofia Papagiannaki
                          dest='content_encoding', default=None,
404 f07c5a53 Sofia Papagiannaki
                          help='provide the object MIME content type')
405 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-disposition', action='store', type='str',
406 25c3841c Sofia Papagiannaki
                          dest='content_disposition', default=None,
407 f07c5a53 Sofia Papagiannaki
                          help='provide the presentation style of the object')
408 25c3841c Sofia Papagiannaki
        #parser.add_option('-S', action='store',
409 25c3841c Sofia Papagiannaki
        #                  dest='segment_size', default=False,
410 25c3841c Sofia Papagiannaki
        #                  help='use for large file support')
411 050ec33b Sofia Papagiannaki
        parser.add_option('--manifest', action='store',
412 25c3841c Sofia Papagiannaki
                          dest='x_object_manifest', default=None,
413 f9e723fd Sofia Papagiannaki
                          help='provide object parts prefix in <container>/<object> form')
414 25c3841c Sofia Papagiannaki
        parser.add_option('--content-type', action='store',
415 25c3841c Sofia Papagiannaki
                          dest='content_type', default=None,
416 f7ab99df Sofia Papagiannaki
                          help='create object with specific content type')
417 d3fd269f Sofia Papagiannaki
        parser.add_option('--sharing', action='store',
418 25c3841c Sofia Papagiannaki
                          dest='x_object_sharing', default=None,
419 d3fd269f Sofia Papagiannaki
                          help='define sharing object policy')
420 bcb7c5a8 Sofia Papagiannaki
        parser.add_option('-f', action='store',
421 bcb7c5a8 Sofia Papagiannaki
                          dest='srcpath', default=None,
422 f89e3cf4 Sofia Papagiannaki
                          help='file descriptor to read from (pass - for standard input)')
423 25c3841c Sofia Papagiannaki
        parser.add_option('--public', action='store_true',
424 25c3841c Sofia Papagiannaki
                          dest='x_object_public', default=False,
425 7812e1f9 Sofia Papagiannaki
                          help='make object publicly accessible')
426 2715ade4 Sofia Papagiannaki
427 bcb7c5a8 Sofia Papagiannaki
    def execute(self, path, *args):
428 bcb7c5a8 Sofia Papagiannaki
        if path.find('=') != -1:
429 bcb7c5a8 Sofia Papagiannaki
            raise Fault('Missing path argument')
430 2715ade4 Sofia Papagiannaki
431 bcb7c5a8 Sofia Papagiannaki
        #prepare user defined meta
432 bcb7c5a8 Sofia Papagiannaki
        meta = {}
433 bcb7c5a8 Sofia Papagiannaki
        for arg in args:
434 bcb7c5a8 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
435 bcb7c5a8 Sofia Papagiannaki
            meta[key] = val
436 2715ade4 Sofia Papagiannaki
437 25c3841c Sofia Papagiannaki
        attrs = ['etag', 'content_encoding', 'content_disposition',
438 25c3841c Sofia Papagiannaki
                 'content_type', 'x_object_sharing', 'x_object_public']
439 25c3841c Sofia Papagiannaki
        args = self._build_args(attrs)
440 2715ade4 Sofia Papagiannaki
441 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
442 2715ade4 Sofia Papagiannaki
443 d2d5c360 Sofia Papagiannaki
        f = None
444 bcb7c5a8 Sofia Papagiannaki
        if self.srcpath:
445 bcb7c5a8 Sofia Papagiannaki
            f = open(self.srcpath) if self.srcpath != '-' else stdin
446 2715ade4 Sofia Papagiannaki
447 bcb7c5a8 Sofia Papagiannaki
        if self.use_hashes and not f:
448 bcb7c5a8 Sofia Papagiannaki
            raise Fault('Illegal option combination')
449 2715ade4 Sofia Papagiannaki
450 25c3841c Sofia Papagiannaki
        if self.chunked:
451 25c3841c Sofia Papagiannaki
            self.client.create_object_using_chunks(container, object, f,
452 2715ade4 Sofia Papagiannaki
                                                   meta=meta, **args)
453 25c3841c Sofia Papagiannaki
        elif self.use_hashes:
454 54ca3d0f Sofia Papagiannaki
            data = f.read()
455 b8fa0222 Sofia Papagiannaki
            hashmap = json.loads(data)
456 b8fa0222 Sofia Papagiannaki
            self.client.create_object_by_hashmap(container, object, hashmap,
457 2715ade4 Sofia Papagiannaki
                                                 meta=meta, **args)
458 25c3841c Sofia Papagiannaki
        elif self.x_object_manifest:
459 2715ade4 Sofia Papagiannaki
            self.client.create_manifestation(
460 2715ade4 Sofia Papagiannaki
                container, object, self.x_object_manifest)
461 cd6ada1d Sofia Papagiannaki
        elif not f:
462 2715ade4 Sofia Papagiannaki
            self.client.create_zero_length_object(
463 2715ade4 Sofia Papagiannaki
                container, object, meta=meta, **args)
464 25c3841c Sofia Papagiannaki
        else:
465 4211443b Sofia Papagiannaki
            self.client.create_object(container, object, f, meta=meta, **args)
466 d2d5c360 Sofia Papagiannaki
        if f:
467 d2d5c360 Sofia Papagiannaki
            f.close()
468 cfac048c Giorgos Verigakis
469 2715ade4 Sofia Papagiannaki
470 cfac048c Giorgos Verigakis
@cli_command('copy', 'cp')
471 cfac048c Giorgos Verigakis
class CopyObject(Command):
472 7812e1f9 Sofia Papagiannaki
    syntax = '<src container>/<src object> [<dst container>/]<dst object> [key=val] [...]'
473 f89e3cf4 Sofia Papagiannaki
    description = 'copy an object to a different location'
474 2715ade4 Sofia Papagiannaki
475 ad71a0ce Sofia Papagiannaki
    def add_options(self, parser):
476 ad71a0ce Sofia Papagiannaki
        parser.add_option('--version', action='store',
477 ad71a0ce Sofia Papagiannaki
                          dest='version', default=False,
478 ad71a0ce Sofia Papagiannaki
                          help='copy specific version')
479 7812e1f9 Sofia Papagiannaki
        parser.add_option('--public', action='store_true',
480 7812e1f9 Sofia Papagiannaki
                          dest='public', default=False,
481 7812e1f9 Sofia Papagiannaki
                          help='make object publicly accessible')
482 d4a63b9b Sofia Papagiannaki
        parser.add_option('--content-type', action='store',
483 d4a63b9b Sofia Papagiannaki
                          dest='content_type', default=None,
484 d4a63b9b Sofia Papagiannaki
                          help='change object\'s content type')
485 db117cac Sofia Papagiannaki
        parser.add_option('--delimiter', action='store', type='str',
486 db117cac Sofia Papagiannaki
                          dest='delimiter', default=None,
487 db117cac Sofia Papagiannaki
                          help='mass copy objects with path staring with <src object> + delimiter')
488 db117cac Sofia Papagiannaki
        parser.add_option('-r', action='store_true',
489 db117cac Sofia Papagiannaki
                          dest='recursive', default=False,
490 db117cac Sofia Papagiannaki
                          help='mass copy with delimiter /')
491 2715ade4 Sofia Papagiannaki
492 7812e1f9 Sofia Papagiannaki
    def execute(self, src, dst, *args):
493 cfac048c Giorgos Verigakis
        src_container, sep, src_object = src.partition('/')
494 cfac048c Giorgos Verigakis
        dst_container, sep, dst_object = dst.partition('/')
495 2715ade4 Sofia Papagiannaki
496 7812e1f9 Sofia Papagiannaki
        #prepare user defined meta
497 7812e1f9 Sofia Papagiannaki
        meta = {}
498 7812e1f9 Sofia Papagiannaki
        for arg in args:
499 7812e1f9 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
500 7812e1f9 Sofia Papagiannaki
            meta[key] = val
501 2715ade4 Sofia Papagiannaki
502 cfac048c Giorgos Verigakis
        if not sep:
503 cfac048c Giorgos Verigakis
            dst_container = src_container
504 cfac048c Giorgos Verigakis
            dst_object = dst
505 2715ade4 Sofia Papagiannaki
506 2715ade4 Sofia Papagiannaki
        args = {'content_type': self.content_type} if self.content_type else {}
507 db117cac Sofia Papagiannaki
        if self.delimiter:
508 2715ade4 Sofia Papagiannaki
            args['delimiter'] = self.delimiter
509 db117cac Sofia Papagiannaki
        elif self.recursive:
510 2715ade4 Sofia Papagiannaki
            args['delimiter'] = '/'
511 f07c5a53 Sofia Papagiannaki
        self.client.copy_object(src_container, src_object, dst_container,
512 d4a63b9b Sofia Papagiannaki
                                dst_object, meta, self.public, self.version,
513 d4a63b9b Sofia Papagiannaki
                                **args)
514 cfac048c Giorgos Verigakis
515 2715ade4 Sofia Papagiannaki
516 cfac048c Giorgos Verigakis
@cli_command('set')
517 3f5b02c7 Sofia Papagiannaki
class SetMeta(Command):
518 3f5b02c7 Sofia Papagiannaki
    syntax = '[<container>[/<object>]] key=val [key=val] [...]'
519 f63cf249 Sofia Papagiannaki
    description = 'set account/container/object metadata'
520 2715ade4 Sofia Papagiannaki
521 cfac048c Giorgos Verigakis
    def execute(self, path, *args):
522 3f5b02c7 Sofia Papagiannaki
        #in case of account fix the args
523 f07c5a53 Sofia Papagiannaki
        if path.find('=') != -1:
524 3f5b02c7 Sofia Papagiannaki
            args = list(args)
525 3f5b02c7 Sofia Papagiannaki
            args.append(path)
526 3f5b02c7 Sofia Papagiannaki
            args = tuple(args)
527 3f5b02c7 Sofia Papagiannaki
            path = ''
528 cfac048c Giorgos Verigakis
        meta = {}
529 cfac048c Giorgos Verigakis
        for arg in args:
530 cfac048c Giorgos Verigakis
            key, sep, val = arg.partition('=')
531 cfac048c Giorgos Verigakis
            meta[key.strip()] = val.strip()
532 3f5b02c7 Sofia Papagiannaki
        container, sep, object = path.partition('/')
533 3f5b02c7 Sofia Papagiannaki
        if object:
534 3f5b02c7 Sofia Papagiannaki
            self.client.update_object_metadata(container, object, **meta)
535 3f5b02c7 Sofia Papagiannaki
        elif container:
536 3f5b02c7 Sofia Papagiannaki
            self.client.update_container_metadata(container, **meta)
537 3f5b02c7 Sofia Papagiannaki
        else:
538 3f5b02c7 Sofia Papagiannaki
            self.client.update_account_metadata(**meta)
539 cfac048c Giorgos Verigakis
540 2715ade4 Sofia Papagiannaki
541 f07c5a53 Sofia Papagiannaki
@cli_command('update')
542 f07c5a53 Sofia Papagiannaki
class UpdateObject(Command):
543 f07c5a53 Sofia Papagiannaki
    syntax = '<container>/<object> path [key=val] [...]'
544 e3fd7f91 Sofia Papagiannaki
    description = 'update object metadata/data (default mode: append)'
545 2715ade4 Sofia Papagiannaki
546 f07c5a53 Sofia Papagiannaki
    def add_options(self, parser):
547 f07c5a53 Sofia Papagiannaki
        parser.add_option('-a', action='store_true', dest='append',
548 e3fd7f91 Sofia Papagiannaki
                          default=True, help='append data')
549 bcb7c5a8 Sofia Papagiannaki
        parser.add_option('--offset', action='store',
550 bcb7c5a8 Sofia Papagiannaki
                          dest='offset',
551 a2defd86 Sofia Papagiannaki
                          default=None, help='starting offest to be updated')
552 f9e723fd Sofia Papagiannaki
        parser.add_option('--range', action='store', dest='content_range',
553 f07c5a53 Sofia Papagiannaki
                          default=None, help='range of data to be updated')
554 f07c5a53 Sofia Papagiannaki
        parser.add_option('--chunked', action='store_true', dest='chunked',
555 f07c5a53 Sofia Papagiannaki
                          default=False, help='set chunked transfer mode')
556 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-encoding', action='store',
557 25c3841c Sofia Papagiannaki
                          dest='content_encoding', default=None,
558 f07c5a53 Sofia Papagiannaki
                          help='provide the object MIME content type')
559 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-disposition', action='store', type='str',
560 25c3841c Sofia Papagiannaki
                          dest='content_disposition', default=None,
561 f07c5a53 Sofia Papagiannaki
                          help='provide the presentation style of the object')
562 f07c5a53 Sofia Papagiannaki
        parser.add_option('--manifest', action='store', type='str',
563 25c3841c Sofia Papagiannaki
                          dest='x_object_manifest', default=None,
564 2715ade4 Sofia Papagiannaki
                          help='use for large file support')
565 d3fd269f Sofia Papagiannaki
        parser.add_option('--sharing', action='store',
566 25c3841c Sofia Papagiannaki
                          dest='x_object_sharing', default=None,
567 d3fd269f Sofia Papagiannaki
                          help='define sharing object policy')
568 bcb7c5a8 Sofia Papagiannaki
        parser.add_option('--nosharing', action='store_true',
569 bcb7c5a8 Sofia Papagiannaki
                          dest='no_sharing', default=None,
570 bcb7c5a8 Sofia Papagiannaki
                          help='clear object sharing policy')
571 bcb7c5a8 Sofia Papagiannaki
        parser.add_option('-f', action='store',
572 bcb7c5a8 Sofia Papagiannaki
                          dest='srcpath', default=None,
573 bcb7c5a8 Sofia Papagiannaki
                          help='file descriptor to read from: pass - for standard input')
574 7812e1f9 Sofia Papagiannaki
        parser.add_option('--public', action='store_true',
575 25c3841c Sofia Papagiannaki
                          dest='x_object_public', default=False,
576 7812e1f9 Sofia Papagiannaki
                          help='make object publicly accessible')
577 633bbb9f Sofia Papagiannaki
        parser.add_option('--replace', action='store_true',
578 633bbb9f Sofia Papagiannaki
                          dest='replace', default=False,
579 633bbb9f Sofia Papagiannaki
                          help='override metadata')
580 2715ade4 Sofia Papagiannaki
581 bcb7c5a8 Sofia Papagiannaki
    def execute(self, path, *args):
582 bcb7c5a8 Sofia Papagiannaki
        if path.find('=') != -1:
583 bcb7c5a8 Sofia Papagiannaki
            raise Fault('Missing path argument')
584 2715ade4 Sofia Papagiannaki
585 f07c5a53 Sofia Papagiannaki
        #prepare user defined meta
586 bcb7c5a8 Sofia Papagiannaki
        meta = {}
587 f07c5a53 Sofia Papagiannaki
        for arg in args:
588 f07c5a53 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
589 bcb7c5a8 Sofia Papagiannaki
            meta[key] = val
590 2715ade4 Sofia Papagiannaki
591 25c3841c Sofia Papagiannaki
        attrs = ['content_encoding', 'content_disposition', 'x_object_sharing',
592 f9e723fd Sofia Papagiannaki
                 'x_object_public', 'x_object_manifest', 'replace', 'offset',
593 f9e723fd Sofia Papagiannaki
                 'content_range']
594 25c3841c Sofia Papagiannaki
        args = self._build_args(attrs)
595 2715ade4 Sofia Papagiannaki
596 38bf2cdc Sofia Papagiannaki
        if self.no_sharing:
597 38bf2cdc Sofia Papagiannaki
            args['x_object_sharing'] = ''
598 2715ade4 Sofia Papagiannaki
599 f07c5a53 Sofia Papagiannaki
        container, sep, object = path.partition('/')
600 2715ade4 Sofia Papagiannaki
601 a2defd86 Sofia Papagiannaki
        f = None
602 bcb7c5a8 Sofia Papagiannaki
        if self.srcpath:
603 25c3841c Sofia Papagiannaki
            f = open(self.srcpath) if self.srcpath != '-' else stdin
604 2715ade4 Sofia Papagiannaki
605 25c3841c Sofia Papagiannaki
        if self.chunked:
606 25c3841c Sofia Papagiannaki
            self.client.update_object_using_chunks(container, object, f,
607 2715ade4 Sofia Papagiannaki
                                                   meta=meta, **args)
608 25c3841c Sofia Papagiannaki
        else:
609 f0964245 Sofia Papagiannaki
            self.client.update_object(container, object, f, meta=meta, **args)
610 a2defd86 Sofia Papagiannaki
        if f:
611 a2defd86 Sofia Papagiannaki
            f.close()
612 f07c5a53 Sofia Papagiannaki
613 2715ade4 Sofia Papagiannaki
614 f07c5a53 Sofia Papagiannaki
@cli_command('move', 'mv')
615 f07c5a53 Sofia Papagiannaki
class MoveObject(Command):
616 f07c5a53 Sofia Papagiannaki
    syntax = '<src container>/<src object> [<dst container>/]<dst object>'
617 f89e3cf4 Sofia Papagiannaki
    description = 'move an object to a different location'
618 2715ade4 Sofia Papagiannaki
619 f89e3cf4 Sofia Papagiannaki
    def add_options(self, parser):
620 7812e1f9 Sofia Papagiannaki
        parser.add_option('--public', action='store_true',
621 7812e1f9 Sofia Papagiannaki
                          dest='public', default=False,
622 7812e1f9 Sofia Papagiannaki
                          help='make object publicly accessible')
623 d4a63b9b Sofia Papagiannaki
        parser.add_option('--content-type', action='store',
624 d4a63b9b Sofia Papagiannaki
                          dest='content_type', default=None,
625 d4a63b9b Sofia Papagiannaki
                          help='change object\'s content type')
626 db117cac Sofia Papagiannaki
        parser.add_option('--delimiter', action='store', type='str',
627 db117cac Sofia Papagiannaki
                          dest='delimiter', default=None,
628 db117cac Sofia Papagiannaki
                          help='mass move objects with path staring with <src object> + delimiter')
629 db117cac Sofia Papagiannaki
        parser.add_option('-r', action='store_true',
630 db117cac Sofia Papagiannaki
                          dest='recursive', default=False,
631 db117cac Sofia Papagiannaki
                          help='mass move objects with delimiter /')
632 2715ade4 Sofia Papagiannaki
633 7812e1f9 Sofia Papagiannaki
    def execute(self, src, dst, *args):
634 f07c5a53 Sofia Papagiannaki
        src_container, sep, src_object = src.partition('/')
635 f07c5a53 Sofia Papagiannaki
        dst_container, sep, dst_object = dst.partition('/')
636 f07c5a53 Sofia Papagiannaki
        if not sep:
637 f07c5a53 Sofia Papagiannaki
            dst_container = src_container
638 f07c5a53 Sofia Papagiannaki
            dst_object = dst
639 2715ade4 Sofia Papagiannaki
640 7812e1f9 Sofia Papagiannaki
        #prepare user defined meta
641 7812e1f9 Sofia Papagiannaki
        meta = {}
642 7812e1f9 Sofia Papagiannaki
        for arg in args:
643 7812e1f9 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
644 7812e1f9 Sofia Papagiannaki
            meta[key] = val
645 2715ade4 Sofia Papagiannaki
646 2715ade4 Sofia Papagiannaki
        args = {'content_type': self.content_type} if self.content_type else {}
647 db117cac Sofia Papagiannaki
        if self.delimiter:
648 2715ade4 Sofia Papagiannaki
            args['delimiter'] = self.delimiter
649 db117cac Sofia Papagiannaki
        elif self.recursive:
650 2715ade4 Sofia Papagiannaki
            args['delimiter'] = '/'
651 f07c5a53 Sofia Papagiannaki
        self.client.move_object(src_container, src_object, dst_container,
652 97d45f69 Antony Chazapis
                                dst_object, meta, self.public, **args)
653 f7ab99df Sofia Papagiannaki
654 2715ade4 Sofia Papagiannaki
655 f7ab99df Sofia Papagiannaki
@cli_command('unset')
656 bcb7c5a8 Sofia Papagiannaki
class UnsetObject(Command):
657 f7ab99df Sofia Papagiannaki
    syntax = '<container>/[<object>] key [key] [...]'
658 f89e3cf4 Sofia Papagiannaki
    description = 'delete metadata info'
659 2715ade4 Sofia Papagiannaki
660 f7ab99df Sofia Papagiannaki
    def execute(self, path, *args):
661 f7ab99df Sofia Papagiannaki
        #in case of account fix the args
662 961f2fbe Sofia Papagiannaki
        if len(args) == 0:
663 f7ab99df Sofia Papagiannaki
            args = list(args)
664 f7ab99df Sofia Papagiannaki
            args.append(path)
665 f7ab99df Sofia Papagiannaki
            args = tuple(args)
666 f7ab99df Sofia Papagiannaki
            path = ''
667 f7ab99df Sofia Papagiannaki
        meta = []
668 f7ab99df Sofia Papagiannaki
        for key in args:
669 f7ab99df Sofia Papagiannaki
            meta.append(key)
670 f7ab99df Sofia Papagiannaki
        container, sep, object = path.partition('/')
671 f7ab99df Sofia Papagiannaki
        if object:
672 f7ab99df Sofia Papagiannaki
            self.client.delete_object_metadata(container, object, meta)
673 f7ab99df Sofia Papagiannaki
        elif container:
674 f7ab99df Sofia Papagiannaki
            self.client.delete_container_metadata(container, meta)
675 f7ab99df Sofia Papagiannaki
        else:
676 f7ab99df Sofia Papagiannaki
            self.client.delete_account_metadata(meta)
677 f7ab99df Sofia Papagiannaki
678 2715ade4 Sofia Papagiannaki
679 d3fd269f Sofia Papagiannaki
@cli_command('group')
680 f63cf249 Sofia Papagiannaki
class CreateGroup(Command):
681 d3fd269f Sofia Papagiannaki
    syntax = 'key=val [key=val] [...]'
682 f63cf249 Sofia Papagiannaki
    description = 'create account groups'
683 2715ade4 Sofia Papagiannaki
684 bcb7c5a8 Sofia Papagiannaki
    def execute(self, *args):
685 d3fd269f Sofia Papagiannaki
        groups = {}
686 d3fd269f Sofia Papagiannaki
        for arg in args:
687 d3fd269f Sofia Papagiannaki
            key, sep, val = arg.partition('=')
688 d3fd269f Sofia Papagiannaki
            groups[key] = val
689 bcb7c5a8 Sofia Papagiannaki
        self.client.set_account_groups(**groups)
690 bcb7c5a8 Sofia Papagiannaki
691 2715ade4 Sofia Papagiannaki
692 f63cf249 Sofia Papagiannaki
@cli_command('ungroup')
693 f63cf249 Sofia Papagiannaki
class DeleteGroup(Command):
694 f63cf249 Sofia Papagiannaki
    syntax = 'key [key] [...]'
695 f63cf249 Sofia Papagiannaki
    description = 'delete account groups'
696 2715ade4 Sofia Papagiannaki
697 f63cf249 Sofia Papagiannaki
    def execute(self, *args):
698 f63cf249 Sofia Papagiannaki
        groups = []
699 f63cf249 Sofia Papagiannaki
        for arg in args:
700 f63cf249 Sofia Papagiannaki
            groups.append(arg)
701 f63cf249 Sofia Papagiannaki
        self.client.unset_account_groups(groups)
702 f63cf249 Sofia Papagiannaki
703 2715ade4 Sofia Papagiannaki
704 bcb7c5a8 Sofia Papagiannaki
@cli_command('policy')
705 bcb7c5a8 Sofia Papagiannaki
class SetPolicy(Command):
706 bcb7c5a8 Sofia Papagiannaki
    syntax = 'container key=val [key=val] [...]'
707 f89e3cf4 Sofia Papagiannaki
    description = 'set container policies'
708 2715ade4 Sofia Papagiannaki
709 bcb7c5a8 Sofia Papagiannaki
    def execute(self, path, *args):
710 bcb7c5a8 Sofia Papagiannaki
        if path.find('=') != -1:
711 bcb7c5a8 Sofia Papagiannaki
            raise Fault('Missing container argument')
712 2715ade4 Sofia Papagiannaki
713 bcb7c5a8 Sofia Papagiannaki
        container, sep, object = path.partition('/')
714 2715ade4 Sofia Papagiannaki
715 bcb7c5a8 Sofia Papagiannaki
        if object:
716 bcb7c5a8 Sofia Papagiannaki
            raise Fault('Only containers have policies')
717 2715ade4 Sofia Papagiannaki
718 bcb7c5a8 Sofia Papagiannaki
        policies = {}
719 bcb7c5a8 Sofia Papagiannaki
        for arg in args:
720 bcb7c5a8 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
721 bcb7c5a8 Sofia Papagiannaki
            policies[key] = val
722 2715ade4 Sofia Papagiannaki
723 bcb7c5a8 Sofia Papagiannaki
        self.client.set_container_policies(container, **policies)
724 d3fd269f Sofia Papagiannaki
725 2715ade4 Sofia Papagiannaki
726 f89e3cf4 Sofia Papagiannaki
@cli_command('publish')
727 f89e3cf4 Sofia Papagiannaki
class PublishObject(Command):
728 f89e3cf4 Sofia Papagiannaki
    syntax = '<container>/<object>'
729 f89e3cf4 Sofia Papagiannaki
    description = 'publish an object'
730 2715ade4 Sofia Papagiannaki
731 f89e3cf4 Sofia Papagiannaki
    def execute(self, src):
732 f89e3cf4 Sofia Papagiannaki
        src_container, sep, src_object = src.partition('/')
733 2715ade4 Sofia Papagiannaki
734 f89e3cf4 Sofia Papagiannaki
        self.client.publish_object(src_container, src_object)
735 f89e3cf4 Sofia Papagiannaki
736 2715ade4 Sofia Papagiannaki
737 f89e3cf4 Sofia Papagiannaki
@cli_command('unpublish')
738 f89e3cf4 Sofia Papagiannaki
class UnpublishObject(Command):
739 f89e3cf4 Sofia Papagiannaki
    syntax = '<container>/<object>'
740 f89e3cf4 Sofia Papagiannaki
    description = 'unpublish an object'
741 2715ade4 Sofia Papagiannaki
742 f89e3cf4 Sofia Papagiannaki
    def execute(self, src):
743 f89e3cf4 Sofia Papagiannaki
        src_container, sep, src_object = src.partition('/')
744 2715ade4 Sofia Papagiannaki
745 f89e3cf4 Sofia Papagiannaki
        self.client.unpublish_object(src_container, src_object)
746 f89e3cf4 Sofia Papagiannaki
747 2715ade4 Sofia Papagiannaki
748 d4a63b9b Sofia Papagiannaki
@cli_command('sharing')
749 d4a63b9b Sofia Papagiannaki
class SharingObject(Command):
750 d4a63b9b Sofia Papagiannaki
    syntax = 'list users sharing objects with the user'
751 d4a63b9b Sofia Papagiannaki
    description = 'list user accounts sharing objects with the user'
752 2715ade4 Sofia Papagiannaki
753 d4a63b9b Sofia Papagiannaki
    def add_options(self, parser):
754 d4a63b9b Sofia Papagiannaki
        parser.add_option('-l', action='store_true', dest='detail',
755 d4a63b9b Sofia Papagiannaki
                          default=False, help='show detailed output')
756 d4a63b9b Sofia Papagiannaki
        parser.add_option('-n', action='store', type='int', dest='limit',
757 d4a63b9b Sofia Papagiannaki
                          default=10000, help='show limited output')
758 d4a63b9b Sofia Papagiannaki
        parser.add_option('--marker', action='store', type='str',
759 d4a63b9b Sofia Papagiannaki
                          dest='marker', default=None,
760 d4a63b9b Sofia Papagiannaki
                          help='show output greater then marker')
761 2715ade4 Sofia Papagiannaki
762 d4a63b9b Sofia Papagiannaki
    def execute(self):
763 d4a63b9b Sofia Papagiannaki
        attrs = ['limit', 'marker']
764 d4a63b9b Sofia Papagiannaki
        args = self._build_args(attrs)
765 d4a63b9b Sofia Papagiannaki
        args['format'] = 'json' if self.detail else 'text'
766 2715ade4 Sofia Papagiannaki
767 d4a63b9b Sofia Papagiannaki
        print_list(self.client.list_shared_by_others(**args))
768 d4a63b9b Sofia Papagiannaki
769 2715ade4 Sofia Papagiannaki
770 822cc7eb Antony Chazapis
@cli_command('send')
771 822cc7eb Antony Chazapis
class Send(Command):
772 822cc7eb Antony Chazapis
    syntax = '<file> <container>[/<prefix>]'
773 822cc7eb Antony Chazapis
    description = 'upload file to container (using prefix)'
774 2715ade4 Sofia Papagiannaki
775 f546c15e Antony Chazapis
    def execute(self, file, path):
776 f546c15e Antony Chazapis
        container, sep, prefix = path.partition('/')
777 822cc7eb Antony Chazapis
        upload(self.client, file, container, prefix)
778 822cc7eb Antony Chazapis
779 2715ade4 Sofia Papagiannaki
780 f546c15e Antony Chazapis
@cli_command('receive')
781 f546c15e Antony Chazapis
class Receive(Command):
782 f546c15e Antony Chazapis
    syntax = '<container>/<object> <file>'
783 f546c15e Antony Chazapis
    description = 'download object to file'
784 2715ade4 Sofia Papagiannaki
785 f546c15e Antony Chazapis
    def execute(self, path, file):
786 f546c15e Antony Chazapis
        container, sep, object = path.partition('/')
787 f546c15e Antony Chazapis
        download(self.client, container, object, file)
788 f546c15e Antony Chazapis
789 2715ade4 Sofia Papagiannaki
790 cfac048c Giorgos Verigakis
def print_usage():
791 10998c60 Sofia Papagiannaki
    cmd = Command('', [])
792 cfac048c Giorgos Verigakis
    parser = cmd.parser
793 cfac048c Giorgos Verigakis
    parser.usage = '%prog <command> [options]'
794 cfac048c Giorgos Verigakis
    parser.print_help()
795 2715ade4 Sofia Papagiannaki
796 cfac048c Giorgos Verigakis
    commands = []
797 cfac048c Giorgos Verigakis
    for cls in set(_cli_commands.values()):
798 cfac048c Giorgos Verigakis
        name = ', '.join(cls.commands)
799 cfac048c Giorgos Verigakis
        description = getattr(cls, 'description', '')
800 cfac048c Giorgos Verigakis
        commands.append('  %s %s' % (name.ljust(12), description))
801 cfac048c Giorgos Verigakis
    print '\nCommands:\n' + '\n'.join(sorted(commands))
802 cfac048c Giorgos Verigakis
803 2715ade4 Sofia Papagiannaki
804 a4c10cbc Sofia Papagiannaki
def print_dict(d, header='name', f=stdout, detail=True):
805 ae75584f Sofia Papagiannaki
    header = header if header in d else 'subdir'
806 f07c5a53 Sofia Papagiannaki
    if header and header in d:
807 2715ade4 Sofia Papagiannaki
        f.write('%s\n' % d.pop(header).encode('utf8'))
808 a4c10cbc Sofia Papagiannaki
    if detail:
809 a4c10cbc Sofia Papagiannaki
        patterns = ['^x_(account|container|object)_meta_(\w+)$']
810 a4c10cbc Sofia Papagiannaki
        patterns.append(patterns[0].replace('_', '-'))
811 a4c10cbc Sofia Papagiannaki
        for key, val in sorted(d.items()):
812 a4c10cbc Sofia Papagiannaki
            f.write('%s: %s\n' % (key.rjust(30), val))
813 f07c5a53 Sofia Papagiannaki
814 2715ade4 Sofia Papagiannaki
815 a4c10cbc Sofia Papagiannaki
def print_list(l, verbose=False, f=stdout, detail=True):
816 f07c5a53 Sofia Papagiannaki
    for elem in l:
817 f07c5a53 Sofia Papagiannaki
        #if it's empty string continue
818 f07c5a53 Sofia Papagiannaki
        if not elem:
819 f07c5a53 Sofia Papagiannaki
            continue
820 2715ade4 Sofia Papagiannaki
        if isinstance(elem, types.DictionaryType):
821 a4c10cbc Sofia Papagiannaki
            print_dict(elem, f=f, detail=detail)
822 2715ade4 Sofia Papagiannaki
        elif isinstance(elem, types.StringType):
823 f07c5a53 Sofia Papagiannaki
            if not verbose:
824 f07c5a53 Sofia Papagiannaki
                elem = elem.split('Traceback')[0]
825 f07c5a53 Sofia Papagiannaki
            f.write('%s\n' % elem)
826 f07c5a53 Sofia Papagiannaki
        else:
827 f07c5a53 Sofia Papagiannaki
            f.write('%s\n' % elem)
828 cfac048c Giorgos Verigakis
829 2715ade4 Sofia Papagiannaki
830 8fe01d72 Sofia Papagiannaki
def print_versions(data, f=stdout):
831 8fe01d72 Sofia Papagiannaki
    if 'versions' not in data:
832 2715ade4 Sofia Papagiannaki
        f.write('%s\n' % data)
833 8fe01d72 Sofia Papagiannaki
        return
834 8fe01d72 Sofia Papagiannaki
    f.write('versions:\n')
835 8fe01d72 Sofia Papagiannaki
    for id, t in data['versions']:
836 2715ade4 Sofia Papagiannaki
        f.write('%s @ %s\n' % (str(id).rjust(30),
837 2715ade4 Sofia Papagiannaki
                datetime.fromtimestamp(float(t))))
838 8fe01d72 Sofia Papagiannaki
839 9e826a59 Kostas Papadimitriou
840 cfac048c Giorgos Verigakis
def main():
841 cfac048c Giorgos Verigakis
    try:
842 cfac048c Giorgos Verigakis
        name = argv[1]
843 cfac048c Giorgos Verigakis
        cls = class_for_cli_command(name)
844 cfac048c Giorgos Verigakis
    except (IndexError, KeyError):
845 cfac048c Giorgos Verigakis
        print_usage()
846 cfac048c Giorgos Verigakis
        exit(1)
847 2715ade4 Sofia Papagiannaki
848 a2defd86 Sofia Papagiannaki
    cmd = cls(name, argv[2:])
849 2715ade4 Sofia Papagiannaki
850 95e92490 Sofia Papagiannaki
    try:
851 95e92490 Sofia Papagiannaki
        cmd.execute(*cmd.args)
852 95e92490 Sofia Papagiannaki
    except TypeError, e:
853 95e92490 Sofia Papagiannaki
        cmd.parser.print_help()
854 95e92490 Sofia Papagiannaki
        exit(1)
855 95e92490 Sofia Papagiannaki
    except Fault, f:
856 af6d3b5d Antony Chazapis
        status = '%s ' % f.status if f.status else ''
857 95e92490 Sofia Papagiannaki
        print '%s%s' % (status, f.data)
858 cfac048c Giorgos Verigakis
859 9e826a59 Kostas Papadimitriou
860 cfac048c Giorgos Verigakis
if __name__ == '__main__':
861 cfac048c Giorgos Verigakis
    main()