Changeset 359 for trunk


Ignore:
Timestamp:
Mar 30, 2008, 2:22:48 PM (17 years ago)
Author:
broder
Message:

Added comments and changed to using the syslog module instead of print

Location:
trunk/packages/sipb-xen-console
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/packages/sipb-xen-console/debian/changelog

    r357 r359  
     1sipb-xen-console (4) unstable; urgency=low
     2
     3  * Added comments to sipb-xen-consolefs
     4  * Added support for symlinks in the realpath
     5  * Changed sipb-xen-consolefs to use syslog instead of printf debugging
     6
     7 -- SIPB Xen Project <sipb-xen@mit.edu>  Sun, 30 Mar 2008 14:17:59 -0400
     8
    19sipb-xen-console (3.2) unstable; urgency=low
    210
  • trunk/packages/sipb-xen-console/files/usr/bin/sipb-xen-consolefs

    r357 r359  
    1111                           # - note: these must be returned as negatives
    1212
     13from syslog import *
     14
    1315import sipb_xen_database
    1416
     
    1618
    1719realpath = "/home/machines/"
    18 
    19 def dirFromList(list):
    20         """
    21         Return a properly formatted list of items suitable to a directory listing.
    22         ['a', 'b', 'c'] => [('a', 0), ('b', 0), ('c', 0)]
    23         """
    24         return [(x, 0) for x in list]
    2520
    2621def getDepth(path):
     
    4035                return ['/']
    4136        else:
     37                # [1:] because otherwise you get an empty list element from the
     38                # initial '/'
    4239                return path[1:].split('/')
    4340
     
    6057class ConsoleFS(Fuse):
    6158        """
     59        ConsoleFS creates a series of subdirectories each mirroring the same real
     60        directory, except for a single file - the .k5login - which is dynamically
     61        generated for each subdirectory
     62       
     63        This filesystem only implements the getattr, getdir, read, and readlink
     64        calls, beacuse this is a read-only filesystem
    6265        """
    6366       
    6467        def __init__(self, *args, **kw):
     68                """Initialize the filesystem and set it to allow_other access besides
     69                the user who mounts the filesystem (i.e. root)
     70                """
    6571                Fuse.__init__(self, *args, **kw)
    6672                self.lasttime = time()
    6773                self.allow_other = 1
    68                 print 'Init complete.'
     74               
     75                openlog('sipb-xen-consolefs ', LOG_PID, LOG_DAEMON)
     76               
     77                syslog(LOG_DEBUG, 'Init complete.')
    6978       
    7079        def mirrorPath(self, path):
     80                """Translate a virtual path to its real path counterpart"""
    7181                return realpath + "/".join(getParts(path)[1:])
    7282       
    7383        def getMachines(self):
     84                """Get the list of VMs in the database, clearing the cache if it's
     85                older than 15 seconds"""
    7486                if time() - self.lasttime > 15:
    7587                        self.lasttime = time()
     
    7890       
    7991        def getUid(self, machine_name):
     92                """Calculate the UID of a machine-account, which is just machine_id+1000
     93                """
    8094                return sipb_xen_database.Machine.get_by(name=machine_name).machine_id + 1000
    8195       
    8296        def getK5login(self, machine_name):
     97                """Build the ACL for a machine and turn it into a .k5login file
     98                """
    8399                machine = sipb_xen_database.Machine.get_by(name=machine_name)
    84100                users = [acl.user for acl in machine.acl]
     
    86102       
    87103        def userToPrinc(self, user):
     104                """Convert Kerberos v4-style names to v5-style and append a default
     105                realm if none is specified
     106                """
    88107                if '@' in user:
    89108                        (princ, realm) = user.split('@')
     
    109128                """
    110129               
    111                 print "*** getattr: " + path
     130                syslog(LOG_DEBUG, "*** getattr: " + path)
    112131               
    113132                depth = getDepth(path)
     
    115134               
    116135                st = MyStat()
     136                # / is a directory
    117137                if path == '/':
    118138                        st.st_mode = stat.S_IFDIR | 0755
    119139                        st.st_nlink = 2
     140                # /foo is a directory if foo is a machine - otherwise it doesn't exist
    120141                elif depth == 1:
    121142                        if parts[-1] in self.getMachines():
    122143                                st.st_mode = stat.S_IFDIR | 0755
    123144                                st.st_nlink = 2
     145                                # Homedirs should be owned by the user whose homedir it is
    124146                                st.st_uid = st.st_gid = self.getUid(parts[0])
    125147                        else:
    126148                                return -errno.ENOENT
     149                # Catch the .k5login file, because it's a special case
    127150                elif depth == 2 and parts[-1] == '.k5login':
    128151                        st.st_mode = stat.S_IFREG | 0444
    129152                        st.st_nlink = 1
    130153                        st.st_size = len(self.getK5login(parts[0]))
     154                        # The .k5login file should be owned by the user whose homedir it is
    131155                        st.st_uid = st.st_gid = self.getUid(parts[0])
     156                # For anything else, we get the mirror path and call out to the OS
    132157                else:
    133158                        stats = list(os.lstat(self.mirrorPath(path)))
     159                        # Shadow the UID and GID from the original homedir
    134160                        stats[4:6] = [self.getUid(parts[0])] * 2
    135161                        return tuple(stats)
    136162                return st.toTuple()
    137163       
     164        # This call isn't actually used in the version of Fuse on console, but we
     165        # wanted to leave it implemented to ease the transition in the future
    138166        def readdir(self, path, offset):
    139                 print '*** readdir', path, offset
     167                """Return a generator with the listing for a directory
     168                """
     169                syslog(LOG_DEBUG, '*** readdir %s %s' % (path, offset))
    140170                for (value, zero) in self.getdir(path):
    141171                        yield fuse.Direntry(value)
    142172       
    143173        def getdir(self, path):
    144                 print '*** getdir', path
     174                """Return a list of tuples of the form (item, 0) with the contents of
     175                the directory path
     176               
     177                Fuse doesn't add '.' or '..' on its own, so we have to
     178                """
     179                syslog(LOG_DEBUG, '*** getdir %s' % path)
     180               
     181                # '/' contains a directory for each machine
    145182                if path == '/':
    146                         contents = ['.', '..']+self.getMachines()
     183                        contents = self.getMachines()
     184                # The directory for each machine contains the same files as the realpath
     185                # but also the .k5login
     186                #
     187                # The list is converted to a set so that we can handle the case where
     188                # there is already a .k5login in the realpath gracefully
    147189                elif getDepth(path) == 1:
    148                         contents = set(os.listdir(self.mirrorPath(path)) + ['.k5login', '.', '..'])
    149                 else:
    150                         contents = os.listdir(self.mirrorPath(path)) + ['.', '..']
    151                 return [(i, 0) for i in contents]
    152        
    153         def read ( self, path, length, offset ):
    154                 print '*** read', path, length, offset
     190                        contents = set(os.listdir(self.mirrorPath(path)) + ['.k5login'])
     191                # If it's not the root of the homedir, just pass the call onto the OS
     192                # for realpath
     193                else:
     194                        contents = os.listdir(self.mirrorPath(path))
     195                # Format the list the way that Fuse wants it - and don't forget to add
     196                # '.' and '..'
     197                return [(i, 0) for i in (list(contents) + ['.', '..'])]
     198       
     199        def read(self, path, length, offset):
     200                """Read length bytes starting at offset of path. In most cases, this
     201                just gets passed on to the OS
     202                """
     203                syslog(LOG_DEBUG, '*** read %s %s %s' % (path, length, offset))
    155204               
    156205                parts = getParts(path)
    157206               
     207                # If the depth is less than 2, then either it's a directory or the file
     208                # doesn't exist
     209                # (realistically this doesn't appear to ever happen)
    158210                if getDepth(path) < 2:
    159211                        return -errno.ENOENT
     212                # If we're asking for a real .k5login file, then create it and return
     213                # the snippet requested
    160214                elif parts[1:] == ['.k5login']:
    161215                        if parts[0] not in self.getMachines():
     
    163217                        else:
    164218                                return self.getK5login(parts[0])[offset:length + offset]
     219                # Otherwise, pass the call onto the OS
     220                # (note that the file will get closed when this call returns and the
     221                # file descriptor goes out of scope)
    165222                else:
    166223                        fname = self.mirrorPath(path)
     
    171228                                f.seek(offset)
    172229                                return f.read(length)
     230       
     231        def readlink(self, path):
     232                syslog(LOG_DEBUG, '*** readlink %s' % path)
     233               
     234                # There aren't any symlinks here
     235                if getDepth(path) < 2:
     236                        return -errno.ENOENT
     237                # But there might be here
     238                else:
     239                        return os.readlink(self.mirrorPath(path))
    173240
    174241if __name__ == '__main__':
Note: See TracChangeset for help on using the changeset viewer.