A patch to make tahoe-fuse.py work with 0.7.0 plus a howto README.

This commit is contained in:
nejucomo 2008-01-12 17:06:39 -07:00
parent c555f1abb4
commit 7214f2f8b8
2 changed files with 118 additions and 9 deletions

90
contrib/fuse/README Normal file
View File

@ -0,0 +1,90 @@
Welcome to the tahoe fuse interface prototype!
Dependencies:
In addition to a working tahoe installation, this interface depends
on the python-fuse interface. This package is available on Ubuntu
systems as "python-fuse". It is only known to work with ubuntu
package version "2.5-5build1". The latest ubuntu package (version
"1:0.2-pre3-3") appears to not work currently.
Unfortunately this package appears poorly maintained (notice the wildy
different version strings and changing API semantics), so if you know
of a good replacement pythonic fuse interface, please let tahoe-dev know
about it!
Configuration:
Currently tahoe-fuse.py uses the same ~/.tahoe/private/root_dir.cap
file (which is also the CLI default). This is not configurable yet.
Place a directory cap in this file. (Hint: If you can run "tahoe ls"
and see a directory listing, this file is properly configured.)
Commandline:
The usage is "tahoe-fuse.py <mountpoint>". The mount point needs to
be an existing directory which should be empty. (If it's not empty
the contents will be safe, but unavailable while the tahoe-fuse.py
process is mounted there.)
Usage:
To use the interface, use other programs to poke around the
mountpoint. You should be able to see the same contents as you would
by using the CLI or WUI for the same directory cap.
Runtime Behavior Notes:
Read-only:
Only reading a tahoe grid is supported, which is reflected in
the permission modes. With Tahoe 0.7.0, write access should be easier
to implement, but is not yet present.
In-Memory File Caching:
Currently requesting a particular file for read causes the entire file to
be retrieved into tahoe-fuse.py memory before the read operation returns!
This caching is reused for subsequent reads. Beware large files.
When transitioning to a finer-grained fuse api, this caching should be
replaced with straight-forward calls to the wapi. In my opinion, the
Tahoe node should do all the caching tricks, so that extensions such as
tahoe-fuse.py can be simple and thin.
Backgrounding Behavior:
When using the 2.5-5build1 ubuntu package, and no other arguments
besides a mountpoint to tahoe-fuse.py, the process should remain in
the foreground and print debug information. Other python-fuse
versions appear to alter this behavior and may fork the process to
the background and obscure the log output. Bonus points to whomever
discovers the fate of these poor log messages in this case.
"Investigative Logging":
This prototype is designed to aide in further fuse development, so
currently *every* fuse interface call figures out the process from
which the file system request originates, then it figures out that
processes commandline (this uses the /proc file system). This is handy
for interactive inspection of what kinds of behavior invokes which
file system operations, but may not work for you. To disable this
inspection, edit the source and comment out all of the "@debugcall"
[FIXME: double check python ref name] method decorators by inserting a
'#' so it looks like "#@debugcall" (without quotes).
Not-to-spec:
The current version was not implemented according to any spec and
makes quite a few dubious "guesses" for what data to pass the fuse
interface. You may see bizarre values, which may potentialy confuse
any processes visiting the files under the mount point.
Serial, blocking operations:
Most fuse operations result in one or more http calls to the WAPI.
These are serial and blocking (at least for the tested python-fuse
version 2.5-5build1), so access to this file system is quite
inefficient.
Good luck!

View File

@ -58,6 +58,7 @@ fuse.fuse_python_api = (0, 1) # Use the silly path-based api for now.
### Config:
TahoeConfigDir = '~/.tahoe'
MagicDevNumber = 42
UnknownSize = -1
def main(args = sys.argv[1:]):
@ -136,12 +137,21 @@ class TahoeFS (fuse.Fuse):
port = int(port)
self.url = 'http://localhost:%d' % (port,)
def _init_bookmarks(self):
f = open(os.path.join(self.confdir, 'fuse-bookmarks.uri'), 'r')
uri = f.read().strip()
f.close()
self.rootdir = TahoeDir(self.url, uri)
def _init_rootdir(self):
# For now we just use the same default as the CLI:
rootdirfn = os.path.join(self.confdir, 'private', 'root_dir.cap')
try:
f = open(rootdirfn, 'r')
cap = f.read().strip()
f.close()
except EnvironmentError, le:
# FIXME: This user-friendly help message may be platform-dependent because it checks the exception description.
if le.args[1].find('No such file or directory') != -1:
raise SystemExit('%s requires a directory capability in %s, but it was not found.\nPlease see "The CLI" in "docs/using.html".\n' % (sys.argv[0], rootdirfn))
else:
raise le
self.rootdir = TahoeDir(self.url, canonicalize_cap(cap))
def _get_node(self, path):
assert path.startswith('/')
@ -335,7 +345,7 @@ class TahoeNode (object):
class TahoeFile (TahoeNode):
def __init__(self, baseurl, uri):
assert uri.split(':', 2)[1] in ('CHK', 'LIT'), `uri`
#assert uri.split(':', 2)[1] in ('CHK', 'LIT'), `uri` # fails as of 0.7.0
TahoeNode.__init__(self, baseurl, uri)
# nonfuse:
@ -346,7 +356,12 @@ class TahoeFile (TahoeNode):
return 1
def get_size(self):
return self.get_metadata()[1]['size']
rawsize = self.get_metadata()[1]['size']
if type(rawsize) is not int: # FIXME: What about sizes which do not fit in python int?
assert rawsize == u'?', `rawsize`
return UnknownSize
else:
return rawsize
def resolve_path(self, path):
assert type(path) is list
@ -356,7 +371,6 @@ class TahoeFile (TahoeNode):
class TahoeDir (TahoeNode):
def __init__(self, baseurl, uri):
#assert uri.split(':', 2)[1] in ('DIR2', 'DIR2-RO'), `uri`
TahoeNode.__init__(self, baseurl, uri)
self.mode = stat.S_IFDIR | 0500 # Read only directory.
@ -408,6 +422,11 @@ class TahoeDir (TahoeNode):
return c
def canonicalize_cap(cap):
i = cap.find('URI:')
assert i != -1, 'A cap must contain "URI:...", but this does not: ' + cap
return cap[i:]
if __name__ == '__main__':
main()