Use xvm.mit.edu on the website.
[invirt/packages/invirt-web.git] / code / validation.py
index fd2b979..97a8819 100644 (file)
@@ -1,9 +1,10 @@
 #!/usr/bin/python
 
+import cache_acls
 import getafsgroups
 import re
 import string
-from sipb_xen_database import Machine, NIC
+from sipb_xen_database import Machine, NIC, Type
 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.
-    
+
     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.
 
-    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
@@ -48,6 +49,11 @@ def maxMemory(user, machine=None, on=True):
     return min(MAX_MEMORY_SINGLE, MAX_MEMORY_TOTAL-mem_usage)
 
 def maxDisk(user, machine=None):
+    """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.
+    """
     machines = getMachinesByOwner(user, machine)
     disk_usage = sum([sum([y.size for y in x.disks])
                       for x in machines if x != machine])
@@ -71,18 +77,11 @@ def validAddVm(user):
 
 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"""
-    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"""
@@ -107,7 +106,7 @@ def validMemory(user, memory, machine=None, on=True):
         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,
@@ -129,14 +128,22 @@ def validDisk(user, disk, machine=None):
         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:
-        raise InvalidInput('machine_id', machine_id, 
+        raise InvalidInput('machine_id', machine_id,
                            "Must specify a machine ID.")
     try:
         machine_id = int(machine_id)
@@ -151,26 +158,46 @@ def testMachineId(user, machine_id, exists=True):
     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 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
-    
+
 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")
-    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):