| 1 | #!/usr/bin/python | 
|---|
| 2 |  | 
|---|
| 3 | import routefs | 
|---|
| 4 | from routes import Mapper | 
|---|
| 5 |  | 
|---|
| 6 | from syslog import * | 
|---|
| 7 | from time import time | 
|---|
| 8 |  | 
|---|
| 9 | from invirt import database | 
|---|
| 10 | from invirt.config import structs as config | 
|---|
| 11 |  | 
|---|
| 12 | class RemConfFS(routefs.RouteFS): | 
|---|
| 13 |         """ | 
|---|
| 14 |         RemConfFS creates a filesytem for configuring remctl, like this: | 
|---|
| 15 |         / | 
|---|
| 16 |         |-- acl | 
|---|
| 17 |         |   |-- machine1 | 
|---|
| 18 |         |   ... | 
|---|
| 19 |         |   `-- machinen | 
|---|
| 20 |         `-- conf | 
|---|
| 21 |          | 
|---|
| 22 |         The machine list and the acls are drawn from a database. | 
|---|
| 23 |         """ | 
|---|
| 24 |          | 
|---|
| 25 |         def __init__(self, *args, **kw): | 
|---|
| 26 |                 """Initialize the filesystem and set it to allow_other access besides | 
|---|
| 27 |                 the user who mounts the filesystem (i.e. root) | 
|---|
| 28 |                 """ | 
|---|
| 29 |                 super(RemConfFS, self).__init__(*args, **kw) | 
|---|
| 30 |                 self.lasttime = time() | 
|---|
| 31 |                 self.fuse_args.add("allow_other", True) | 
|---|
| 32 |                  | 
|---|
| 33 |                 openlog('sipb-xen-remconffs ', LOG_PID, LOG_DAEMON) | 
|---|
| 34 |                  | 
|---|
| 35 |                 syslog(LOG_DEBUG, 'Init complete.') | 
|---|
| 36 |          | 
|---|
| 37 |         def make_map(self): | 
|---|
| 38 |                 m = Mapper() | 
|---|
| 39 |                 m.connect('', controller='getroot') | 
|---|
| 40 |                 m.connect('acl', controller='getmachines') | 
|---|
| 41 |                 m.connect('acl/:machine', controller='getacl') | 
|---|
| 42 |                 m.connect('conf', controller='getconf') | 
|---|
| 43 |                 return m | 
|---|
| 44 |          | 
|---|
| 45 |         def getroot(self, **kw): | 
|---|
| 46 |                 return ['acl', 'conf'] | 
|---|
| 47 |          | 
|---|
| 48 |         def getacl(self, machine, **kw): | 
|---|
| 49 |                 """Build the ACL file for a machine | 
|---|
| 50 |                 """ | 
|---|
| 51 |                 machine = database.Machine.query().filter_by(name=machine).one() | 
|---|
| 52 |                 users = [acl.user for acl in machine.acl] | 
|---|
| 53 |                 return "\n".join(map(self.userToPrinc, users) | 
|---|
| 54 |                                  + ['include /etc/remctl/acl/web', | 
|---|
| 55 |                                     '']) | 
|---|
| 56 |          | 
|---|
| 57 |         def getconf(self, **kw): | 
|---|
| 58 |                 """Build the master conf file, with all machines | 
|---|
| 59 |                 """ | 
|---|
| 60 |                 return '\n'.join("control %s /usr/sbin/sipb-xen-remote-proxy-control" | 
|---|
| 61 |                                  " /etc/remctl/remconffs/acl/%s" | 
|---|
| 62 |                                  % (machine_name, machine_name) | 
|---|
| 63 |                                  for machine_name in self.getmachines())+'\n' | 
|---|
| 64 |          | 
|---|
| 65 |         def getmachines(self, **kw): | 
|---|
| 66 |                 """Get the list of VMs in the database, clearing the cache if it's  | 
|---|
| 67 |                 older than 15 seconds""" | 
|---|
| 68 |                 if time() - self.lasttime > 15: | 
|---|
| 69 |                         self.lasttime = time() | 
|---|
| 70 |                         database.clear_cache() | 
|---|
| 71 |                 return [machine.name for machine in database.session.query(database.Machine).all()] | 
|---|
| 72 |          | 
|---|
| 73 |         def userToPrinc(self, user): | 
|---|
| 74 |                 """Convert Kerberos v4-style names to v5-style and append a default | 
|---|
| 75 |                 realm if none is specified | 
|---|
| 76 |                 """ | 
|---|
| 77 |                 if '@' in user: | 
|---|
| 78 |                         (princ, realm) = user.split('@') | 
|---|
| 79 |                 else: | 
|---|
| 80 |                         princ = user | 
|---|
| 81 |                         realm = config.authn[0].realm | 
|---|
| 82 |                  | 
|---|
| 83 |                 return princ.replace('.', '/') + '@' + realm | 
|---|
| 84 |  | 
|---|
| 85 | if __name__ == '__main__': | 
|---|
| 86 |         database.connect() | 
|---|
| 87 |         routefs.main(RemConfFS) | 
|---|