Statistics
| Branch: | Tag: | Revision:

root / tools / store @ e3fd7f91

History | View | Annotate | Download (18.4 kB)

1 cfac048c Giorgos Verigakis
#!/usr/bin/env python
2 cfac048c Giorgos Verigakis
3 cfac048c Giorgos Verigakis
from getpass import getuser
4 cfac048c Giorgos Verigakis
from optparse import OptionParser
5 cfac048c Giorgos Verigakis
from os.path import basename
6 f07c5a53 Sofia Papagiannaki
from sys import argv, exit, stdin, stdout
7 3f5b02c7 Sofia Papagiannaki
from pithos.lib.client import Client, Fault
8 d2d5c360 Sofia Papagiannaki
from datetime import datetime
9 cfac048c Giorgos Verigakis
10 cfac048c Giorgos Verigakis
import json
11 cfac048c Giorgos Verigakis
import logging
12 f07c5a53 Sofia Papagiannaki
import types
13 d2d5c360 Sofia Papagiannaki
import re
14 d2d5c360 Sofia Papagiannaki
import time as _time
15 cfac048c Giorgos Verigakis
16 e5cd3e33 Sofia Papagiannaki
DEFAULT_HOST = 'pithos.dev.grnet.gr'
17 cfac048c Giorgos Verigakis
DEFAULT_API = 'v1'
18 cfac048c Giorgos Verigakis
19 cfac048c Giorgos Verigakis
_cli_commands = {}
20 cfac048c Giorgos Verigakis
21 cfac048c Giorgos Verigakis
def cli_command(*args):
22 cfac048c Giorgos Verigakis
    def decorator(cls):
23 cfac048c Giorgos Verigakis
        cls.commands = args
24 cfac048c Giorgos Verigakis
        for name in args:
25 cfac048c Giorgos Verigakis
            _cli_commands[name] = cls
26 cfac048c Giorgos Verigakis
        return cls
27 cfac048c Giorgos Verigakis
    return decorator
28 cfac048c Giorgos Verigakis
29 cfac048c Giorgos Verigakis
def class_for_cli_command(name):
30 cfac048c Giorgos Verigakis
    return _cli_commands[name]
31 cfac048c Giorgos Verigakis
32 cfac048c Giorgos Verigakis
class Command(object):
33 cfac048c Giorgos Verigakis
    def __init__(self, argv):
34 cfac048c Giorgos Verigakis
        parser = OptionParser()
35 f07c5a53 Sofia Papagiannaki
        parser.add_option('--host', dest='host', metavar='HOST',
36 f07c5a53 Sofia Papagiannaki
                          default=DEFAULT_HOST, help='use server HOST')
37 f07c5a53 Sofia Papagiannaki
        parser.add_option('--user', dest='user', metavar='USERNAME',
38 f07c5a53 Sofia Papagiannaki
                          default=getuser(), help='use account USERNAME')
39 f07c5a53 Sofia Papagiannaki
        parser.add_option('--api', dest='api', metavar='API',
40 f07c5a53 Sofia Papagiannaki
                          default=DEFAULT_API, help='use api API')
41 f07c5a53 Sofia Papagiannaki
        parser.add_option('-v', action='store_true', dest='verbose',
42 f07c5a53 Sofia Papagiannaki
                          default=False, help='use verbose output')
43 f07c5a53 Sofia Papagiannaki
        parser.add_option('-d', action='store_true', dest='debug',
44 f07c5a53 Sofia Papagiannaki
                          default=False, help='use debug output')
45 cfac048c Giorgos Verigakis
        self.add_options(parser)
46 cfac048c Giorgos Verigakis
        options, args = parser.parse_args(argv)
47 cfac048c Giorgos Verigakis
        
48 cfac048c Giorgos Verigakis
        # Add options to self
49 cfac048c Giorgos Verigakis
        for opt in parser.option_list:
50 cfac048c Giorgos Verigakis
            key = opt.dest
51 cfac048c Giorgos Verigakis
            if key:
52 cfac048c Giorgos Verigakis
                val = getattr(options, key)
53 cfac048c Giorgos Verigakis
                setattr(self, key, val)
54 cfac048c Giorgos Verigakis
        
55 f07c5a53 Sofia Papagiannaki
        self.client = Client(self.host, self.user, self.api, self.verbose,
56 f07c5a53 Sofia Papagiannaki
                             self.debug)
57 cfac048c Giorgos Verigakis
        
58 cfac048c Giorgos Verigakis
        self.parser = parser
59 cfac048c Giorgos Verigakis
        self.args = args
60 e3fd7f91 Sofia Papagiannaki
61 cfac048c Giorgos Verigakis
    def add_options(self, parser):
62 cfac048c Giorgos Verigakis
        pass
63 cfac048c Giorgos Verigakis
64 cfac048c Giorgos Verigakis
    def execute(self, *args):
65 cfac048c Giorgos Verigakis
        pass
66 cfac048c Giorgos Verigakis
67 cfac048c Giorgos Verigakis
@cli_command('list', 'ls')
68 cfac048c Giorgos Verigakis
class List(Command):
69 f07c5a53 Sofia Papagiannaki
    syntax = '[<container>[/<object>]]'
70 cfac048c Giorgos Verigakis
    description = 'list containers or objects'
71 cfac048c Giorgos Verigakis
    
72 cfac048c Giorgos Verigakis
    def add_options(self, parser):
73 3f5b02c7 Sofia Papagiannaki
        parser.add_option('-l', action='store_true', dest='detail',
74 3f5b02c7 Sofia Papagiannaki
                          default=False, help='show detailed output')
75 3f5b02c7 Sofia Papagiannaki
        parser.add_option('-n', action='store', type='int', dest='limit',
76 3f5b02c7 Sofia Papagiannaki
                          default=1000, help='show limited output')
77 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--marker', action='store', type='str',
78 3f5b02c7 Sofia Papagiannaki
                          dest='marker', default=None,
79 3f5b02c7 Sofia Papagiannaki
                          help='show output greater then marker')
80 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--prefix', action='store', type='str',
81 3f5b02c7 Sofia Papagiannaki
                          dest='prefix', default=None,
82 3f5b02c7 Sofia Papagiannaki
                          help='show output starting with prefix')
83 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--delimiter', action='store', type='str',
84 3f5b02c7 Sofia Papagiannaki
                          dest='delimiter', default=None,
85 3f5b02c7 Sofia Papagiannaki
                          help='show output up to the delimiter')
86 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--path', action='store', type='str',
87 3f5b02c7 Sofia Papagiannaki
                          dest='path', default=None,
88 3f5b02c7 Sofia Papagiannaki
                          help='show output starting with prefix up to /')
89 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--meta', action='store', type='str',
90 3f5b02c7 Sofia Papagiannaki
                          dest='meta', default=None,
91 3f5b02c7 Sofia Papagiannaki
                          help='show output having the specified meta keys')
92 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--if-modified-since', action='store', type='str',
93 3f5b02c7 Sofia Papagiannaki
                          dest='if_modified_since', default=None,
94 3f5b02c7 Sofia Papagiannaki
                          help='show output if modified since then')
95 3f5b02c7 Sofia Papagiannaki
        parser.add_option('--if-unmodified-since', action='store', type='str',
96 3f5b02c7 Sofia Papagiannaki
                          dest='if_unmodified_since', default=None,
97 3f5b02c7 Sofia Papagiannaki
                          help='show output if not modified since then')
98 d2d5c360 Sofia Papagiannaki
        parser.add_option('--until', action='store', dest='until',
99 d2d5c360 Sofia Papagiannaki
                          default=False, help='show metadata until that date')
100 d2d5c360 Sofia Papagiannaki
        parser.add_option('--format', action='store', dest='format',
101 d2d5c360 Sofia Papagiannaki
                          default='%d/%m/%Y', help='format to parse until date')
102 f07c5a53 Sofia Papagiannaki
103 cfac048c Giorgos Verigakis
    def execute(self, container=None):
104 cfac048c Giorgos Verigakis
        if container:
105 cfac048c Giorgos Verigakis
            self.list_objects(container)
106 cfac048c Giorgos Verigakis
        else:
107 cfac048c Giorgos Verigakis
            self.list_containers()
108 e3fd7f91 Sofia Papagiannaki
109 cfac048c Giorgos Verigakis
    def list_containers(self):
110 f07c5a53 Sofia Papagiannaki
        params = {'limit':self.limit, 'marker':self.marker}
111 f07c5a53 Sofia Papagiannaki
        headers = {'IF_MODIFIED_SINCE':self.if_modified_since,
112 f07c5a53 Sofia Papagiannaki
                   'IF_UNMODIFIED_SINCE':self.if_unmodified_since}
113 d2d5c360 Sofia Papagiannaki
        
114 d2d5c360 Sofia Papagiannaki
        if self.until:
115 d2d5c360 Sofia Papagiannaki
            t = _time.strptime(self.until, self.format)
116 d2d5c360 Sofia Papagiannaki
            params['until'] = int(_time.mktime(t))
117 d2d5c360 Sofia Papagiannaki
        
118 f07c5a53 Sofia Papagiannaki
        l = self.client.list_containers(self.detail, params, headers)
119 f07c5a53 Sofia Papagiannaki
        print_list(l)
120 3f5b02c7 Sofia Papagiannaki
121 cfac048c Giorgos Verigakis
    def list_objects(self, container):
122 f07c5a53 Sofia Papagiannaki
        params = {'limit':self.limit, 'marker':self.marker,
123 f07c5a53 Sofia Papagiannaki
                  'prefix':self.prefix, 'delimiter':self.delimiter,
124 f07c5a53 Sofia Papagiannaki
                  'path':self.path, 'meta':self.meta}
125 f07c5a53 Sofia Papagiannaki
        headers = {'IF_MODIFIED_SINCE':self.if_modified_since,
126 f07c5a53 Sofia Papagiannaki
                   'IF_UNMODIFIED_SINCE':self.if_unmodified_since}
127 d2d5c360 Sofia Papagiannaki
        container, sep, object = container.partition('/')
128 d2d5c360 Sofia Papagiannaki
        if object:
129 d2d5c360 Sofia Papagiannaki
            print '%s/%s is an object' %(container, object)
130 d2d5c360 Sofia Papagiannaki
            return
131 d2d5c360 Sofia Papagiannaki
        
132 d2d5c360 Sofia Papagiannaki
        if self.until:
133 d2d5c360 Sofia Papagiannaki
            t = _time.strptime(self.until, self.format)
134 d2d5c360 Sofia Papagiannaki
            params['until'] = int(_time.mktime(t))
135 d2d5c360 Sofia Papagiannaki
        
136 f07c5a53 Sofia Papagiannaki
        l = self.client.list_objects(container, self.detail, params, headers)
137 f07c5a53 Sofia Papagiannaki
        print_list(l)
138 cfac048c Giorgos Verigakis
139 cfac048c Giorgos Verigakis
@cli_command('meta')
140 cfac048c Giorgos Verigakis
class Meta(Command):
141 cfac048c Giorgos Verigakis
    syntax = '[<container>[/<object>]]'
142 cfac048c Giorgos Verigakis
    description = 'get the metadata of an account, a container or an object'
143 0ea1dcc4 Sofia Papagiannaki
    
144 0ea1dcc4 Sofia Papagiannaki
    def add_options(self, parser):
145 0ea1dcc4 Sofia Papagiannaki
        parser.add_option('-r', action='store_true', dest='restricted',
146 0ea1dcc4 Sofia Papagiannaki
                          default=False, help='show only user defined metadata')
147 d2d5c360 Sofia Papagiannaki
        parser.add_option('--until', action='store', dest='until',
148 d2d5c360 Sofia Papagiannaki
                          default=False, help='show metadata until that date')
149 d2d5c360 Sofia Papagiannaki
        parser.add_option('--format', action='store', dest='format',
150 d2d5c360 Sofia Papagiannaki
                          default='%d/%m/%Y', help='format to parse until date')
151 e3fd7f91 Sofia Papagiannaki
        parser.add_option('--version', action='store', dest='version',
152 e3fd7f91 Sofia Papagiannaki
                          default=None, help='show specific version \
153 e3fd7f91 Sofia Papagiannaki
                                  (applies only for objects)')
154 cfac048c Giorgos Verigakis
155 cfac048c Giorgos Verigakis
    def execute(self, path=''):
156 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
157 d2d5c360 Sofia Papagiannaki
        if self.until:
158 d2d5c360 Sofia Papagiannaki
            t = _time.strptime(self.until, self.format)
159 d2d5c360 Sofia Papagiannaki
            self.until = int(_time.mktime(t))
160 cfac048c Giorgos Verigakis
        if object:
161 0ea1dcc4 Sofia Papagiannaki
            meta = self.client.retrieve_object_metadata(container, object,
162 0ea1dcc4 Sofia Papagiannaki
                                                        self.restricted)
163 cfac048c Giorgos Verigakis
        elif container:
164 0ea1dcc4 Sofia Papagiannaki
            meta = self.client.retrieve_container_metadata(container,
165 d2d5c360 Sofia Papagiannaki
                                                           self.restricted,
166 d2d5c360 Sofia Papagiannaki
                                                           self.until)
167 cfac048c Giorgos Verigakis
        else:
168 d2d5c360 Sofia Papagiannaki
            meta = self.client.account_metadata(self.restricted, self.until)
169 f07c5a53 Sofia Papagiannaki
        if meta == None:
170 f07c5a53 Sofia Papagiannaki
            print 'Entity does not exist'
171 f07c5a53 Sofia Papagiannaki
        else:
172 f07c5a53 Sofia Papagiannaki
            print_dict(meta, header=None)
173 cfac048c Giorgos Verigakis
174 cfac048c Giorgos Verigakis
@cli_command('create')
175 cfac048c Giorgos Verigakis
class CreateContainer(Command):
176 f07c5a53 Sofia Papagiannaki
    syntax = '<container> [key=val] [...]'
177 cfac048c Giorgos Verigakis
    description = 'create a container'
178 cfac048c Giorgos Verigakis
    
179 f07c5a53 Sofia Papagiannaki
    def execute(self, container, *args):
180 f07c5a53 Sofia Papagiannaki
        headers = {}
181 f07c5a53 Sofia Papagiannaki
        for arg in args:
182 f07c5a53 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
183 f07c5a53 Sofia Papagiannaki
            headers['X_CONTAINER_META_%s' %key.strip().upper()] = val.strip()
184 f07c5a53 Sofia Papagiannaki
        ret = self.client.create_container(container, headers)
185 cfac048c Giorgos Verigakis
        if not ret:
186 cfac048c Giorgos Verigakis
            print 'Container already exists'
187 cfac048c Giorgos Verigakis
188 cfac048c Giorgos Verigakis
@cli_command('delete', 'rm')
189 cfac048c Giorgos Verigakis
class Delete(Command):
190 cfac048c Giorgos Verigakis
    syntax = '<container>[/<object>]'
191 cfac048c Giorgos Verigakis
    description = 'delete a container or an object'
192 cfac048c Giorgos Verigakis
    
193 cfac048c Giorgos Verigakis
    def execute(self, path):
194 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
195 cfac048c Giorgos Verigakis
        if object:
196 cfac048c Giorgos Verigakis
            self.client.delete_object(container, object)
197 cfac048c Giorgos Verigakis
        else:
198 cfac048c Giorgos Verigakis
            self.client.delete_container(container)
199 cfac048c Giorgos Verigakis
200 cfac048c Giorgos Verigakis
@cli_command('get')
201 cfac048c Giorgos Verigakis
class GetObject(Command):
202 cfac048c Giorgos Verigakis
    syntax = '<container>/<object>'
203 cfac048c Giorgos Verigakis
    description = 'get the data of an object'
204 cfac048c Giorgos Verigakis
    
205 f07c5a53 Sofia Papagiannaki
    def add_options(self, parser):
206 f07c5a53 Sofia Papagiannaki
        parser.add_option('-l', action='store_true', dest='detail',
207 f07c5a53 Sofia Papagiannaki
                          default=False, help='show detailed output')
208 f07c5a53 Sofia Papagiannaki
        parser.add_option('--range', action='store', dest='range',
209 f07c5a53 Sofia Papagiannaki
                          default=None, help='show range of data')
210 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-match', action='store', dest='if-match',
211 f07c5a53 Sofia Papagiannaki
                          default=None, help='show output if ETags match')
212 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-none-match', action='store',
213 f07c5a53 Sofia Papagiannaki
                          dest='if-none-match', default=None,
214 f07c5a53 Sofia Papagiannaki
                          help='show output if ETags don\'t match')
215 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-modified-since', action='store', type='str',
216 f07c5a53 Sofia Papagiannaki
                          dest='if-modified-since', default=None,
217 f07c5a53 Sofia Papagiannaki
                          help='show output if modified since then')
218 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-unmodified-since', action='store', type='str',
219 f07c5a53 Sofia Papagiannaki
                          dest='if-unmodified-since', default=None,
220 f07c5a53 Sofia Papagiannaki
                          help='show output if not modified since then')
221 f07c5a53 Sofia Papagiannaki
        parser.add_option('-f', action='store', type='str',
222 f07c5a53 Sofia Papagiannaki
                          dest='file', default=None,
223 f07c5a53 Sofia Papagiannaki
                          help='save output in file')
224 f07c5a53 Sofia Papagiannaki
225 cfac048c Giorgos Verigakis
    def execute(self, path):
226 f07c5a53 Sofia Papagiannaki
        headers = {}
227 f07c5a53 Sofia Papagiannaki
        if self.range:
228 f07c5a53 Sofia Papagiannaki
            headers['RANGE'] = 'bytes=%s' %self.range
229 f07c5a53 Sofia Papagiannaki
        attrs = ['if-match', 'if-none-match', 'if-modified-since',
230 f07c5a53 Sofia Papagiannaki
                 'if-unmodified-since']
231 f07c5a53 Sofia Papagiannaki
        attrs = [a for a in attrs if getattr(self, a)]
232 f07c5a53 Sofia Papagiannaki
        for a in attrs:
233 f07c5a53 Sofia Papagiannaki
            headers[a.replace('-', '_').upper()] = getattr(self, a)
234 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
235 f07c5a53 Sofia Papagiannaki
        data = self.client.retrieve_object(container, object, self.detail,
236 f07c5a53 Sofia Papagiannaki
                                          headers)
237 f07c5a53 Sofia Papagiannaki
        if self.file:
238 f07c5a53 Sofia Papagiannaki
            if self.detail:
239 f07c5a53 Sofia Papagiannaki
                f = self.file and open(self.file, 'w') or stdout
240 f07c5a53 Sofia Papagiannaki
                data = json.loads(data)
241 f07c5a53 Sofia Papagiannaki
                print_dict(data, f=f)
242 f07c5a53 Sofia Papagiannaki
            else:
243 f07c5a53 Sofia Papagiannaki
                fw = open(self.file, 'w')
244 f07c5a53 Sofia Papagiannaki
                fw.write(data)
245 f07c5a53 Sofia Papagiannaki
                fw.close()
246 f07c5a53 Sofia Papagiannaki
        else:
247 f07c5a53 Sofia Papagiannaki
            print data
248 cfac048c Giorgos Verigakis
249 cfac048c Giorgos Verigakis
@cli_command('put')
250 cfac048c Giorgos Verigakis
class PutObject(Command):
251 f07c5a53 Sofia Papagiannaki
    syntax = '<container>/<object> <path> [key=val] [...]'
252 f07c5a53 Sofia Papagiannaki
    description = 'create/override object with path contents or standard input'
253 cfac048c Giorgos Verigakis
254 f07c5a53 Sofia Papagiannaki
    def add_options(self, parser):
255 f07c5a53 Sofia Papagiannaki
        parser.add_option('--chunked', action='store_true', dest='chunked',
256 f07c5a53 Sofia Papagiannaki
                          default=False, help='set chunked transfer mode')
257 f07c5a53 Sofia Papagiannaki
        parser.add_option('--etag', action='store', dest='etag',
258 f07c5a53 Sofia Papagiannaki
                          default=None, help='check written data')
259 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-encoding', action='store',
260 f07c5a53 Sofia Papagiannaki
                          dest='content-encoding', default=None,
261 f07c5a53 Sofia Papagiannaki
                          help='provide the object MIME content type')
262 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-disposition', action='store', type='str',
263 f07c5a53 Sofia Papagiannaki
                          dest='content-disposition', default=None,
264 f07c5a53 Sofia Papagiannaki
                          help='provide the presentation style of the object')
265 f07c5a53 Sofia Papagiannaki
        parser.add_option('--manifest', action='store', type='str',
266 f07c5a53 Sofia Papagiannaki
                          dest='manifest', default=None,
267 f07c5a53 Sofia Papagiannaki
                          help='use for large file support')
268 d2d5c360 Sofia Papagiannaki
        parser.add_option('--touch', action='store_true',
269 e3fd7f91 Sofia Papagiannaki
                          dest='touch', default=False,
270 d2d5c360 Sofia Papagiannaki
                          help='create object with zero data')
271 f07c5a53 Sofia Papagiannaki
272 d2d5c360 Sofia Papagiannaki
    def execute(self, path, srcpath='-', *args):
273 f07c5a53 Sofia Papagiannaki
        headers = {}
274 f07c5a53 Sofia Papagiannaki
        if self.manifest:
275 f07c5a53 Sofia Papagiannaki
            headers['X_OBJECT_MANIFEST'] = self.manifest
276 f07c5a53 Sofia Papagiannaki
            
277 f07c5a53 Sofia Papagiannaki
        attrs = ['etag', 'content-encoding', 'content-disposition']
278 f07c5a53 Sofia Papagiannaki
        attrs = [a for a in attrs if getattr(self, a)]
279 f07c5a53 Sofia Papagiannaki
        for a in attrs:
280 f07c5a53 Sofia Papagiannaki
            headers[a.replace('-', '_').upper()] = getattr(self, a)
281 f07c5a53 Sofia Papagiannaki
        
282 f07c5a53 Sofia Papagiannaki
        #prepare user defined meta
283 f07c5a53 Sofia Papagiannaki
        for arg in args:
284 f07c5a53 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
285 f07c5a53 Sofia Papagiannaki
            headers['X_OBJECT_META_%s' %key.strip().upper()] = val.strip()
286 f07c5a53 Sofia Papagiannaki
        
287 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
288 f07c5a53 Sofia Papagiannaki
        
289 d2d5c360 Sofia Papagiannaki
        f = None
290 d2d5c360 Sofia Papagiannaki
        chunked = False
291 d2d5c360 Sofia Papagiannaki
        if not self.touch:
292 d2d5c360 Sofia Papagiannaki
            f = srcpath != '-' and open(srcpath) or stdin
293 d2d5c360 Sofia Papagiannaki
            chunked = (self.chunked or f == stdin) and True or False
294 f07c5a53 Sofia Papagiannaki
        self.client.create_object(container, object, f, chunked=chunked,
295 f07c5a53 Sofia Papagiannaki
                                  headers=headers)
296 d2d5c360 Sofia Papagiannaki
        if f:
297 d2d5c360 Sofia Papagiannaki
            f.close()
298 cfac048c Giorgos Verigakis
299 cfac048c Giorgos Verigakis
@cli_command('copy', 'cp')
300 cfac048c Giorgos Verigakis
class CopyObject(Command):
301 cfac048c Giorgos Verigakis
    syntax = '<src container>/<src object> [<dst container>/]<dst object>'
302 cfac048c Giorgos Verigakis
    description = 'copies an object to a different location'
303 cfac048c Giorgos Verigakis
    
304 cfac048c Giorgos Verigakis
    def execute(self, src, dst):
305 cfac048c Giorgos Verigakis
        src_container, sep, src_object = src.partition('/')
306 cfac048c Giorgos Verigakis
        dst_container, sep, dst_object = dst.partition('/')
307 cfac048c Giorgos Verigakis
        if not sep:
308 cfac048c Giorgos Verigakis
            dst_container = src_container
309 cfac048c Giorgos Verigakis
            dst_object = dst
310 f07c5a53 Sofia Papagiannaki
        self.client.copy_object(src_container, src_object, dst_container,
311 f07c5a53 Sofia Papagiannaki
                                dst_object)
312 cfac048c Giorgos Verigakis
313 cfac048c Giorgos Verigakis
@cli_command('set')
314 3f5b02c7 Sofia Papagiannaki
class SetMeta(Command):
315 3f5b02c7 Sofia Papagiannaki
    syntax = '[<container>[/<object>]] key=val [key=val] [...]'
316 3f5b02c7 Sofia Papagiannaki
    description = 'set metadata'
317 cfac048c Giorgos Verigakis
    
318 cfac048c Giorgos Verigakis
    def execute(self, path, *args):
319 3f5b02c7 Sofia Papagiannaki
        #in case of account fix the args
320 f07c5a53 Sofia Papagiannaki
        if path.find('=') != -1:
321 3f5b02c7 Sofia Papagiannaki
            args = list(args)
322 3f5b02c7 Sofia Papagiannaki
            args.append(path)
323 3f5b02c7 Sofia Papagiannaki
            args = tuple(args)
324 3f5b02c7 Sofia Papagiannaki
            path = ''
325 cfac048c Giorgos Verigakis
        meta = {}
326 cfac048c Giorgos Verigakis
        for arg in args:
327 cfac048c Giorgos Verigakis
            key, sep, val = arg.partition('=')
328 cfac048c Giorgos Verigakis
            meta[key.strip()] = val.strip()
329 3f5b02c7 Sofia Papagiannaki
        container, sep, object = path.partition('/')
330 3f5b02c7 Sofia Papagiannaki
        if object:
331 3f5b02c7 Sofia Papagiannaki
            self.client.update_object_metadata(container, object, **meta)
332 3f5b02c7 Sofia Papagiannaki
        elif container:
333 3f5b02c7 Sofia Papagiannaki
            self.client.update_container_metadata(container, **meta)
334 3f5b02c7 Sofia Papagiannaki
        else:
335 3f5b02c7 Sofia Papagiannaki
            self.client.update_account_metadata(**meta)
336 cfac048c Giorgos Verigakis
337 f07c5a53 Sofia Papagiannaki
@cli_command('update')
338 f07c5a53 Sofia Papagiannaki
class UpdateObject(Command):
339 f07c5a53 Sofia Papagiannaki
    syntax = '<container>/<object> path [key=val] [...]'
340 e3fd7f91 Sofia Papagiannaki
    description = 'update object metadata/data (default mode: append)'
341 f07c5a53 Sofia Papagiannaki
    
342 f07c5a53 Sofia Papagiannaki
    def add_options(self, parser):
343 f07c5a53 Sofia Papagiannaki
        parser.add_option('-a', action='store_true', dest='append',
344 e3fd7f91 Sofia Papagiannaki
                          default=True, help='append data')
345 f07c5a53 Sofia Papagiannaki
        parser.add_option('--start', action='store',
346 f07c5a53 Sofia Papagiannaki
                          dest='start',
347 f07c5a53 Sofia Papagiannaki
                          default=None, help='range of data to be updated')
348 f07c5a53 Sofia Papagiannaki
        parser.add_option('--range', action='store', dest='content-range',
349 f07c5a53 Sofia Papagiannaki
                          default=None, help='range of data to be updated')
350 f07c5a53 Sofia Papagiannaki
        parser.add_option('--chunked', action='store_true', dest='chunked',
351 f07c5a53 Sofia Papagiannaki
                          default=False, help='set chunked transfer mode')
352 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-encoding', action='store',
353 f07c5a53 Sofia Papagiannaki
                          dest='content-encoding', default=None,
354 f07c5a53 Sofia Papagiannaki
                          help='provide the object MIME content type')
355 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-disposition', action='store', type='str',
356 f07c5a53 Sofia Papagiannaki
                          dest='content-disposition', default=None,
357 f07c5a53 Sofia Papagiannaki
                          help='provide the presentation style of the object')
358 f07c5a53 Sofia Papagiannaki
        parser.add_option('--manifest', action='store', type='str',
359 f07c5a53 Sofia Papagiannaki
                          dest='manifest', default=None,
360 f07c5a53 Sofia Papagiannaki
                          help='use for large file support')
361 f07c5a53 Sofia Papagiannaki
362 e3fd7f91 Sofia Papagiannaki
    def execute(self, path, srcpath='-', *args):
363 f07c5a53 Sofia Papagiannaki
        headers = {}
364 f07c5a53 Sofia Papagiannaki
        if self.manifest:
365 f07c5a53 Sofia Papagiannaki
            headers['X_OBJECT_MANIFEST'] = self.manifest
366 f07c5a53 Sofia Papagiannaki
        
367 f07c5a53 Sofia Papagiannaki
        if self.append:
368 f07c5a53 Sofia Papagiannaki
            headers['CONTENT_RANGE'] = 'bytes */*'
369 f07c5a53 Sofia Papagiannaki
        elif self.start:
370 f07c5a53 Sofia Papagiannaki
            headers['CONTENT_RANGE'] = 'bytes %s-/*' % self.first-byte-pos
371 f07c5a53 Sofia Papagiannaki
        
372 f07c5a53 Sofia Papagiannaki
        attrs = ['content-encoding', 'content-disposition']
373 f07c5a53 Sofia Papagiannaki
        attrs = [a for a in attrs if getattr(self, a)]
374 f07c5a53 Sofia Papagiannaki
        for a in attrs:
375 f07c5a53 Sofia Papagiannaki
            headers[a.replace('-', '_').upper()] = getattr(self, a)
376 f07c5a53 Sofia Papagiannaki
        
377 f07c5a53 Sofia Papagiannaki
        #prepare user defined meta
378 f07c5a53 Sofia Papagiannaki
        for arg in args:
379 f07c5a53 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
380 f07c5a53 Sofia Papagiannaki
            headers['X_OBJECT_META_%s' %key.strip().upper()] = val.strip()
381 f07c5a53 Sofia Papagiannaki
        
382 f07c5a53 Sofia Papagiannaki
        container, sep, object = path.partition('/')
383 f07c5a53 Sofia Papagiannaki
        
384 f07c5a53 Sofia Papagiannaki
        f = srcpath != '-' and open(srcpath) or stdin
385 f07c5a53 Sofia Papagiannaki
        chunked = (self.chunked or f == stdin) and True or False
386 f07c5a53 Sofia Papagiannaki
        self.client.update_object(container, object, f, chunked=chunked,
387 f07c5a53 Sofia Papagiannaki
                                  headers=headers)
388 f07c5a53 Sofia Papagiannaki
        f.close()
389 f07c5a53 Sofia Papagiannaki
390 f07c5a53 Sofia Papagiannaki
@cli_command('move', 'mv')
391 f07c5a53 Sofia Papagiannaki
class MoveObject(Command):
392 f07c5a53 Sofia Papagiannaki
    syntax = '<src container>/<src object> [<dst container>/]<dst object>'
393 f07c5a53 Sofia Papagiannaki
    description = 'moves an object to a different location'
394 f07c5a53 Sofia Papagiannaki
    
395 f07c5a53 Sofia Papagiannaki
    def execute(self, src, dst):
396 f07c5a53 Sofia Papagiannaki
        src_container, sep, src_object = src.partition('/')
397 f07c5a53 Sofia Papagiannaki
        dst_container, sep, dst_object = dst.partition('/')
398 f07c5a53 Sofia Papagiannaki
        if not sep:
399 f07c5a53 Sofia Papagiannaki
            dst_container = src_container
400 f07c5a53 Sofia Papagiannaki
            dst_object = dst
401 f07c5a53 Sofia Papagiannaki
        self.client.move_object(src_container, src_object, dst_container,
402 f07c5a53 Sofia Papagiannaki
                                dst_object)
403 f07c5a53 Sofia Papagiannaki
404 cfac048c Giorgos Verigakis
def print_usage():
405 cfac048c Giorgos Verigakis
    cmd = Command([])
406 cfac048c Giorgos Verigakis
    parser = cmd.parser
407 cfac048c Giorgos Verigakis
    parser.usage = '%prog <command> [options]'
408 cfac048c Giorgos Verigakis
    parser.print_help()
409 cfac048c Giorgos Verigakis
    
410 cfac048c Giorgos Verigakis
    commands = []
411 cfac048c Giorgos Verigakis
    for cls in set(_cli_commands.values()):
412 cfac048c Giorgos Verigakis
        name = ', '.join(cls.commands)
413 cfac048c Giorgos Verigakis
        description = getattr(cls, 'description', '')
414 cfac048c Giorgos Verigakis
        commands.append('  %s %s' % (name.ljust(12), description))
415 cfac048c Giorgos Verigakis
    print '\nCommands:\n' + '\n'.join(sorted(commands))
416 cfac048c Giorgos Verigakis
417 f07c5a53 Sofia Papagiannaki
def print_dict(d, header='name', f=stdout):
418 f07c5a53 Sofia Papagiannaki
    header = header in d and header or 'subdir'
419 f07c5a53 Sofia Papagiannaki
    if header and header in d:
420 f07c5a53 Sofia Papagiannaki
        f.write('%s\n' %d.pop(header))
421 d2d5c360 Sofia Papagiannaki
    patterns = ['^x_(account|container|object)_meta_(\w+)$']
422 d2d5c360 Sofia Papagiannaki
    patterns.append(patterns[0].replace('_', '-'))
423 f07c5a53 Sofia Papagiannaki
    for key, val in sorted(d.items()):
424 d2d5c360 Sofia Papagiannaki
        for p in patterns:
425 d2d5c360 Sofia Papagiannaki
            p = re.compile(p)
426 d2d5c360 Sofia Papagiannaki
            m = p.match(key)
427 d2d5c360 Sofia Papagiannaki
            if m:
428 d2d5c360 Sofia Papagiannaki
                key = m.group(2)
429 d2d5c360 Sofia Papagiannaki
        f.write('%s: %s\n' % (key.rjust(30), val))
430 f07c5a53 Sofia Papagiannaki
431 f07c5a53 Sofia Papagiannaki
def print_list(l, verbose=False, f=stdout):
432 f07c5a53 Sofia Papagiannaki
    for elem in l:
433 f07c5a53 Sofia Papagiannaki
        #if it's empty string continue
434 f07c5a53 Sofia Papagiannaki
        if not elem:
435 f07c5a53 Sofia Papagiannaki
            continue
436 f07c5a53 Sofia Papagiannaki
        if type(elem) == types.DictionaryType:
437 f07c5a53 Sofia Papagiannaki
            print_dict(elem, f=f)
438 f07c5a53 Sofia Papagiannaki
        elif type(elem) == types.StringType:
439 f07c5a53 Sofia Papagiannaki
            if not verbose:
440 f07c5a53 Sofia Papagiannaki
                elem = elem.split('Traceback')[0]
441 f07c5a53 Sofia Papagiannaki
            f.write('%s\n' % elem)
442 f07c5a53 Sofia Papagiannaki
        else:
443 f07c5a53 Sofia Papagiannaki
            f.write('%s\n' % elem)
444 cfac048c Giorgos Verigakis
445 cfac048c Giorgos Verigakis
def main():
446 cfac048c Giorgos Verigakis
    try:
447 cfac048c Giorgos Verigakis
        name = argv[1]
448 cfac048c Giorgos Verigakis
        cls = class_for_cli_command(name)
449 cfac048c Giorgos Verigakis
    except (IndexError, KeyError):
450 cfac048c Giorgos Verigakis
        print_usage()
451 cfac048c Giorgos Verigakis
        exit(1)
452 f07c5a53 Sofia Papagiannaki
    
453 cfac048c Giorgos Verigakis
    cmd = cls(argv[2:])
454 cfac048c Giorgos Verigakis
    
455 e5cd3e33 Sofia Papagiannaki
    try:
456 e5cd3e33 Sofia Papagiannaki
        cmd.execute(*cmd.args)
457 e3fd7f91 Sofia Papagiannaki
    except TypeError, e:
458 e3fd7f91 Sofia Papagiannaki
        print e
459 e5cd3e33 Sofia Papagiannaki
        cmd.parser.usage = '%%prog %s [options] %s' % (name, cmd.syntax)
460 e5cd3e33 Sofia Papagiannaki
        cmd.parser.print_help()
461 e5cd3e33 Sofia Papagiannaki
        exit(1)
462 e5cd3e33 Sofia Papagiannaki
    except Fault, f:
463 e3fd7f91 Sofia Papagiannaki
        print f.status, f.data
464 cfac048c Giorgos Verigakis
465 cfac048c Giorgos Verigakis
if __name__ == '__main__':
466 cfac048c Giorgos Verigakis
    main()