Statistics
| Branch: | Tag: | Revision:

root / tools / storefs.py @ 75453cf2

History | View | Annotate | Download (12.1 kB)

1 51f905a2 Giorgos Verigakis
#!/usr/bin/env python
2 51f905a2 Giorgos Verigakis
3 51f905a2 Giorgos Verigakis
# Copyright 2011 GRNET S.A. All rights reserved.
4 51f905a2 Giorgos Verigakis
# 
5 51f905a2 Giorgos Verigakis
# Redistribution and use in source and binary forms, with or
6 51f905a2 Giorgos Verigakis
# without modification, are permitted provided that the following
7 51f905a2 Giorgos Verigakis
# conditions are met:
8 51f905a2 Giorgos Verigakis
# 
9 51f905a2 Giorgos Verigakis
#   1. Redistributions of source code must retain the above
10 51f905a2 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
11 51f905a2 Giorgos Verigakis
#      disclaimer.
12 51f905a2 Giorgos Verigakis
# 
13 51f905a2 Giorgos Verigakis
#   2. Redistributions in binary form must reproduce the above
14 51f905a2 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
15 51f905a2 Giorgos Verigakis
#      disclaimer in the documentation and/or other materials
16 51f905a2 Giorgos Verigakis
#      provided with the distribution.
17 51f905a2 Giorgos Verigakis
# 
18 51f905a2 Giorgos Verigakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 51f905a2 Giorgos Verigakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 51f905a2 Giorgos Verigakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 51f905a2 Giorgos Verigakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 51f905a2 Giorgos Verigakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 51f905a2 Giorgos Verigakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 51f905a2 Giorgos Verigakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 51f905a2 Giorgos Verigakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 51f905a2 Giorgos Verigakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 51f905a2 Giorgos Verigakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 51f905a2 Giorgos Verigakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 51f905a2 Giorgos Verigakis
# POSSIBILITY OF SUCH DAMAGE.
30 51f905a2 Giorgos Verigakis
# 
31 51f905a2 Giorgos Verigakis
# The views and conclusions contained in the software and
32 51f905a2 Giorgos Verigakis
# documentation are those of the authors and should not be
33 51f905a2 Giorgos Verigakis
# interpreted as representing official policies, either expressed
34 51f905a2 Giorgos Verigakis
# or implied, of GRNET S.A.
35 51f905a2 Giorgos Verigakis
36 51f905a2 Giorgos Verigakis
from cStringIO import StringIO
37 51f905a2 Giorgos Verigakis
from errno import (EACCES, EBADF, EINVAL, EISDIR, EIO, ENOENT, ENOTDIR,
38 51f905a2 Giorgos Verigakis
                    ENOTEMPTY)
39 51f905a2 Giorgos Verigakis
from getpass import getuser
40 51f905a2 Giorgos Verigakis
from stat import S_IFDIR, S_IFREG
41 51f905a2 Giorgos Verigakis
from sys import argv
42 51f905a2 Giorgos Verigakis
from time import time
43 51f905a2 Giorgos Verigakis
44 51f905a2 Giorgos Verigakis
from pithos.api.compat import parse_http_date
45 71c0f614 Giorgos Verigakis
from pithos.lib.client import OOS_Client, Fault
46 51f905a2 Giorgos Verigakis
from pithos.lib.fuse import FUSE, FuseOSError, Operations
47 51f905a2 Giorgos Verigakis
48 51f905a2 Giorgos Verigakis
DEFAULT_HOST = 'pithos.dev.grnet.gr'
49 51f905a2 Giorgos Verigakis
50 51f905a2 Giorgos Verigakis
51 51f905a2 Giorgos Verigakis
epoch = int(time())
52 51f905a2 Giorgos Verigakis
53 51f905a2 Giorgos Verigakis
54 51f905a2 Giorgos Verigakis
class StoreFS(Operations):
55 71c0f614 Giorgos Verigakis
    def __init__(self, user, token, verbose=False):
56 51f905a2 Giorgos Verigakis
        self.verbose = verbose
57 71c0f614 Giorgos Verigakis
        self.client = OOS_Client(DEFAULT_HOST, token, user)
58 51f905a2 Giorgos Verigakis
    
59 51f905a2 Giorgos Verigakis
    def __call__(self, op, path, *args):
60 51f905a2 Giorgos Verigakis
        container, sep, object = path[1:].partition('/')
61 51f905a2 Giorgos Verigakis
        if self.verbose:
62 51f905a2 Giorgos Verigakis
            data = repr(args)[:100]
63 51f905a2 Giorgos Verigakis
            print '-> %s %r %r %r' % (op, container, object, data)
64 51f905a2 Giorgos Verigakis
        ret = '[Unhandled Exception]'
65 51f905a2 Giorgos Verigakis
        
66 51f905a2 Giorgos Verigakis
        try:
67 51f905a2 Giorgos Verigakis
            if object:
68 71c0f614 Giorgos Verigakis
                func = getattr(self, 'object_' + op, None)
69 71c0f614 Giorgos Verigakis
                funcargs = (container, object) + args
70 51f905a2 Giorgos Verigakis
            elif container:
71 71c0f614 Giorgos Verigakis
                func = getattr(self, 'container_' + op, None)
72 71c0f614 Giorgos Verigakis
                funcargs = (container,) + args
73 51f905a2 Giorgos Verigakis
            else:
74 71c0f614 Giorgos Verigakis
                func = getattr(self, 'account_' + op, None)
75 71c0f614 Giorgos Verigakis
                funcargs = args
76 71c0f614 Giorgos Verigakis
77 71c0f614 Giorgos Verigakis
            if not func:
78 71c0f614 Giorgos Verigakis
                # Fallback to defaults
79 71c0f614 Giorgos Verigakis
                func = getattr(self, op)
80 71c0f614 Giorgos Verigakis
                funcargs = (path,) + args
81 71c0f614 Giorgos Verigakis
            
82 71c0f614 Giorgos Verigakis
            ret = func(*funcargs)
83 51f905a2 Giorgos Verigakis
            return ret
84 51f905a2 Giorgos Verigakis
        except FuseOSError, e:
85 51f905a2 Giorgos Verigakis
            ret = str(e)
86 51f905a2 Giorgos Verigakis
            raise
87 51f905a2 Giorgos Verigakis
        finally:
88 51f905a2 Giorgos Verigakis
            if self.verbose:
89 51f905a2 Giorgos Verigakis
                print '<-', op, repr(ret)
90 51f905a2 Giorgos Verigakis
    
91 51f905a2 Giorgos Verigakis
    
92 51f905a2 Giorgos Verigakis
    def _get_container_meta(self, container, **kwargs):
93 51f905a2 Giorgos Verigakis
        try:
94 51f905a2 Giorgos Verigakis
            return self.client.retrieve_container_metadata(container, **kwargs)
95 51f905a2 Giorgos Verigakis
        except Fault:
96 51f905a2 Giorgos Verigakis
            raise FuseOSError(ENOENT)
97 51f905a2 Giorgos Verigakis
    
98 51f905a2 Giorgos Verigakis
    def _get_object_meta(self, container, object, **kwargs):
99 51f905a2 Giorgos Verigakis
        try:
100 51f905a2 Giorgos Verigakis
            return self.client.retrieve_object_metadata(container, object,
101 51f905a2 Giorgos Verigakis
                                                        **kwargs)
102 51f905a2 Giorgos Verigakis
        except Fault:
103 51f905a2 Giorgos Verigakis
            raise FuseOSError(ENOENT)
104 51f905a2 Giorgos Verigakis
    
105 51f905a2 Giorgos Verigakis
    
106 51f905a2 Giorgos Verigakis
    # Global
107 51f905a2 Giorgos Verigakis
    
108 51f905a2 Giorgos Verigakis
    def statfs(self, path):
109 51f905a2 Giorgos Verigakis
        return dict(f_bsize=1024, f_blocks=1024**2, f_bfree=1024**2,
110 51f905a2 Giorgos Verigakis
                    f_bavail=1024**2)
111 51f905a2 Giorgos Verigakis
    
112 51f905a2 Giorgos Verigakis
    
113 51f905a2 Giorgos Verigakis
    # Account Level
114 51f905a2 Giorgos Verigakis
    
115 51f905a2 Giorgos Verigakis
    def account_chmod(self, mode):
116 71c0f614 Giorgos Verigakis
        self.client.update_account_metadata(mode=str(mode))
117 51f905a2 Giorgos Verigakis
    
118 51f905a2 Giorgos Verigakis
    def account_chown(self, uid, gid):
119 51f905a2 Giorgos Verigakis
        self.client.update_account_metadata(uid=uid, gid=gid)
120 51f905a2 Giorgos Verigakis
    
121 51f905a2 Giorgos Verigakis
    def account_getattr(self, fh=None):
122 71c0f614 Giorgos Verigakis
        meta = self.client.retrieve_account_metadata()
123 51f905a2 Giorgos Verigakis
        mode = int(meta.get('x-account-meta-mode', 0755))
124 71c0f614 Giorgos Verigakis
        last_modified = meta.get('last-modified', None)
125 71c0f614 Giorgos Verigakis
        modified = parse_http_date(last_modified) if last_modified else epoch
126 51f905a2 Giorgos Verigakis
        count = int(meta['x-account-container-count'])
127 51f905a2 Giorgos Verigakis
        uid = int(meta.get('x-account-meta-uid', 0))
128 51f905a2 Giorgos Verigakis
        gid = int(meta.get('x-account-meta-gid', 0))
129 51f905a2 Giorgos Verigakis
        
130 51f905a2 Giorgos Verigakis
        return {
131 51f905a2 Giorgos Verigakis
            'st_mode': S_IFDIR | mode,
132 51f905a2 Giorgos Verigakis
            'st_nlink': 2 + count,
133 51f905a2 Giorgos Verigakis
            'st_uid': uid,
134 51f905a2 Giorgos Verigakis
            'st_gid': gid,
135 51f905a2 Giorgos Verigakis
            'st_ctime': epoch,
136 51f905a2 Giorgos Verigakis
            'st_mtime': modified,
137 51f905a2 Giorgos Verigakis
            'st_atime': modified}
138 51f905a2 Giorgos Verigakis
    
139 51f905a2 Giorgos Verigakis
    def account_getxattr(self, name, position=0):
140 51f905a2 Giorgos Verigakis
        meta = self.client.retrieve_account_metadata(restricted=True)
141 51f905a2 Giorgos Verigakis
        return meta.get('xattr-' + name, '')
142 51f905a2 Giorgos Verigakis
    
143 51f905a2 Giorgos Verigakis
    def account_listxattr(self):
144 51f905a2 Giorgos Verigakis
        meta = self.client.retrieve_account_metadata(restricted=True)
145 51f905a2 Giorgos Verigakis
        prefix = 'xattr-'
146 51f905a2 Giorgos Verigakis
        return [k[len(prefix):] for k in meta if k.startswith(prefix)]
147 51f905a2 Giorgos Verigakis
    
148 51f905a2 Giorgos Verigakis
    def account_readdir(self, fh):
149 51f905a2 Giorgos Verigakis
        return ['.', '..'] + self.client.list_containers()
150 51f905a2 Giorgos Verigakis
    
151 51f905a2 Giorgos Verigakis
    def account_removexattr(self, name):
152 51f905a2 Giorgos Verigakis
        attr = 'xattr-' + name
153 51f905a2 Giorgos Verigakis
        self.client.delete_account_metadata([attr])
154 51f905a2 Giorgos Verigakis
    
155 51f905a2 Giorgos Verigakis
    def account_setxattr(self, name, value, options, position=0):
156 51f905a2 Giorgos Verigakis
        attr = 'xattr-' + name
157 51f905a2 Giorgos Verigakis
        meta = {attr: value}
158 51f905a2 Giorgos Verigakis
        self.client.update_account_metadata(**meta)
159 51f905a2 Giorgos Verigakis
    
160 51f905a2 Giorgos Verigakis
    
161 51f905a2 Giorgos Verigakis
    # Container Level
162 51f905a2 Giorgos Verigakis
    
163 51f905a2 Giorgos Verigakis
    def container_chmod(self, container, mode):
164 71c0f614 Giorgos Verigakis
        self.client.update_container_metadata(container, mode=str(mode))
165 51f905a2 Giorgos Verigakis
    
166 51f905a2 Giorgos Verigakis
    def container_chown(self, container, uid, gid):
167 51f905a2 Giorgos Verigakis
        self.client.update_container_metadata(container, uid=uid, gid=gid)
168 51f905a2 Giorgos Verigakis
    
169 51f905a2 Giorgos Verigakis
    def container_getattr(self, container, fh=None):
170 51f905a2 Giorgos Verigakis
        meta = self._get_container_meta(container)
171 51f905a2 Giorgos Verigakis
        mode = int(meta.get('x-container-meta-mode', 0755))
172 51f905a2 Giorgos Verigakis
        modified = parse_http_date(meta['last-modified'])
173 51f905a2 Giorgos Verigakis
        count = int(meta['x-container-object-count'])
174 51f905a2 Giorgos Verigakis
        uid = int(meta.get('x-account-meta-uid', 0))
175 51f905a2 Giorgos Verigakis
        gid = int(meta.get('x-account-meta-gid', 0))
176 51f905a2 Giorgos Verigakis
        
177 51f905a2 Giorgos Verigakis
        return {
178 51f905a2 Giorgos Verigakis
            'st_mode': S_IFDIR | mode,
179 51f905a2 Giorgos Verigakis
            'st_nlink': 2 + count,
180 51f905a2 Giorgos Verigakis
            'st_uid': uid,
181 51f905a2 Giorgos Verigakis
            'st_gid': gid,
182 51f905a2 Giorgos Verigakis
            'st_ctime': epoch,
183 51f905a2 Giorgos Verigakis
            'st_mtime': modified,
184 51f905a2 Giorgos Verigakis
            'st_atime': modified}
185 51f905a2 Giorgos Verigakis
    
186 51f905a2 Giorgos Verigakis
    def container_getxattr(self, container, name, position=0):
187 51f905a2 Giorgos Verigakis
        meta = self._get_container_meta(container)
188 51f905a2 Giorgos Verigakis
        return meta.get('xattr-' + name, '')
189 51f905a2 Giorgos Verigakis
    
190 51f905a2 Giorgos Verigakis
    def container_listxattr(self, container):
191 51f905a2 Giorgos Verigakis
        meta = self._get_container_meta(container, restricted=True)
192 51f905a2 Giorgos Verigakis
        prefix = 'xattr-'
193 51f905a2 Giorgos Verigakis
        return [k[len(prefix):] for k in meta if k.startswith(prefix)]
194 51f905a2 Giorgos Verigakis
    
195 51f905a2 Giorgos Verigakis
    def container_mkdir(self, container, mode):
196 71c0f614 Giorgos Verigakis
        mode = str(mode & 0777)
197 71c0f614 Giorgos Verigakis
        self.client.create_container(container, mode=mode)
198 51f905a2 Giorgos Verigakis
    
199 51f905a2 Giorgos Verigakis
    def container_readdir(self, container, fh):
200 51f905a2 Giorgos Verigakis
        params = {'delimiter': '/', 'prefix': ''}
201 51f905a2 Giorgos Verigakis
        objects = self.client.list_objects(container, params=params)
202 51f905a2 Giorgos Verigakis
        files = [o for o in objects if not o.endswith('/')]
203 51f905a2 Giorgos Verigakis
        return ['.', '..'] + files
204 51f905a2 Giorgos Verigakis
    
205 51f905a2 Giorgos Verigakis
    def container_removexattr(self, container, name):
206 51f905a2 Giorgos Verigakis
        attr = 'xattr-' + name
207 51f905a2 Giorgos Verigakis
        self.client.delete_container_metadata(container, [attr])
208 51f905a2 Giorgos Verigakis
    
209 51f905a2 Giorgos Verigakis
    def container_rename(self, container, path):
210 51f905a2 Giorgos Verigakis
        new_container, sep, new_object = path[1:].partition('/')
211 51f905a2 Giorgos Verigakis
        if not new_container or new_object:
212 51f905a2 Giorgos Verigakis
            raise FuseOSError(EINVAL)
213 51f905a2 Giorgos Verigakis
        self.client.delete_container(container)
214 51f905a2 Giorgos Verigakis
        self.client.create_container(new_container)
215 51f905a2 Giorgos Verigakis
    
216 51f905a2 Giorgos Verigakis
    def container_rmdir(self, container):
217 51f905a2 Giorgos Verigakis
        try:
218 51f905a2 Giorgos Verigakis
            self.client.delete_container(container)
219 51f905a2 Giorgos Verigakis
        except Fault:
220 51f905a2 Giorgos Verigakis
            raise FuseOSError(ENOENT)
221 51f905a2 Giorgos Verigakis
    
222 51f905a2 Giorgos Verigakis
    def container_setxattr(self, container, name, value, options, position=0):
223 51f905a2 Giorgos Verigakis
        attr = 'xattr-' + name
224 51f905a2 Giorgos Verigakis
        meta = {attr: value}
225 51f905a2 Giorgos Verigakis
        self.client.update_container_metadata(container, **meta)
226 51f905a2 Giorgos Verigakis
    
227 51f905a2 Giorgos Verigakis
    
228 51f905a2 Giorgos Verigakis
    # Object Level
229 51f905a2 Giorgos Verigakis
    
230 51f905a2 Giorgos Verigakis
    def object_chmod(self, container, object, mode):
231 71c0f614 Giorgos Verigakis
        self.client.update_object_metadata(container, object, mode=str(mode))
232 51f905a2 Giorgos Verigakis
    
233 51f905a2 Giorgos Verigakis
    def object_chown(self, container, uid, gid):
234 71c0f614 Giorgos Verigakis
        self.client.update_object_metadata(container, object,
235 71c0f614 Giorgos Verigakis
                                            uid=str(uid), gid=str(gid))
236 51f905a2 Giorgos Verigakis
    
237 51f905a2 Giorgos Verigakis
    def object_create(self, container, object, mode, fi=None):
238 51f905a2 Giorgos Verigakis
        mode &= 0777
239 71c0f614 Giorgos Verigakis
        self.client.create_object(container, object,
240 71c0f614 Giorgos Verigakis
                                    f=None,
241 71c0f614 Giorgos Verigakis
                                    content_type='application/octet-stream',
242 71c0f614 Giorgos Verigakis
                                    mode=str(mode))
243 51f905a2 Giorgos Verigakis
        return 0
244 51f905a2 Giorgos Verigakis
    
245 51f905a2 Giorgos Verigakis
    def object_getattr(self, container, object, fh=None):
246 51f905a2 Giorgos Verigakis
        meta = self._get_object_meta(container, object)
247 51f905a2 Giorgos Verigakis
        mode = int(meta.get('x-object-meta-mode', 0644))
248 51f905a2 Giorgos Verigakis
        modified = parse_http_date(meta['last-modified'])
249 51f905a2 Giorgos Verigakis
        uid = int(meta.get('x-account-meta-uid', 0))
250 51f905a2 Giorgos Verigakis
        gid = int(meta.get('x-account-meta-gid', 0))
251 51f905a2 Giorgos Verigakis
        size = int(meta['content-length'])
252 51f905a2 Giorgos Verigakis
        
253 51f905a2 Giorgos Verigakis
        if meta['content-type'] == 'application/directory':
254 51f905a2 Giorgos Verigakis
            flags = S_IFDIR
255 51f905a2 Giorgos Verigakis
            nlink = 2
256 51f905a2 Giorgos Verigakis
        else:
257 51f905a2 Giorgos Verigakis
            flags = S_IFREG
258 51f905a2 Giorgos Verigakis
            nlink = 1
259 51f905a2 Giorgos Verigakis
        
260 51f905a2 Giorgos Verigakis
        return {
261 51f905a2 Giorgos Verigakis
            'st_mode': flags | mode,
262 51f905a2 Giorgos Verigakis
            'st_nlink': nlink,
263 51f905a2 Giorgos Verigakis
            'st_uid': uid,
264 51f905a2 Giorgos Verigakis
            'st_gid': gid,
265 51f905a2 Giorgos Verigakis
            'st_ctime': epoch,
266 51f905a2 Giorgos Verigakis
            'st_mtime': modified,
267 51f905a2 Giorgos Verigakis
            'st_atime': modified,
268 51f905a2 Giorgos Verigakis
            'st_size': size}
269 51f905a2 Giorgos Verigakis
    
270 51f905a2 Giorgos Verigakis
    def object_getxattr(self, container, object, name, position=0):
271 51f905a2 Giorgos Verigakis
        meta = self._get_object_meta(container, object, restricted=True)
272 51f905a2 Giorgos Verigakis
        return meta.get('xattr-' + name, '')
273 51f905a2 Giorgos Verigakis
    
274 51f905a2 Giorgos Verigakis
    def object_listxattr(self, container, object):
275 51f905a2 Giorgos Verigakis
        meta = self._get_object_meta(container, object, restricted=True)
276 51f905a2 Giorgos Verigakis
        prefix = 'xattr-'
277 51f905a2 Giorgos Verigakis
        return [k[len(prefix):] for k in meta if k.startswith(prefix)]
278 51f905a2 Giorgos Verigakis
    
279 51f905a2 Giorgos Verigakis
    def object_mkdir(self, container, object, mode):
280 71c0f614 Giorgos Verigakis
        mode = str(mode & 0777)
281 51f905a2 Giorgos Verigakis
        self.client.create_directory_marker(container, object)
282 51f905a2 Giorgos Verigakis
        self.client.update_object_metadata(container, object, mode=mode)
283 51f905a2 Giorgos Verigakis
    
284 51f905a2 Giorgos Verigakis
    def object_read(self, container, object, nbyte, offset, fh):
285 51f905a2 Giorgos Verigakis
        data = self.client.retrieve_object(container, object)
286 51f905a2 Giorgos Verigakis
        return data[offset:offset + nbyte]
287 51f905a2 Giorgos Verigakis
    
288 51f905a2 Giorgos Verigakis
    def object_readdir(self, container, object, fh):
289 51f905a2 Giorgos Verigakis
        params = {'delimiter': '/', 'prefix': object}
290 51f905a2 Giorgos Verigakis
        objects = self.client.list_objects(container, params=params)
291 51f905a2 Giorgos Verigakis
        files = [o.rpartition('/')[2] for o in objects if not o.endswith('/')]
292 51f905a2 Giorgos Verigakis
        return ['.', '..'] + files
293 51f905a2 Giorgos Verigakis
    
294 51f905a2 Giorgos Verigakis
    def object_removexattr(self, container, object, name):
295 51f905a2 Giorgos Verigakis
        attr = 'xattr-' + name
296 51f905a2 Giorgos Verigakis
        self.client.delete_object_metadata(container, object, [attr])
297 51f905a2 Giorgos Verigakis
    
298 51f905a2 Giorgos Verigakis
    def object_rename(self, container, object, path):
299 51f905a2 Giorgos Verigakis
        new_container, sep, new_object = path[1:].partition('/')
300 51f905a2 Giorgos Verigakis
        if not new_container or not new_object:
301 51f905a2 Giorgos Verigakis
            raise FuseOSError(EINVAL)
302 51f905a2 Giorgos Verigakis
        self.client.move_object(container, object, new_container, new_object)
303 51f905a2 Giorgos Verigakis
    
304 51f905a2 Giorgos Verigakis
    def object_rmdir(self, container, object):
305 51f905a2 Giorgos Verigakis
        self.client.delete_object(container, object)
306 51f905a2 Giorgos Verigakis
    
307 51f905a2 Giorgos Verigakis
    def object_setxattr(self, container, object, name, value, options,
308 51f905a2 Giorgos Verigakis
                        position=0):
309 51f905a2 Giorgos Verigakis
        attr = 'xattr-' + name
310 51f905a2 Giorgos Verigakis
        meta = {attr: value}
311 51f905a2 Giorgos Verigakis
        self.client.update_object_metadata(container, object, **meta)
312 51f905a2 Giorgos Verigakis
    
313 51f905a2 Giorgos Verigakis
    def object_truncate(self, container, object, length, fh=None):
314 51f905a2 Giorgos Verigakis
        data = self.client.retrieve_object(container, object)
315 51f905a2 Giorgos Verigakis
        f = StringIO(data[:length])
316 51f905a2 Giorgos Verigakis
        self.client.update_object(container, object, f)
317 51f905a2 Giorgos Verigakis
    
318 51f905a2 Giorgos Verigakis
    def object_unlink(self, container, object):
319 51f905a2 Giorgos Verigakis
        self.client.delete_object(container, object)
320 51f905a2 Giorgos Verigakis
    
321 51f905a2 Giorgos Verigakis
    def object_write(self, container, object, data, offset, fh):
322 51f905a2 Giorgos Verigakis
        f = StringIO(data)
323 71c0f614 Giorgos Verigakis
        self.client.update_object(container, object, f, offset=offset)
324 51f905a2 Giorgos Verigakis
        return len(data)
325 51f905a2 Giorgos Verigakis
326 51f905a2 Giorgos Verigakis
327 51f905a2 Giorgos Verigakis
if __name__ == "__main__":
328 71c0f614 Giorgos Verigakis
    if len(argv) != 4:
329 71c0f614 Giorgos Verigakis
        print 'usage: %s <user> <token> <mountpoint>' % argv[0]
330 51f905a2 Giorgos Verigakis
        exit(1)
331 51f905a2 Giorgos Verigakis
    
332 51f905a2 Giorgos Verigakis
    user = getuser()
333 71c0f614 Giorgos Verigakis
    fs = StoreFS(argv[1], argv[2], verbose=True)
334 71c0f614 Giorgos Verigakis
    fuse = FUSE(fs, argv[3], foreground=True)