Revision d50ed8d4 snf-pithos-tools/pithos/tools/fs.py

b/snf-pithos-tools/pithos/tools/fs.py
1 1
#!/usr/bin/env python
2 2

  
3 3
# Copyright 2011-2012 GRNET S.A. All rights reserved.
4
# 
4
#
5 5
# Redistribution and use in source and binary forms, with or
6 6
# without modification, are permitted provided that the following
7 7
# conditions are met:
8
# 
8
#
9 9
#   1. Redistributions of source code must retain the above
10 10
#      copyright notice, this list of conditions and the following
11 11
#      disclaimer.
12
# 
12
#
13 13
#   2. Redistributions in binary form must reproduce the above
14 14
#      copyright notice, this list of conditions and the following
15 15
#      disclaimer in the documentation and/or other materials
16 16
#      provided with the distribution.
17
# 
17
#
18 18
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 19
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 20
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
......
27 27
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 28
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 29
# POSSIBILITY OF SUCH DAMAGE.
30
# 
30
#
31 31
# The views and conclusions contained in the software and
32 32
# documentation are those of the authors and should not be
33 33
# interpreted as representing official policies, either expressed
......
35 35

  
36 36
from cStringIO import StringIO
37 37
from errno import (EACCES, EBADF, EINVAL, EISDIR, EIO, ENOENT, ENOTDIR,
38
                    ENOTEMPTY)
38
                   ENOTEMPTY)
39 39
from getpass import getuser
40 40
from stat import S_IFDIR, S_IFREG
41 41
from sys import argv
......
55 55
    def __init__(self, verbose=False):
56 56
        self.verbose = verbose
57 57
        self.client = OOS_Client(get_url(), get_auth(), get_user())
58
    
58

  
59 59
    def __call__(self, op, path, *args):
60 60
        container, sep, object = path[1:].partition('/')
61 61
        if self.verbose:
62 62
            data = repr(args)[:100]
63 63
            print '-> %s %r %r %r' % (op, container, object, data)
64 64
        ret = '[Unhandled Exception]'
65
        
65

  
66 66
        try:
67 67
            if object:
68 68
                func = getattr(self, 'object_' + op, None)
......
78 78
                # Fallback to defaults
79 79
                func = getattr(self, op)
80 80
                funcargs = (path,) + args
81
            
81

  
82 82
            ret = func(*funcargs)
83 83
            return ret
84 84
        except FuseOSError, e:
......
87 87
        finally:
88 88
            if self.verbose:
89 89
                print '<-', op, repr(ret)
90
    
91
    
90

  
92 91
    def _get_container_meta(self, container, **kwargs):
93 92
        try:
94 93
            return self.client.retrieve_container_metadata(container, **kwargs)
95 94
        except Fault:
96 95
            raise FuseOSError(ENOENT)
97
    
96

  
98 97
    def _get_object_meta(self, container, object, **kwargs):
99 98
        try:
100 99
            return self.client.retrieve_object_metadata(container, object,
101 100
                                                        **kwargs)
102 101
        except Fault:
103 102
            raise FuseOSError(ENOENT)
104
    
105
    
103

  
106 104
    # Global
107
    
108 105
    def statfs(self, path):
109
        return dict(f_bsize=1024, f_blocks=1024**2, f_bfree=1024**2,
110
                    f_bavail=1024**2)
111
    
112
    
106
        return dict(f_bsize=1024, f_blocks=1024 ** 2, f_bfree=1024 ** 2,
107
                    f_bavail=1024 ** 2)
108

  
113 109
    # Account Level
114
    
115 110
    def account_chmod(self, mode):
116 111
        self.client.update_account_metadata(mode=str(mode))
117
    
112

  
118 113
    def account_chown(self, uid, gid):
119 114
        self.client.update_account_metadata(uid=uid, gid=gid)
120
    
115

  
121 116
    def account_getattr(self, fh=None):
122 117
        meta = self.client.retrieve_account_metadata()
123 118
        mode = int(meta.get('x-account-meta-mode', 0755))
......
126 121
        count = int(meta['x-account-container-count'])
127 122
        uid = int(meta.get('x-account-meta-uid', 0))
128 123
        gid = int(meta.get('x-account-meta-gid', 0))
129
        
124

  
130 125
        return {
131 126
            'st_mode': S_IFDIR | mode,
132 127
            'st_nlink': 2 + count,
......
135 130
            'st_ctime': epoch,
136 131
            'st_mtime': modified,
137 132
            'st_atime': modified}
138
    
133

  
139 134
    def account_getxattr(self, name, position=0):
140 135
        meta = self.client.retrieve_account_metadata(restricted=True)
141 136
        return meta.get('xattr-' + name, '')
142
    
137

  
143 138
    def account_listxattr(self):
144 139
        meta = self.client.retrieve_account_metadata(restricted=True)
145 140
        prefix = 'xattr-'
146 141
        return [k[len(prefix):] for k in meta if k.startswith(prefix)]
147
    
142

  
148 143
    def account_readdir(self, fh):
149 144
        return ['.', '..'] + self.client.list_containers() or []
150
    
145

  
151 146
    def account_removexattr(self, name):
152 147
        attr = 'xattr-' + name
153 148
        self.client.delete_account_metadata([attr])
154
    
149

  
155 150
    def account_setxattr(self, name, value, options, position=0):
156 151
        attr = 'xattr-' + name
157 152
        meta = {attr: value}
158 153
        self.client.update_account_metadata(**meta)
159
    
160
    
154

  
161 155
    # Container Level
162
    
163 156
    def container_chmod(self, container, mode):
164 157
        self.client.update_container_metadata(container, mode=str(mode))
165
    
158

  
166 159
    def container_chown(self, container, uid, gid):
167 160
        self.client.update_container_metadata(container, uid=uid, gid=gid)
168
    
161

  
169 162
    def container_getattr(self, container, fh=None):
170 163
        meta = self._get_container_meta(container)
171 164
        mode = int(meta.get('x-container-meta-mode', 0755))
......
173 166
        count = int(meta['x-container-object-count'])
174 167
        uid = int(meta.get('x-account-meta-uid', 0))
175 168
        gid = int(meta.get('x-account-meta-gid', 0))
176
        
169

  
177 170
        return {
178 171
            'st_mode': S_IFDIR | mode,
179 172
            'st_nlink': 2 + count,
......
182 175
            'st_ctime': epoch,
183 176
            'st_mtime': modified,
184 177
            'st_atime': modified}
185
    
178

  
186 179
    def container_getxattr(self, container, name, position=0):
187 180
        meta = self._get_container_meta(container)
188 181
        return meta.get('xattr-' + name, '')
189
    
182

  
190 183
    def container_listxattr(self, container):
191 184
        meta = self._get_container_meta(container, restricted=True)
192 185
        prefix = 'xattr-'
193 186
        return [k[len(prefix):] for k in meta if k.startswith(prefix)]
194
    
187

  
195 188
    def container_mkdir(self, container, mode):
196 189
        mode = str(mode & 0777)
197 190
        self.client.create_container(container, mode=mode)
198
    
191

  
199 192
    def container_readdir(self, container, fh):
200 193
        objects = self.client.list_objects(container, delimiter='/', prefix='')
201 194
        files = [o for o in objects if not o.endswith('/')]
202 195
        return ['.', '..'] + files
203
    
196

  
204 197
    def container_removexattr(self, container, name):
205 198
        attr = 'xattr-' + name
206 199
        self.client.delete_container_metadata(container, [attr])
207
    
200

  
208 201
    def container_rename(self, container, path):
209 202
        new_container, sep, new_object = path[1:].partition('/')
210 203
        if not new_container or new_object:
211 204
            raise FuseOSError(EINVAL)
212 205
        self.client.delete_container(container)
213 206
        self.client.create_container(new_container)
214
    
207

  
215 208
    def container_rmdir(self, container):
216 209
        try:
217 210
            self.client.delete_container(container)
218 211
        except Fault:
219 212
            raise FuseOSError(ENOENT)
220
    
213

  
221 214
    def container_setxattr(self, container, name, value, options, position=0):
222 215
        attr = 'xattr-' + name
223 216
        meta = {attr: value}
224 217
        self.client.update_container_metadata(container, **meta)
225
    
226
    
218

  
227 219
    # Object Level
228
    
229 220
    def object_chmod(self, container, object, mode):
230 221
        self.client.update_object_metadata(container, object, mode=str(mode))
231
    
222

  
232 223
    def object_chown(self, container, uid, gid):
233 224
        self.client.update_object_metadata(container, object,
234
                                            uid=str(uid), gid=str(gid))
235
    
225
                                           uid=str(uid), gid=str(gid))
226

  
236 227
    def object_create(self, container, object, mode, fi=None):
237 228
        mode &= 0777
238 229
        self.client.create_object(container, object,
239
                                    f=None,
240
                                    content_type='application/octet-stream',
241
                                    mode=str(mode))
230
                                  f=None,
231
                                  content_type='application/octet-stream',
232
                                  mode=str(mode))
242 233
        return 0
243
    
234

  
244 235
    def object_getattr(self, container, object, fh=None):
245 236
        meta = self._get_object_meta(container, object)
246 237
        modified = parse_http_date(meta['last-modified'])
247 238
        uid = int(meta.get('x-account-meta-uid', 0))
248 239
        gid = int(meta.get('x-account-meta-gid', 0))
249 240
        size = int(meta.get('content-length', 0))
250
        
241

  
251 242
        if meta['content-type'].split(';', 1)[0].strip() == 'application/directory':
252 243
            mode = int(meta.get('x-object-meta-mode', 0755))
253 244
            flags = S_IFDIR
......
256 247
            mode = int(meta.get('x-object-meta-mode', 0644))
257 248
            flags = S_IFREG
258 249
            nlink = 1
259
        
250

  
260 251
        return {
261 252
            'st_mode': flags | mode,
262 253
            'st_nlink': nlink,
......
266 257
            'st_mtime': modified,
267 258
            'st_atime': modified,
268 259
            'st_size': size}
269
    
260

  
270 261
    def object_getxattr(self, container, object, name, position=0):
271 262
        meta = self._get_object_meta(container, object, restricted=True)
272 263
        return meta.get('xattr-' + name, '')
273
    
264

  
274 265
    def object_listxattr(self, container, object):
275 266
        meta = self._get_object_meta(container, object, restricted=True)
276 267
        prefix = 'xattr-'
277 268
        return [k[len(prefix):] for k in meta if k.startswith(prefix)]
278
    
269

  
279 270
    def object_mkdir(self, container, object, mode):
280 271
        mode = str(mode & 0777)
281 272
        self.client.create_directory_marker(container, object)
282 273
        self.client.update_object_metadata(container, object, mode=mode)
283
    
274

  
284 275
    def object_read(self, container, object, nbyte, offset, fh):
285 276
        data = self.client.retrieve_object(container, object)
286 277
        return data[offset:offset + nbyte]
287
    
278

  
288 279
    def object_readdir(self, container, object, fh):
289 280
        objects = self.client.list_objects(container, delimiter='/',
290
                                            prefix=object)
281
                                           prefix=object)
291 282
        files = [o.rpartition('/')[2] for o in objects if not o.endswith('/')]
292 283
        return ['.', '..'] + files
293
    
284

  
294 285
    def object_removexattr(self, container, object, name):
295 286
        attr = 'xattr-' + name
296 287
        self.client.delete_object_metadata(container, object, [attr])
297
    
288

  
298 289
    def object_rename(self, container, object, path):
299 290
        new_container, sep, new_object = path[1:].partition('/')
300 291
        if not new_container or not new_object:
301 292
            raise FuseOSError(EINVAL)
302 293
        self.client.move_object(container, object, new_container, new_object)
303
    
294

  
304 295
    def object_rmdir(self, container, object):
305 296
        self.client.delete_object(container, object)
306
    
297

  
307 298
    def object_setxattr(self, container, object, name, value, options,
308 299
                        position=0):
309 300
        attr = 'xattr-' + name
310 301
        meta = {attr: value}
311 302
        self.client.update_object_metadata(container, object, **meta)
312
    
303

  
313 304
    def object_truncate(self, container, object, length, fh=None):
314 305
        data = self.client.retrieve_object(container, object)
315 306
        f = StringIO(data[:length])
316 307
        self.client.update_object(container, object, f)
317
    
308

  
318 309
    def object_unlink(self, container, object):
319 310
        self.client.delete_object(container, object)
320
    
311

  
321 312
    def object_write(self, container, object, data, offset, fh):
322 313
        f = StringIO(data)
323 314
        self.client.update_object(container, object, f, offset=offset)
......
328 319
    if len(argv) != 2:
329 320
        print 'usage: %s <mountpoint>' % argv[0]
330 321
        exit(1)
331
    
322

  
332 323
    user = getuser()
333 324
    fs = StoreFS(verbose=True)
334 325
    fuse = FUSE(fs, argv[1], foreground=True)
......
336 327

  
337 328
if __name__ == '__main__':
338 329
    main()
339

  

Also available in: Unified diff