Fix jis's bug
[invirt/packages/invirt-web.git] / code / validation.py
index fd2b979..c0e3aeb 100644 (file)
@@ -1,9 +1,10 @@
 #!/usr/bin/python
 
 #!/usr/bin/python
 
+import cache_acls
 import getafsgroups
 import re
 import string
 import getafsgroups
 import re
 import string
-from sipb_xen_database import Machine, NIC
+from sipb_xen_database import Machine, NIC, Type, Disk
 from webcommon import InvalidInput, g
 
 MAX_MEMORY_TOTAL = 512
 from webcommon import InvalidInput, g
 
 MAX_MEMORY_TOTAL = 512
@@ -17,7 +18,7 @@ MAX_VMS_ACTIVE = 4
 
 def getMachinesByOwner(user, machine=None):
     """Return the machines owned by the same as a machine.
 
 def getMachinesByOwner(user, machine=None):
     """Return the machines owned by the same as a machine.
-    
+
     If the machine is None, return the machines owned by the same
     user.
     """
     If the machine is None, return the machines owned by the same
     user.
     """
@@ -30,7 +31,7 @@ def getMachinesByOwner(user, machine=None):
 def maxMemory(user, machine=None, on=True):
     """Return the maximum memory for a machine or a user.
 
 def maxMemory(user, machine=None, on=True):
     """Return the maximum memory for a machine or a user.
 
-    If machine is None, return the memory available for a new 
+    If machine is None, return the memory available for a new
     machine.  Else, return the maximum that machine can have.
 
     on is whether the machine should be turned on.  If false, the max
     machine.  Else, return the maximum that machine can have.
 
     on is whether the machine should be turned on.  If false, the max
@@ -43,19 +44,27 @@ def maxMemory(user, machine=None, on=True):
     if not on:
         return MAX_MEMORY_SINGLE
     machines = getMachinesByOwner(user, machine)
     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)
 
 def maxDisk(user, machine=None):
     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):
-    machines = getMachinesByOwner(user, machine)
-    disk_usage = sum([sum([y.size for y in x.disks])
-                      for x in machines if x != machine])
+    """Return the maximum disk that a machine can reach.
+
+    If machine is None, the maximum disk for a new machine. Otherwise,
+    return the maximum that a given machine can be changed to.
+    """
+    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) or 0
     return min(MAX_DISK_SINGLE, MAX_DISK_TOTAL-disk_usage/1024.)
 
 def cantAddVm(user):
     machines = getMachinesByOwner(user)
     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:
     if len(machines) >= MAX_VMS_TOTAL:
         return 'You have too many VMs to create a new one.'
     if len(active_machines) >= MAX_VMS_ACTIVE:
@@ -71,18 +80,11 @@ def validAddVm(user):
 
 def haveAccess(user, machine):
     """Return whether a user has administrative access to a machine"""
 
 def haveAccess(user, machine):
     """Return whether a user has administrative access to a machine"""
-    if user in (machine.administrator, machine.owner):
-        return True
-    if getafsgroups.checkAfsGroup(user, machine.administrator, 
-                                  'athena.mit.edu'): #XXX Cell?
-        return True
-    if not getafsgroups.notLockerOwner(user, machine.owner):
-        return True
-    return owns(user, machine)
+    return user in cache_acls.accessList(machine)
 
 def owns(user, machine):
     """Return whether a user owns a machine"""
 
 def owns(user, machine):
     """Return whether a user owns a machine"""
-    return not getafsgroups.notLockerOwner(user, machine.owner)
+    return user in expandLocker(machine.owner)
 
 def validMachineName(name):
     """Check that name is valid for a machine name"""
 
 def validMachineName(name):
     """Check that name is valid for a machine name"""
@@ -107,7 +109,7 @@ def validMemory(user, memory, machine=None, on=True):
         if memory < MIN_MEMORY_SINGLE:
             raise ValueError
     except ValueError:
         if memory < MIN_MEMORY_SINGLE:
             raise ValueError
     except ValueError:
-        raise InvalidInput('memory', memory, 
+        raise InvalidInput('memory', memory,
                            "Minimum %s MiB" % MIN_MEMORY_SINGLE)
     if memory > maxMemory(user, machine, on):
         raise InvalidInput('memory', memory,
                            "Minimum %s MiB" % MIN_MEMORY_SINGLE)
     if memory > maxMemory(user, machine, on):
         raise InvalidInput('memory', memory,
@@ -129,14 +131,22 @@ def validDisk(user, disk, machine=None):
         raise InvalidInput('disk', disk,
                            "Minimum %s GiB" % MIN_DISK_SINGLE)
     return disk
         raise InvalidInput('disk', disk,
                            "Minimum %s GiB" % MIN_DISK_SINGLE)
     return disk
-            
+
+def validVmType(vm_type):
+    if vm_type is None:
+        return None
+    t = Type.get(vm_type)
+    if t is None:
+        raise CodeError("Invalid vm type '%s'"  % vm_type)
+    return t
+
 def testMachineId(user, machine_id, exists=True):
     """Parse, validate and check authorization for a given user and machine.
 
     If exists is False, don't check that it exists.
     """
     if machine_id is None:
 def testMachineId(user, machine_id, exists=True):
     """Parse, validate and check authorization for a given user and machine.
 
     If exists is False, don't check that it exists.
     """
     if machine_id is None:
-        raise InvalidInput('machine_id', machine_id, 
+        raise InvalidInput('machine_id', machine_id,
                            "Must specify a machine ID.")
     try:
         machine_id = int(machine_id)
                            "Must specify a machine ID.")
     try:
         machine_id = int(machine_id)
@@ -151,26 +161,46 @@ def testMachineId(user, machine_id, exists=True):
     return machine
 
 def testAdmin(user, admin, machine):
     return machine
 
 def testAdmin(user, admin, machine):
+    """Determine whether a user can set the admin of a machine to this value.
+
+    Return the value to set the admin field to (possibly 'system:' +
+    admin).  XXX is modifying this a good idea?
+    """
     if admin in (None, machine.administrator):
         return None
     if admin == user:
         return admin
     if admin in (None, machine.administrator):
         return None
     if admin == user:
         return admin
-    if getafsgroups.checkAfsGroup(user, admin, 'athena.mit.edu'):
-        return admin
-    if getafsgroups.checkAfsGroup(user, 'system:'+admin,
-                                  'athena.mit.edu'):
-        return 'system:'+admin
+    if ':' not in admin:
+        if cache_acls.isUser(admin):
+            return admin
+        admin = 'system:' + admin
+    try:
+        if user in getafsgroups.getAfsGroupMembers(admin, 'athena.mit.edu'):
+            return admin
+    except getafsgroups.AfsProcessError, e:
+        errmsg = str(e)
+        if errmsg.startswith("pts: User or group doesn't exist"):
+            errmsg = 'The group "%s" does not exist.' % admin
+        raise InvalidInput('administrator', admin, errmsg)
+    #XXX Should we require that user is in the admin group?
     return admin
     return admin
-    
+
 def testOwner(user, owner, machine=None):
 def testOwner(user, owner, machine=None):
+    """Determine whether a user can set the owner of a machine to this value.
+
+    If machine is None, this is the owner of a new machine.
+    """
     if owner == user or machine is not None and owner == machine.owner:
         return owner
     if owner is None:
         raise InvalidInput('owner', owner, "Owner must be specified")
     if owner == user or machine is not None and owner == machine.owner:
         return owner
     if owner is None:
         raise InvalidInput('owner', owner, "Owner must be specified")
-    value = getafsgroups.notLockerOwner(user, owner)
-    if not value:
-        return owner
-    raise InvalidInput('owner', owner, value)
+    try:
+        if user not in cache_acls.expandLocker(owner):
+            raise InvalidInput('owner', owner, 'You do not have access to the '
+                               + owner + ' locker')
+    except getafsgroups.AfsProcessError, e:
+        raise InvalidInput('owner', owner, str(e))
+    return owner
 
 def testContact(user, contact, machine=None):
     if contact in (None, machine.contact):
 
 def testContact(user, contact, machine=None):
     if contact in (None, machine.contact):