Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/bareos/python-bareos.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoerg Steffens <joerg.steffens@dass-it.de>2015-09-06 23:26:04 +0300
committerJoerg Steffens <joerg.steffens@dass-it.de>2015-09-07 11:57:26 +0300
commit505701598f4b6816b90e37daa6432e39e4dcd235 (patch)
tree81d92205e4ba49195b1c6cd49788986cc80f60ea
parent418408f96dc9f0f883864fe86bce327ab98520cf (diff)
bareos-fuse: first tries
-rw-r--r--bareos/bareosfuse.py208
-rwxr-xr-xbin/bareos-fuse.py71
2 files changed, 279 insertions, 0 deletions
diff --git a/bareos/bareosfuse.py b/bareos/bareosfuse.py
new file mode 100644
index 0000000..a5d56cd
--- /dev/null
+++ b/bareos/bareosfuse.py
@@ -0,0 +1,208 @@
+"""
+"""
+
+#import bareos.bsock
+from bareos.bsock import BSockJson
+import errno
+import fuse
+import logging
+import os
+from pprint import pformat
+import stat
+
+fuse.fuse_python_api = (0, 2)
+
+TYPE_NONE = None
+TYPE_FILE = 1
+TYPE_DIR = 2
+
+
+class Base():
+ def __init__(self, bsock):
+ self.logger = logging.getLogger()
+ self.bsock = bsock
+ self.defaultdirs = [ ".", ".." ]
+
+
+class Jobs(Base):
+
+ def getattr(self, path):
+ self.logger.debug("Jobs \"%s\"" % (path))
+ result = -errno.ENOENT
+ st = fuse.Stat()
+ part = path.split("/")
+ if len(part) == 1:
+ if part[0] == "":
+ st.st_mode = stat.S_IFDIR | 0755
+ #st.st_size = 4096
+ number_entires = len(self.bsock.call("list jobs")['jobs'])
+ st.st_nlink = len(self.defaultdirs) + 1
+ result = st
+ else:
+ st.st_mode = stat.S_IFDIR | 0755
+ #st.st_size = 4096
+ st.st_nlink = len(self.defaultdirs) + 1
+ result = st
+ elif len(part) == 2:
+ if part[1] == "":
+ st.st_mode = stat.S_IFDIR | 0755
+ #st.st_size = 4096
+ st.st_nlink = len(self.defaultdirs) + 1
+ result = st
+ elif part[1] == ".bareos-jobinfo":
+ st.st_mode = stat.S_IFREG | 0444
+ st.st_nlink = 1
+ st.st_size = 0
+ result = st
+ self.logger.debug("Jobs \"%s\": nlink: %s" % (path, str(st.st_nlink)))
+ return result
+
+ def readdir(self, path, offset):
+ splitted = os.path.split(path)
+ # copy default dirs
+ dirs = list(self.defaultdirs)
+ if path == "":
+ # TODO: only successful
+ data = self.bsock.call("llist jobs")
+ #self.logger.debug(data)
+ dirs.extend([ str(d['jobid']) for d in data['jobs'] ])
+ self.logger.debug("Jobs: \"%s\": %s" % (path, dirs))
+ elif splitted[0] == "" or splitted[1] == 0:
+ dirs.append( ".bareos-jobinfo" )
+ return dirs
+
+
+class FuseCache():
+ """
+ jobs/
+ <jobid>
+ """
+
+ def __init__(self, bsock):
+ self.logger = logging.getLogger()
+ self.bsock = bsock
+ self.jobs = Jobs(bsock)
+ self.path = {
+ '': { 'type': TYPE_DIR, 'dirs': [ ".", "..", "jobs" ], 'files': [] },
+ }
+
+ def get_type(self, path):
+ if self.path.has_key(path):
+ return self.path[path]['type']
+
+ def is_file(self, path):
+ return self.get_type(path) == TYPE_FILE
+
+ def is_directory(self, path):
+ return self.get_type(path) == TYPE_DIR
+
+ def exists(self, path):
+ return self.path.has_key(path)
+
+ def get_nlink(self, path):
+ if self.exists(path):
+ return len(self.path[path]['dirs'])
+ else:
+ # TODO: correct?
+ return 2
+
+ def readdir(self, path, offset):
+ entries = None
+ if self.path.has_key(path) and self.path[path]['type'] == TYPE_DIR:
+ entries = self.path[path]['dirs'] + self.path[path]['files']
+ self.logger.debug( "Cache: \"%s\": %s" % (path, entries) )
+ return entries
+
+
+class BareosWrapper():
+ def __init__(self, bsock):
+ self.logger = logging.getLogger()
+ self.jobs = Jobs(bsock)
+ self.cache = FuseCache(bsock)
+
+
+ def getattr(self, path):
+
+ # TODO: may cause problems with filenames that ends with "/"
+ path = path.rstrip( '/' )
+ self.logger.debug( "wrapper: \"%s\"" % (path) )
+
+ if path == "/jobs" or path.startswith("/jobs/"):
+ st = self.jobs.getattr(path.lstrip("/jobs").lstrip("/"))
+ return st
+ else:
+ st = fuse.Stat()
+
+ if self.cache.is_file(path):
+ st.st_mode = stat.S_IFREG | 0444
+ st.st_nlink = 1
+ st.st_size = 0
+ return st
+ elif self.cache.is_directory(path):
+ st.st_mode = stat.S_IFDIR | 0755
+ #if 'dirs' in file:
+ # st.st_nlink = len(file['dirs'])
+ #else:
+ st.st_nlink = self.cache.get_nlink(path)
+ return st
+
+ # TODO: check for existens
+ return -errno.ENOENT
+
+
+ def readdir(self, path, offset):
+ #self.logger.debug( '"' + path + '", offset=' + str(offset) + ')' )
+
+ # TODO: may cause problems with filenames that ends with "/"
+ path = path.rstrip( '/' )
+
+ if path == "/jobs" or path.startswith("/jobs/"):
+ entries = self.jobs.readdir(path.lstrip("/jobs").lstrip("/"), offset)
+ else:
+ entries = self.cache.readdir(path, offset)
+
+ self.logger.debug( "wrapper: \"%s\": %s" % (path, pformat(entries)) )
+
+ if not entries:
+ return -errno.ENOENT
+ else:
+ return [fuse.Direntry(f) for f in entries]
+
+
+class BareosFuse(fuse.Fuse):
+
+ def __init__(self, *args, **kw):
+ self.logger = logging.getLogger()
+ self.logger.debug('init')
+
+ self.bsock = kw['bsockjson']
+ if not isinstance(self.bsock,BSockJson):
+ raise RuntimeError("parameter bsock")
+ del(kw['bsockjson'])
+ self.bareos = BareosWrapper(self.bsock)
+
+ super(BareosFuse, self).__init__(*args, **kw)
+
+
+ def getattr(self, path):
+ stat = self.bareos.getattr(path)
+ if isinstance(stat, fuse.Stat):
+ self.logger.debug("fuse %s: nlink=%i" % (path, stat.st_nlink))
+ else:
+ self.logger.debug("fuse %s: (int) %i" % (path, stat))
+ return stat
+
+
+ def readdir(self, path, offset):
+ entries = self.bareos.readdir(path, offset)
+ self.logger.debug("fuse %s: %s" % (path, entries))
+ return entries
+
+
+ #def open( self, path, flags ):
+ #logging.debug( "open " + path )
+ #return -errno.ENOENT
+
+ #def read( self, path, length, offset):
+ #logging.debug( "read " + path )
+ #return -errno.ENOENT
diff --git a/bin/bareos-fuse.py b/bin/bareos-fuse.py
new file mode 100755
index 0000000..37ee52b
--- /dev/null
+++ b/bin/bareos-fuse.py
@@ -0,0 +1,71 @@
+#!/usr/bin/python
+
+import argparse
+import bareos.bareosfuse
+import bareos.bsock
+import fuse
+import logging
+import sys
+
+LOG_FILENAME = '/tmp/bareos-fuse-bsock.log'
+
+#def getArguments():
+ #parser = argparse.ArgumentParser(description='Console to Bareos Director.' )
+ #parser.add_argument( '-d', '--debug', action='store_true', help="enable debugging output" )
+ #parser.add_argument( '-p', '--password', help="password to authenticate at Bareos Director" )
+ #parser.add_argument( '--port', default=9101, help="Bareos Director network port" )
+ #parser.add_argument( 'address', default="localhost", help="Bareos Director host" )
+ #parser.add_argument( 'dirname', nargs='?', default=None, help="Bareos Director name" )
+ #args = parser.parse_args()
+ #return args
+
+if __name__ == '__main__':
+ # initialize logging
+ #logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,format="%(asctime)s %(process)5d(%(threadName)s) %(levelname)-7s %(module)s %(funcName)s( %(message)s )")
+ if sys.argv[1] == "--test":
+ logging.basicConfig(level=logging.DEBUG,format="%(levelname)-7s %(module)s %(funcName)s( %(message)s )")
+ else:
+ logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,format="%(asctime)s %(levelname)-7s %(module)s %(funcName)s( %(message)s )")
+ logger = logging.getLogger()
+
+ #args=getArguments()
+ #if args.debug:
+ #logger.setLevel(logging.DEBUG)
+
+ usage = """
+ Bareos Fuse filesystem: displays files from Bareos backups as a (userspace) filesystem.
+ Internaly, it uses the Bareos bconsole.
+
+ """ + fuse.Fuse.fusage
+
+ args = {
+ 'address': "localhost",
+ 'port': 8001,
+ 'password': "RGd7GuCtX+5osHzRoGzJYXkwUpevs2OEMozPOZvbpi4f",
+ }
+
+ password = bareos.bsock.Password(args['password'])
+ director = bareos.bsock.BSockJson(address=args['address'], port=args['port'], password=password)
+
+ if sys.argv[1] == "--test":
+ test = bareos.bareosfuse.BareosWrapper(bsock=director)
+ print test.readdir("", 0)
+ test.getattr("")
+ print test.readdir("/jobs", 0)
+ test.getattr("/jobs")
+ print test.readdir("/NOT", 0)
+ test.getattr("/NOT")
+ else:
+ fs = bareos.bareosfuse.BareosFuse(
+ #version="%prog: " + BAREOS_FUSE_VERSION,
+ usage = usage,
+ # required to let "-s" set single-threaded execution
+ dash_s_do = 'setsingle',
+ bsockjson = director,
+ )
+
+ #server.parser.add_option(mountopt="root", metavar="PATH", default='/',help="mirror filesystem from under PATH [default: %default]")
+ #server.parse(values=server, errex=1)
+ fs.parse()
+
+ fs.main()