Use joins, new xmlist.py
authorEric Price <ecprice@mit.edu>
Fri, 16 May 2008 01:55:17 +0000 (21:55 -0400)
committerEric Price <ecprice@mit.edu>
Fri, 16 May 2008 01:55:17 +0000 (21:55 -0400)
svn path=/trunk/packages/sipb-xen-www/; revision=535

code/controls.py
code/main.py
code/templates/list.tmpl
code/validation.py
code/webcommon.py

index 3cf6b1d..68e911c 100644 (file)
@@ -11,6 +11,7 @@ import sys
 import time
 import re
 import cache_acls
+import cPickle
 
 # ... and stolen from xend/uuid.py
 def randomUUID():
@@ -113,7 +114,7 @@ def createVm(owner, contact, name, memory, disk_size, machine_type, cdrom, clone
         machine.boot_off_cd = True
         machine.type_id = machine_type.type_id
         ctx.current.save(machine)
-        disk = Disk(machine_id=machine.machine_id, 
+        disk = Disk(machine_id=machine.machine_id,
                     guest_device_name='hda', size=disk_size)
         open_nics = NIC.select_by(machine_id=None)
         if not open_nics: #No IPs left!
@@ -122,7 +123,7 @@ def createVm(owner, contact, name, memory, disk_size, machine_type, cdrom, clone
         nic = open_nics[0]
         nic.machine_id = machine.machine_id
         nic.hostname = name
-        ctx.current.save(nic)    
+        ctx.current.save(nic)
         ctx.current.save(disk)
         cache_acls.refreshMachine(machine)
         transaction.commit()
@@ -136,20 +137,13 @@ def createVm(owner, contact, name, memory, disk_size, machine_type, cdrom, clone
     bootMachine(machine, cdrom)
     return machine
 
-def getUptimes(machines=None):
-    """Return a dictionary mapping machine names to uptime strings"""
-    value_string = remctl('web', 'listvms')
-    lines = value_string.splitlines()
-    d = {}
-    for line in lines:
-        lst = line.split()
-        name, id = lst[:2]
-        uptime = ' '.join(lst[2:])
-        d[name] = uptime
-    ans = {}
-    for m in machines:
-        ans[m] = d.get(m.name)
-    return ans
+def getList(machines):
+    """Return a dictionary mapping machine  to dicts."""
+    value_string = remctl('web', 'listvms', '--pickle')
+    value_dict = cPickle.loads(value_string)
+
+    d = dict((m, value_dict[m.name]) for m in machines if m.name in value_dict)
+    return d
 
 def parseStatus(s):
     """Parse a status string into nested tuples of strings.
index e5fdfa9..e208a13 100755 (executable)
@@ -196,20 +196,25 @@ def create(user, fields):
 
 def getListDict(user):
     """Gets the list of local variables used by list.tmpl."""
+    checkpoint.checkpoint('Starting')
     machines = g.machines
     checkpoint.checkpoint('Got my machines')
     on = {}
     has_vnc = {}
-    on = g.uptimes
+    xmlist = g.xmlist
     checkpoint.checkpoint('Got uptimes')
     for m in machines:
-        m.uptime = g.uptimes.get(m)
-        if not on[m]:
+        if m not in xmlist:
             has_vnc[m] = 'Off'
-        elif m.type.hvm:
-            has_vnc[m] = True
+            m.uptime = None
         else:
-            has_vnc[m] = "ParaVM"+helppopup("paravm_console")
+            m.uptime = xmlist[m]['uptime']
+            if xmlist[m]['console']:
+                has_vnc[m] = True
+            elif m.type.hvm:
+                has_vnc[m] = "WTF?"
+            else:
+                has_vnc[m] = "ParaVM"+helppopup("paravm_console")
     max_memory = validation.maxMemory(user)
     max_disk = validation.maxDisk(user)
     checkpoint.checkpoint('Got max mem/disk')
@@ -227,8 +232,7 @@ def getListDict(user):
              max_disk=max_disk,
              defaults=defaults,
              machines=machines,
-             has_vnc=has_vnc,
-             uptimes=g.uptimes)
+             has_vnc=has_vnc)
     return d
 
 def listVms(user, fields):
@@ -651,7 +655,8 @@ def main(operation, user, fields):
         output_string =  str(output)
         checkpoint.checkpoint('output as a string')
         print output_string
-        print '<!-- <pre>%s</pre> -->' % checkpoint
+        if fields.has_key('timedebug'):
+            print '<pre>%s</pre>' % checkpoint
     except Exception, err:
         if not fields.has_key('js'):
             if isinstance(err, CodeError):
@@ -675,6 +680,13 @@ def main(operation, user, fields):
 
 if __name__ == '__main__':
     fields = cgi.FieldStorage()
+
+    if fields.has_key('sqldebug'):
+        import logging
+        logging.basicConfig()
+        logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
+        logging.getLogger('sqlalchemy.orm.unitofwork').setLevel(logging.INFO)
+
     u = getUser()
     g.user = u
     operation = os.environ.get('PATH_INFO', '')
index 2475542..f6c9a09 100644 (file)
@@ -1,5 +1,6 @@
 #from skeleton import skeleton
 #extends skeleton
+#import datetime
 
 
 #def title
@@ -118,7 +119,7 @@ $errorRow('cdrom', $err)
 #end if
 <td>#slurp
 #if $machine.uptime
-$machine.uptime#slurp
+${datetime.timedelta(seconds=int(machine.uptime))}#slurp
 #end if
 </td>
        <td>#slurp
index 97a8819..874dbb0 100644 (file)
@@ -4,7 +4,7 @@ import cache_acls
 import getafsgroups
 import re
 import string
-from sipb_xen_database import Machine, NIC, Type
+from sipb_xen_database import Machine, NIC, Type, Disk
 from webcommon import InvalidInput, g
 
 MAX_MEMORY_TOTAL = 512
@@ -44,7 +44,7 @@ def maxMemory(user, machine=None, on=True):
     if not on:
         return MAX_MEMORY_SINGLE
     machines = getMachinesByOwner(user, machine)
-    active_machines = [x for x in machines if g.uptimes.get(x)]
+    active_machines = [x for x in machines if g.xmlist.get(x)]
     mem_usage = sum([x.memory for x in active_machines if x != machine])
     return min(MAX_MEMORY_SINGLE, MAX_MEMORY_TOTAL-mem_usage)
 
@@ -54,14 +54,17 @@ def maxDisk(user, machine=None):
     If machine is None, the maximum disk for a new machine. Otherwise,
     return the maximum that a given machine can be changed to.
     """
-    machines = getMachinesByOwner(user, machine)
-    disk_usage = sum([sum([y.size for y in x.disks])
-                      for x in machines if x != machine])
+    if machine is not None:
+        machine_id = machine.machine_id
+    else:
+        machine_id = None
+    disk_usage = Disk.query().filter_by(Disk.c.machine_id != machine_id,
+                                        owner=user).sum(Disk.c.size)
     return min(MAX_DISK_SINGLE, MAX_DISK_TOTAL-disk_usage/1024.)
 
 def cantAddVm(user):
     machines = getMachinesByOwner(user)
-    active_machines = [x for x in machines if g.uptimes.get(x)]
+    active_machines = [x for x in machines if g.xmlist.get(x)]
     if len(machines) >= MAX_VMS_TOTAL:
         return 'You have too many VMs to create a new one.'
     if len(active_machines) >= MAX_VMS_ACTIVE:
index 4b58e6b..ee9bb73 100644 (file)
@@ -1,5 +1,6 @@
 """Exceptions for the web interface."""
 
+import time
 from sipb_xen_database import Machine, MachineAccess
 
 class MyException(Exception):
@@ -39,12 +40,11 @@ class Global(object):
     """Global state of the system, to avoid duplicate remctls to get state"""
     def __init__(self, user):
         self.user = user
-    
-    machines = cachedproperty(lambda self: 
-                             [ma.machine for ma in 
-                              MachineAccess.select_by(user=self.user)])
-    uptimes = cachedproperty(lambda self: 
-                             controls.getUptimes(self.machines))
+
+    machines = cachedproperty(lambda self:
+                                  Machine.query().join('acl').select_by(user=self.user))
+    xmlist = cachedproperty(lambda self:
+                                controls.getList(self.machines))
 
     def clear(self):
         """Clear the state so future accesses reload it."""