#!/usr/bin/python import routefs from routes import Mapper from syslog import * from time import time from invirt import database from invirt.config import structs as config class RemConfFS(routefs.RouteFS): """ RemConfFS creates a filesytem for configuring remctl, like this: / |-- acl | |-- machine1 | ... | `-- machinen `-- conf The machine list and the acls are drawn from a database. """ def __init__(self, *args, **kw): """Initialize the filesystem and set it to allow_other access besides the user who mounts the filesystem (i.e. root) """ super(RemConfFS, self).__init__(*args, **kw) self.lasttime = time() self.fuse_args.add("allow_other", True) openlog('sipb-xen-remconffs ', LOG_PID, LOG_DAEMON) syslog(LOG_DEBUG, 'Init complete.') def make_map(self): m = Mapper() m.connect('', controller='getroot') m.connect('acl', controller='getmachines') m.connect('acl/:machine', controller='getacl') m.connect('conf', controller='getconf') return m def getroot(self, **kw): return ['acl', 'conf'] def getacl(self, machine, **kw): """Build the ACL file for a machine """ machine = database.Machine.query().filter_by(name=machine).one() users = [acl.user for acl in machine.acl] return "\n".join(map(self.userToPrinc, users) + ['include /etc/remctl/acl/web', '']) def getconf(self, **kw): """Build the master conf file, with all machines """ return '\n'.join("control %s /usr/sbin/sipb-xen-remote-proxy-control" " /etc/remctl/remconffs/acl/%s" % (machine_name, machine_name) for machine_name in self.getmachines())+'\n' def getmachines(self, **kw): """Get the list of VMs in the database, clearing the cache if it's older than 15 seconds""" if time() - self.lasttime > 15: self.lasttime = time() database.clear_cache() return [machine.name for machine in database.session.query(database.Machine).all()] def userToPrinc(self, user): """Convert Kerberos v4-style names to v5-style and append a default realm if none is specified """ if '@' in user: (princ, realm) = user.split('@') else: princ = user realm = config.authn[0].realm return princ.replace('.', '/') + '@' + realm if __name__ == '__main__': database.connect() routefs.main(RemConfFS)