Added some code to display a service message from the xvm team to the unauth page...
[invirt/packages/invirt-web.git] / code / main.py
index a494046..b05906e 100755 (executable)
@@ -6,6 +6,7 @@ import cPickle
 import cgi
 import datetime
 import hmac
+import os
 import random
 import sha
 import sys
@@ -37,11 +38,26 @@ from invirt.common import InvalidInput, CodeError
 
 from view import View, revertStandardError
 
+
+static_dir = os.path.join(os.path.dirname(__file__), 'static')
+InvirtStatic = cherrypy.tools.staticdir.handler(
+    root=static_dir,
+    dir=static_dir,
+    section='/static')
+
 class InvirtUnauthWeb(View):
+    static = InvirtStatic
+
     @cherrypy.expose
     @cherrypy.tools.mako(filename="/unauth.mako")
     def index(self):
-        return {'simple': True}
+        if(os.path.exists("/etc/invirt/message")):
+            f = open('/etc/invirt/message')
+            message = f.read()
+        else:message = None
+        d = dict(simple = True, serviceMessage = message)
+        return d
+
 
 class InvirtWeb(View):
     def __init__(self):
@@ -53,6 +69,8 @@ class InvirtWeb(View):
                                                  'from invirt import database']
         self._cp_config['request.error_response'] = self.handle_error
 
+    static = InvirtStatic
+
     @cherrypy.expose
     @cherrypy.tools.mako(filename="/invalid.mako")
     def invalidInput(self):
@@ -86,7 +104,7 @@ class InvirtWeb(View):
 
     def __getattr__(self, name):
         if name in ("admin", "overlord"):
-            if not cherrypy.request.login in getAfsGroupMembers(config.adminacl, config.authz[0].cell):
+            if not cherrypy.request.login in getAfsGroupMembers(config.adminacl, config.authz.afs.cells[0].cell):
                 raise InvalidInput('username', cherrypy.request.login,
                                    'Not in admin group %s.' % config.adminacl)
             cherrypy.request.state = State(cherrypy.request.login, isadmin=True)
@@ -112,11 +130,9 @@ class InvirtWeb(View):
     @cherrypy.tools.mako(filename="/list.mako")
     def list(self, result=None):
         """Handler for list requests."""
-        checkpoint.checkpoint('Getting list dict')
         d = getListDict(cherrypy.request.login, cherrypy.request.state)
         if result is not None:
             d['result'] = result
-        checkpoint.checkpoint('Got list dict')
         return d
     index=list
 
@@ -248,11 +264,17 @@ console will suffer artifacts.
         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
-        # string
-
         def __getattr__(self, name):
+            """Synthesize attributes to allow RESTful URLs like
+            /machine/13/info. This is hairy. CherryPy 3.2 adds a
+            method called _cp_dispatch that allows you to explicitly
+            handle URLs that can't be mapped, and it allows you to
+            rewrite the path components and continue processing.
+
+            This function gets the next path component being resolved
+            as a string. _cp_dispatch will get an array of strings
+            representing any subsequent path components as well."""
+
             try:
                 cherrypy.request.params['machine_id'] = int(name)
                 return self
@@ -267,7 +289,6 @@ console will suffer artifacts.
                                           cherrypy.request.state,
                                           machine_id=machine_id).machine
             d = infoDict(cherrypy.request.login, cherrypy.request.state, machine)
-            checkpoint.checkpoint('Got infodict')
             return d
         index = info
 
@@ -347,12 +368,12 @@ console will suffer artifacts.
         def command(self, command_name, machine_id, **kwargs):
             """Handler for running commands like boot and delete on a VM."""
             back = kwargs.get('back')
+            if command_name == 'delete':
+                back = 'list'
             try:
                 d = controls.commandResult(cherrypy.request.login,
                                            cherrypy.request.state,
                                            command_name, machine_id, kwargs)
-                if d['command'] == 'Delete VM':
-                    back = 'list'
             except InvalidInput, err:
                 if not back:
                     raise
@@ -375,20 +396,6 @@ console will suffer artifacts.
 
     machine = MachineView()
 
-class Checkpoint:
-    def __init__(self):
-        self.start_time = time.time()
-        self.checkpoints = []
-
-    def checkpoint(self, s):
-        self.checkpoints.append((s, time.time()))
-
-    def __str__(self):
-        return ('Timing info:\n%s\n' %
-                '\n'.join(['%s: %s' % (d, t - self.start_time) for
-                           (d, t) in self.checkpoints]))
-
-checkpoint = Checkpoint()
 
 class Defaults:
     """Class to store default values for fields."""
@@ -422,37 +429,29 @@ def hasVnc(status):
 
 def getListDict(username, state):
     """Gets the list of local variables used by list.tmpl."""
-    checkpoint.checkpoint('Starting')
     machines = state.machines
-    checkpoint.checkpoint('Got my machines')
     on = {}
     has_vnc = {}
     installing = {}
     xmlist = state.xmlist
-    checkpoint.checkpoint('Got uptimes')
     for m in machines:
         if m not in xmlist:
             has_vnc[m] = 'Off'
             m.uptime = None
         else:
             m.uptime = xmlist[m]['uptime']
+            installing[m] = bool(xmlist[m].get('autoinstall'))
             if xmlist[m]['console']:
                 has_vnc[m] = True
             elif m.type.hvm:
                 has_vnc[m] = "WTF?"
             else:
                 has_vnc[m] = "ParaVM"
-            if xmlist[m].get('autoinstall'):
-                installing[m] = True
-            else:
-                installing[m] = False
     max_memory = validation.maxMemory(username, state)
     max_disk = validation.maxDisk(username)
-    checkpoint.checkpoint('Got max mem/disk')
     defaults = Defaults(max_memory=max_memory,
                         max_disk=max_disk,
                         owner=username)
-    checkpoint.checkpoint('Got defaults')
     def sortkey(machine):
         return (machine.owner != username, machine.owner, machine.name)
     machines = sorted(machines, key=sortkey)
@@ -582,7 +581,6 @@ def modifyDict(username, state, machine_id, fields):
 def infoDict(username, state, machine):
     """Get the variables used by info.tmpl."""
     status = controls.statusInfo(machine)
-    checkpoint.checkpoint('Getting status info')
     has_vnc = hasVnc(status)
     if status is None:
         main_status = dict(name=machine.name,
@@ -596,7 +594,6 @@ def infoDict(username, state, machine):
         uptime = datetime.timedelta(seconds=int(time.time()-start_time))
         cpu_time_float = float(main_status.get('cpu_time', 0))
         cputime = datetime.timedelta(seconds=int(cpu_time_float))
-    checkpoint.checkpoint('Status')
     display_fields = [('name', 'Name'),
                       ('description', 'Description'),
                       ('owner', 'Owner'),
@@ -642,11 +639,7 @@ def infoDict(username, state, machine):
             pass
             #fields.append((disp, None))
 
-    checkpoint.checkpoint('Got fields')
-
-
     max_mem = validation.maxMemory(machine.owner, state, machine, False)
-    checkpoint.checkpoint('Got mem')
     max_disk = validation.maxDisk(machine.owner, machine)
     defaults = Defaults()
     for name in 'machine_id name description administrator owner memory contact'.split():
@@ -654,7 +647,6 @@ def infoDict(username, state, machine):
             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')
     d = dict(user=username,
              on=status is not None,
              machine=machine,