There's a race condition for if the VM gets powered off between the
[invirt/packages/invirt-remote.git] / files / usr / sbin / sipb-xen-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 = 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)