import cache_acls
from webcommon import InvalidInput, CodeError, State
import controls
+from getafsgroups import getAfsGroupMembers
+
+def pathSplit(path):
+ if path.startswith('/'):
+ path = path[1:]
+ i = path.find('/')
+ if i == -1:
+ i = len(path)
+ return path[:i], path[i:]
class Checkpoint:
def __init__(self):
cdrom=getattr(validate, 'cdrom', None),
autoinstall=getattr(validate, 'autoinstall', None))
-def create(username, state, fields):
+def create(username, state, path, fields):
"""Handler for create requests."""
try:
parsed_fields = parseCreate(username, state, fields)
can_clone=can_clone)
return d
-def listVms(username, state, fields):
+def listVms(username, state, path, fields):
"""Handler for list requests."""
checkpoint.checkpoint('Getting list dict')
d = getListDict(username, state)
checkpoint.checkpoint('Got list dict')
return templates.list(searchList=[d])
-def vnc(username, state, fields):
+def vnc(username, state, path, fields):
"""VNC applet page.
Note that due to same-domain restrictions, the applet connects to
data_dict['%s_size' % name] = "%0.1f GiB" % (disk.size / 1024.)
return disk_fields
-def command(username, state, fields):
+def command(username, state, path, fields):
"""Handler for running commands like boot and delete on a VM."""
back = fields.getfirst('back')
try:
command="modify",
machine=machine)
-def modify(username, state, fields):
+def modify(username, state, path, fields):
"""Handler for modifying attributes of a machine."""
try:
modify_dict = modifyDict(username, state, fields)
return templates.info(searchList=[info_dict])
-def helpHandler(username, state, fields):
+def helpHandler(username, state, path, fields):
"""Handler for help messages."""
simple = fields.getfirst('simple')
subjects = fields.getlist('subject')
return templates.help(searchList=[d])
-def badOperation(u, s, e):
+def badOperation(u, s, p, e):
"""Function called when accessing an unknown URI."""
return ({'Status': '404 Not Found'}, 'Invalid operation.')
fields = fields)
return d
-def info(username, state, fields):
+def info(username, state, path, fields):
"""Handler for info on a single VM."""
machine = validation.Validate(username, state, machine_id=fields.getfirst('machine_id')).machine
d = infoDict(username, state, machine)
checkpoint.checkpoint('Got infodict')
return templates.info(searchList=[d])
-def unauthFront(_, _2, fields):
+def unauthFront(_, _2, _3, fields):
"""Information for unauth'd users."""
return templates.unauth(searchList=[{'simple' : True}])
-def throwError(_, __, ___):
+def overlord(username, state, path, fields):
+ if not username in getAfsGroupMembers('system:xvm', 'athena.mit.edu'):
+ raise InvalidInput('username', username, 'Not an overlord.')
+ newstate = State(username, overlord=True)
+ newstate.environ = state.environ
+ return handler(username, newstate, path, fields)
+
+def throwError(_, __, ___, ____):
"""Throw an error, to test the error-tracing mechanisms."""
raise RuntimeError("test of the emergency broadcast system")
create=create,
help=helpHandler,
unauth=unauthFront,
+ overlord=overlord,
errortest=throwError)
def printHeaders(headers):
"""Return the current user based on the SSL environment variables"""
return environ.get('REMOTE_USER', None)
+def handler(username, state, path, fields):
+ operation, path = pathSplit(path)
+ if not operation:
+ operation = 'list'
+ print 'Starting', operation
+ fun = mapping.get(operation, badOperation)
+ return fun(username, state, path, fields)
+
class App:
def __init__(self, environ, start_response):
self.environ = environ
self.state.environ = environ
def __iter__(self):
+ start_time = time.time()
sipb_xen_database.clear_cache()
sys.stderr = StringIO()
fields = cgi.FieldStorage(fp=self.environ['wsgi.input'], environ=self.environ)
return
if self.username is None:
operation = 'unauth'
- if operation.startswith('/'):
- operation = operation[1:]
- if not operation:
- operation = 'list'
- print 'Starting', operation
- start_time = time.time()
- fun = mapping.get(operation, badOperation)
try:
checkpoint.checkpoint('Before')
- output = fun(self.username, self.state, fields)
+ output = handler(self.username, self.state, operation, fields)
checkpoint.checkpoint('After')
headers = dict(DEFAULT_HEADERS)
raise InvalidInput('disk', disksize, "You must provide a disk size.")
if machine_id is not None:
- self.machine = testMachineId(username, machine_id)
+ self.machine = testMachineId(username, state, machine_id)
machine = getattr(self, 'machine', None)
owner = testOwner(username, owner, machine)
self.memory = validMemory(self.owner, state, memory, machine,
on=not created_new)
if disksize is not None:
- self.disksize = validDisk(self.owner, disksize, machine)
+ self.disksize = validDisk(self.owner, state, disksize, machine)
if vmtype is not None:
self.vmtype = validVmType(vmtype)
if cdrom is not None:
'To create more, turn one off.')
return False
-def haveAccess(user, machine):
+def haveAccess(user, state, machine):
"""Return whether a user has administrative access to a machine"""
- return user in cache_acls.accessList(machine)
+ return state.overlord or user in cache_acls.accessList(machine)
def owns(user, machine):
"""Return whether a user owns a machine"""
raise InvalidInput('memory', memory,
"Minimum %s MiB" % MIN_MEMORY_SINGLE)
max_val = maxMemory(owner, g, machine, on)
- if memory > max_val:
+ if not g.overlord and memory > max_val:
raise InvalidInput('memory', memory,
'Maximum %s MiB for %s' % (max_val, owner))
return memory
-def validDisk(owner, disk, machine=None):
+def validDisk(owner, g, disk, machine=None):
"""Parse and validate limits for disk for a given owner and machine."""
try:
disk = float(disk)
- if disk > maxDisk(owner, machine):
+ if not g.overlord and disk > maxDisk(owner, machine):
raise InvalidInput('disk', disk,
"Maximum %s G" % maxDisk(owner, machine))
disk = int(disk * 1024)
raise CodeError("Invalid vm type '%s'" % vm_type)
return t
-def testMachineId(user, machine_id, exists=True):
+def testMachineId(user, state, 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.
machine = Machine.get(machine_id)
if exists and machine is None:
raise InvalidInput('machine_id', machine_id, "Does not exist.")
- if machine is not None and not haveAccess(user, machine):
+ if machine is not None and not haveAccess(user, state, machine):
raise InvalidInput('machine_id', machine_id,
"You do not have access to this machine.")
return machine