X-Git-Url: http://xvm.mit.edu/gitweb/invirt/packages/invirt-web.git/blobdiff_plain/3d1cc19a7889d4ac32b00bbddb142755dd4bb24a..1da92cb8c769d7e9cdad595ffebe0ffa80b545d6:/templates/main.py diff --git a/templates/main.py b/templates/main.py index 09cc0ac..8e4c303 100755 --- a/templates/main.py +++ b/templates/main.py @@ -13,6 +13,7 @@ import sha import hmac import datetime import StringIO +import getafsgroups sys.stderr = StringIO.StringIO() sys.path.append('/home/ecprice/.local/lib/python2.5/site-packages') @@ -33,7 +34,7 @@ class InvalidInput(MyException): the select box). """ def __init__(self, err_field, err_value, expl=None): - super(InvalidInput, self).__init__(expl) + MyException.__init__(self, expl) self.err_field = err_field self.err_value = err_value @@ -47,7 +48,7 @@ class Global(object): def __get_uptimes(self): if not hasattr(self, '_uptimes'): - self._uptimes = getUptimes(self.machines) + self._uptimes = getUptimes(Machine.select()) return self._uptimes uptimes = property(__get_uptimes) @@ -117,7 +118,7 @@ def haveAccess(user, machine): """Return whether a user has access to a machine""" if user.username == 'moo': return True - return machine.owner == user.username + return getafsgroups.checkLockerOwner(user.username,machine.owner) def error(op, user, fields, err, emsg): """Print an error page when a CodeError occurs""" @@ -231,7 +232,7 @@ def parseStatus(s): stack[-1].extend(v.split()) return stack[-1] -def getUptimes(machines): +def getUptimes(machines=None): """Return a dictionary mapping machine names to uptime strings""" value_string = remctl('web', 'listvms') lines = value_string.splitlines() @@ -352,7 +353,7 @@ def create(user, fields): name = fields.getfirst('name') if not validMachineName(name): raise InvalidInput('name', name) - name = user.username + '_' + name.lower() + name = name.lower() if Machine.get_by(name=name): raise InvalidInput('name', name, @@ -406,7 +407,7 @@ def listVms(user, fields): default_disk=min(4.0, max_disk), machines=machines, has_vnc=has_vnc, - uptimes=uptimes, + uptimes=g.uptimes, cdroms=CDROM.select()) return Template(file='list.tmpl', searchList=[d, global_dict]) @@ -510,6 +511,10 @@ def getDiskInfo(data_dict, machine): def deleteVM(machine): """Delete a VM.""" + try: + remctl('destroy', machine.name) + except: + pass transaction = ctx.current.create_transaction() delete_disk_pairs = [(machine.name, d.guest_device_name) for d in machine.disks] try: @@ -530,11 +535,11 @@ def deleteVM(machine): def command(user, fields): """Handler for running commands like boot and delete on a VM.""" - print time.time()-start_time + print >> sys.stderr, time.time()-start_time machine = testMachineId(user, fields.getfirst('machine_id')) action = fields.getfirst('action') cdrom = fields.getfirst('cdrom') - print time.time()-start_time + print >> sys.stderr, time.time()-start_time if cdrom is not None and not CDROM.get(cdrom): raise CodeError("Invalid cdrom type '%s'" % cdrom) if action not in ('Reboot', 'Power on', 'Power off', 'Shutdown', 'Delete VM'): @@ -555,7 +560,7 @@ def command(user, fields): remctl('shutdown', machine.name) elif action == 'Delete VM': deleteVM(machine) - print time.time()-start_time + print >> sys.stderr, time.time()-start_time d = dict(user=user, command=action, @@ -563,7 +568,7 @@ def command(user, fields): return Template(file="command.tmpl", searchList=[d, global_dict]) def testOwner(user, owner, machine=None): - if owner != user.username: + if not getafsgroups.checkLockerOwner(user.username, owner): raise InvalidInput('owner', owner, "Invalid") return owner @@ -574,10 +579,24 @@ def testContact(user, contact, machine=None): "Invalid") return contact +def testDisk(user, disksize, machine=None): + return disksize + +def testName(user, name, machine=None): + if Machine.select_by(name=name) == []: + return name + if name == machine.name: + return name + raise InvalidInput('name', name, + "Already taken") + def testHostname(user, hostname, machine): for nic in machine.nics: if hostname == nic.hostname: return hostname + # check if doesn't already exist + if NIC.select_by(hostname=hostname) == []: + return hostname raise InvalidInput('hostname', hostname, "Different from before") @@ -585,19 +604,64 @@ def testHostname(user, hostname, machine): def modify(user, fields): """Handler for modifying attributes of a machine.""" #XXX not written yet - machine = testMachineId(user, fields.getfirst('machine_id')) - owner = testOwner(user, fields.getfirst('owner'), machine) - contact = testContact(user, fields.getfirst('contact')) - hostname = testHostname(user, fields.getfirst('hostname'), + + transaction = ctx.current.create_transaction() + try: + machine = testMachineId(user, fields.getfirst('machine_id')) + owner = testOwner(user, fields.getfirst('owner'), machine) + contact = testContact(user, fields.getfirst('contact')) + hostname = testHostname(owner, fields.getfirst('hostname'), machine) - ram = fields.getfirst('memory') - if ram is not None: - ram = validMemory(user, ram, machine) - disk = testDisk(user, fields.getfirst('disk')) - if disk is not None: - disk = validDisk(user, disk, machine) + name = testName(user, fields.getfirst('name'), machine) + oldname = machine.name + command="modify" + olddisk = {} + + memory = fields.getfirst('memory') + if memory is not None: + memory = validMemory(user, memory, machine) + else: + memory = machine.memory + if memory != machine.memory: + machine.memory = memory + + disksize = testDisk(user, fields.getfirst('disk')) + if disksize is not None: + disksize = validDisk(user, disksize, machine) + else: + disksize = machine.disks[0].size + for disk in machine.disks: + olddisk[disk.guest_device_name] = disk.size + disk.size = disksize + ctx.current.save(disk) + + # XXX all NICs get same hostname on change? Interface doesn't support more. + for nic in machine.nics: + nic.hostname = hostname + ctx.current.save(nic) + + if owner != machine.owner: + machine.owner = owner + if name != machine.name: + machine.name = name + + ctx.current.save(machine) + transaction.commit() + except: + transaction.rollback() + raise + remctl("web", "moveregister", oldname, name) + for disk in machine.disks: + # XXX all disks get the same size on change? Interface doesn't support more. + if disk.size != olddisk[disk.guest_device_name]: + remctl("web", "lvresize", oldname, disk.guest_device_name, str(disk.size)) + if oldname != name: + remctl("web", "lvrename", oldname, disk.guest_device_name, name) + d = dict(user=user, + command=command, + machine=machine) + return Template(file="command.tmpl", searchList=[d, global_dict]) - def help(user, fields): """Handler for help messages.""" @@ -722,8 +786,8 @@ if __name__ == '__main__': u.email = 'nobody' connect('postgres://sipb-xen@sipb-xen-dev/sipb_xen') operation = os.environ.get('PATH_INFO', '') - #print 'Content-Type: text/plain\n' - #print operation +# print 'Content-Type: text/plain\n' +# print operation if not operation: print "Status: 301 Moved Permanently" print 'Location: ' + os.environ['SCRIPT_NAME']+'/\n' @@ -733,7 +797,7 @@ if __name__ == '__main__': operation = operation[1:] if not operation: operation = 'list' - + def badOperation(u, e): raise CodeError("Unknown operation") @@ -746,17 +810,20 @@ if __name__ == '__main__': sys.stderr.seek(0) e = sys.stderr.read() if e: - output = output.replace('', '
'+e+'
') + output = str(output) + output = output.replace('', '

STDERR:

'+e+'
') print output except CodeError, err: print 'Content-Type: text/html\n' sys.stderr.seek(0) e = sys.stderr.read() + sys.stderr=sys.stdout print error(operation, u, fields, err, e) except InvalidInput, err: print 'Content-Type: text/html\n' sys.stderr.seek(0) e = sys.stderr.read() + sys.stderr=sys.stdout print invalidInput(operation, u, fields, err, e) except: print 'Content-Type: text/plain\n' @@ -764,4 +831,5 @@ if __name__ == '__main__': e = sys.stderr.read() print e print '----' + sys.stderr = sys.stdout raise