Index: trunk/web/templates/main.py
===================================================================
--- trunk/web/templates/main.py	(revision 140)
+++ trunk/web/templates/main.py	(revision 144)
@@ -42,9 +42,37 @@
                      "%02x" * 6]) % tuple(u)
 
-def maxMemory(user, machine=None):
-    return 256
+MAX_MEMORY_TOTAL = 512
+MAX_MEMORY_SINGLE = 256
+MIN_MEMORY_SINGLE = 16
+MAX_DISK_TOTAL = 50
+MAX_DISK_SINGLE = 50
+MIN_DISK_SINGLE = 0.1
+MAX_VMS_TOTAL = 10
+MAX_VMS_ACTIVE = 4
+
+def getMachinesOwner(owner):
+    return Machine.select_by(owner=owner)
+
+def maxMemory(user, machine=None, on=None):
+    machines = getMachinesOwner(user.username)
+    if on is None:
+        on = getUptimes(machines)
+    active_machines = [x for x in machines if on[x]]
+    mem_usage = sum([x.memory for x in active_machines if x != machine])
+    return min(MAX_MEMORY_SINGLE, MAX_MEMORY_TOTAL-mem_usage)
 
 def maxDisk(user, machine=None):
-    return 10.0
+    machines = getMachinesOwner(user.username)
+    disk_usage = sum([sum([y.size for y in x.disks])
+                      for x in machines if x != machine])
+    return min(MAX_DISK_SINGLE, MAX_DISK_TOTAL-disk_usage/1024.)
+
+def canAddVm(user, on=None):
+    machines = getMachinesOwner(user.username)
+    if on is None:
+        on = getUptimes(machines)
+    active_machines = [x for x in machines if on[x]]
+    return (len(machines) < MAX_VMS_TOTAL and
+            len(active_machines) < MAX_VMS_ACTIVE)
 
 def haveAccess(user, machine):
@@ -95,8 +123,9 @@
                          stderr=subprocess.PIPE)
     if kws.get('err'):
+        p.wait()
         return p.stdout.read(), p.stderr.read()
     if p.wait():
-        print >> sys.stderr, 'ERROR on remctl ', args
-        print >> sys.stderr, p.stderr.read()
+        raise MyException('ERROR on remctl %s: %s' %
+                          (args, p.stderr.read()))
     return p.stdout.read()
 
@@ -159,5 +188,8 @@
         uptime = ' '.join(lst[2:])
         d[name] = uptime
-    return d
+    ans = {}
+    for m in machines:
+        ans[m] = d.get(m.name)
+    return ans
 
 def statusInfo(machine):
@@ -191,4 +223,10 @@
     transaction = ctx.current.create_transaction()
     try:
+        if memory > maxMemory(user):
+            raise MyException("Too much memory requested")
+        if disk > maxDisk(user) * 1024:
+            raise MyException("Too much disk requested")
+        if not canAddVm(user):
+            raise MyException("Too many VMs requested")
         res = meta.engine.execute('select nextval(\'"machines_machine_id_seq"\')')
         id = res.fetchone()[0]
@@ -218,6 +256,6 @@
         transaction.rollback()
         raise
+    registerMachine(machine)
     makeDisks()
-    registerMachine(machine)
     # tell it to boot with cdrom
     bootMachine(machine, cdrom)
@@ -228,8 +266,9 @@
     try:
         memory = int(memory)
-        if memory <= 0:
+        if memory < MIN_MEMORY_SINGLE:
             raise ValueError
     except ValueError:
-        raise MyException("Invalid memory amount")
+        raise MyException("Invalid memory amount; must be at least %s MB" %
+                          MIN_MEMORY_SINGLE)
     if memory > maxMemory(user, machine):
         raise MyException("Too much memory requested")
@@ -242,8 +281,9 @@
             raise MyException("Too much disk requested")
         disk = int(disk * 1024)
-        if disk <= 0:
+        if disk < MIN_DISK_SINGLE * 1024:
             raise ValueError
     except ValueError:
-        raise MyException("Invalid disk amount")
+        raise MyException("Invalid disk amount; minimum is %s GB" %
+                          MIN_DISK_SINGLE)
     return disk
 
@@ -287,17 +327,22 @@
     on = uptimes
     for m in machines:
-        if not on.get(m.name):
-            has_vnc[m.name] = 'Off'
+        if not on[m]:
+            has_vnc[m] = 'Off'
         elif m.type.hvm:
-            has_vnc[m.name] = True
+            has_vnc[m] = True
         else:
-            has_vnc[m.name] = "ParaVM"+helppopup("paravm_console")
+            has_vnc[m] = "ParaVM"+helppopup("paravm_console")
     #     for m in machines:
     #         status = statusInfo(m)
     #         on[m.name] = status is not None
     #         has_vnc[m.name] = hasVnc(status)
+    max_mem=maxMemory(user, on=on)
+    max_disk=maxDisk(user)
     d = dict(user=user,
-             maxmem=maxMemory(user),
-             maxdisk=maxDisk(user),
+             can_add_vm=canAddVm(user, on=on),
+             max_mem=max_mem,
+             max_disk=max_disk,
+             default_mem=max_mem,
+             default_disk=min(4.0, max_disk),
              machines=machines,
              has_vnc=has_vnc,
@@ -418,4 +463,6 @@
             remctl('reboot', machine.name)
     elif action == 'Power on':
+        if maxMemory(user) < machine.memory:
+            raise MyException("You don't have enough free RAM quota")
         bootMachine(machine, cdrom)
     elif action == 'Power off':
@@ -515,5 +562,6 @@
             pass
             #fields.append((disp, None))
-
+    max_mem = maxMemory(user, machine)
+    max_disk = maxDisk(user, machine)
     d = dict(user=user,
              cdroms=CDROM.select(),
@@ -523,6 +571,6 @@
              uptime=str(uptime),
              ram=machine.memory,
-             maxmem=maxMemory(user, machine),
-             maxdisk=maxDisk(user, machine),
+             max_mem=max_mem,
+             max_disk=max_disk,
              fields = fields)
     print Template(file='info.tmpl',
@@ -549,6 +597,6 @@
         u.email = os.environ[ 'SSL_CLIENT_S_DN_Email']
     else:
-        u.username = 'nobody'
-        u.email = None
+        u.username = 'moo'
+        u.email = 'nobody'
     connect('postgres://sipb-xen@sipb-xen-dev/sipb_xen')
     operation = os.environ.get('PATH_INFO', '')
