Use cached ACLs
authorEric Price <ecprice@mit.edu>
Fri, 25 Jan 2008 02:34:53 +0000 (21:34 -0500)
committerEric Price <ecprice@mit.edu>
Fri, 25 Jan 2008 02:34:53 +0000 (21:34 -0500)
svn path=/trunk/web/; revision=261

controls.py
main.py
webcommon.py

index 2e9b541..b6f6dec 100644 (file)
@@ -74,10 +74,20 @@ def bootMachine(machine, cdtype):
     id of the CD (e.g. 'gutsy_i386')
     """
     if cdtype is not None:
-        remctl('control', machine.name, 'create', 
-               cdtype)
+        out, err = remctl('control', machine.name, 'create', 
+                          cdtype, err=True)
     else:
-        remctl('control', machine.name, 'create')
+        out, err = remctl('control', machine.name, 'create',
+                          err=True)
+    if 'already exists' in out:
+        raise InvalidInput('action', 'create',
+                           'VM %s is already on' % machine.name)
+    elif err:
+        raise CodeError('"%s" on "control %s create %s' 
+                        % (err, machine.name, cdtype))
+    else:
+        raise CodeError('"%s" on "control %s create %s' 
+                        % (err, machine.name, cdtype))
 
 def registerMachine(machine):
     """Register a machine to be controlled by the web interface"""
@@ -214,11 +224,9 @@ def deleteVM(machine):
 
 def commandResult(user, fields):
     start_time = 0
-    print >> sys.stderr, time.time()-start_time
     machine = validation.testMachineId(user, fields.getfirst('machine_id'))
     action = fields.getfirst('action')
     cdrom = fields.getfirst('cdrom')
-    print >> sys.stderr, time.time()-start_time
     if cdrom is not None and not CDROM.get(cdrom):
         raise CodeError("Invalid cdrom type '%s'" % cdrom)    
     if action not in ('Reboot', 'Power on', 'Power off', 'Shutdown', 
@@ -268,7 +276,6 @@ def commandResult(user, fields):
                 raise CodeError('ERROR on remctl')
     elif action == 'Delete VM':
         deleteVM(machine)
-    print >> sys.stderr, time.time()-start_time
 
     d = dict(user=user,
              command=action,
diff --git a/main.py b/main.py
index f567c71..7e7e23d 100755 (executable)
--- a/main.py
+++ b/main.py
@@ -36,7 +36,7 @@ sys.path.append('/home/ecprice/.local/lib/python2.5/site-packages')
 
 import templates
 from Cheetah.Template import Template
-from sipb_xen_database import Machine, CDROM, ctx, connect
+from sipb_xen_database import Machine, CDROM, ctx, connect, MachineAccess
 import validation
 from webcommon import InvalidInput, CodeError, g
 import controls
@@ -183,8 +183,7 @@ def create(user, fields):
 
 
 def getListDict(user):
-    machines = [m for m in Machine.select()
-                if validation.haveAccess(user, m)]
+    machines = g.machines
     checkpoint.checkpoint('Got my machines')
     on = {}
     has_vnc = {}
@@ -327,8 +326,8 @@ def command(user, fields):
     except InvalidInput, err:
         if not back:
             raise
-        print >> sys.stderr, err
-        result = None
+        #print >> sys.stderr, err
+        result = err
     else:
         result = 'Success!'
         if not back:
@@ -344,8 +343,7 @@ def command(user, fields):
         d['result'] = result
         return templates.info(searchList=[d])
     else:
-        raise InvalidInput
-    ('back', back, 'Not a known back page.')
+        raise InvalidInput('back', back, 'Not a known back page.')
 
 def modifyDict(user, fields):
     olddisk = {}
index 01b820a..1b39a2c 100644 (file)
@@ -1,6 +1,6 @@
 """Exceptions for the web interface."""
 
-from sipb_xen_database import Machine
+from sipb_xen_database import Machine, MachineAccess
 
 class MyException(Exception):
     """Base class for my exceptions"""
@@ -24,21 +24,32 @@ class CodeError(MyException):
 
 import controls
 
+def cachedproperty(func):
+    name = '__cache_' + func.__name__ + '_' + str(id(func))
+    def getter(self):
+        try:
+            return getattr(self, name)
+        except AttributeError:
+            value = func(self)
+            setattr(self, name, value)
+            return value
+    return property(getter)
+
 class Global(object):
     """Global state of the system, to avoid duplicate remctls to get state"""
     def __init__(self, user):
         self.user = user
-
-    def __get_uptimes(self):
-        if not hasattr(self, '_uptimes'):
-            self._uptimes = controls.getUptimes(Machine.select())
-        return self._uptimes
-    uptimes = property(__get_uptimes)
+    
+    machines = cachedproperty(lambda self: 
+                             [ma.machine for ma in 
+                              MachineAccess.select_by(user=self.user)])
+    uptimes = cachedproperty(lambda self: 
+                             controls.getUptimes(self.machines))
 
     def clear(self):
         """Clear the state so future accesses reload it."""
-        for attr in ('_uptimes', ):
-            if hasattr(self, attr):
+        for attr in self.__dict__:
+            if attr.startswith('__cache_'):
                 delattr(self, attr)
 
 g = Global(None)