Changeset 982 for trunk/packages/sipb-xen-remote-server/files/usr/sbin
- Timestamp:
- Oct 1, 2008, 12:20:21 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/packages/sipb-xen-remote-server/files/usr/sbin/sipb-xen-remconffs
r835 r982 1 1 #!/usr/bin/python 2 2 3 import fuse 4 from fuse import Fuse 5 6 from time import time 7 8 import stat # for file properties 9 import os # for filesystem modes (O_RDONLY, etc) 10 import errno # for error number codes (ENOENT, etc) 11 # - note: these must be returned as negatives 3 import routefs 4 from routes import Mapper 12 5 13 6 from syslog import * 7 from time import time 14 8 15 9 from invirt import database 16 10 from invirt.config import structs as config 17 11 18 fuse.fuse_python_api = (0, 2) 19 20 def getDepth(path): 21 """ 22 Return the depth of a given path, zero-based from root ('/') 23 """ 24 if path == '/': 25 return 0 26 else: 27 return path.count('/') 28 29 def getParts(path): 30 """ 31 Return the slash-separated parts of a given path as a list 32 """ 33 # [1:] to exclude leading empty element 34 split = path.split('/') 35 if split[-1]: 36 return split[1:] 37 else: 38 return split[1:-1] 39 40 def parse(path): 41 parts = getParts(path) 42 return parts, len(parts) 43 44 class MyStat: 45 def __init__(self): 46 self.st_mode = 0 47 self.st_ino = 0 48 self.st_dev = 0 49 self.st_nlink = 0 50 self.st_uid = 0 51 self.st_gid = 0 52 self.st_size = 0 53 self.st_atime = 0 54 self.st_mtime = 0 55 self.st_ctime = 0 56 57 def toTuple(self): 58 return (self.st_mode, self.st_ino, self.st_dev, self.st_nlink, self.st_uid, self.st_gid, self.st_size, self.st_atime, self.st_mtime, self.st_ctime) 59 60 class RemConfFS(Fuse): 12 class RemConfFS(routefs.RouteFS): 61 13 """ 62 14 RemConfFS creates a filesytem for configuring remctl, like this: … … 66 18 | ... 67 19 | `-- machinen 68 `-- conf.d 69 |-- machine1 70 ... 71 `-- machinen 72 20 `-- conf 21 73 22 The machine list and the acls are drawn from a database. 74 23 … … 81 30 the user who mounts the filesystem (i.e. root) 82 31 """ 83 Fuse.__init__(self,*args, **kw)32 super(RemConfFS, self).__init__(*args, **kw) 84 33 self.lasttime = time() 85 self. allow_other = 134 self.fuse_args.add("allow_other", True) 86 35 87 36 openlog('sipb-xen-remconffs ', LOG_PID, LOG_DAEMON) 88 37 89 38 syslog(LOG_DEBUG, 'Init complete.') 90 39 40 def make_map(self): 41 m = Mapper() 42 m.connect('', controller='getroot') 43 m.connect('acl/:machine', controller='getacl') 44 m.connect('conf', controller='getconf') 45 return m 46 47 def getroot(self, **kw): 48 return ['acl', 'conf'] 49 50 def getacl(self, machine, **kw): 51 """Build the ACL file for a machine 52 """ 53 machine = database.Machine.get_by(name=machine) 54 users = [acl.user for acl in machine.acl] 55 return "\n".join(map(self.userToPrinc, users) 56 + ['include /etc/remctl/acl/web', 57 '']) 58 59 def getconf(self, **kw): 60 """Build the master conf file, with all machines 61 """ 62 return '\n'.join("control %s /usr/sbin/sipb-xen-remote-proxy-control" 63 " /etc/remctl/remconffs/acl/%s" 64 % (machine_name, machine_name) 65 for machine_name in self.getMachines())+'\n' 66 91 67 def getMachines(self): 92 68 """Get the list of VMs in the database, clearing the cache if it's … … 96 72 database.clear_cache() 97 73 return [machine.name for machine in database.Machine.select()] 98 99 def getacl(self, machine_name): 100 """Build the ACL file for a machine 101 """ 102 machine = database.Machine.get_by(name=machine_name) 103 users = [acl.user for acl in machine.acl] 104 return "\n".join(map(self.userToPrinc, users) 105 + ['include /etc/remctl/acl/web', 106 '']) 107 108 def getconf(self): 109 """Build the master conf file, with all machines 110 """ 111 return '\n'.join("control %s /usr/sbin/sipb-xen-remote-proxy-control" 112 " /etc/remctl/remconffs/acl/%s" 113 % (machine_name, machine_name) 114 for machine_name in self.getMachines())+'\n' 115 74 116 75 def userToPrinc(self, user): 117 76 """Convert Kerberos v4-style names to v5-style and append a default … … 125 84 126 85 return princ.replace('.', '/') + '@' + realm 127 128 def getattr(self, path):129 """130 - st_mode (protection bits)131 - st_ino (inode number)132 - st_dev (device)133 - st_nlink (number of hard links)134 - st_uid (user ID of owner)135 - st_gid (group ID of owner)136 - st_size (size of file, in bytes)137 - st_atime (time of most recent access)138 - st_mtime (time of most recent content modification)139 - st_ctime (platform dependent; time of most recent metadata change on Unix,140 or the time of creation on Windows).141 """142 143 syslog(LOG_DEBUG, "*** getattr: " + path)144 145 depth = getDepth(path)146 parts = getParts(path)147 148 st = MyStat()149 if path == '/':150 st.st_mode = stat.S_IFDIR | 0755151 st.st_nlink = 2152 elif depth == 1:153 if parts[0] == 'acl':154 st.st_mode = stat.S_IFDIR | 0755155 st.st_nlink = 2156 elif parts[0] == 'conf':157 st.st_mode = stat.S_IFREG | 0444158 st.st_nlink = 1159 st.st_size = len(self.getconf())160 else:161 return -errno.ENOENT162 elif depth == 2:163 if parts[0] != 'acl':164 return -errno.ENOENT165 if parts[1] not in self.getMachines():166 return -errno.ENOENT167 st.st_mode = stat.S_IFREG | 0444168 st.st_nlink = 1169 st.st_size = len(self.getacl(parts[1]))170 171 return st.toTuple()172 173 # This call isn't actually used in the version of Fuse on console, but we174 # wanted to leave it implemented to ease the transition in the future175 def readdir(self, path, offset):176 """Return a generator with the listing for a directory177 """178 syslog(LOG_DEBUG, '*** readdir %s %s' % (path, offset))179 for (value, zero) in self.getdir(path):180 yield fuse.Direntry(value)181 182 def getdir(self, path):183 """Return a list of tuples of the form (item, 0) with the contents of184 the directory path185 186 Fuse doesn't add '.' or '..' on its own, so we have to187 """188 syslog(LOG_DEBUG, '*** getdir %s' % path)189 190 parts, depth = parse(path)191 192 if depth == 0:193 contents = ('acl', 'conf')194 elif depth == 1:195 if parts[0] == 'acl':196 contents = self.getMachines()197 else:198 return -errno.ENOENT199 else:200 return -errno.ENOTDIR201 202 # Format the list the way that Fuse wants it - and don't forget to add203 # '.' and '..'204 return [(i, 0) for i in (list(contents) + ['.', '..'])]205 206 def read(self, path, length, offset):207 """Read length bytes starting at offset of path. In most cases, this208 just gets passed on to the OS209 """210 syslog(LOG_DEBUG, '*** read %s %s %s' % (path, length, offset))211 212 parts, depth = parse(path)213 214 if depth == 0:215 return -errno.EISDIR216 elif parts[0] == 'conf':217 return self.getconf()[offset:offset+length]218 elif parts[0] == 'acl':219 if depth == 1:220 return -errno.EISDIR221 if parts[1] in self.getMachines():222 return self.getacl(parts[1])[offset:offset+length]223 return -errno.ENOENT224 225 def readlink(self, path):226 syslog(LOG_DEBUG, '*** readlink %s' % path)227 return -errno.ENOENT228 229 86 230 87 if __name__ == '__main__': 231 88 database.connect() 232 usage=""" 233 $0 [mount_path] 234 """ 235 server = RemConfFS() 236 server.flags = 0 237 server.main() 89 routefs.main(RemConfFS)
Note: See TracChangeset
for help on using the changeset viewer.