Add real caching to remconffs
[invirt/packages/invirt-remote.git] / files / usr / sbin / invirt-remconffs
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 = 0
31                 self.fuse_args.add("allow_other", True)
32                 
33                 openlog('invirt-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 recache(self):
46                 if time() - self.lasttime > 15:
47                         self.lasttime = time()
48                         database.clear_cache()
49                         self.machines = dict((machine.name, machine) for machine in database.session.query(database.Machine).all())
50         
51         def getroot(self, **kw):
52                 return ['acl', 'conf']
53         
54         def getacl(self, machine, **kw):
55                 """Build the ACL file for a machine
56                 """
57                 self.recache()
58                 machine = self.machines[machine]
59                 users = [acl.user for acl in machine.acl]
60                 return "\n".join(map(self.userToPrinc, users)
61                                  + ['include /etc/remctl/acl/web',
62                                         ''])
63         
64         def getconf(self, **kw):
65                 """Build the master conf file, with all machines
66                 """
67                 return '\n'.join("control %s /usr/sbin/invirt-remote-proxy-control"
68                                  " /etc/remctl/remconffs/acl/%s"
69                                  % (machine_name, machine_name)
70                                  for machine_name in self.getmachines())+'\n'
71         
72         def getmachines(self, **kw):
73                 """Get the list of VMs in the database, clearing the cache if it's 
74                 older than 15 seconds"""
75                 self.recache()
76                 return self.machines.keys()
77         
78         def userToPrinc(self, user):
79                 """Convert Kerberos v4-style names to v5-style and append a default
80                 realm if none is specified
81                 """
82                 if '@' in user:
83                         (princ, realm) = user.split('@')
84                 else:
85                         princ = user
86                         realm = config.authn[0].realm
87                 
88                 return princ.replace('.', '/') + '@' + realm
89
90 if __name__ == '__main__':
91         database.connect()
92         routefs.main(RemConfFS)