X-Git-Url: http://xvm.mit.edu/gitweb/invirt/packages/invirt-web.git/blobdiff_plain/230d47ec0096ba45aeb3a690fa2c4551f4fcbb16..18eb0699531716f3ed495d1e4677c8b981a35439:/code/main.py diff --git a/code/main.py b/code/main.py index 9caf7c4..60c2818 100755 --- a/code/main.py +++ b/code/main.py @@ -11,6 +11,7 @@ import sha import simplejson import sys import time +import urllib from StringIO import StringIO def revertStandardError(): @@ -36,8 +37,10 @@ sys.path.append('/home/ecprice/.local/lib/python2.5/site-packages') import templates from Cheetah.Template import Template -from sipb_xen_database import Machine, CDROM, ctx, connect, MachineAccess +import sipb_xen_database +from sipb_xen_database import Machine, CDROM, ctx, connect, MachineAccess, Type, Autoinstall import validation +import cache_acls from webcommon import InvalidInput, CodeError, g import controls @@ -56,12 +59,15 @@ class Checkpoint: checkpoint = Checkpoint() +def jquote(string): + return "'" + string.replace('\\', '\\\\').replace("'", "\\'").replace('\n', '\\n') + "'" def helppopup(subj): """Return HTML code for a (?) link to a specified help topic""" - return ('(?)') + return ('(?)') def makeErrorPre(old, addition): if addition is None: @@ -71,6 +77,7 @@ def makeErrorPre(old, addition): else: return '

STDERR:

' + str(addition) + '
' +Template.sipb_xen_database = sipb_xen_database Template.helppopup = staticmethod(helppopup) Template.err = None @@ -96,8 +103,10 @@ class Defaults: memory = 256 disk = 4.0 cdrom = '' + autoinstall = '' name = '' - vmtype = 'hvm' + type = 'linux-hvm' + def __init__(self, max_memory=None, max_disk=None, **kws): if max_memory is not None: self.memory = min(self.memory, max_memory) @@ -187,20 +196,26 @@ def create(user, fields): def getListDict(user): """Gets the list of local variables used by list.tmpl.""" + checkpoint.checkpoint('Starting') machines = g.machines checkpoint.checkpoint('Got my machines') on = {} has_vnc = {} - on = g.uptimes + xmlist = g.xmlist checkpoint.checkpoint('Got uptimes') + can_clone = (controls.getList([Machine.get_by(name='ice3')])) == {} for m in machines: - m.uptime = g.uptimes.get(m) - if not on[m]: + if m not in xmlist: has_vnc[m] = 'Off' - elif m.type.hvm: - has_vnc[m] = True + m.uptime = None else: - has_vnc[m] = "ParaVM"+helppopup("paravm_console") + m.uptime = xmlist[m]['uptime'] + if xmlist[m]['console']: + has_vnc[m] = True + elif m.type.hvm: + has_vnc[m] = "WTF?" + else: + has_vnc[m] = "ParaVM"+helppopup("ParaVM Console") max_memory = validation.maxMemory(user) max_disk = validation.maxDisk(user) checkpoint.checkpoint('Got max mem/disk') @@ -219,8 +234,7 @@ def getListDict(user): defaults=defaults, machines=machines, has_vnc=has_vnc, - uptimes=g.uptimes, - cdroms=CDROM.select()) + can_clone=can_clone) return d def listVms(user, fields): @@ -284,7 +298,7 @@ def getHostname(nic): if nic.hostname and '.' in nic.hostname: return nic.hostname elif nic.machine: - return nic.machine.name + '.servers.csail.mit.edu' + return nic.machine.name + '.xvm.mit.edu' else: return None @@ -379,6 +393,10 @@ def modifyDict(user, fields): memory = validation.validMemory(user, memory, machine, on=False) machine.memory = memory + vm_type = validation.validVmType(fields.getfirst('vmtype')) + if vm_type is not None: + machine.type = vm_type + disksize = validation.testDisk(user, fields.getfirst('disk')) if disksize is not None: disksize = validation.validDisk(user, disksize, machine) @@ -388,16 +406,21 @@ def modifyDict(user, fields): disk.size = disksize ctx.current.save(disk) - if owner is not None: + update_acl = False + if owner is not None and owner != machine.owner: machine.owner = owner + update_acl = True if name is not None: machine.name = name - if admin is not None: + if admin is not None and admin != machine.administrator: machine.administrator = admin + update_acl = True if contact is not None: machine.contact = contact ctx.current.save(machine) + if update_acl: + cache_acls.refreshMachine(machine) transaction.commit() except: transaction.rollback() @@ -435,40 +458,40 @@ def helpHandler(user, fields): simple = fields.getfirst('simple') subjects = fields.getlist('subject') - help_mapping = dict(paravm_console=""" + help_mapping = {'ParaVM Console': """ ParaVM machines do not support local console access over VNC. To access the serial console of these machines, you can SSH with Kerberos -to sipb-xen-console.mit.edu, using the name of the machine as your +to console.xvm.mit.edu, using the name of the machine as your username.""", - hvm_paravm=""" + 'HVM/ParaVM': """ HVM machines use the virtualization features of the processor, while ParaVM machines use Xen's emulation of virtualization features. You want an HVM virtualized machine.""", - cpu_weight=""" + 'CPU Weight': """ Don't ask us! We're as mystified as you are.""", - owner=""" + 'Owner': """ The owner field is used to determine quotas. It must be the name of a +href="help?subject=Quotas">quotas. It must be the name of a locker that you are an AFS administrator of. In particular, you or an AFS group you are a member of must have AFS rlidwka bits on the locker. You can check who administers the LOCKER locker using the commands 'attach LOCKER; fs la /mit/LOCKER' on Athena.) See also administrator.""", - administrator=""" +href="help?subject=Administrator">administrator.""", + 'Administrator': """ The administrator field determines who can access the console and power on and off the machine. This can be either a user or a moira group.""", - quotas=""" + 'Quotas': """ Quotas are determined on a per-locker basis. Each locker may have a maximum of 512 megabytes of active ram, 50 gigabytes of disk, and 4 active machines.""", - console=""" + 'Console': """ Framebuffer: At a Linux boot prompt in your VM, try setting fb=false to disable the framebuffer. If you don't, your machine will run just fine, but the applet's display of the console will suffer artifacts. """ - ) + } if not subjects: subjects = sorted(help_mapping.keys()) @@ -515,7 +538,7 @@ def infoDict(user, machine): ('memory', 'RAM'), 'DISK_INFO', ('state', 'state (xen format)'), - ('cpu_weight', 'CPU weight'+helppopup('cpu_weight')), + ('cpu_weight', 'CPU weight'+helppopup('CPU Weight')), ('on_reboot', 'Action on VM reboot'), ('on_poweroff', 'Action on VM poweroff'), ('on_crash', 'Action on VM crash'), @@ -562,10 +585,10 @@ def infoDict(user, machine): defaults = Defaults() for name in 'machine_id name administrator owner memory contact'.split(): setattr(defaults, name, getattr(machine, name)) + defaults.type = machine.type.type_id defaults.disk = "%0.2f" % (machine.disks[0].size/1024.) checkpoint.checkpoint('Got defaults') d = dict(user=user, - cdroms=CDROM.select(), on=status is not None, machine=machine, defaults=defaults, @@ -574,7 +597,7 @@ def infoDict(user, machine): ram=machine.memory, max_mem=max_mem, max_disk=max_disk, - owner_help=helppopup("owner"), + owner_help=helppopup("Owner"), fields = fields) return d @@ -585,13 +608,18 @@ def info(user, fields): checkpoint.checkpoint('Got infodict') return templates.info(searchList=[d]) +def unauthFront(_, fields): + """Information for unauth'd users.""" + return templates.unauth(searchList=[{'simple' : True}]) + mapping = dict(list=listVms, vnc=vnc, command=command, modify=modify, info=info, create=create, - help=helpHandler) + help=helpHandler, + unauth=unauthFront) def printHeaders(headers): """Print a dictionary as HTTP headers.""" @@ -602,8 +630,10 @@ def printHeaders(headers): def getUser(): """Return the current user based on the SSL environment variables""" - username = os.environ['SSL_CLIENT_S_DN_Email'].split("@")[0] - return username + email = os.environ.get('SSL_CLIENT_S_DN_Email', None) + if email is None: + return None + return email.split("@")[0] def main(operation, user, fields): start_time = time.time() @@ -627,7 +657,8 @@ def main(operation, user, fields): output_string = str(output) checkpoint.checkpoint('output as a string') print output_string - print '' % checkpoint + if fields.has_key('timedebug'): + print '
%s
' % checkpoint except Exception, err: if not fields.has_key('js'): if isinstance(err, CodeError): @@ -642,7 +673,7 @@ def main(operation, user, fields): sys.exit(1) print 'Content-Type: text/plain\n' print 'Uh-oh! We experienced an error.' - print 'Please email sipb-xen@mit.edu with the contents of this page.' + print 'Please email xvm-dev@mit.edu with the contents of this page.' print '----' e = revertStandardError() print e @@ -651,6 +682,13 @@ def main(operation, user, fields): if __name__ == '__main__': fields = cgi.FieldStorage() + + if fields.has_key('sqldebug'): + import logging + logging.basicConfig() + logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO) + logging.getLogger('sqlalchemy.orm.unitofwork').setLevel(logging.INFO) + u = getUser() g.user = u operation = os.environ.get('PATH_INFO', '') @@ -659,6 +697,9 @@ if __name__ == '__main__': print 'Location: ' + os.environ['SCRIPT_NAME']+'/\n' sys.exit(0) + if u is None: + operation = 'unauth' + if operation.startswith('/'): operation = operation[1:] if not operation: