Unauthenticated front page
[invirt/packages/invirt-web.git] / code / main.py
index 00a79ae..361fbbd 100755 (executable)
@@ -47,6 +47,12 @@ from invirt.common import InvalidInput, CodeError
 
 from view import View
 
+class InvirtUnauthWeb(View):
+    @cherrypy.expose
+    @cherrypy.tools.mako(filename="/unauth.mako")
+    def index(self):
+        return {'simple': True}
+
 class InvirtWeb(View):
     def __init__(self):
         super(self.__class__,self).__init__()
@@ -55,6 +61,15 @@ class InvirtWeb(View):
         self._cp_config['tools.mako.imports'] = ['from invirt.config import structs as config',
                                                  'from invirt import database']
 
+    def __getattr__(self, name):
+        if name in ("admin", "overlord"):
+            if not cherrypy.request.login in getAfsGroupMembers(config.adminacl, config.authz[0].cell):
+                raise InvalidInput('username', cherrypy.request.login,
+                                   'Not in admin group %s.' % config.adminacl)
+            cherrypy.request.state = State(cherrypy.request.login, isadmin=True)
+            return self
+        else:
+            return super(InvirtWeb, self).__getattr__(name)
 
     @cherrypy.expose
     @cherrypy.tools.mako(filename="/list.mako")
@@ -182,6 +197,11 @@ console will suffer artifacts.
         return {'request': cherrypy.request, 'kwargs': kwargs}
     helloworld._cp_config['tools.require_login.on'] = False
 
+    @cherrypy.expose
+    def errortest(self):
+        """Throw an error, to test the error-tracing mechanisms."""
+        raise RuntimeError("test of the emergency broadcast system")
+
     class MachineView(View):
         # This is hairy. Fix when CherryPy 3.2 is out. (rename to
         # _cp_dispatch, and parse the argument as a list instead of
@@ -206,6 +226,28 @@ console will suffer artifacts.
         index = info
 
         @cherrypy.expose
+        @cherrypy.tools.mako(filename="/info.mako")
+        @cherrypy.tools.require_POST()
+        def modify(self, machine_id, **fields):
+            """Handler for modifying attributes of a machine."""
+            try:
+                modify_dict = modifyDict(cherrypy.request.login, cherrypy.request.state, machine_id, fields)
+            except InvalidInput, err:
+                result = None
+                machine = validation.Validate(cherrypy.request.login, cherrypy.request.state, machine_id=machine_id).machine
+            else:
+                machine = modify_dict['machine']
+                result = 'Success!'
+                err = None
+            info_dict = infoDict(cherrypy.request.login, cherrypy.request.state, machine)
+            info_dict['err'] = err
+            if err:
+                for field in fields.keys():
+                    setattr(info_dict['defaults'], field, fields.get(field))
+            info_dict['result'] = result
+            return info_dict
+
+        @cherrypy.expose
         @cherrypy.tools.mako(filename="/vnc.mako")
         def vnc(self, machine_id):
             """VNC applet page.
@@ -335,6 +377,7 @@ class Defaults:
     autoinstall = ''
     name = ''
     description = ''
+    administrator = ''
     type = 'linux-hvm'
 
     def __init__(self, max_memory=None, max_disk=None, **kws):
@@ -466,15 +509,16 @@ def getDiskInfo(data_dict, machine):
         data_dict['%s_size' % name] = "%0.1f GiB" % (disk.size / 1024.)
     return disk_fields
 
-def modifyDict(username, state, fields):
+def modifyDict(username, state, machine_id, fields):
     """Modify a machine as specified by CGI arguments.
 
-    Return a list of local variables for modify.tmpl.
+    Return a dict containing the machine that was modified.
     """
     olddisk = {}
     session.begin()
     try:
-        kws = dict([(kw, fields.getfirst(kw)) for kw in 'machine_id owner admin contact name description memory vmtype disksize'.split()])
+        kws = dict([(kw, fields.get(kw)) for kw in 'owner admin contact name description memory vmtype disksize'.split() if fields.get(kw)])
+        kws['machine_id'] = machine_id
         validate = validation.Validate(username, state, **kws)
         machine = validate.machine
         oldname = machine.name
@@ -521,28 +565,8 @@ def modifyDict(username, state, fields):
         controls.resizeDisk(oldname, diskname, str(olddisk[diskname]))
     if hasattr(validate, 'name'):
         controls.renameMachine(machine, oldname, validate.name)
-    return dict(user=username,
-                command="modify",
-                machine=machine)
+    return dict(machine=machine)
 
-def modify(username, state, path, fields):
-    """Handler for modifying attributes of a machine."""
-    try:
-        modify_dict = modifyDict(username, state, fields)
-    except InvalidInput, err:
-        result = None
-        machine = validation.Validate(username, state, machine_id=fields.getfirst('machine_id')).machine
-    else:
-        machine = modify_dict['machine']
-        result = 'Success!'
-        err = None
-    info_dict = infoDict(username, state, machine)
-    info_dict['err'] = err
-    if err:
-        for field in fields.keys():
-            setattr(info_dict['defaults'], field, fields.getfirst(field))
-    info_dict['result'] = result
-    return templates.info(searchList=[info_dict])
 
 def badOperation(u, s, p, e):
     """Function called when accessing an unknown URI."""
@@ -619,7 +643,8 @@ def infoDict(username, state, machine):
     max_disk = validation.maxDisk(machine.owner, machine)
     defaults = Defaults()
     for name in 'machine_id name description administrator owner memory contact'.split():
-        setattr(defaults, name, getattr(machine, name))
+        if getattr(machine, name):
+            setattr(defaults, name, getattr(machine, name))
     defaults.type = machine.type.type_id
     defaults.disk = "%0.2f" % (machine.disks[0].size/1024.)
     checkpoint.checkpoint('Got defaults')
@@ -635,33 +660,7 @@ def infoDict(username, state, machine):
              fields = fields)
     return d
 
-def unauthFront(_, _2, _3, fields):
-    """Information for unauth'd users."""
-    return templates.unauth(searchList=[{'simple' : True, 
-            'hostname' : socket.getfqdn()}])
-
-def admin(username, state, path, fields):
-    if path == '':
-        return ({'Status': '303 See Other',
-                 'Location': 'admin/'},
-                "You shouldn't see this message.")
-    if not username in getAfsGroupMembers(config.adminacl, 'athena.mit.edu'):
-        raise InvalidInput('username', username,
-                           'Not in admin group %s.' % config.adminacl)
-    newstate = State(username, isadmin=True)
-    newstate.environ = state.environ
-    return handler(username, newstate, path, fields)
-
-def throwError(_, __, ___, ____):
-    """Throw an error, to test the error-tracing mechanisms."""
-    raise RuntimeError("test of the emergency broadcast system")
-
-mapping = dict(
-               modify=modify,
-               unauth=unauthFront,
-               admin=admin,
-               overlord=admin,
-               errortest=throwError)
+mapping = dict()
 
 def printHeaders(headers):
     """Print a dictionary as HTTP headers."""