6 from sipb_xen_database import Machine, NIC
7 from webcommon import InvalidInput, g
10 MAX_MEMORY_SINGLE = 256
11 MIN_MEMORY_SINGLE = 16
18 def getMachinesByOwner(user, machine=None):
19 """Return the machines owned by the same as a machine.
21 If the machine is None, return the machines owned by the same
28 return Machine.select_by(owner=owner)
30 def maxMemory(user, machine=None, on=True):
31 """Return the maximum memory for a machine or a user.
33 If machine is None, return the memory available for a new
34 machine. Else, return the maximum that machine can have.
36 on is whether the machine should be turned on. If false, the max
37 memory for the machine to change to, if it is left off, is
41 return MAX_MEMORY_SINGLE
42 machines = getMachinesByOwner(user, machine)
43 active_machines = [x for x in machines if g.uptimes[x]]
44 mem_usage = sum([x.memory for x in active_machines if x != machine])
45 return min(MAX_MEMORY_SINGLE, MAX_MEMORY_TOTAL-mem_usage)
47 def maxDisk(user, machine=None):
48 machines = getMachinesByOwner(user, machine)
49 disk_usage = sum([sum([y.size for y in x.disks])
50 for x in machines if x != machine])
51 return min(MAX_DISK_SINGLE, MAX_DISK_TOTAL-disk_usage/1024.)
54 machines = getMachinesByOwner(user)
55 active_machines = [x for x in machines if g.uptimes[x]]
56 if len(machines) >= MAX_VMS_TOTAL:
57 return 'You have too many VMs to create a new one.'
58 if len(active_machines) >= MAX_VMS_ACTIVE:
59 return ('You already have the maximum number of VMs turned on. '
60 'To create more, turn one off.')
64 reason = cantAddVm(user)
66 raise InvalidInput('create', True, reason)
69 def haveAccess(user, machine):
70 """Return whether a user has adminstrative access to a machine"""
71 if user.username == 'moo':
73 if user.username in (machine.administrator, machine.owner):
75 if getafsgroups.checkAfsGroup(user.username, machine.administrator,
76 'athena.mit.edu'): #XXX Cell?
78 if getafsgroups.checkLockerOwner(user.username, machine.owner):
80 return owns(user, machine)
82 def owns(user, machine):
83 """Return whether a user owns a machine"""
84 if user.username == 'moo':
86 return getafsgroups.checkLockerOwner(user.username, machine.owner)
88 def validMachineName(name):
89 """Check that name is valid for a machine name"""
92 charset = string.ascii_letters + string.digits + '-_'
93 if name[0] in '-_' or len(name) > 22:
100 def validMemory(user, memory, machine=None, on=True):
101 """Parse and validate limits for memory for a given user and machine.
103 on is whether the memory must be valid after the machine is
108 if memory < MIN_MEMORY_SINGLE:
111 raise InvalidInput('memory', memory,
112 "Minimum %s MB" % MIN_MEMORY_SINGLE)
113 if memory > maxMemory(user, machine, on):
114 raise InvalidInput('memory', memory,
115 'Maximum %s MB' % maxMemory(user, machine))
118 def validDisk(user, disk, machine=None):
119 """Parse and validate limits for disk for a given user and machine."""
122 if disk > maxDisk(user, machine):
123 raise InvalidInput('disk', disk,
124 "Maximum %s G" % maxDisk(user, machine))
125 disk = int(disk * 1024)
126 if disk < MIN_DISK_SINGLE * 1024:
129 raise InvalidInput('disk', disk,
130 "Minimum %s GB" % MIN_DISK_SINGLE)
133 def testMachineId(user, machine_id, exists=True):
134 """Parse, validate and check authorization for a given user and machine.
136 If exists is False, don't check that it exists.
138 if machine_id is None:
139 raise InvalidInput('machine_id', machine_id,
140 "Must specify a machine ID.")
142 machine_id = int(machine_id)
144 raise InvalidInput('machine_id', machine_id, "Must be an integer.")
145 machine = Machine.get(machine_id)
146 if exists and machine is None:
147 raise InvalidInput('machine_id', machine_id, "Does not exist.")
148 if machine is not None and not haveAccess(user, machine):
149 raise InvalidInput('machine_id', machine_id,
150 "You do not have access to this machine.")
153 def testAdmin(user, admin, machine):
154 if admin in (None, machine.administrator):
156 if admin == user.username:
158 if getafsgroups.checkAfsGroup(user.username, admin, 'athena.mit.edu'):
160 if getafsgroups.checkAfsGroup(user.username, 'system:'+admin,
162 return 'system:'+admin
165 def testOwner(user, owner, machine):
166 if owner in (None, machine.owner):
168 value = getafsgroups.checkLockerOwner(user.username, owner, verbose=True)
171 raise InvalidInput('owner', owner, value)
173 def testContact(user, contact, machine=None):
174 if contact in (None, machine.contact):
176 if not re.match("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$", contact, re.I):
177 raise InvalidInput('contact', contact, "Not a valid email.")
180 def testDisk(user, disksize, machine=None):
183 def testName(user, name, machine=None):
184 if name in (None, machine.name):
186 if not Machine.select_by(name=name):
188 raise InvalidInput('name', name, "Name is already taken.")
190 def testHostname(user, hostname, machine):
191 for nic in machine.nics:
192 if hostname == nic.hostname:
194 # check if doesn't already exist
195 if NIC.select_by(hostname=hostname):
196 raise InvalidInput('hostname', hostname,
198 if not re.match("^[A-Z0-9-]{1,22}$", hostname, re.I):
199 raise InvalidInput('hostname', hostname, "Not a valid hostname; "
200 "must only use number, letters, and dashes.")