#!/usr/bin/python import routefs from routes import Mapper from syslog import * from time import time import sqlalchemy as sa from invirt import database from invirt.config import structs as config class RemConfFS(routefs.RouteFS): """ RemConfFS creates a filesytem for configuring remctl, like this: / |-- adminacl |-- 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.fuse_args.add("allow_other", True) openlog('invirt-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('adminacl', controller='getadmin') m.connect('conf', controller='getconf') return m def getroot(self, **kw): return ['adminacl', 'acl', 'conf'] def getacl(self, machine, **kw): """Build the ACL file for a machine """ s = sa.sql.select([database.machine_access_table.c.user], # Field to select from sa.sql.and_( # where clause database.machine_table.c.machine_id==database.machine_access_table.c.machine_id, # join field database.machine_table.c.name == machine), # filter field from_obj=[database.machine_access_table, database.machine_table]) # from tables users = [self.userToPrinc(acl[0]) for acl in database.session.execute(s)] return "\n".join(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/invirt-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. Does not cache to prevent race conditions.""" return list(row[0] for row in database.session.execute(sa.sql.select([database.Machine.c.name]))) def getadmin(self, **kw): """ Get the list of administrators for the global ACL. """ acl = [self.userToPrinc(row[0]) for row in database.session.execute(sa.sql.select([database.admins_table.c.user]))] acl.append('include /etc/remctl/acl/web\n') return '\n'.join(acl) 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.kerberos.realm return princ.replace('.', '/') + '@' + realm if __name__ == '__main__': database.connect() routefs.main(RemConfFS)