First stab at a package to create the console server
authorEvan Broder <broder@mit.edu>
Sun, 30 Mar 2008 05:39:19 +0000 (01:39 -0400)
committerEvan Broder <broder@mit.edu>
Sun, 30 Mar 2008 05:39:19 +0000 (01:39 -0400)
svn path=/trunk/packages/sipb-xen-console/; revision=335

12 files changed:
debian/changelog [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control.in [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/rules [new file with mode: 0755]
debian/sipb-xen-console.init [new file with mode: 0755]
debian/sipb-xen-console.install [new file with mode: 0644]
files/etc/nss-pgsql.conf [new file with mode: 0644]
files/etc/nsswitch.conf.sipb-xen [new file with mode: 0644]
files/etc/ssh/ssh_config.sipb-xen [new file with mode: 0644]
files/home/machines/.ssh/known_hosts [new file with mode: 0644]
files/usr/bin/sipb-xen-consolefs [new file with mode: 0755]

diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..92eff1e
--- /dev/null
@@ -0,0 +1,5 @@
+sipb-xen-console (1) unstable; urgency=low
+
+  * Initial release.
+
+ -- SIPB Xen Project <sipb-xen@mit.edu>  Sun, 30 Mar 2008 01:08:50 -0400
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..7ed6ff8
--- /dev/null
@@ -0,0 +1 @@
+5
diff --git a/debian/control.in b/debian/control.in
new file mode 100644 (file)
index 0000000..8b594df
--- /dev/null
@@ -0,0 +1,15 @@
+Source: sipb-xen-console
+Section: servers
+Priority: important
+Maintainer: sipb-xen@mit.edu
+Build-Depends: @cdbs@
+Standards-Version: 3.7.2
+
+Package: sipb-xen-console
+Architecture: all
+Provides: ${diverted-files}
+Conflicts: ${diverted-files}
+Depends: ${shlibs:Depends}, ${misc:Depends}, fuse-utils, libnss-pgsql1, openssh-client, openssh-server, python-fuse, sipb-xen-database-common
+Description: SIPB Xen serial console server
+ This package  should be installed on sipb-xen-console
+ It makes sure that necessary tools are available.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..7789434
--- /dev/null
@@ -0,0 +1,3 @@
+This package was created for internal use of the SIPB Xen Project of
+the MIT Student Information Processing Board.  Ask sipb-xen@mit.edu if
+you have questions about redistribution.
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..8dfab96
--- /dev/null
@@ -0,0 +1,10 @@
+#!/usr/bin/make -f
+
+DEB_AUTO_UPDATE_DEBIAN_CONTROL = 1
+DEB_DIVERT_EXTENSION = .sipb-xen
+DEB_DIVERT_FILES_sipb-xen-console += \
+       /etc/nsswitch.conf
+       /etc/ssh/ssh_config
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/rules/replace-files.mk
diff --git a/debian/sipb-xen-console.init b/debian/sipb-xen-console.init
new file mode 100755 (executable)
index 0000000..14ed7e8
--- /dev/null
@@ -0,0 +1,124 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          sipb-xen-console
+# Required-Start:    $local_fs $remote_fs
+# Required-Stop:     $local_fs $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: sipb-xen Console Server homedir filesystem
+# Description:       
+### END INIT INFO
+
+# Author: SIPB Xen Project <sipb-xen@mit.edu>
+
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+DESC="The sipb-xen console server homedir filesystem"
+NAME=sipb-xen-console
+DAEMON=/usr/bin/sipb-xen-consolefs
+DAEMON_ARGS="/consolefs"
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/$NAME
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+       # Return
+       #   0 if daemon has been started
+       #   1 if daemon was already running
+       #   2 if daemon could not be started
+       daemon --running -n $NAME && return 1
+       daemon -r -O daemon.info -E daemon.err -n $NAME -U $DAEMON $DAEMON_ARGS || return 2
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+       # Return
+       #   0 if daemon has been stopped
+       #   1 if daemon was already stopped
+       #   2 if daemon could not be stopped
+       #   other if a failure occurred
+       daemon --stop -n $NAME
+       RETVAL="$?"
+       [ "$RETVAL" = 2 ] && return 2
+       # Many daemons don't delete their pidfiles when they exit.
+       rm -f $PIDFILE
+       return "$RETVAL"
+}
+
+case "$1" in
+  start)
+       [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+       do_start
+       case "$?" in
+               0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+               2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+       esac
+       ;;
+  stop)
+       [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+       do_stop
+       case "$?" in
+               0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+               2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+       esac
+       ;;
+  #reload|force-reload)
+       #
+       # If do_reload() is not implemented then leave this commented out
+       # and leave 'force-reload' as an alias for 'restart'.
+       #
+       #log_daemon_msg "Reloading $DESC" "$NAME"
+       #do_reload
+       #log_end_msg $?
+       #;;
+  restart|force-reload)
+       #
+       # If the "reload" option is implemented then remove the
+       # 'force-reload' alias
+       #
+       log_daemon_msg "Restarting $DESC" "$NAME"
+       do_stop
+       case "$?" in
+         0|1)
+               do_start
+               case "$?" in
+                       0) log_end_msg 0 ;;
+                       1) log_end_msg 1 ;; # Old process is still running
+                       *) log_end_msg 1 ;; # Failed to start
+               esac
+               ;;
+         *)
+               # Failed to stop
+               log_end_msg 1
+               ;;
+       esac
+       ;;
+  *)
+       #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+       echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
+       exit 3
+       ;;
+esac
+
+:
diff --git a/debian/sipb-xen-console.install b/debian/sipb-xen-console.install
new file mode 100644 (file)
index 0000000..9da31b3
--- /dev/null
@@ -0,0 +1 @@
+files/* .
diff --git a/files/etc/nss-pgsql.conf b/files/etc/nss-pgsql.conf
new file mode 100644 (file)
index 0000000..d4ddcfe
--- /dev/null
@@ -0,0 +1,23 @@
+# example configfile for PostgreSQL NSS module
+
+# these are entries as used with the BOFHMS tool (sf.net/projects/bofhms)
+host           = sipb-xen-dev
+port           = 5432
+database       = sipb_xen
+login          = sipb-xen
+#passwd                = foo
+#passwdtable   = machines
+#grouptable    = machines
+# you can use anything postgres accepts as table expression
+#groupmembertable = accounts JOIN usergroups ON accounts.uid=usergroups.uid JOIN groups ON usergroups.gid=groups.gid
+
+querypasswd = SELECT name, 'moo', 1000 as uid, 1000, '', '/vmhome/'|| name, '/usr/local/bin/sipb-xen-consolesh' FROM machines
+querygroup = SELECT name, NULL, 1000 as gid FROM machines
+querymembers = SELECT name FROM machines WHERE 1000 = %d
+queryids = SELECT 1000 AS gid FROM machines LIMIT 0;
+
+passwd_name = name
+passwd_uid = uid
+
+group_name = name
+group_gid = gid
diff --git a/files/etc/nsswitch.conf.sipb-xen b/files/etc/nsswitch.conf.sipb-xen
new file mode 100644 (file)
index 0000000..4fcecf6
--- /dev/null
@@ -0,0 +1,19 @@
+# /etc/nsswitch.conf
+#
+# Example configuration of GNU Name Service Switch functionality.
+# If you have the `glibc-doc-reference' and `info' packages installed, try:
+# `info libc "Name Service Switch"' for information about this file.
+
+passwd:         compat pgsql
+group:          compat
+shadow:         compat
+
+hosts:          files dns
+networks:       files
+
+protocols:      db files
+services:       db files
+ethers:         db files
+rpc:            db files
+
+netgroup:       nis
diff --git a/files/etc/ssh/ssh_config.sipb-xen b/files/etc/ssh/ssh_config.sipb-xen
new file mode 100644 (file)
index 0000000..3630fc0
--- /dev/null
@@ -0,0 +1,47 @@
+
+# This is the ssh client system-wide configuration file.  See
+# ssh_config(5) for more information.  This file provides defaults for
+# users, and the values can be changed in per-user configuration files
+# or on the command line.
+
+# Configuration data is parsed as follows:
+#  1. command line options
+#  2. user-specific file
+#  3. system-wide file
+# Any configuration value is only changed the first time it is set.
+# Thus, host-specific definitions should be at the beginning of the
+# configuration file, and defaults at the end.
+
+# Site-wide defaults for some commonly used options.  For a comprehensive
+# list of available options, their meanings and defaults, please see the
+# ssh_config(5) man page.
+
+Host *
+   SetEnv VM_NAME
+#   ForwardAgent no
+#   ForwardX11 no
+#   ForwardX11Trusted yes
+#   RhostsRSAAuthentication no
+#   RSAAuthentication yes
+#   PasswordAuthentication yes
+#   HostbasedAuthentication no
+#   BatchMode no
+#   CheckHostIP yes
+#   AddressFamily any
+#   ConnectTimeout 0
+#   StrictHostKeyChecking ask
+#   IdentityFile ~/.ssh/identity
+#   IdentityFile ~/.ssh/id_rsa
+#   IdentityFile ~/.ssh/id_dsa
+#   Port 22
+#   Protocol 2,1
+#   Cipher 3des
+#   Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc
+#   EscapeChar ~
+#   Tunnel no
+#   TunnelDevice any:any
+#   PermitLocalCommand no
+    SendEnv LANG LC_*
+    HashKnownHosts yes
+    GSSAPIAuthentication yes
+    GSSAPIDelegateCredentials no
diff --git a/files/home/machines/.ssh/known_hosts b/files/home/machines/.ssh/known_hosts
new file mode 100644 (file)
index 0000000..3056107
--- /dev/null
@@ -0,0 +1,2 @@
+|1|CoekhjakJDYiibQ38vZna+XKwCg=|Ts2GavZxl8KVEl++tnJnjqfn84s= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAsoOOazVHn04z6s+kQnoFcw9fv7dGB9s/9H1QygYW9QAbvklWx0q4J8KGTATXCFwjooLNqjHYONOQ8x0h1fZPDmhdoHk24wH/EBUAAyhtrwTMpsgfqZwG7yuRpcbO382F3wRv6CIRYZ6hyIlm0Zt3680mO/u7l2wAFoMTyYwSdZ8Gl9p5Ay750TFCZoEI/Z4EQY5lGPHrHIXN+uo0Yus//AmWIzY9y3TSKabHz77rPGIzJc8Y4XjDqA7LzXCY+KGw2Of059AseVHNTCMo6KzVIKgdZoRBtiY7fD1l7ystgKL6lGJr4C1UyWoM41EVkDqsRJZ70C4Elcr1x/MrQFLEgQ==
+|1|SFl+Ci6EXZcVvxvxDm4Cf85nGho=|InwYz5wWUf/NRbBQRa/TO3Lm2uQ= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAsoOOazVHn04z6s+kQnoFcw9fv7dGB9s/9H1QygYW9QAbvklWx0q4J8KGTATXCFwjooLNqjHYONOQ8x0h1fZPDmhdoHk24wH/EBUAAyhtrwTMpsgfqZwG7yuRpcbO382F3wRv6CIRYZ6hyIlm0Zt3680mO/u7l2wAFoMTyYwSdZ8Gl9p5Ay750TFCZoEI/Z4EQY5lGPHrHIXN+uo0Yus//AmWIzY9y3TSKabHz77rPGIzJc8Y4XjDqA7LzXCY+KGw2Of059AseVHNTCMo6KzVIKgdZoRBtiY7fD1l7ystgKL6lGJr4C1UyWoM41EVkDqsRJZ70C4Elcr1x/MrQFLEgQ==
diff --git a/files/usr/bin/sipb-xen-consolefs b/files/usr/bin/sipb-xen-consolefs
new file mode 100755 (executable)
index 0000000..7cd3766
--- /dev/null
@@ -0,0 +1,143 @@
+#!/usr/bin/python
+
+import fuse
+from fuse import Fuse
+
+from time import time
+
+import stat    # for file properties
+import os        # for filesystem modes (O_RDONLY, etc)
+import errno   # for error number codes (ENOENT, etc)
+                          # - note: these must be returned as negatives
+
+fuse.fuse_python_api = (0, 2)
+
+machines = ['moo17', 'remus']
+realpath = "/home/machines/"
+uid = 1000
+
+def dirFromList(list):
+       """
+       Return a properly formatted list of items suitable to a directory listing.
+       ['a', 'b', 'c'] => [('a', 0), ('b', 0), ('c', 0)]
+       """
+       return [(x, 0) for x in list]
+
+def getDepth(path):
+       """
+       Return the depth of a given path, zero-based from root ('/')
+       """
+       if path == '/':
+               return 0
+       else:
+               return path.count('/')
+
+def getParts(path):
+       """
+       Return the slash-separated parts of a given path as a list
+       """
+       if path == '/':
+               return ['/']
+       else:
+               return path[1:].split('/')
+
+class MyStat:
+       def __init__(self):
+               self.st_mode = 0
+               self.st_ino = 0
+               self.st_dev = 0
+               self.st_nlink = 0
+               self.st_uid = uid
+               self.st_gid = 0
+               self.st_size = 0
+               self.st_atime = 0
+               self.st_mtime = 0
+               self.st_ctime = 0
+       
+       def toTuple(self):
+               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)
+
+class ConsoleFS(Fuse):
+       """
+       """
+       
+       def __init__(self, *args, **kw):
+               Fuse.__init__(self, *args, **kw)
+               print 'Init complete.'
+       
+       def mirrorPath(self, path):
+               return realpath + "/".join(getParts(path)[1:])
+       
+       def getattr(self, path):
+               """
+               - st_mode (protection bits)
+               - st_ino (inode number)
+               - st_dev (device)
+               - st_nlink (number of hard links)
+               - st_uid (user ID of owner)
+               - st_gid (group ID of owner)
+               - st_size (size of file, in bytes)
+               - st_atime (time of most recent access)
+               - st_mtime (time of most recent content modification)
+               - st_ctime (platform dependent; time of most recent metadata change on Unix,
+                                       or the time of creation on Windows).
+               """
+               
+               print "*** getattr: " + path
+               
+               depth = getDepth(path)
+               parts = getParts(path)
+               
+               st = MyStat()
+               if path == '/':
+                       st.st_mode = stat.S_IFDIR | 0755
+                       st.st_nlink = 2
+               elif depth == 1:
+                       if parts[-1] in machines:
+                               st.st_mode = stat.S_IFDIR | 0755
+                               st.st_nlink = 2
+                       else:
+                               return -errno.ENOENT
+               elif depth == 2 and parts[-1] == '.k5login':
+                       st.st_mode = stat.S_IFREG | 0444
+                       st.st_nlink = 1
+                       st.st_size = 17
+               else:
+                       st = os.lstat(self.mirrorPath(path))
+               return st.toTuple()
+       
+       def readdir(self, path, offset):
+               print '*** readdir', path, offset
+               if path == '/':
+                       for r in  ['.', '..']+machines:
+                               yield fuse.Direntry(r)
+               elif getDepth(path) == 1:
+                       for r in set(os.listdir(self.mirrorPath(path)) + ['.k5login']):
+                               yield fuse.Direntry(r)
+               else:
+                       for r in os.listdir(self.mirrorPath(path)):
+                               yield fuse.Direntry(r)
+       
+       def read ( self, path, length, offset ):
+               print '*** read', path, length, offset
+               
+               if getDepth(path) < 2:
+                       return -errno.ENOENT
+               elif getParts(path)[1:] == ['.k5login']:
+                       pass
+               else:
+                       fname = self.mirrorPath(path)
+                       if not os.path.isfile(fname):
+                               return -errno.ENOENT
+                       else:
+                               f = open(fname)
+                               f.seek(offset)
+                               return f.read(length)
+
+if __name__ == '__main__':
+       usage="""
+ConsoleFS [mount_path]
+"""
+       server = ConsoleFS()
+       server.flags = 0
+       server.main()