Get username from cherrypy request object
[invirt/packages/invirt-web.git] / code / main.py
index 6fdd31a..47f9b01 100755 (executable)
@@ -13,8 +13,8 @@ import sys
 import time
 import urllib
 import socket
 import time
 import urllib
 import socket
+import cherrypy
 from StringIO import StringIO
 from StringIO import StringIO
-
 def revertStandardError():
     """Move stderr to stdout, and return the contents of the old stderr."""
     errio = sys.stderr
 def revertStandardError():
     """Move stderr to stdout, and return the contents of the old stderr."""
     errio = sys.stderr
@@ -45,6 +45,111 @@ from invirt.database import Machine, CDROM, session, connect, MachineAccess, Typ
 from invirt.config import structs as config
 from invirt.common import InvalidInput, CodeError
 
 from invirt.config import structs as config
 from invirt.common import InvalidInput, CodeError
 
+from view import View
+
+class InvirtWeb(View):
+    def __init__(self):
+        super(self.__class__,self).__init__()
+        connect()
+        self._cp_config['tools.require_login.on'] = True
+        self._cp_config['tools.mako.imports'] = ['from invirt.config import structs as config',
+                                                 'from invirt import database']
+
+
+    @cherrypy.expose
+    @cherrypy.tools.mako(filename="/list.mako")
+    def list(self):
+        """Handler for list requests."""
+        checkpoint.checkpoint('Getting list dict')
+        d = getListDict(cherrypy.request.login, cherrypy.request.state)
+        checkpoint.checkpoint('Got list dict')
+        return d
+    index=list
+
+    @cherrypy.expose
+    @cherrypy.tools.mako(filename="/help.mako")
+    def help(self, subject=None, simple=False):
+        """Handler for help messages."""
+
+        help_mapping = {
+            'Autoinstalls': """
+The autoinstaller builds a minimal Debian or Ubuntu system to run as a
+ParaVM.  You can access the resulting system by logging into the <a
+href="help?simple=true&subject=ParaVM+Console">serial console server</a>
+with your Kerberos tickets; there is no root password so sshd will
+refuse login.</p>
+
+<p>Under the covers, the autoinstaller uses our own patched version of
+xen-create-image, which is a tool based on debootstrap.  If you log
+into the serial console while the install is running, you can watch
+it.
+""",
+            'ParaVM Console': """
+ParaVM machines do not support local console access over VNC.  To
+access the serial console of these machines, you can SSH with Kerberos
+to %s, using the name of the machine as your
+username.""" % config.console.hostname,
+            'HVM/ParaVM': """
+HVM machines use the virtualization features of the processor, while
+ParaVM machines rely on a modified kernel to communicate directly with
+the hypervisor.  HVMs support boot CDs of any operating system, and
+the VNC console applet.  The three-minute autoinstaller produces
+ParaVMs.  ParaVMs typically are more efficient, and always support the
+<a href="help?subject=ParaVM+Console">console server</a>.</p>
+
+<p>More details are <a
+href="https://xvm.scripts.mit.edu/wiki/Paravirtualization">on the
+wiki</a>, including steps to prepare an HVM guest to boot as a ParaVM
+(which you can skip by using the autoinstaller to begin with.)</p>
+
+<p>We recommend using a ParaVM when possible and an HVM when necessary.
+""",
+            'CPU Weight': """
+Don't ask us!  We're as mystified as you are.""",
+            'Owner': """
+The owner field is used to determine <a
+href="help?subject=Quotas">quotas</a>.  It must be the name of a
+locker that you are an AFS administrator of.  In particular, you or an
+AFS group you are a member of must have AFS rlidwka bits on the
+locker.  You can check who administers the LOCKER locker using the
+commands 'attach LOCKER; fs la /mit/LOCKER' on Athena.)  See also <a
+href="help?subject=Administrator">administrator</a>.""",
+            'Administrator': """
+The administrator field determines who can access the console and
+power on and off the machine.  This can be either a user or a moira
+group.""",
+            'Quotas': """
+Quotas are determined on a per-locker basis.  Each locker may have a
+maximum of 512 mebibytes of active ram, 50 gibibytes of disk, and 4
+active machines.""",
+            'Console': """
+<strong>Framebuffer:</strong> At a Linux boot prompt in your VM, try
+setting <tt>fb=false</tt> to disable the framebuffer.  If you don't,
+your machine will run just fine, but the applet's display of the
+console will suffer artifacts.
+""",
+            'Windows': """
+<strong>Windows Vista:</strong> The Vista image is licensed for all MIT students and will automatically activate off the network; see <a href="/static/msca-email.txt">the licensing confirmation e-mail</a> for details. The installer requires 512 MiB RAM and at least 7.5 GiB disk space (15 GiB or more recommended).<br>
+<strong>Windows XP:</strong> This is the volume license CD image. You will need your own volume license key to complete the install. We do not have these available for the general MIT community; ask your department if they have one.
+"""
+            }
+
+        if not subject:
+            subject = sorted(help_mapping.keys())
+        if not isinstance(subject, list):
+            subject = [subject]
+
+        return dict(simple=simple,
+                    subjects=subject,
+                    mapping=help_mapping)
+    help._cp_config['tools.require_login.on'] = False
+
+    @cherrypy.expose
+    @cherrypy.tools.mako(filename="/helloworld.mako")
+    def helloworld(self, **kwargs):
+        return {'request': cherrypy.request, 'kwargs': kwargs}
+    helloworld._cp_config['tools.require_login.on'] = False
+
 def pathSplit(path):
     if path.startswith('/'):
         path = path[1:]
 def pathSplit(path):
     if path.startswith('/'):
         path = path[1:]
@@ -68,16 +173,6 @@ class Checkpoint:
 
 checkpoint = Checkpoint()
 
 
 checkpoint = Checkpoint()
 
-def jquote(string):
-    return "'" + string.replace('\\', '\\\\').replace("'", "\\'").replace('\n', '\\n') + "'"
-
-def helppopup(subj):
-    """Return HTML code for a (?) link to a specified help topic"""
-    return ('<span class="helplink"><a href="help?' +
-            cgi.escape(urllib.urlencode(dict(subject=subj, simple='true')))
-            +'" target="_blank" ' +
-            'onclick="return helppopup(' + cgi.escape(jquote(subj)) + ')">(?)</a></span>')
-
 def makeErrorPre(old, addition):
     if addition is None:
         return
 def makeErrorPre(old, addition):
     if addition is None:
         return
@@ -88,7 +183,6 @@ def makeErrorPre(old, addition):
 
 Template.database = database
 Template.config = config
 
 Template.database = database
 Template.config = config
-Template.helppopup = staticmethod(helppopup)
 Template.err = None
 
 class JsonDict:
 Template.err = None
 
 class JsonDict:
@@ -217,13 +311,6 @@ def getListDict(username, state):
              can_clone=can_clone)
     return d
 
              can_clone=can_clone)
     return d
 
-def listVms(username, state, path, fields):
-    """Handler for list requests."""
-    checkpoint.checkpoint('Getting list dict')
-    d = getListDict(username, state)
-    checkpoint.checkpoint('Got list dict')
-    return templates.list(searchList=[d])
-
 def vnc(username, state, path, fields):
     """VNC applet page.
 
 def vnc(username, state, path, fields):
     """VNC applet page.
 
@@ -425,86 +512,6 @@ def modify(username, state, path, fields):
     info_dict['result'] = result
     return templates.info(searchList=[info_dict])
 
     info_dict['result'] = result
     return templates.info(searchList=[info_dict])
 
-
-def helpHandler(username, state, path, fields):
-    """Handler for help messages."""
-    simple = fields.getfirst('simple')
-    subjects = fields.getlist('subject')
-
-    help_mapping = {
-                    'Autoinstalls': """
-The autoinstaller builds a minimal Debian or Ubuntu system to run as a
-ParaVM.  You can access the resulting system by logging into the <a
-href="help?simple=true&subject=ParaVM+Console">serial console server</a>
-with your Kerberos tickets; there is no root password so sshd will
-refuse login.</p>
-
-<p>Under the covers, the autoinstaller uses our own patched version of
-xen-create-image, which is a tool based on debootstrap.  If you log
-into the serial console while the install is running, you can watch
-it.
-""",
-                    'ParaVM Console': """
-ParaVM machines do not support local console access over VNC.  To
-access the serial console of these machines, you can SSH with Kerberos
-to %s, using the name of the machine as your
-username.""" % config.console.hostname,
-                    'HVM/ParaVM': """
-HVM machines use the virtualization features of the processor, while
-ParaVM machines rely on a modified kernel to communicate directly with
-the hypervisor.  HVMs support boot CDs of any operating system, and
-the VNC console applet.  The three-minute autoinstaller produces
-ParaVMs.  ParaVMs typically are more efficient, and always support the
-<a href="help?subject=ParaVM+Console">console server</a>.</p>
-
-<p>More details are <a
-href="https://xvm.scripts.mit.edu/wiki/Paravirtualization">on the
-wiki</a>, including steps to prepare an HVM guest to boot as a ParaVM
-(which you can skip by using the autoinstaller to begin with.)</p>
-
-<p>We recommend using a ParaVM when possible and an HVM when necessary.
-""",
-                    'CPU Weight': """
-Don't ask us!  We're as mystified as you are.""",
-                    'Owner': """
-The owner field is used to determine <a
-href="help?subject=Quotas">quotas</a>.  It must be the name of a
-locker that you are an AFS administrator of.  In particular, you or an
-AFS group you are a member of must have AFS rlidwka bits on the
-locker.  You can check who administers the LOCKER locker using the
-commands 'attach LOCKER; fs la /mit/LOCKER' on Athena.)  See also <a
-href="help?subject=Administrator">administrator</a>.""",
-                    'Administrator': """
-The administrator field determines who can access the console and
-power on and off the machine.  This can be either a user or a moira
-group.""",
-                    'Quotas': """
-Quotas are determined on a per-locker basis.  Each locker may have a
-maximum of 512 mebibytes of active ram, 50 gibibytes of disk, and 4
-active machines.""",
-                    'Console': """
-<strong>Framebuffer:</strong> At a Linux boot prompt in your VM, try
-setting <tt>fb=false</tt> to disable the framebuffer.  If you don't,
-your machine will run just fine, but the applet's display of the
-console will suffer artifacts.
-""",
-                    'Windows': """
-<strong>Windows Vista:</strong> The Vista image is licensed for all MIT students and will automatically activate off the network; see <a href="/static/msca-email.txt">the licensing confirmation e-mail</a> for details. The installer requires 512 MiB RAM and at least 7.5 GiB disk space (15 GiB or more recommended).<br>
-<strong>Windows XP:</strong> This is the volume license CD image. You will need your own volume license key to complete the install. We do not have these available for the general MIT community; ask your department if they have one.
-"""
-                    }
-
-    if not subjects:
-        subjects = sorted(help_mapping.keys())
-
-    d = dict(user=username,
-             simple=simple,
-             subjects=subjects,
-             mapping=help_mapping)
-
-    return templates.help(searchList=[d])
-
-
 def badOperation(u, s, p, e):
     """Function called when accessing an unknown URI."""
     return ({'Status': '404 Not Found'}, 'Invalid operation.')
 def badOperation(u, s, p, e):
     """Function called when accessing an unknown URI."""
     return ({'Status': '404 Not Found'}, 'Invalid operation.')
@@ -626,13 +633,11 @@ def throwError(_, __, ___, ____):
     """Throw an error, to test the error-tracing mechanisms."""
     raise RuntimeError("test of the emergency broadcast system")
 
     """Throw an error, to test the error-tracing mechanisms."""
     raise RuntimeError("test of the emergency broadcast system")
 
-mapping = dict(list=listVms,
-               vnc=vnc,
+mapping = dict(vnc=vnc,
                command=command,
                modify=modify,
                info=info,
                create=create,
                command=command,
                modify=modify,
                info=info,
                create=create,
-               help=helpHandler,
                unauth=unauthFront,
                admin=admin,
                overlord=admin,
                unauth=unauthFront,
                admin=admin,
                overlord=admin,
@@ -672,21 +677,6 @@ def show_error(op, username, fields, err, emsg, traceback):
     d['details'] = details
     return templates.error(searchList=[d])
 
     d['details'] = details
     return templates.error(searchList=[d])
 
-def getUser(environ):
-    """Return the current user based on the SSL environment variables"""
-    user = environ.get('REMOTE_USER')
-    if user is None:
-        return
-    
-    if environ.get('AUTH_TYPE') == 'Negotiate':
-        # Convert the krb5 principal into a krb4 username
-        if not user.endswith('@%s' % config.kerberos.realm):
-            return
-        else:
-            return user.split('@')[0].replace('/', '.')
-    else:
-        return user
-
 def handler(username, state, path, fields):
     operation, path = pathSplit(path)
     if not operation:
 def handler(username, state, path, fields):
     operation, path = pathSplit(path)
     if not operation: