Statistics
| Branch: | Tag: | Revision:

root / tools / store @ 8fe01d72

History | View | Annotate | Download (19 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 8fe01d72 Sofia Papagiannaki
                                                        self.restricted,
163 8fe01d72 Sofia Papagiannaki
                                                        self.version)
164 cfac048c Giorgos Verigakis
        elif container:
165 0ea1dcc4 Sofia Papagiannaki
            meta = self.client.retrieve_container_metadata(container,
166 d2d5c360 Sofia Papagiannaki
                                                           self.restricted,
167 d2d5c360 Sofia Papagiannaki
                                                           self.until)
168 cfac048c Giorgos Verigakis
        else:
169 d2d5c360 Sofia Papagiannaki
            meta = self.client.account_metadata(self.restricted, self.until)
170 f07c5a53 Sofia Papagiannaki
        if meta == None:
171 f07c5a53 Sofia Papagiannaki
            print 'Entity does not exist'
172 f07c5a53 Sofia Papagiannaki
        else:
173 f07c5a53 Sofia Papagiannaki
            print_dict(meta, header=None)
174 cfac048c Giorgos Verigakis
175 cfac048c Giorgos Verigakis
@cli_command('create')
176 cfac048c Giorgos Verigakis
class CreateContainer(Command):
177 f07c5a53 Sofia Papagiannaki
    syntax = '<container> [key=val] [...]'
178 cfac048c Giorgos Verigakis
    description = 'create a container'
179 cfac048c Giorgos Verigakis
    
180 f07c5a53 Sofia Papagiannaki
    def execute(self, container, *args):
181 f07c5a53 Sofia Papagiannaki
        headers = {}
182 f07c5a53 Sofia Papagiannaki
        for arg in args:
183 f07c5a53 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
184 f07c5a53 Sofia Papagiannaki
            headers['X_CONTAINER_META_%s' %key.strip().upper()] = val.strip()
185 f07c5a53 Sofia Papagiannaki
        ret = self.client.create_container(container, headers)
186 cfac048c Giorgos Verigakis
        if not ret:
187 cfac048c Giorgos Verigakis
            print 'Container already exists'
188 cfac048c Giorgos Verigakis
189 cfac048c Giorgos Verigakis
@cli_command('delete', 'rm')
190 cfac048c Giorgos Verigakis
class Delete(Command):
191 cfac048c Giorgos Verigakis
    syntax = '<container>[/<object>]'
192 cfac048c Giorgos Verigakis
    description = 'delete a container or an object'
193 cfac048c Giorgos Verigakis
    
194 cfac048c Giorgos Verigakis
    def execute(self, path):
195 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
196 cfac048c Giorgos Verigakis
        if object:
197 cfac048c Giorgos Verigakis
            self.client.delete_object(container, object)
198 cfac048c Giorgos Verigakis
        else:
199 cfac048c Giorgos Verigakis
            self.client.delete_container(container)
200 cfac048c Giorgos Verigakis
201 cfac048c Giorgos Verigakis
@cli_command('get')
202 cfac048c Giorgos Verigakis
class GetObject(Command):
203 cfac048c Giorgos Verigakis
    syntax = '<container>/<object>'
204 cfac048c Giorgos Verigakis
    description = 'get the data of an object'
205 cfac048c Giorgos Verigakis
    
206 f07c5a53 Sofia Papagiannaki
    def add_options(self, parser):
207 f07c5a53 Sofia Papagiannaki
        parser.add_option('-l', action='store_true', dest='detail',
208 f07c5a53 Sofia Papagiannaki
                          default=False, help='show detailed output')
209 f07c5a53 Sofia Papagiannaki
        parser.add_option('--range', action='store', dest='range',
210 f07c5a53 Sofia Papagiannaki
                          default=None, help='show range of data')
211 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-match', action='store', dest='if-match',
212 f07c5a53 Sofia Papagiannaki
                          default=None, help='show output if ETags match')
213 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-none-match', action='store',
214 f07c5a53 Sofia Papagiannaki
                          dest='if-none-match', default=None,
215 f07c5a53 Sofia Papagiannaki
                          help='show output if ETags don\'t match')
216 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-modified-since', action='store', type='str',
217 f07c5a53 Sofia Papagiannaki
                          dest='if-modified-since', default=None,
218 f07c5a53 Sofia Papagiannaki
                          help='show output if modified since then')
219 f07c5a53 Sofia Papagiannaki
        parser.add_option('--if-unmodified-since', action='store', type='str',
220 f07c5a53 Sofia Papagiannaki
                          dest='if-unmodified-since', default=None,
221 f07c5a53 Sofia Papagiannaki
                          help='show output if not modified since then')
222 f07c5a53 Sofia Papagiannaki
        parser.add_option('-f', action='store', type='str',
223 f07c5a53 Sofia Papagiannaki
                          dest='file', default=None,
224 f07c5a53 Sofia Papagiannaki
                          help='save output in file')
225 8fe01d72 Sofia Papagiannaki
        parser.add_option('--version', action='store', type='str',
226 8fe01d72 Sofia Papagiannaki
                          dest='version', default='list',
227 8fe01d72 Sofia Papagiannaki
                          help='if \'list\' and in detailed mode get object\'s \
228 8fe01d72 Sofia Papagiannaki
                               full version list otherwise get the specific \
229 8fe01d72 Sofia Papagiannaki
                               version')
230 f07c5a53 Sofia Papagiannaki
231 cfac048c Giorgos Verigakis
    def execute(self, path):
232 f07c5a53 Sofia Papagiannaki
        headers = {}
233 f07c5a53 Sofia Papagiannaki
        if self.range:
234 f07c5a53 Sofia Papagiannaki
            headers['RANGE'] = 'bytes=%s' %self.range
235 f07c5a53 Sofia Papagiannaki
        attrs = ['if-match', 'if-none-match', 'if-modified-since',
236 f07c5a53 Sofia Papagiannaki
                 'if-unmodified-since']
237 f07c5a53 Sofia Papagiannaki
        attrs = [a for a in attrs if getattr(self, a)]
238 f07c5a53 Sofia Papagiannaki
        for a in attrs:
239 f07c5a53 Sofia Papagiannaki
            headers[a.replace('-', '_').upper()] = getattr(self, a)
240 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
241 f07c5a53 Sofia Papagiannaki
        data = self.client.retrieve_object(container, object, self.detail,
242 8fe01d72 Sofia Papagiannaki
                                          headers, self.version)
243 8fe01d72 Sofia Papagiannaki
        f = self.file and open(self.file, 'w') or stdout
244 8fe01d72 Sofia Papagiannaki
        if self.detail:
245 8fe01d72 Sofia Papagiannaki
            data = json.loads(data)
246 8fe01d72 Sofia Papagiannaki
            if self.version == 'list':
247 8fe01d72 Sofia Papagiannaki
                print_versions(data, f=f)
248 f07c5a53 Sofia Papagiannaki
            else:
249 8fe01d72 Sofia Papagiannaki
                print_dict(data, f=f)
250 f07c5a53 Sofia Papagiannaki
        else:
251 8fe01d72 Sofia Papagiannaki
            f.write(data)
252 8fe01d72 Sofia Papagiannaki
        f.close()
253 cfac048c Giorgos Verigakis
254 cfac048c Giorgos Verigakis
@cli_command('put')
255 cfac048c Giorgos Verigakis
class PutObject(Command):
256 f07c5a53 Sofia Papagiannaki
    syntax = '<container>/<object> <path> [key=val] [...]'
257 f07c5a53 Sofia Papagiannaki
    description = 'create/override object with path contents or standard input'
258 cfac048c Giorgos Verigakis
259 f07c5a53 Sofia Papagiannaki
    def add_options(self, parser):
260 f07c5a53 Sofia Papagiannaki
        parser.add_option('--chunked', action='store_true', dest='chunked',
261 f07c5a53 Sofia Papagiannaki
                          default=False, help='set chunked transfer mode')
262 f07c5a53 Sofia Papagiannaki
        parser.add_option('--etag', action='store', dest='etag',
263 f07c5a53 Sofia Papagiannaki
                          default=None, help='check written data')
264 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-encoding', action='store',
265 f07c5a53 Sofia Papagiannaki
                          dest='content-encoding', default=None,
266 f07c5a53 Sofia Papagiannaki
                          help='provide the object MIME content type')
267 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-disposition', action='store', type='str',
268 f07c5a53 Sofia Papagiannaki
                          dest='content-disposition', default=None,
269 f07c5a53 Sofia Papagiannaki
                          help='provide the presentation style of the object')
270 f07c5a53 Sofia Papagiannaki
        parser.add_option('--manifest', action='store', type='str',
271 f07c5a53 Sofia Papagiannaki
                          dest='manifest', default=None,
272 f07c5a53 Sofia Papagiannaki
                          help='use for large file support')
273 d2d5c360 Sofia Papagiannaki
        parser.add_option('--touch', action='store_true',
274 e3fd7f91 Sofia Papagiannaki
                          dest='touch', default=False,
275 d2d5c360 Sofia Papagiannaki
                          help='create object with zero data')
276 f07c5a53 Sofia Papagiannaki
277 d2d5c360 Sofia Papagiannaki
    def execute(self, path, srcpath='-', *args):
278 f07c5a53 Sofia Papagiannaki
        headers = {}
279 f07c5a53 Sofia Papagiannaki
        if self.manifest:
280 f07c5a53 Sofia Papagiannaki
            headers['X_OBJECT_MANIFEST'] = self.manifest
281 f07c5a53 Sofia Papagiannaki
            
282 f07c5a53 Sofia Papagiannaki
        attrs = ['etag', 'content-encoding', 'content-disposition']
283 f07c5a53 Sofia Papagiannaki
        attrs = [a for a in attrs if getattr(self, a)]
284 f07c5a53 Sofia Papagiannaki
        for a in attrs:
285 f07c5a53 Sofia Papagiannaki
            headers[a.replace('-', '_').upper()] = getattr(self, a)
286 f07c5a53 Sofia Papagiannaki
        
287 f07c5a53 Sofia Papagiannaki
        #prepare user defined meta
288 f07c5a53 Sofia Papagiannaki
        for arg in args:
289 f07c5a53 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
290 f07c5a53 Sofia Papagiannaki
            headers['X_OBJECT_META_%s' %key.strip().upper()] = val.strip()
291 f07c5a53 Sofia Papagiannaki
        
292 cfac048c Giorgos Verigakis
        container, sep, object = path.partition('/')
293 f07c5a53 Sofia Papagiannaki
        
294 d2d5c360 Sofia Papagiannaki
        f = None
295 d2d5c360 Sofia Papagiannaki
        chunked = False
296 d2d5c360 Sofia Papagiannaki
        if not self.touch:
297 d2d5c360 Sofia Papagiannaki
            f = srcpath != '-' and open(srcpath) or stdin
298 d2d5c360 Sofia Papagiannaki
            chunked = (self.chunked or f == stdin) and True or False
299 f07c5a53 Sofia Papagiannaki
        self.client.create_object(container, object, f, chunked=chunked,
300 f07c5a53 Sofia Papagiannaki
                                  headers=headers)
301 d2d5c360 Sofia Papagiannaki
        if f:
302 d2d5c360 Sofia Papagiannaki
            f.close()
303 cfac048c Giorgos Verigakis
304 cfac048c Giorgos Verigakis
@cli_command('copy', 'cp')
305 cfac048c Giorgos Verigakis
class CopyObject(Command):
306 cfac048c Giorgos Verigakis
    syntax = '<src container>/<src object> [<dst container>/]<dst object>'
307 cfac048c Giorgos Verigakis
    description = 'copies an object to a different location'
308 cfac048c Giorgos Verigakis
    
309 cfac048c Giorgos Verigakis
    def execute(self, src, dst):
310 cfac048c Giorgos Verigakis
        src_container, sep, src_object = src.partition('/')
311 cfac048c Giorgos Verigakis
        dst_container, sep, dst_object = dst.partition('/')
312 cfac048c Giorgos Verigakis
        if not sep:
313 cfac048c Giorgos Verigakis
            dst_container = src_container
314 cfac048c Giorgos Verigakis
            dst_object = dst
315 f07c5a53 Sofia Papagiannaki
        self.client.copy_object(src_container, src_object, dst_container,
316 f07c5a53 Sofia Papagiannaki
                                dst_object)
317 cfac048c Giorgos Verigakis
318 cfac048c Giorgos Verigakis
@cli_command('set')
319 3f5b02c7 Sofia Papagiannaki
class SetMeta(Command):
320 3f5b02c7 Sofia Papagiannaki
    syntax = '[<container>[/<object>]] key=val [key=val] [...]'
321 3f5b02c7 Sofia Papagiannaki
    description = 'set metadata'
322 cfac048c Giorgos Verigakis
    
323 cfac048c Giorgos Verigakis
    def execute(self, path, *args):
324 3f5b02c7 Sofia Papagiannaki
        #in case of account fix the args
325 f07c5a53 Sofia Papagiannaki
        if path.find('=') != -1:
326 3f5b02c7 Sofia Papagiannaki
            args = list(args)
327 3f5b02c7 Sofia Papagiannaki
            args.append(path)
328 3f5b02c7 Sofia Papagiannaki
            args = tuple(args)
329 3f5b02c7 Sofia Papagiannaki
            path = ''
330 cfac048c Giorgos Verigakis
        meta = {}
331 cfac048c Giorgos Verigakis
        for arg in args:
332 cfac048c Giorgos Verigakis
            key, sep, val = arg.partition('=')
333 cfac048c Giorgos Verigakis
            meta[key.strip()] = val.strip()
334 3f5b02c7 Sofia Papagiannaki
        container, sep, object = path.partition('/')
335 3f5b02c7 Sofia Papagiannaki
        if object:
336 3f5b02c7 Sofia Papagiannaki
            self.client.update_object_metadata(container, object, **meta)
337 3f5b02c7 Sofia Papagiannaki
        elif container:
338 3f5b02c7 Sofia Papagiannaki
            self.client.update_container_metadata(container, **meta)
339 3f5b02c7 Sofia Papagiannaki
        else:
340 3f5b02c7 Sofia Papagiannaki
            self.client.update_account_metadata(**meta)
341 cfac048c Giorgos Verigakis
342 f07c5a53 Sofia Papagiannaki
@cli_command('update')
343 f07c5a53 Sofia Papagiannaki
class UpdateObject(Command):
344 f07c5a53 Sofia Papagiannaki
    syntax = '<container>/<object> path [key=val] [...]'
345 e3fd7f91 Sofia Papagiannaki
    description = 'update object metadata/data (default mode: append)'
346 f07c5a53 Sofia Papagiannaki
    
347 f07c5a53 Sofia Papagiannaki
    def add_options(self, parser):
348 f07c5a53 Sofia Papagiannaki
        parser.add_option('-a', action='store_true', dest='append',
349 e3fd7f91 Sofia Papagiannaki
                          default=True, help='append data')
350 f07c5a53 Sofia Papagiannaki
        parser.add_option('--start', action='store',
351 f07c5a53 Sofia Papagiannaki
                          dest='start',
352 f07c5a53 Sofia Papagiannaki
                          default=None, help='range of data to be updated')
353 f07c5a53 Sofia Papagiannaki
        parser.add_option('--range', action='store', dest='content-range',
354 f07c5a53 Sofia Papagiannaki
                          default=None, help='range of data to be updated')
355 f07c5a53 Sofia Papagiannaki
        parser.add_option('--chunked', action='store_true', dest='chunked',
356 f07c5a53 Sofia Papagiannaki
                          default=False, help='set chunked transfer mode')
357 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-encoding', action='store',
358 f07c5a53 Sofia Papagiannaki
                          dest='content-encoding', default=None,
359 f07c5a53 Sofia Papagiannaki
                          help='provide the object MIME content type')
360 f07c5a53 Sofia Papagiannaki
        parser.add_option('--content-disposition', action='store', type='str',
361 f07c5a53 Sofia Papagiannaki
                          dest='content-disposition', default=None,
362 f07c5a53 Sofia Papagiannaki
                          help='provide the presentation style of the object')
363 f07c5a53 Sofia Papagiannaki
        parser.add_option('--manifest', action='store', type='str',
364 f07c5a53 Sofia Papagiannaki
                          dest='manifest', default=None,
365 f07c5a53 Sofia Papagiannaki
                          help='use for large file support')
366 f07c5a53 Sofia Papagiannaki
367 e3fd7f91 Sofia Papagiannaki
    def execute(self, path, srcpath='-', *args):
368 f07c5a53 Sofia Papagiannaki
        headers = {}
369 f07c5a53 Sofia Papagiannaki
        if self.manifest:
370 f07c5a53 Sofia Papagiannaki
            headers['X_OBJECT_MANIFEST'] = self.manifest
371 f07c5a53 Sofia Papagiannaki
        
372 f07c5a53 Sofia Papagiannaki
        if self.append:
373 f07c5a53 Sofia Papagiannaki
            headers['CONTENT_RANGE'] = 'bytes */*'
374 f07c5a53 Sofia Papagiannaki
        elif self.start:
375 f07c5a53 Sofia Papagiannaki
            headers['CONTENT_RANGE'] = 'bytes %s-/*' % self.first-byte-pos
376 f07c5a53 Sofia Papagiannaki
        
377 f07c5a53 Sofia Papagiannaki
        attrs = ['content-encoding', 'content-disposition']
378 f07c5a53 Sofia Papagiannaki
        attrs = [a for a in attrs if getattr(self, a)]
379 f07c5a53 Sofia Papagiannaki
        for a in attrs:
380 f07c5a53 Sofia Papagiannaki
            headers[a.replace('-', '_').upper()] = getattr(self, a)
381 f07c5a53 Sofia Papagiannaki
        
382 f07c5a53 Sofia Papagiannaki
        #prepare user defined meta
383 f07c5a53 Sofia Papagiannaki
        for arg in args:
384 f07c5a53 Sofia Papagiannaki
            key, sep, val = arg.partition('=')
385 f07c5a53 Sofia Papagiannaki
            headers['X_OBJECT_META_%s' %key.strip().upper()] = val.strip()
386 f07c5a53 Sofia Papagiannaki
        
387 f07c5a53 Sofia Papagiannaki
        container, sep, object = path.partition('/')
388 f07c5a53 Sofia Papagiannaki
        
389 f07c5a53 Sofia Papagiannaki
        f = srcpath != '-' and open(srcpath) or stdin
390 f07c5a53 Sofia Papagiannaki
        chunked = (self.chunked or f == stdin) and True or False
391 f07c5a53 Sofia Papagiannaki
        self.client.update_object(container, object, f, chunked=chunked,
392 f07c5a53 Sofia Papagiannaki
                                  headers=headers)
393 f07c5a53 Sofia Papagiannaki
        f.close()
394 f07c5a53 Sofia Papagiannaki
395 f07c5a53 Sofia Papagiannaki
@cli_command('move', 'mv')
396 f07c5a53 Sofia Papagiannaki
class MoveObject(Command):
397 f07c5a53 Sofia Papagiannaki
    syntax = '<src container>/<src object> [<dst container>/]<dst object>'
398 f07c5a53 Sofia Papagiannaki
    description = 'moves an object to a different location'
399 f07c5a53 Sofia Papagiannaki
    
400 f07c5a53 Sofia Papagiannaki
    def execute(self, src, dst):
401 f07c5a53 Sofia Papagiannaki
        src_container, sep, src_object = src.partition('/')
402 f07c5a53 Sofia Papagiannaki
        dst_container, sep, dst_object = dst.partition('/')
403 f07c5a53 Sofia Papagiannaki
        if not sep:
404 f07c5a53 Sofia Papagiannaki
            dst_container = src_container
405 f07c5a53 Sofia Papagiannaki
            dst_object = dst
406 f07c5a53 Sofia Papagiannaki
        self.client.move_object(src_container, src_object, dst_container,
407 f07c5a53 Sofia Papagiannaki
                                dst_object)
408 f07c5a53 Sofia Papagiannaki
409 cfac048c Giorgos Verigakis
def print_usage():
410 cfac048c Giorgos Verigakis
    cmd = Command([])
411 cfac048c Giorgos Verigakis
    parser = cmd.parser
412 cfac048c Giorgos Verigakis
    parser.usage = '%prog <command> [options]'
413 cfac048c Giorgos Verigakis
    parser.print_help()
414 cfac048c Giorgos Verigakis
    
415 cfac048c Giorgos Verigakis
    commands = []
416 cfac048c Giorgos Verigakis
    for cls in set(_cli_commands.values()):
417 cfac048c Giorgos Verigakis
        name = ', '.join(cls.commands)
418 cfac048c Giorgos Verigakis
        description = getattr(cls, 'description', '')
419 cfac048c Giorgos Verigakis
        commands.append('  %s %s' % (name.ljust(12), description))
420 cfac048c Giorgos Verigakis
    print '\nCommands:\n' + '\n'.join(sorted(commands))
421 cfac048c Giorgos Verigakis
422 f07c5a53 Sofia Papagiannaki
def print_dict(d, header='name', f=stdout):
423 f07c5a53 Sofia Papagiannaki
    header = header in d and header or 'subdir'
424 f07c5a53 Sofia Papagiannaki
    if header and header in d:
425 f07c5a53 Sofia Papagiannaki
        f.write('%s\n' %d.pop(header))
426 d2d5c360 Sofia Papagiannaki
    patterns = ['^x_(account|container|object)_meta_(\w+)$']
427 d2d5c360 Sofia Papagiannaki
    patterns.append(patterns[0].replace('_', '-'))
428 f07c5a53 Sofia Papagiannaki
    for key, val in sorted(d.items()):
429 d2d5c360 Sofia Papagiannaki
        for p in patterns:
430 d2d5c360 Sofia Papagiannaki
            p = re.compile(p)
431 d2d5c360 Sofia Papagiannaki
            m = p.match(key)
432 d2d5c360 Sofia Papagiannaki
            if m:
433 d2d5c360 Sofia Papagiannaki
                key = m.group(2)
434 d2d5c360 Sofia Papagiannaki
        f.write('%s: %s\n' % (key.rjust(30), val))
435 f07c5a53 Sofia Papagiannaki
436 f07c5a53 Sofia Papagiannaki
def print_list(l, verbose=False, f=stdout):
437 f07c5a53 Sofia Papagiannaki
    for elem in l:
438 f07c5a53 Sofia Papagiannaki
        #if it's empty string continue
439 f07c5a53 Sofia Papagiannaki
        if not elem:
440 f07c5a53 Sofia Papagiannaki
            continue
441 f07c5a53 Sofia Papagiannaki
        if type(elem) == types.DictionaryType:
442 f07c5a53 Sofia Papagiannaki
            print_dict(elem, f=f)
443 f07c5a53 Sofia Papagiannaki
        elif type(elem) == types.StringType:
444 f07c5a53 Sofia Papagiannaki
            if not verbose:
445 f07c5a53 Sofia Papagiannaki
                elem = elem.split('Traceback')[0]
446 f07c5a53 Sofia Papagiannaki
            f.write('%s\n' % elem)
447 f07c5a53 Sofia Papagiannaki
        else:
448 f07c5a53 Sofia Papagiannaki
            f.write('%s\n' % elem)
449 cfac048c Giorgos Verigakis
450 8fe01d72 Sofia Papagiannaki
def print_versions(data, f=stdout):
451 8fe01d72 Sofia Papagiannaki
    if 'versions' not in data:
452 8fe01d72 Sofia Papagiannaki
        f.write('%s\n' %data)
453 8fe01d72 Sofia Papagiannaki
        return
454 8fe01d72 Sofia Papagiannaki
    f.write('versions:\n')
455 8fe01d72 Sofia Papagiannaki
    for id, t in data['versions']:
456 8fe01d72 Sofia Papagiannaki
        f.write('%s @ %s\n' % (str(id).rjust(30), datetime.fromtimestamp(t)))
457 8fe01d72 Sofia Papagiannaki
458 cfac048c Giorgos Verigakis
def main():
459 cfac048c Giorgos Verigakis
    try:
460 cfac048c Giorgos Verigakis
        name = argv[1]
461 cfac048c Giorgos Verigakis
        cls = class_for_cli_command(name)
462 cfac048c Giorgos Verigakis
    except (IndexError, KeyError):
463 cfac048c Giorgos Verigakis
        print_usage()
464 cfac048c Giorgos Verigakis
        exit(1)
465 f07c5a53 Sofia Papagiannaki
    
466 cfac048c Giorgos Verigakis
    cmd = cls(argv[2:])
467 cfac048c Giorgos Verigakis
    
468 e5cd3e33 Sofia Papagiannaki
    try:
469 e5cd3e33 Sofia Papagiannaki
        cmd.execute(*cmd.args)
470 e3fd7f91 Sofia Papagiannaki
    except TypeError, e:
471 e3fd7f91 Sofia Papagiannaki
        print e
472 e5cd3e33 Sofia Papagiannaki
        cmd.parser.usage = '%%prog %s [options] %s' % (name, cmd.syntax)
473 e5cd3e33 Sofia Papagiannaki
        cmd.parser.print_help()
474 e5cd3e33 Sofia Papagiannaki
        exit(1)
475 e5cd3e33 Sofia Papagiannaki
    except Fault, f:
476 e3fd7f91 Sofia Papagiannaki
        print f.status, f.data
477 cfac048c Giorgos Verigakis
478 cfac048c Giorgos Verigakis
if __name__ == '__main__':
479 cfac048c Giorgos Verigakis
    main()