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