Statistics
| Branch: | Tag: | Revision:

root / tools / store @ 10998c60

History | View | Annotate | Download (24.6 kB)

1 cfac048c Giorgos Verigakis
#!/usr/bin/env python
2 cfac048c Giorgos Verigakis
3 a4c10cbc Sofia Papagiannaki
# Copyright 2011 GRNET S.A. All rights reserved.
4 a4c10cbc 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 a4c10cbc 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 a4c10cbc 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 a4c10cbc 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 a4c10cbc 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 cfac048c Giorgos Verigakis
from os.path import basename
39 f07c5a53 Sofia Papagiannaki
from sys import argv, exit, stdin, stdout
40 3f5b02c7 Sofia Papagiannaki
from pithos.lib.client import Client, Fault
41 d2d5c360 Sofia Papagiannaki
from datetime import datetime
42 cfac048c Giorgos Verigakis
43 cfac048c Giorgos Verigakis
import json
44 cfac048c Giorgos Verigakis
import logging
45 f07c5a53 Sofia Papagiannaki
import types
46 d2d5c360 Sofia Papagiannaki
import re
47 d2d5c360 Sofia Papagiannaki
import time as _time
48 cfac048c Giorgos Verigakis
49 e5cd3e33 Sofia Papagiannaki
DEFAULT_HOST = 'pithos.dev.grnet.gr'
50 cfac048c Giorgos Verigakis
DEFAULT_API = 'v1'
51 cfac048c Giorgos Verigakis
52 cfac048c Giorgos Verigakis
_cli_commands = {}
53 cfac048c Giorgos Verigakis
54 cfac048c Giorgos Verigakis
def cli_command(*args):
55 cfac048c Giorgos Verigakis
    def decorator(cls):
56 cfac048c Giorgos Verigakis
        cls.commands = args
57 cfac048c Giorgos Verigakis
        for name in args:
58 cfac048c Giorgos Verigakis
            _cli_commands[name] = cls
59 cfac048c Giorgos Verigakis
        return cls
60 cfac048c Giorgos Verigakis
    return decorator
61 cfac048c Giorgos Verigakis
62 cfac048c Giorgos Verigakis
def class_for_cli_command(name):
63 cfac048c Giorgos Verigakis
    return _cli_commands[name]
64 cfac048c Giorgos Verigakis
65 cfac048c Giorgos Verigakis
class Command(object):
66 10998c60 Sofia Papagiannaki
    syntax = ''
67 10998c60 Sofia Papagiannaki
    
68 a2defd86 Sofia Papagiannaki
    def __init__(self, name, argv):
69 a2defd86 Sofia Papagiannaki
        parser = OptionParser('%%prog %s [options] %s' % (name, self.syntax))
70 f07c5a53 Sofia Papagiannaki
        parser.add_option('--host', dest='host', metavar='HOST',
71 f07c5a53 Sofia Papagiannaki
                          default=DEFAULT_HOST, help='use server HOST')
72 f07c5a53 Sofia Papagiannaki
        parser.add_option('--user', dest='user', metavar='USERNAME',
73 f07c5a53 Sofia Papagiannaki
                          default=getuser(), help='use account USERNAME')
74 f07c5a53 Sofia Papagiannaki
        parser.add_option('--api', dest='api', metavar='API',
75 f07c5a53 Sofia Papagiannaki
                          default=DEFAULT_API, help='use api API')
76 f07c5a53 Sofia Papagiannaki
        parser.add_option('-v', action='store_true', dest='verbose',
77 f07c5a53 Sofia Papagiannaki
                          default=False, help='use verbose output')
78 f07c5a53 Sofia Papagiannaki
        parser.add_option('-d', action='store_true', dest='debug',
79 f07c5a53 Sofia Papagiannaki
                          default=False, help='use debug output')
80 cfac048c Giorgos Verigakis
        self.add_options(parser)
81 cfac048c Giorgos Verigakis
        options, args = parser.parse_args(argv)
82 cfac048c Giorgos Verigakis
        
83 cfac048c Giorgos Verigakis
        # Add options to self
84 cfac048c Giorgos Verigakis
        for opt in parser.option_list:
85 cfac048c Giorgos Verigakis
            key = opt.dest
86 cfac048c Giorgos Verigakis
            if key:
87 cfac048c Giorgos Verigakis
                val = getattr(options, key)
88 cfac048c Giorgos Verigakis
                setattr(self, key, val)
89 cfac048c Giorgos Verigakis
        
90 f07c5a53 Sofia Papagiannaki
        self.client = Client(self.host, self.user, self.api, self.verbose,
91 f07c5a53 Sofia Papagiannaki
                             self.debug)
92 cfac048c Giorgos Verigakis
        
93 cfac048c Giorgos Verigakis
        self.parser = parser
94 cfac048c Giorgos Verigakis
        self.args = args
95 f7ab99df Sofia Papagiannaki
        
96 cfac048c Giorgos Verigakis
    def add_options(self, parser):
97 cfac048c Giorgos Verigakis
        pass
98 f7ab99df Sofia Papagiannaki
    
99 cfac048c Giorgos Verigakis
    def execute(self, *args):
100 cfac048c Giorgos Verigakis
        pass
101 cfac048c Giorgos Verigakis
102 cfac048c Giorgos Verigakis
@cli_command('list', 'ls')
103 cfac048c Giorgos Verigakis
class List(Command):
104 f07c5a53 Sofia Papagiannaki
    syntax = '[<container>[/<object>]]'
105 cfac048c Giorgos Verigakis
    description = 'list containers or objects'
106 cfac048c Giorgos Verigakis
    
107 cfac048c Giorgos Verigakis
    def add_options(self, parser):
108 3f5b02c7 Sofia Papagiannaki
        parser.add_option('-l', action='store_true', dest='detail',
109 3f5b02c7 Sofia Papagiannaki
                          default=False, help='show detailed output')
110 3f5b02c7 Sofia Papagiannaki
        parser.add_option('-n', action='store', type='int', dest='limit',
111 3f5b02c7 Sofia Papagiannaki
                          default=1000, help='show limited output')
112 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--marker', action='store', type='str',
113 3f5b02c7 Sofia Papagiannaki
                          dest='marker', default=None,
114 3f5b02c7 Sofia Papagiannaki
                          help='show output greater then marker')
115 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--prefix', action='store', type='str',
116 3f5b02c7 Sofia Papagiannaki
                          dest='prefix', default=None,
117 3f5b02c7 Sofia Papagiannaki
                          help='show output starting with prefix')
118 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--delimiter', action='store', type='str',
119 3f5b02c7 Sofia Papagiannaki
                          dest='delimiter', default=None,
120 3f5b02c7 Sofia Papagiannaki
                          help='show output up to the delimiter')
121 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--path', action='store', type='str',
122 3f5b02c7 Sofia Papagiannaki
                          dest='path', default=None,
123 3f5b02c7 Sofia Papagiannaki
                          help='show output starting with prefix up to /')
124 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--meta', action='store', type='str',
125 3f5b02c7 Sofia Papagiannaki
                          dest='meta', default=None,
126 3f5b02c7 Sofia Papagiannaki
                          help='show output having the specified meta keys')
127 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--if-modified-since', action='store', type='str',
128 3f5b02c7 Sofia Papagiannaki
                          dest='if_modified_since', default=None,
129 3f5b02c7 Sofia Papagiannaki
                          help='show output if modified since then')
130 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--if-unmodified-since', action='store', type='str',
131 3f5b02c7 Sofia Papagiannaki
                          dest='if_unmodified_since', default=None,
132 3f5b02c7 Sofia Papagiannaki
                          help='show output if not modified since then')
133 d2d5c360 Sofia Papagiannaki
        parser.add_option('--until', action='store', dest='until',
134 d2d5c360 Sofia Papagiannaki
                          default=False, help='show metadata until that date')
135 d2d5c360 Sofia Papagiannaki
        parser.add_option('--format', action='store', dest='format',
136 d2d5c360 Sofia Papagiannaki
                          default='%d/%m/%Y', help='format to parse until date')
137 f7ab99df Sofia Papagiannaki
    
138 cfac048c Giorgos Verigakis
    def execute(self, container=None):
139 cfac048c Giorgos Verigakis
        if container:
140 cfac048c Giorgos Verigakis
            self.list_objects(container)
141 cfac048c Giorgos Verigakis
        else:
142 cfac048c Giorgos Verigakis
            self.list_containers()
143 f7ab99df Sofia Papagiannaki
    
144 cfac048c Giorgos Verigakis
    def list_containers(self):
145 f07c5a53 Sofia Papagiannaki
        params = {'limit':self.limit, 'marker':self.marker}
146 f07c5a53 Sofia Papagiannaki
        headers = {'IF_MODIFIED_SINCE':self.if_modified_since,
147 f07c5a53 Sofia Papagiannaki
                   'IF_UNMODIFIED_SINCE':self.if_unmodified_since}
148 d2d5c360 Sofia Papagiannaki
        
149 d2d5c360 Sofia Papagiannaki
        if self.until:
150 d2d5c360 Sofia Papagiannaki
            t = _time.strptime(self.until, self.format)
151 d2d5c360 Sofia Papagiannaki
            params['until'] = int(_time.mktime(t))
152 d2d5c360 Sofia Papagiannaki
        
153 f07c5a53 Sofia Papagiannaki
        l = self.client.list_containers(self.detail, params, headers)
154 f07c5a53 Sofia Papagiannaki
        print_list(l)
155 f7ab99df Sofia Papagiannaki
    
156 cfac048c Giorgos Verigakis
    def list_objects(self, container):
157 f07c5a53 Sofia Papagiannaki
        params = {'limit':self.limit, 'marker':self.marker,
158 f07c5a53 Sofia Papagiannaki
                  'prefix':self.prefix, 'delimiter':self.delimiter,
159 f07c5a53 Sofia Papagiannaki
                  'path':self.path, 'meta':self.meta}
160 f07c5a53 Sofia Papagiannaki
        headers = {'IF_MODIFIED_SINCE':self.if_modified_since,
161 f07c5a53 Sofia Papagiannaki
                   'IF_UNMODIFIED_SINCE':self.if_unmodified_since}
162 d2d5c360 Sofia Papagiannaki
        container, sep, object = container.partition('/')
163 d2d5c360 Sofia Papagiannaki
        if object:
164 d2d5c360 Sofia Papagiannaki
            return
165 d2d5c360 Sofia Papagiannaki
        
166 d2d5c360 Sofia Papagiannaki
        if self.until:
167 d2d5c360 Sofia Papagiannaki
            t = _time.strptime(self.until, self.format)
168 d2d5c360 Sofia Papagiannaki
            params['until'] = int(_time.mktime(t))
169 d2d5c360 Sofia Papagiannaki
        
170 a4c10cbc Sofia Papagiannaki
        detail = 'json'
171 a2defd86 Sofia Papagiannaki
        #if request with meta quering disable trash filtering
172 a2defd86 Sofia Papagiannaki
        show_trashed = True if self.meta else False
173 a2defd86 Sofia Papagiannaki
        l = self.client.list_objects(container, detail, params, headers,
174 a2defd86 Sofia Papagiannaki
                                     include_trashed = show_trashed)
175 a4c10cbc Sofia Papagiannaki
        print_list(l, detail=self.detail)
176 cfac048c Giorgos Verigakis
177 cfac048c Giorgos Verigakis
@cli_command('meta')
178 cfac048c Giorgos Verigakis
class Meta(Command):
179 cfac048c Giorgos Verigakis
    syntax = '[<container>[/<object>]]'
180 cfac048c Giorgos Verigakis
    description = 'get the metadata of an account, a container or an object'
181 0ea1dcc4 Sofia Papagiannaki
    
182 0ea1dcc4 Sofia Papagiannaki
    def add_options(self, parser):
183 0ea1dcc4 Sofia Papagiannaki
        parser.add_option('-r', action='store_true', dest='restricted',
184 0ea1dcc4 Sofia Papagiannaki
                          default=False, help='show only user defined metadata')
185 d2d5c360 Sofia Papagiannaki
        parser.add_option('--until', action='store', dest='until',
186 d2d5c360 Sofia Papagiannaki
                          default=False, help='show metadata until that date')
187 d2d5c360 Sofia Papagiannaki
        parser.add_option('--format', action='store', dest='format',
188 d2d5c360 Sofia Papagiannaki
                          default='%d/%m/%Y', help='format to parse until date')
189 e3fd7f91 Sofia Papagiannaki
        parser.add_option('--version', action='store', dest='version',
190 e3fd7f91 Sofia Papagiannaki
                          default=None, help='show specific version \
191 e3fd7f91 Sofia Papagiannaki
                                  (applies only for objects)')
192 f7ab99df Sofia Papagiannaki
    
193 cfac048c Giorgos Verigakis
    def execute(self, path=''):
194 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
195 d2d5c360 Sofia Papagiannaki
        if self.until:
196 d2d5c360 Sofia Papagiannaki
            t = _time.strptime(self.until, self.format)
197 d2d5c360 Sofia Papagiannaki
            self.until = int(_time.mktime(t))
198 cfac048c Giorgos Verigakis
        if object:
199 0ea1dcc4 Sofia Papagiannaki
            meta = self.client.retrieve_object_metadata(container, object,
200 8fe01d72 Sofia Papagiannaki
                                                        self.restricted,
201 8fe01d72 Sofia Papagiannaki
                                                        self.version)
202 cfac048c Giorgos Verigakis
        elif container:
203 0ea1dcc4 Sofia Papagiannaki
            meta = self.client.retrieve_container_metadata(container,
204 d2d5c360 Sofia Papagiannaki
                                                           self.restricted,
205 d2d5c360 Sofia Papagiannaki
                                                           self.until)
206 cfac048c Giorgos Verigakis
        else:
207 d2d5c360 Sofia Papagiannaki
            meta = self.client.account_metadata(self.restricted, self.until)
208 f07c5a53 Sofia Papagiannaki
        if meta == None:
209 f07c5a53 Sofia Papagiannaki
            print 'Entity does not exist'
210 f07c5a53 Sofia Papagiannaki
        else:
211 f07c5a53 Sofia Papagiannaki
            print_dict(meta, header=None)
212 cfac048c Giorgos Verigakis
213 cfac048c Giorgos Verigakis
@cli_command('create')
214 cfac048c Giorgos Verigakis
class CreateContainer(Command):
215 f07c5a53 Sofia Papagiannaki
    syntax = '<container> [key=val] [...]'
216 cfac048c Giorgos Verigakis
    description = 'create a container'
217 cfac048c Giorgos Verigakis
    
218 f07c5a53 Sofia Papagiannaki
    def execute(self, container, *args):
219 f07c5a53 Sofia Papagiannaki
        headers = {}
220 f07c5a53 Sofia Papagiannaki
        for arg in args:
221 f07c5a53 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
222 f07c5a53 Sofia Papagiannaki
            headers['X_CONTAINER_META_%s' %key.strip().upper()] = val.strip()
223 f07c5a53 Sofia Papagiannaki
        ret = self.client.create_container(container, headers)
224 cfac048c Giorgos Verigakis
        if not ret:
225 cfac048c Giorgos Verigakis
            print 'Container already exists'
226 cfac048c Giorgos Verigakis
227 cfac048c Giorgos Verigakis
@cli_command('delete', 'rm')
228 cfac048c Giorgos Verigakis
class Delete(Command):
229 cfac048c Giorgos Verigakis
    syntax = '<container>[/<object>]'
230 cfac048c Giorgos Verigakis
    description = 'delete a container or an object'
231 cfac048c Giorgos Verigakis
    
232 cfac048c Giorgos Verigakis
    def execute(self, path):
233 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
234 cfac048c Giorgos Verigakis
        if object:
235 cfac048c Giorgos Verigakis
            self.client.delete_object(container, object)
236 cfac048c Giorgos Verigakis
        else:
237 cfac048c Giorgos Verigakis
            self.client.delete_container(container)
238 cfac048c Giorgos Verigakis
239 cfac048c Giorgos Verigakis
@cli_command('get')
240 cfac048c Giorgos Verigakis
class GetObject(Command):
241 cfac048c Giorgos Verigakis
    syntax = '<container>/<object>'
242 cfac048c Giorgos Verigakis
    description = 'get the data of an object'
243 cfac048c Giorgos Verigakis
    
244 f07c5a53 Sofia Papagiannaki
    def add_options(self, parser):
245 f07c5a53 Sofia Papagiannaki
        parser.add_option('-l', action='store_true', dest='detail',
246 f07c5a53 Sofia Papagiannaki
                          default=False, help='show detailed output')
247 f07c5a53 Sofia Papagiannaki
        parser.add_option('--range', action='store', dest='range',
248 f07c5a53 Sofia Papagiannaki
                          default=None, help='show range of data')
249 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-match', action='store', dest='if-match',
250 f07c5a53 Sofia Papagiannaki
                          default=None, help='show output if ETags match')
251 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-none-match', action='store',
252 f07c5a53 Sofia Papagiannaki
                          dest='if-none-match', default=None,
253 f07c5a53 Sofia Papagiannaki
                          help='show output if ETags don\'t match')
254 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-modified-since', action='store', type='str',
255 f07c5a53 Sofia Papagiannaki
                          dest='if-modified-since', default=None,
256 f07c5a53 Sofia Papagiannaki
                          help='show output if modified since then')
257 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-unmodified-since', action='store', type='str',
258 f07c5a53 Sofia Papagiannaki
                          dest='if-unmodified-since', default=None,
259 f07c5a53 Sofia Papagiannaki
                          help='show output if not modified since then')
260 f07c5a53 Sofia Papagiannaki
        parser.add_option('-f', action='store', type='str',
261 f07c5a53 Sofia Papagiannaki
                          dest='file', default=None,
262 f07c5a53 Sofia Papagiannaki
                          help='save output in file')
263 8fe01d72 Sofia Papagiannaki
        parser.add_option('--version', action='store', type='str',
264 ad71a0ce Sofia Papagiannaki
                          dest='version', default=None,
265 085a31d7 Sofia Papagiannaki
                          help='get the specific \
266 8fe01d72 Sofia Papagiannaki
                               version')
267 085a31d7 Sofia Papagiannaki
        parser.add_option('--versionlist', action='store_true',
268 085a31d7 Sofia Papagiannaki
                          dest='versionlist', default=False,
269 085a31d7 Sofia Papagiannaki
                          help='get the full object version list')
270 f7ab99df Sofia Papagiannaki
    
271 cfac048c Giorgos Verigakis
    def execute(self, path):
272 f07c5a53 Sofia Papagiannaki
        headers = {}
273 f07c5a53 Sofia Papagiannaki
        if self.range:
274 f07c5a53 Sofia Papagiannaki
            headers['RANGE'] = 'bytes=%s' %self.range
275 f07c5a53 Sofia Papagiannaki
        attrs = ['if-match', 'if-none-match', 'if-modified-since',
276 f07c5a53 Sofia Papagiannaki
                 'if-unmodified-since']
277 f07c5a53 Sofia Papagiannaki
        attrs = [a for a in attrs if getattr(self, a)]
278 f07c5a53 Sofia Papagiannaki
        for a in attrs:
279 f07c5a53 Sofia Papagiannaki
            headers[a.replace('-', '_').upper()] = getattr(self, a)
280 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
281 085a31d7 Sofia Papagiannaki
        if self.versionlist:
282 085a31d7 Sofia Papagiannaki
            self.version = 'list'
283 085a31d7 Sofia Papagiannaki
            self.detail = True
284 f07c5a53 Sofia Papagiannaki
        data = self.client.retrieve_object(container, object, self.detail,
285 8fe01d72 Sofia Papagiannaki
                                          headers, self.version)
286 8fe01d72 Sofia Papagiannaki
        f = self.file and open(self.file, 'w') or stdout
287 8fe01d72 Sofia Papagiannaki
        if self.detail:
288 8fe01d72 Sofia Papagiannaki
            data = json.loads(data)
289 085a31d7 Sofia Papagiannaki
            if self.versionlist:
290 8fe01d72 Sofia Papagiannaki
                print_versions(data, f=f)
291 f07c5a53 Sofia Papagiannaki
            else:
292 8fe01d72 Sofia Papagiannaki
                print_dict(data, f=f)
293 f07c5a53 Sofia Papagiannaki
        else:
294 8fe01d72 Sofia Papagiannaki
            f.write(data)
295 8fe01d72 Sofia Papagiannaki
        f.close()
296 cfac048c Giorgos Verigakis
297 f7ab99df Sofia Papagiannaki
@cli_command('mkdir')
298 f7ab99df Sofia Papagiannaki
class PutMarker(Command):
299 f7ab99df Sofia Papagiannaki
    syntax = '<container>/<directory marker>'
300 f7ab99df Sofia Papagiannaki
    description = 'create a directory marker'
301 f7ab99df Sofia Papagiannaki
    
302 f7ab99df Sofia Papagiannaki
    def execute(self, path):
303 f7ab99df Sofia Papagiannaki
        container, sep, object = path.partition('/')
304 f7ab99df Sofia Papagiannaki
        self.client.create_directory_marker(container, object)
305 f7ab99df Sofia Papagiannaki
306 cfac048c Giorgos Verigakis
@cli_command('put')
307 cfac048c Giorgos Verigakis
class PutObject(Command):
308 f07c5a53 Sofia Papagiannaki
    syntax = '<container>/<object> <path> [key=val] [...]'
309 f07c5a53 Sofia Papagiannaki
    description = 'create/override object with path contents or standard input'
310 f7ab99df Sofia Papagiannaki
    
311 f07c5a53 Sofia Papagiannaki
    def add_options(self, parser):
312 f07c5a53 Sofia Papagiannaki
        parser.add_option('--chunked', action='store_true', dest='chunked',
313 f07c5a53 Sofia Papagiannaki
                          default=False, help='set chunked transfer mode')
314 f07c5a53 Sofia Papagiannaki
        parser.add_option('--etag', action='store', dest='etag',
315 f07c5a53 Sofia Papagiannaki
                          default=None, help='check written data')
316 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-encoding', action='store',
317 f07c5a53 Sofia Papagiannaki
                          dest='content-encoding', default=None,
318 f07c5a53 Sofia Papagiannaki
                          help='provide the object MIME content type')
319 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-disposition', action='store', type='str',
320 f07c5a53 Sofia Papagiannaki
                          dest='content-disposition', default=None,
321 f07c5a53 Sofia Papagiannaki
                          help='provide the presentation style of the object')
322 961f2fbe Sofia Papagiannaki
        parser.add_option('-S', action='store',
323 961f2fbe Sofia Papagiannaki
                          dest='segment-size', default=False,
324 f07c5a53 Sofia Papagiannaki
                          help='use for large file support')
325 961f2fbe Sofia Papagiannaki
        parser.add_option('--manifest', action='store_true',
326 961f2fbe Sofia Papagiannaki
                          dest='manifest', default=None,
327 961f2fbe Sofia Papagiannaki
                          help='upload a manifestation file')
328 f7ab99df Sofia Papagiannaki
        parser.add_option('--type', action='store',
329 f7ab99df Sofia Papagiannaki
                          dest='content-type', default=False,
330 f7ab99df Sofia Papagiannaki
                          help='create object with specific content type')
331 d2d5c360 Sofia Papagiannaki
        parser.add_option('--touch', action='store_true',
332 e3fd7f91 Sofia Papagiannaki
                          dest='touch', default=False,
333 d2d5c360 Sofia Papagiannaki
                          help='create object with zero data')
334 d3fd269f Sofia Papagiannaki
        parser.add_option('--sharing', action='store',
335 d3fd269f Sofia Papagiannaki
                          dest='sharing', default=None,
336 d3fd269f Sofia Papagiannaki
                          help='define sharing object policy')
337 d3fd269f Sofia Papagiannaki
        
338 d2d5c360 Sofia Papagiannaki
    def execute(self, path, srcpath='-', *args):
339 f07c5a53 Sofia Papagiannaki
        headers = {}
340 f07c5a53 Sofia Papagiannaki
        if self.manifest:
341 f07c5a53 Sofia Papagiannaki
            headers['X_OBJECT_MANIFEST'] = self.manifest
342 d3fd269f Sofia Papagiannaki
        if self.sharing:
343 d3fd269f Sofia Papagiannaki
            headers['X_OBJECT_SHARING'] = self.sharing
344 f7ab99df Sofia Papagiannaki
        
345 f7ab99df Sofia Papagiannaki
        attrs = ['etag', 'content-encoding', 'content-disposition',
346 f7ab99df Sofia Papagiannaki
                 'content-type']
347 f07c5a53 Sofia Papagiannaki
        attrs = [a for a in attrs if getattr(self, a)]
348 f07c5a53 Sofia Papagiannaki
        for a in attrs:
349 f07c5a53 Sofia Papagiannaki
            headers[a.replace('-', '_').upper()] = getattr(self, a)
350 f07c5a53 Sofia Papagiannaki
        
351 f07c5a53 Sofia Papagiannaki
        #prepare user defined meta
352 f07c5a53 Sofia Papagiannaki
        for arg in args:
353 f07c5a53 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
354 f07c5a53 Sofia Papagiannaki
            headers['X_OBJECT_META_%s' %key.strip().upper()] = val.strip()
355 f07c5a53 Sofia Papagiannaki
        
356 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
357 f07c5a53 Sofia Papagiannaki
        
358 d2d5c360 Sofia Papagiannaki
        f = None
359 d2d5c360 Sofia Papagiannaki
        chunked = False
360 d2d5c360 Sofia Papagiannaki
        if not self.touch:
361 d2d5c360 Sofia Papagiannaki
            f = srcpath != '-' and open(srcpath) or stdin
362 d2d5c360 Sofia Papagiannaki
            chunked = (self.chunked or f == stdin) and True or False
363 f07c5a53 Sofia Papagiannaki
        self.client.create_object(container, object, f, chunked=chunked,
364 f07c5a53 Sofia Papagiannaki
                                  headers=headers)
365 d2d5c360 Sofia Papagiannaki
        if f:
366 d2d5c360 Sofia Papagiannaki
            f.close()
367 cfac048c Giorgos Verigakis
368 cfac048c Giorgos Verigakis
@cli_command('copy', 'cp')
369 cfac048c Giorgos Verigakis
class CopyObject(Command):
370 cfac048c Giorgos Verigakis
    syntax = '<src container>/<src object> [<dst container>/]<dst object>'
371 cfac048c Giorgos Verigakis
    description = 'copies an object to a different location'
372 cfac048c Giorgos Verigakis
    
373 ad71a0ce Sofia Papagiannaki
    def add_options(self, parser):
374 ad71a0ce Sofia Papagiannaki
        parser.add_option('--version', action='store',
375 ad71a0ce Sofia Papagiannaki
                          dest='version', default=False,
376 ad71a0ce Sofia Papagiannaki
                          help='copy specific version')
377 f7ab99df Sofia Papagiannaki
    
378 cfac048c Giorgos Verigakis
    def execute(self, src, dst):
379 cfac048c Giorgos Verigakis
        src_container, sep, src_object = src.partition('/')
380 cfac048c Giorgos Verigakis
        dst_container, sep, dst_object = dst.partition('/')
381 cfac048c Giorgos Verigakis
        if not sep:
382 cfac048c Giorgos Verigakis
            dst_container = src_container
383 cfac048c Giorgos Verigakis
            dst_object = dst
384 ad71a0ce Sofia Papagiannaki
        version = getattr(self, 'version')
385 ad71a0ce Sofia Papagiannaki
        if version:
386 ad71a0ce Sofia Papagiannaki
            headers = {}
387 7e999dec Sofia Papagiannaki
            headers['X_SOURCE_VERSION'] = version
388 f07c5a53 Sofia Papagiannaki
        self.client.copy_object(src_container, src_object, dst_container,
389 7e999dec Sofia Papagiannaki
                                dst_object, headers)
390 cfac048c Giorgos Verigakis
391 cfac048c Giorgos Verigakis
@cli_command('set')
392 3f5b02c7 Sofia Papagiannaki
class SetMeta(Command):
393 3f5b02c7 Sofia Papagiannaki
    syntax = '[<container>[/<object>]] key=val [key=val] [...]'
394 3f5b02c7 Sofia Papagiannaki
    description = 'set metadata'
395 cfac048c Giorgos Verigakis
    
396 cfac048c Giorgos Verigakis
    def execute(self, path, *args):
397 3f5b02c7 Sofia Papagiannaki
        #in case of account fix the args
398 f07c5a53 Sofia Papagiannaki
        if path.find('=') != -1:
399 3f5b02c7 Sofia Papagiannaki
            args = list(args)
400 3f5b02c7 Sofia Papagiannaki
            args.append(path)
401 3f5b02c7 Sofia Papagiannaki
            args = tuple(args)
402 3f5b02c7 Sofia Papagiannaki
            path = ''
403 cfac048c Giorgos Verigakis
        meta = {}
404 cfac048c Giorgos Verigakis
        for arg in args:
405 cfac048c Giorgos Verigakis
            key, sep, val = arg.partition('=')
406 cfac048c Giorgos Verigakis
            meta[key.strip()] = val.strip()
407 3f5b02c7 Sofia Papagiannaki
        container, sep, object = path.partition('/')
408 3f5b02c7 Sofia Papagiannaki
        if object:
409 3f5b02c7 Sofia Papagiannaki
            self.client.update_object_metadata(container, object, **meta)
410 3f5b02c7 Sofia Papagiannaki
        elif container:
411 3f5b02c7 Sofia Papagiannaki
            self.client.update_container_metadata(container, **meta)
412 3f5b02c7 Sofia Papagiannaki
        else:
413 3f5b02c7 Sofia Papagiannaki
            self.client.update_account_metadata(**meta)
414 cfac048c Giorgos Verigakis
415 f07c5a53 Sofia Papagiannaki
@cli_command('update')
416 f07c5a53 Sofia Papagiannaki
class UpdateObject(Command):
417 f07c5a53 Sofia Papagiannaki
    syntax = '<container>/<object> path [key=val] [...]'
418 e3fd7f91 Sofia Papagiannaki
    description = 'update object metadata/data (default mode: append)'
419 f07c5a53 Sofia Papagiannaki
    
420 f07c5a53 Sofia Papagiannaki
    def add_options(self, parser):
421 f07c5a53 Sofia Papagiannaki
        parser.add_option('-a', action='store_true', dest='append',
422 e3fd7f91 Sofia Papagiannaki
                          default=True, help='append data')
423 f07c5a53 Sofia Papagiannaki
        parser.add_option('--start', action='store',
424 f07c5a53 Sofia Papagiannaki
                          dest='start',
425 a2defd86 Sofia Papagiannaki
                          default=None, help='starting offest to be updated')
426 f07c5a53 Sofia Papagiannaki
        parser.add_option('--range', action='store', dest='content-range',
427 f07c5a53 Sofia Papagiannaki
                          default=None, help='range of data to be updated')
428 f07c5a53 Sofia Papagiannaki
        parser.add_option('--chunked', action='store_true', dest='chunked',
429 f07c5a53 Sofia Papagiannaki
                          default=False, help='set chunked transfer mode')
430 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-encoding', action='store',
431 f07c5a53 Sofia Papagiannaki
                          dest='content-encoding', default=None,
432 f07c5a53 Sofia Papagiannaki
                          help='provide the object MIME content type')
433 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-disposition', action='store', type='str',
434 f07c5a53 Sofia Papagiannaki
                          dest='content-disposition', default=None,
435 f07c5a53 Sofia Papagiannaki
                          help='provide the presentation style of the object')
436 f07c5a53 Sofia Papagiannaki
        parser.add_option('--manifest', action='store', type='str',
437 f07c5a53 Sofia Papagiannaki
                          dest='manifest', default=None,
438 d3fd269f Sofia Papagiannaki
                          help='use for large file support')        
439 d3fd269f Sofia Papagiannaki
        parser.add_option('--sharing', action='store',
440 d3fd269f Sofia Papagiannaki
                          dest='sharing', default=None,
441 d3fd269f Sofia Papagiannaki
                          help='define sharing object policy')
442 a2defd86 Sofia Papagiannaki
        parser.add_option('--touch', action='store_true',
443 a2defd86 Sofia Papagiannaki
                          dest='touch', default=False,
444 10998c60 Sofia Papagiannaki
                          help='change object properties')
445 f7ab99df Sofia Papagiannaki
    
446 e3fd7f91 Sofia Papagiannaki
    def execute(self, path, srcpath='-', *args):
447 f07c5a53 Sofia Papagiannaki
        headers = {}
448 f07c5a53 Sofia Papagiannaki
        if self.manifest:
449 f07c5a53 Sofia Papagiannaki
            headers['X_OBJECT_MANIFEST'] = self.manifest
450 d3fd269f Sofia Papagiannaki
        if self.sharing:
451 d3fd269f Sofia Papagiannaki
            headers['X_OBJECT_SHARING'] = self.sharing
452 f07c5a53 Sofia Papagiannaki
        
453 7e999dec Sofia Papagiannaki
        if getattr(self, 'start'):
454 7e999dec Sofia Papagiannaki
            headers['CONTENT_RANGE'] = 'bytes %s-/*' % getattr(self, 'start')
455 7e999dec Sofia Papagiannaki
        elif self.append:
456 f07c5a53 Sofia Papagiannaki
            headers['CONTENT_RANGE'] = 'bytes */*'
457 f07c5a53 Sofia Papagiannaki
        
458 f07c5a53 Sofia Papagiannaki
        attrs = ['content-encoding', 'content-disposition']
459 f07c5a53 Sofia Papagiannaki
        attrs = [a for a in attrs if getattr(self, a)]
460 f07c5a53 Sofia Papagiannaki
        for a in attrs:
461 f07c5a53 Sofia Papagiannaki
            headers[a.replace('-', '_').upper()] = getattr(self, a)
462 f07c5a53 Sofia Papagiannaki
        
463 f07c5a53 Sofia Papagiannaki
        #prepare user defined meta
464 f07c5a53 Sofia Papagiannaki
        for arg in args:
465 f07c5a53 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
466 f07c5a53 Sofia Papagiannaki
            headers['X_OBJECT_META_%s' %key.strip().upper()] = val.strip()
467 f07c5a53 Sofia Papagiannaki
        
468 f07c5a53 Sofia Papagiannaki
        container, sep, object = path.partition('/')
469 f07c5a53 Sofia Papagiannaki
        
470 a2defd86 Sofia Papagiannaki
        f = None
471 a2defd86 Sofia Papagiannaki
        chunked = False
472 a2defd86 Sofia Papagiannaki
        if not self.touch:
473 a2defd86 Sofia Papagiannaki
            f = srcpath != '-' and open(srcpath) or stdin
474 a2defd86 Sofia Papagiannaki
            chunked = (self.chunked or f == stdin) and True or False
475 f07c5a53 Sofia Papagiannaki
        self.client.update_object(container, object, f, chunked=chunked,
476 f07c5a53 Sofia Papagiannaki
                                  headers=headers)
477 a2defd86 Sofia Papagiannaki
        if f:
478 a2defd86 Sofia Papagiannaki
            f.close()
479 f07c5a53 Sofia Papagiannaki
480 f07c5a53 Sofia Papagiannaki
@cli_command('move', 'mv')
481 f07c5a53 Sofia Papagiannaki
class MoveObject(Command):
482 f07c5a53 Sofia Papagiannaki
    syntax = '<src container>/<src object> [<dst container>/]<dst object>'
483 f07c5a53 Sofia Papagiannaki
    description = 'moves an object to a different location'
484 f07c5a53 Sofia Papagiannaki
    
485 f07c5a53 Sofia Papagiannaki
    def execute(self, src, dst):
486 f07c5a53 Sofia Papagiannaki
        src_container, sep, src_object = src.partition('/')
487 f07c5a53 Sofia Papagiannaki
        dst_container, sep, dst_object = dst.partition('/')
488 f07c5a53 Sofia Papagiannaki
        if not sep:
489 f07c5a53 Sofia Papagiannaki
            dst_container = src_container
490 f07c5a53 Sofia Papagiannaki
            dst_object = dst
491 085a31d7 Sofia Papagiannaki
        
492 f07c5a53 Sofia Papagiannaki
        self.client.move_object(src_container, src_object, dst_container,
493 085a31d7 Sofia Papagiannaki
                                dst_object, headers)
494 f07c5a53 Sofia Papagiannaki
495 a2defd86 Sofia Papagiannaki
@cli_command('remove')
496 f7ab99df Sofia Papagiannaki
class TrashObject(Command):
497 f7ab99df Sofia Papagiannaki
    syntax = '<container>/<object>'
498 f7ab99df Sofia Papagiannaki
    description = 'trashes an object'
499 f7ab99df Sofia Papagiannaki
    
500 f7ab99df Sofia Papagiannaki
    def execute(self, src):
501 f7ab99df Sofia Papagiannaki
        src_container, sep, src_object = src.partition('/')
502 f7ab99df Sofia Papagiannaki
        
503 f7ab99df Sofia Papagiannaki
        self.client.trash_object(src_container, src_object)
504 f7ab99df Sofia Papagiannaki
505 f7ab99df Sofia Papagiannaki
@cli_command('restore')
506 f7ab99df Sofia Papagiannaki
class TrashObject(Command):
507 f7ab99df Sofia Papagiannaki
    syntax = '<container>/<object>'
508 f7ab99df Sofia Papagiannaki
    description = 'trashes an object'
509 f7ab99df Sofia Papagiannaki
    
510 f7ab99df Sofia Papagiannaki
    def execute(self, src):
511 f7ab99df Sofia Papagiannaki
        src_container, sep, src_object = src.partition('/')
512 f7ab99df Sofia Papagiannaki
        
513 f7ab99df Sofia Papagiannaki
        self.client.restore_object(src_container, src_object)
514 f7ab99df Sofia Papagiannaki
515 f7ab99df Sofia Papagiannaki
@cli_command('unset')
516 f7ab99df Sofia Papagiannaki
class TrashObject(Command):
517 f7ab99df Sofia Papagiannaki
    syntax = '<container>/[<object>] key [key] [...]'
518 f7ab99df Sofia Papagiannaki
    description = 'deletes metadata info'
519 f7ab99df Sofia Papagiannaki
    
520 f7ab99df Sofia Papagiannaki
    def execute(self, path, *args):
521 f7ab99df Sofia Papagiannaki
        #in case of account fix the args
522 961f2fbe Sofia Papagiannaki
        if len(args) == 0:
523 f7ab99df Sofia Papagiannaki
            args = list(args)
524 f7ab99df Sofia Papagiannaki
            args.append(path)
525 f7ab99df Sofia Papagiannaki
            args = tuple(args)
526 f7ab99df Sofia Papagiannaki
            path = ''
527 f7ab99df Sofia Papagiannaki
        meta = []
528 f7ab99df Sofia Papagiannaki
        for key in args:
529 f7ab99df Sofia Papagiannaki
            meta.append(key)
530 f7ab99df Sofia Papagiannaki
        container, sep, object = path.partition('/')
531 f7ab99df Sofia Papagiannaki
        if object:
532 f7ab99df Sofia Papagiannaki
            self.client.delete_object_metadata(container, object, meta)
533 f7ab99df Sofia Papagiannaki
        elif container:
534 f7ab99df Sofia Papagiannaki
            self.client.delete_container_metadata(container, meta)
535 f7ab99df Sofia Papagiannaki
        else:
536 f7ab99df Sofia Papagiannaki
            self.client.delete_account_metadata(meta)
537 f7ab99df Sofia Papagiannaki
538 d3fd269f Sofia Papagiannaki
@cli_command('group')
539 d3fd269f Sofia Papagiannaki
class SetGroup(Command):
540 d3fd269f Sofia Papagiannaki
    syntax = 'key=val [key=val] [...]'
541 d3fd269f Sofia Papagiannaki
    description = 'sets group account info'
542 d3fd269f Sofia Papagiannaki
    
543 d3fd269f Sofia Papagiannaki
    def execute(self, path='', **args):
544 d3fd269f Sofia Papagiannaki
        if len(args) == 0:
545 d3fd269f Sofia Papagiannaki
            args = list(args)
546 d3fd269f Sofia Papagiannaki
            args.append(path)
547 d3fd269f Sofia Papagiannaki
            args = tuple(args)
548 d3fd269f Sofia Papagiannaki
            path = ''
549 d3fd269f Sofia Papagiannaki
        groups = {}
550 d3fd269f Sofia Papagiannaki
        for arg in args:
551 d3fd269f Sofia Papagiannaki
            key, sep, val = arg.partition('=')
552 d3fd269f Sofia Papagiannaki
            groups[key] = val
553 d3fd269f Sofia Papagiannaki
        self.client.set_account_groups(groups)
554 d3fd269f Sofia Papagiannaki
555 cfac048c Giorgos Verigakis
def print_usage():
556 10998c60 Sofia Papagiannaki
    cmd = Command('', [])
557 cfac048c Giorgos Verigakis
    parser = cmd.parser
558 cfac048c Giorgos Verigakis
    parser.usage = '%prog <command> [options]'
559 cfac048c Giorgos Verigakis
    parser.print_help()
560 cfac048c Giorgos Verigakis
    
561 cfac048c Giorgos Verigakis
    commands = []
562 cfac048c Giorgos Verigakis
    for cls in set(_cli_commands.values()):
563 cfac048c Giorgos Verigakis
        name = ', '.join(cls.commands)
564 cfac048c Giorgos Verigakis
        description = getattr(cls, 'description', '')
565 cfac048c Giorgos Verigakis
        commands.append('  %s %s' % (name.ljust(12), description))
566 cfac048c Giorgos Verigakis
    print '\nCommands:\n' + '\n'.join(sorted(commands))
567 cfac048c Giorgos Verigakis
568 a4c10cbc Sofia Papagiannaki
def print_dict(d, header='name', f=stdout, detail=True):
569 f07c5a53 Sofia Papagiannaki
    header = header in d and header or 'subdir'
570 f07c5a53 Sofia Papagiannaki
    if header and header in d:
571 f07c5a53 Sofia Papagiannaki
        f.write('%s\n' %d.pop(header))
572 a4c10cbc Sofia Papagiannaki
    if detail:
573 a4c10cbc Sofia Papagiannaki
        patterns = ['^x_(account|container|object)_meta_(\w+)$']
574 a4c10cbc Sofia Papagiannaki
        patterns.append(patterns[0].replace('_', '-'))
575 a4c10cbc Sofia Papagiannaki
        for key, val in sorted(d.items()):
576 a4c10cbc Sofia Papagiannaki
            for p in patterns:
577 a4c10cbc Sofia Papagiannaki
                p = re.compile(p)
578 a4c10cbc Sofia Papagiannaki
                m = p.match(key)
579 a4c10cbc Sofia Papagiannaki
                if m:
580 a4c10cbc Sofia Papagiannaki
                    key = m.group(2)
581 a4c10cbc Sofia Papagiannaki
            f.write('%s: %s\n' % (key.rjust(30), val))
582 f07c5a53 Sofia Papagiannaki
583 a4c10cbc Sofia Papagiannaki
def print_list(l, verbose=False, f=stdout, detail=True):
584 f07c5a53 Sofia Papagiannaki
    for elem in l:
585 f07c5a53 Sofia Papagiannaki
        #if it's empty string continue
586 f07c5a53 Sofia Papagiannaki
        if not elem:
587 f07c5a53 Sofia Papagiannaki
            continue
588 f07c5a53 Sofia Papagiannaki
        if type(elem) == types.DictionaryType:
589 a4c10cbc Sofia Papagiannaki
            print_dict(elem, f=f, detail=detail)
590 f07c5a53 Sofia Papagiannaki
        elif type(elem) == types.StringType:
591 f07c5a53 Sofia Papagiannaki
            if not verbose:
592 f07c5a53 Sofia Papagiannaki
                elem = elem.split('Traceback')[0]
593 f07c5a53 Sofia Papagiannaki
            f.write('%s\n' % elem)
594 f07c5a53 Sofia Papagiannaki
        else:
595 f07c5a53 Sofia Papagiannaki
            f.write('%s\n' % elem)
596 cfac048c Giorgos Verigakis
597 8fe01d72 Sofia Papagiannaki
def print_versions(data, f=stdout):
598 8fe01d72 Sofia Papagiannaki
    if 'versions' not in data:
599 8fe01d72 Sofia Papagiannaki
        f.write('%s\n' %data)
600 8fe01d72 Sofia Papagiannaki
        return
601 8fe01d72 Sofia Papagiannaki
    f.write('versions:\n')
602 8fe01d72 Sofia Papagiannaki
    for id, t in data['versions']:
603 8fe01d72 Sofia Papagiannaki
        f.write('%s @ %s\n' % (str(id).rjust(30), datetime.fromtimestamp(t)))
604 8fe01d72 Sofia Papagiannaki
605 cfac048c Giorgos Verigakis
def main():
606 cfac048c Giorgos Verigakis
    try:
607 cfac048c Giorgos Verigakis
        name = argv[1]
608 cfac048c Giorgos Verigakis
        cls = class_for_cli_command(name)
609 cfac048c Giorgos Verigakis
    except (IndexError, KeyError):
610 cfac048c Giorgos Verigakis
        print_usage()
611 cfac048c Giorgos Verigakis
        exit(1)
612 f07c5a53 Sofia Papagiannaki
    
613 a2defd86 Sofia Papagiannaki
    cmd = cls(name, argv[2:])
614 cfac048c Giorgos Verigakis
    
615 e5cd3e33 Sofia Papagiannaki
    try:
616 e5cd3e33 Sofia Papagiannaki
        cmd.execute(*cmd.args)
617 e3fd7f91 Sofia Papagiannaki
    except TypeError, e:
618 e5cd3e33 Sofia Papagiannaki
        cmd.parser.print_help()
619 e5cd3e33 Sofia Papagiannaki
        exit(1)
620 e5cd3e33 Sofia Papagiannaki
    except Fault, f:
621 f7ab99df Sofia Papagiannaki
        status = f.status and '%s ' % f.status or ''
622 f7ab99df Sofia Papagiannaki
        print '%s%s' % (status, f.data)
623 cfac048c Giorgos Verigakis
624 cfac048c Giorgos Verigakis
if __name__ == '__main__':
625 cfac048c Giorgos Verigakis
    main()