Statistics
| Branch: | Tag: | Revision:

root / tools / store @ d2d5c360

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