Changeset 209
- Timestamp:
- Oct 21, 2007, 1:35:13 AM (17 years ago)
- Location:
- trunk/web/templates
- Files:
-
- 3 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/web/templates/getafsgroups.py
r177 r209 40 40 def checkLockerOwner(user, locker, verbose=False): 41 41 """ 42 checkLockerOwner(user, locker) returns True if and only if user administers locker 42 checkLockerOwner(user, locker) returns True if and only if user administers locker. 43 44 If verbose is true, instead return the reason for failure, or None 45 if there is no failure. 43 46 """ 44 47 p = subprocess.Popen(["fs", "whichcell", "/mit/" + locker], … … 62 65 if entry[0] == user or (entry[0][0:6] == "system" and 63 66 checkAfsGroup(user, entry[0], cell)): 67 if verbose: 68 return None 64 69 return True 65 70 if verbose: -
trunk/web/templates/main.py
r207 r209 6 6 import cgi 7 7 import datetime 8 import getafsgroups9 8 import hmac 10 9 import os 11 import random12 import re13 10 import sha 14 11 import simplejson 15 import string16 import subprocess17 12 import sys 18 13 import time … … 42 37 43 38 from Cheetah.Template import Template 44 from sipb_xen_database import * 45 46 class MyException(Exception): 47 """Base class for my exceptions""" 48 pass 49 50 class InvalidInput(MyException): 51 """Exception for user-provided input is invalid but maybe in good faith. 52 53 This would include setting memory to negative (which might be a 54 typo) but not setting an invalid boot CD (which requires bypassing 55 the select box). 56 """ 57 def __init__(self, err_field, err_value, expl=None): 58 MyException.__init__(self, expl) 59 self.err_field = err_field 60 self.err_value = err_value 61 62 class CodeError(MyException): 63 """Exception for internal errors or bad faith input.""" 64 pass 39 from sipb_xen_database import Machine, CDROM, ctx, connect 40 import validation 41 from webcommon import InvalidInput, CodeError, g 42 import controls 65 43 66 44 def helppopup(subj): … … 69 47 '&simple=true" target="_blank" ' + 70 48 'onclick="return helppopup(\'' + subj + '\')">(?)</a></span>') 71 72 class Global(object):73 """Global state of the system, to avoid duplicate remctls to get state"""74 def __init__(self, user):75 self.user = user76 77 def __get_uptimes(self):78 if not hasattr(self, '_uptimes'):79 self._uptimes = getUptimes(Machine.select())80 return self._uptimes81 uptimes = property(__get_uptimes)82 83 def clear(self):84 """Clear the state so future accesses reload it."""85 for attr in ('_uptimes', ):86 if hasattr(self, attr):87 delattr(self, attr)88 89 g = None90 49 91 50 class User: … … 140 99 141 100 142 default_headers = {'Content-Type': 'text/html'} 143 144 # ... and stolen from xend/uuid.py 145 def randomUUID(): 146 """Generate a random UUID.""" 147 148 return [ random.randint(0, 255) for _ in range(0, 16) ] 149 150 def uuidToString(u): 151 """Turn a numeric UUID to a hyphen-seperated one.""" 152 return "-".join(["%02x" * 4, "%02x" * 2, "%02x" * 2, "%02x" * 2, 153 "%02x" * 6]) % tuple(u) 154 155 MAX_MEMORY_TOTAL = 512 156 MAX_MEMORY_SINGLE = 256 157 MIN_MEMORY_SINGLE = 16 158 MAX_DISK_TOTAL = 50 159 MAX_DISK_SINGLE = 50 160 MIN_DISK_SINGLE = 0.1 161 MAX_VMS_TOTAL = 10 162 MAX_VMS_ACTIVE = 4 163 164 def getMachinesByOwner(user, machine=None): 165 """Return the machines owned by the same as a machine. 166 167 If the machine is None, return the machines owned by the same 168 user. 169 """ 170 if machine: 171 owner = machine.owner 172 else: 173 owner = user.username 174 return Machine.select_by(owner=owner) 175 176 def maxMemory(user, machine=None, on=True): 177 """Return the maximum memory for a machine or a user. 178 179 If machine is None, return the memory available for a new 180 machine. Else, return the maximum that machine can have. 181 182 on is whether the machine should be turned on. If false, the max 183 memory for the machine to change to, if it is left off, is 184 returned. 185 """ 186 if not on: 187 return MAX_MEMORY_SINGLE 188 machines = getMachinesByOwner(user, machine) 189 active_machines = [x for x in machines if g.uptimes[x]] 190 mem_usage = sum([x.memory for x in active_machines if x != machine]) 191 return min(MAX_MEMORY_SINGLE, MAX_MEMORY_TOTAL-mem_usage) 192 193 def maxDisk(user, machine=None): 194 machines = getMachinesByOwner(user, machine) 195 disk_usage = sum([sum([y.size for y in x.disks]) 196 for x in machines if x != machine]) 197 return min(MAX_DISK_SINGLE, MAX_DISK_TOTAL-disk_usage/1024.) 198 199 def cantAddVm(user): 200 machines = getMachinesByOwner(user) 201 active_machines = [x for x in machines if g.uptimes[x]] 202 if len(machines) >= MAX_VMS_TOTAL: 203 return 'You have too many VMs to create a new one.' 204 if len(active_machines) >= MAX_VMS_ACTIVE: 205 return ('You already have the maximum number of VMs turned on. ' 206 'To create more, turn one off.') 207 return False 208 209 def haveAccess(user, machine): 210 """Return whether a user has adminstrative access to a machine""" 211 if user.username == 'moo': 212 return True 213 if user.username in (machine.administrator, machine.owner): 214 return True 215 if getafsgroups.checkAfsGroup(user.username, machine.administrator, 216 'athena.mit.edu'): #XXX Cell? 217 return True 218 if getafsgroups.checkLockerOwner(user.username, machine.owner): 219 return True 220 return owns(user, machine) 221 222 def owns(user, machine): 223 """Return whether a user owns a machine""" 224 if user.username == 'moo': 225 return True 226 return getafsgroups.checkLockerOwner(user.username, machine.owner) 101 DEFAULT_HEADERS = {'Content-Type': 'text/html'} 227 102 228 103 def error(op, user, fields, err, emsg): … … 230 105 d = dict(op=op, user=user, errorMessage=str(err), 231 106 stderr=emsg) 232 return Template(file='error.tmpl', searchList=[d]) ;107 return Template(file='error.tmpl', searchList=[d]) 233 108 234 109 def invalidInput(op, user, fields, err, emsg): … … 237 112 err_value=str(err.err_value), stderr=emsg, 238 113 errorMessage=str(err)) 239 return Template(file='invalid.tmpl', searchList=[d]); 240 241 def validMachineName(name): 242 """Check that name is valid for a machine name""" 243 if not name: 244 return False 245 charset = string.ascii_letters + string.digits + '-_' 246 if name[0] in '-_' or len(name) > 22: 247 return False 248 for x in name: 249 if x not in charset: 250 return False 251 return True 252 253 def kinit(username = 'tabbott/extra', keytab = '/etc/tabbott.keytab'): 254 """Kinit with a given username and keytab""" 255 256 p = subprocess.Popen(['kinit', "-k", "-t", keytab, username], 257 stderr=subprocess.PIPE) 258 e = p.wait() 259 if e: 260 raise CodeError("Error %s in kinit: %s" % (e, p.stderr.read())) 261 262 def checkKinit(): 263 """If we lack tickets, kinit.""" 264 p = subprocess.Popen(['klist', '-s']) 265 if p.wait(): 266 kinit() 267 268 def remctl(*args, **kws): 269 """Perform a remctl and return the output. 270 271 kinits if necessary, and outputs errors to stderr. 272 """ 273 checkKinit() 274 p = subprocess.Popen(['remctl', 'black-mesa.mit.edu'] 275 + list(args), 276 stdout=subprocess.PIPE, 277 stderr=subprocess.PIPE) 278 v = p.wait() 279 if kws.get('err'): 280 return p.stdout.read(), p.stderr.read() 281 if v: 282 print >> sys.stderr, 'Error', v, 'on remctl', args, ':' 283 print >> sys.stderr, p.stderr.read() 284 raise CodeError('ERROR on remctl') 285 return p.stdout.read() 286 287 def lvcreate(machine, disk): 288 """Create a single disk for a machine""" 289 remctl('web', 'lvcreate', machine.name, 290 disk.guest_device_name, str(disk.size)) 291 292 def makeDisks(machine): 293 """Update the lvm partitions to add a disk.""" 294 for disk in machine.disks: 295 lvcreate(machine, disk) 296 297 def bootMachine(machine, cdtype): 298 """Boot a machine with a given boot CD. 299 300 If cdtype is None, give no boot cd. Otherwise, it is the string 301 id of the CD (e.g. 'gutsy_i386') 302 """ 303 if cdtype is not None: 304 remctl('control', machine.name, 'create', 305 cdtype) 306 else: 307 remctl('control', machine.name, 'create') 308 309 def registerMachine(machine): 310 """Register a machine to be controlled by the web interface""" 311 remctl('web', 'register', machine.name) 312 313 def unregisterMachine(machine): 314 """Unregister a machine to not be controlled by the web interface""" 315 remctl('web', 'unregister', machine.name) 316 317 def parseStatus(s): 318 """Parse a status string into nested tuples of strings. 319 320 s = output of xm list --long <machine_name> 321 """ 322 values = re.split('([()])', s) 323 stack = [[]] 324 for v in values[2:-2]: #remove initial and final '()' 325 if not v: 326 continue 327 v = v.strip() 328 if v == '(': 329 stack.append([]) 330 elif v == ')': 331 if len(stack[-1]) == 1: 332 stack[-1].append('') 333 stack[-2].append(stack[-1]) 334 stack.pop() 335 else: 336 if not v: 337 continue 338 stack[-1].extend(v.split()) 339 return stack[-1] 340 341 def getUptimes(machines=None): 342 """Return a dictionary mapping machine names to uptime strings""" 343 value_string = remctl('web', 'listvms') 344 lines = value_string.splitlines() 345 d = {} 346 for line in lines: 347 lst = line.split() 348 name, id = lst[:2] 349 uptime = ' '.join(lst[2:]) 350 d[name] = uptime 351 ans = {} 352 for m in machines: 353 ans[m] = d.get(m.name) 354 return ans 355 356 def statusInfo(machine): 357 """Return the status list for a given machine. 358 359 Gets and parses xm list --long 360 """ 361 value_string, err_string = remctl('control', machine.name, 'list-long', 362 err=True) 363 if 'Unknown command' in err_string: 364 raise CodeError("ERROR in remctl list-long %s is not registered" % 365 (machine.name,)) 366 elif 'does not exist' in err_string: 367 return None 368 elif err_string: 369 raise CodeError("ERROR in remctl list-long %s: %s" % 370 (machine.name, err_string)) 371 status = parseStatus(value_string) 372 return status 114 return Template(file='invalid.tmpl', searchList=[d]) 373 115 374 116 def hasVnc(status): … … 382 124 return False 383 125 384 def createVm(user, name, memory, disk, is_hvm, cdrom):385 """Create a VM and put it in the database"""386 # put stuff in the table387 transaction = ctx.current.create_transaction()388 try:389 if memory > maxMemory(user):390 raise InvalidInput('memory', memory,391 "Max %s" % maxMemory(user))392 if disk > maxDisk(user) * 1024:393 raise InvalidInput('disk', disk,394 "Max %s" % maxDisk(user))395 reason = cantAddVm(user)396 if reason:397 raise InvalidInput('create', True, reason)398 res = meta.engine.execute('select nextval('399 '\'"machines_machine_id_seq"\')')400 id = res.fetchone()[0]401 machine = Machine()402 machine.machine_id = id403 machine.name = name404 machine.memory = memory405 machine.owner = user.username406 machine.administrator = user.username407 machine.contact = user.email408 machine.uuid = uuidToString(randomUUID())409 machine.boot_off_cd = True410 machine_type = Type.get_by(hvm=is_hvm)411 machine.type_id = machine_type.type_id412 ctx.current.save(machine)413 disk = Disk(machine.machine_id,414 'hda', disk)415 open_nics = NIC.select_by(machine_id=None)416 if not open_nics: #No IPs left!417 raise CodeError("No IP addresses left! "418 "Contact sipb-xen-dev@mit.edu")419 nic = open_nics[0]420 nic.machine_id = machine.machine_id421 nic.hostname = name422 ctx.current.save(nic)423 ctx.current.save(disk)424 transaction.commit()425 except:426 transaction.rollback()427 raise428 registerMachine(machine)429 makeDisks(machine)430 # tell it to boot with cdrom431 bootMachine(machine, cdrom)432 433 return machine434 435 def validMemory(user, memory, machine=None, on=True):436 """Parse and validate limits for memory for a given user and machine.437 438 on is whether the memory must be valid after the machine is439 switched on.440 """441 try:442 memory = int(memory)443 if memory < MIN_MEMORY_SINGLE:444 raise ValueError445 except ValueError:446 raise InvalidInput('memory', memory,447 "Minimum %s MB" % MIN_MEMORY_SINGLE)448 if memory > maxMemory(user, machine, on):449 raise InvalidInput('memory', memory,450 'Maximum %s MB' % maxMemory(user, machine))451 return memory452 453 def validDisk(user, disk, machine=None):454 """Parse and validate limits for disk for a given user and machine."""455 try:456 disk = float(disk)457 if disk > maxDisk(user, machine):458 raise InvalidInput('disk', disk,459 "Maximum %s G" % maxDisk(user, machine))460 disk = int(disk * 1024)461 if disk < MIN_DISK_SINGLE * 1024:462 raise ValueError463 except ValueError:464 raise InvalidInput('disk', disk,465 "Minimum %s GB" % MIN_DISK_SINGLE)466 return disk467 468 126 def parseCreate(user, fields): 469 127 name = fields.getfirst('name') 470 if not valid MachineName(name):128 if not validation.validMachineName(name): 471 129 raise InvalidInput('name', name, 'You must provide a machine name.') 472 130 name = name.lower() … … 477 135 478 136 memory = fields.getfirst('memory') 479 memory = valid Memory(user, memory, on=True)137 memory = validation.validMemory(user, memory, on=True) 480 138 481 139 disk = fields.getfirst('disk') 482 disk = valid Disk(user, disk)140 disk = validation.validDisk(user, disk) 483 141 484 142 vm_type = fields.getfirst('vmtype') … … 497 155 try: 498 156 parsed_fields = parseCreate(user, fields) 499 machine = c reateVm(**parsed_fields)157 machine = controls.createVm(**parsed_fields) 500 158 except InvalidInput, err: 501 159 pass … … 514 172 515 173 def getListDict(user): 516 machines = [m for m in Machine.select() if haveAccess(user, m)] 174 machines = [m for m in Machine.select() 175 if validation.haveAccess(user, m)] 517 176 on = {} 518 177 has_vnc = {} … … 526 185 else: 527 186 has_vnc[m] = "ParaVM"+helppopup("paravm_console") 528 # for m in machines: 529 # status = statusInfo(m) 530 # on[m.name] = status is not None 531 # has_vnc[m.name] = hasVnc(status) 532 max_memory = maxMemory(user) 533 max_disk = maxDisk(user) 187 max_memory = validation.maxMemory(user) 188 max_disk = validation.maxDisk(user) 534 189 defaults = Defaults(max_memory=max_memory, 535 190 max_disk=max_disk, 536 191 cdrom='gutsy-i386') 537 192 d = dict(user=user, 538 cant_add_vm= cantAddVm(user),193 cant_add_vm=validation.cantAddVm(user), 539 194 max_memory=max_memory, 540 195 max_disk=max_disk, … … 551 206 return Template(file='list.tmpl', searchList=[d]) 552 207 553 def testMachineId(user, machineId, exists=True):554 """Parse, validate and check authorization for a given machineId.555 556 If exists is False, don't check that it exists.557 """558 if machineId is None:559 raise CodeError("No machine ID specified")560 try:561 machineId = int(machineId)562 except ValueError:563 raise CodeError("Invalid machine ID '%s'" % machineId)564 machine = Machine.get(machineId)565 if exists and machine is None:566 raise CodeError("No such machine ID '%s'" % machineId)567 if machine is not None and not haveAccess(user, machine):568 raise CodeError("No access to machine ID '%s'" % machineId)569 return machine570 571 208 def vnc(user, fields): 572 209 """VNC applet page. … … 589 226 echo 1 > /proc/sys/net/ipv4/ip_forward 590 227 """ 591 machine = testMachineId(user, fields.getfirst('machine_id'))228 machine = validation.testMachineId(user, fields.getfirst('machine_id')) 592 229 593 230 TOKEN_KEY = "0M6W0U1IXexThi5idy8mnkqPKEq1LtEnlK/pZSn0cDrN" … … 604 241 token = base64.urlsafe_b64encode(token) 605 242 606 status = statusInfo(machine)243 status = controls.statusInfo(machine) 607 244 has_vnc = hasVnc(status) 608 245 … … 653 290 return disk_fields 654 291 655 def deleteVM(machine):656 """Delete a VM."""657 remctl('control', machine.name, 'destroy', err=True)658 transaction = ctx.current.create_transaction()659 delete_disk_pairs = [(machine.name, d.guest_device_name)660 for d in machine.disks]661 try:662 for nic in machine.nics:663 nic.machine_id = None664 nic.hostname = None665 ctx.current.save(nic)666 for disk in machine.disks:667 ctx.current.delete(disk)668 ctx.current.delete(machine)669 transaction.commit()670 except:671 transaction.rollback()672 raise673 for mname, dname in delete_disk_pairs:674 remctl('web', 'lvremove', mname, dname)675 unregisterMachine(machine)676 677 def commandResult(user, fields):678 print >> sys.stderr, time.time()-start_time679 machine = testMachineId(user, fields.getfirst('machine_id'))680 action = fields.getfirst('action')681 cdrom = fields.getfirst('cdrom')682 print >> sys.stderr, time.time()-start_time683 if cdrom is not None and not CDROM.get(cdrom):684 raise CodeError("Invalid cdrom type '%s'" % cdrom)685 if action not in ('Reboot', 'Power on', 'Power off', 'Shutdown',686 'Delete VM'):687 raise CodeError("Invalid action '%s'" % action)688 if action == 'Reboot':689 if cdrom is not None:690 out, err = remctl('control', machine.name, 'reboot', cdrom,691 err=True)692 else:693 out, err = remctl('control', machine.name, 'reboot',694 err=True)695 if err:696 if re.match("Error: Domain '.*' does not exist.", err):697 raise InvalidInput("action", "reboot",698 "Machine is not on")699 else:700 print >> sys.stderr, 'Error on reboot:'701 print >> sys.stderr, err702 raise CodeError('ERROR on remctl')703 704 elif action == 'Power on':705 if maxMemory(user) < machine.memory:706 raise InvalidInput('action', 'Power on',707 "You don't have enough free RAM quota "708 "to turn on this machine.")709 bootMachine(machine, cdrom)710 elif action == 'Power off':711 out, err = remctl('control', machine.name, 'destroy', err=True)712 if err:713 if re.match("Error: Domain '.*' does not exist.", err):714 raise InvalidInput("action", "Power off",715 "Machine is not on.")716 else:717 print >> sys.stderr, 'Error on power off:'718 print >> sys.stderr, err719 raise CodeError('ERROR on remctl')720 elif action == 'Shutdown':721 out, err = remctl('control', machine.name, 'shutdown', err=True)722 if err:723 if re.match("Error: Domain '.*' does not exist.", err):724 raise InvalidInput("action", "Shutdown",725 "Machine is not on.")726 else:727 print >> sys.stderr, 'Error on Shutdown:'728 print >> sys.stderr, err729 raise CodeError('ERROR on remctl')730 elif action == 'Delete VM':731 deleteVM(machine)732 print >> sys.stderr, time.time()-start_time733 734 d = dict(user=user,735 command=action,736 machine=machine)737 return d738 739 292 def command(user, fields): 740 293 """Handler for running commands like boot and delete on a VM.""" 741 294 back = fields.getfirst('back') 742 295 try: 743 d = co mmandResult(user, fields)296 d = controls.commandResult(user, fields) 744 297 if d['command'] == 'Delete VM': 745 298 back = 'list' … … 759 312 return Template(file='list.tmpl', searchList=[d]) 760 313 elif back == 'info': 761 machine = testMachineId(user, fields.getfirst('machine_id'))314 machine = validation.testMachineId(user, fields.getfirst('machine_id')) 762 315 d = infoDict(user, machine) 763 316 d['result'] = result … … 765 318 else: 766 319 raise InvalidInput('back', back, 'Not a known back page.') 767 768 def testAdmin(user, admin, machine):769 if admin in (None, machine.administrator):770 return None771 if admin == user.username:772 return admin773 if getafsgroups.checkAfsGroup(user.username, admin, 'athena.mit.edu'):774 return admin775 if getafsgroups.checkAfsGroup(user.username, 'system:'+admin,776 'athena.mit.edu'):777 return 'system:'+admin778 return admin779 #raise InvalidInput('administrator', admin,780 # 'You must control the group you move it to.')781 782 def testOwner(user, owner, machine):783 if owner in (None, machine.owner):784 return None785 value = getafsgroups.checkLockerOwner(user.username, owner, verbose=True)786 if value == True:787 return owner788 raise InvalidInput('owner', owner, value)789 790 def testContact(user, contact, machine=None):791 if contact in (None, machine.contact):792 return None793 if not re.match("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$", contact, re.I):794 raise InvalidInput('contact', contact, "Not a valid email.")795 return contact796 797 def testDisk(user, disksize, machine=None):798 return disksize799 800 def testName(user, name, machine=None):801 if name in (None, machine.name):802 return None803 if not Machine.select_by(name=name):804 return name805 raise InvalidInput('name', name, "Name is already taken.")806 807 def testHostname(user, hostname, machine):808 for nic in machine.nics:809 if hostname == nic.hostname:810 return hostname811 # check if doesn't already exist812 if NIC.select_by(hostname=hostname):813 raise InvalidInput('hostname', hostname,814 "Already exists")815 if not re.match("^[A-Z0-9-]{1,22}$", hostname, re.I):816 raise InvalidInput('hostname', hostname, "Not a valid hostname; "817 "must only use number, letters, and dashes.")818 return hostname819 320 820 321 def modifyDict(user, fields): … … 822 323 transaction = ctx.current.create_transaction() 823 324 try: 824 machine = testMachineId(user, fields.getfirst('machine_id')) 825 owner = testOwner(user, fields.getfirst('owner'), machine) 826 admin = testAdmin(user, fields.getfirst('administrator'), machine) 827 contact = testContact(user, fields.getfirst('contact'), machine) 828 hostname = testHostname(owner, fields.getfirst('hostname'), machine) 829 name = testName(user, fields.getfirst('name'), machine) 325 machine = validation.testMachineId(user, fields.getfirst('machine_id')) 326 owner = validation.testOwner(user, fields.getfirst('owner'), machine) 327 admin = validation.testAdmin(user, fields.getfirst('administrator'), 328 machine) 329 contact = validation.testContact(user, fields.getfirst('contact'), 330 machine) 331 hostname = validation.testHostname(owner, fields.getfirst('hostname'), 332 machine) 333 name = validation.testName(user, fields.getfirst('name'), machine) 830 334 oldname = machine.name 831 335 command = "modify" … … 833 337 memory = fields.getfirst('memory') 834 338 if memory is not None: 835 memory = valid Memory(user, memory, machine, on=False)339 memory = validation.validMemory(user, memory, machine, on=False) 836 340 machine.memory = memory 837 341 838 disksize = testDisk(user, fields.getfirst('disk'))342 disksize = validation.testDisk(user, fields.getfirst('disk')) 839 343 if disksize is not None: 840 disksize = valid Disk(user, disksize, machine)344 disksize = validation.validDisk(user, disksize, machine) 841 345 disk = machine.disks[0] 842 346 if disk.size != disksize: … … 866 370 raise 867 371 for diskname in olddisk: 868 remctl("web", "lvresize",oldname, diskname, str(olddisk[diskname]))372 controls.resizeDisk(oldname, diskname, str(olddisk[diskname])) 869 373 if name is not None: 870 for disk in machine.disks: 871 remctl("web", "lvrename", oldname, disk.guest_device_name, name) 872 remctl("web", "moveregister", oldname, name) 374 controls.renameMachine(machine, oldname, name) 873 375 return dict(user=user, 874 376 command=command, … … 881 383 except InvalidInput, err: 882 384 result = None 883 machine = testMachineId(user, fields.getfirst('machine_id'))385 machine = validation.testMachineId(user, fields.getfirst('machine_id')) 884 386 else: 885 387 machine = modify_dict['machine'] 886 result ='Success!'388 result = 'Success!' 887 389 err = None 888 390 info_dict = infoDict(user, machine) … … 943 445 944 446 def infoDict(user, machine): 945 status = statusInfo(machine)447 status = controls.statusInfo(machine) 946 448 has_vnc = hasVnc(status) 947 449 if status is None: … … 1006 508 pass 1007 509 #fields.append((disp, None)) 1008 max_mem = maxMemory(user, machine)1009 max_disk = maxDisk(user, machine)1010 defaults =Defaults()510 max_mem = validation.maxMemory(user, machine) 511 max_disk = validation.maxDisk(user, machine) 512 defaults = Defaults() 1011 513 for name in 'machine_id name administrator owner memory contact'.split(): 1012 514 setattr(defaults, name, getattr(machine, name)) … … 1030 532 def info(user, fields): 1031 533 """Handler for info on a single VM.""" 1032 machine = testMachineId(user, fields.getfirst('machine_id'))534 machine = validation.testMachineId(user, fields.getfirst('machine_id')) 1033 535 d = infoDict(user, machine) 1034 536 return Template(file='info.tmpl', searchList=[d]) … … 1056 558 return User('moo', 'nobody') 1057 559 1058 if __name__ == '__main__': 1059 start_time = time.time() 1060 fields = cgi.FieldStorage() 1061 u = getUser() 1062 g = Global(u) 1063 operation = os.environ.get('PATH_INFO', '') 1064 if not operation: 1065 print "Status: 301 Moved Permanently" 1066 print 'Location: ' + os.environ['SCRIPT_NAME']+'/\n' 1067 sys.exit(0) 1068 1069 if operation.startswith('/'): 1070 operation = operation[1:] 1071 if not operation: 1072 operation = 'list' 1073 1074 1075 560 def main(operation, user, fields): 1076 561 fun = mapping.get(operation, badOperation) 1077 562 … … 1081 566 output = fun(u, fields) 1082 567 1083 headers = dict( default_headers)568 headers = dict(DEFAULT_HEADERS) 1084 569 if isinstance(output, tuple): 1085 570 new_headers, output = output … … 1111 596 print '----' 1112 597 raise 598 599 if __name__ == '__main__': 600 start_time = time.time() 601 fields = cgi.FieldStorage() 602 u = getUser() 603 g.user = u 604 operation = os.environ.get('PATH_INFO', '') 605 if not operation: 606 print "Status: 301 Moved Permanently" 607 print 'Location: ' + os.environ['SCRIPT_NAME']+'/\n' 608 sys.exit(0) 609 610 if operation.startswith('/'): 611 operation = operation[1:] 612 if not operation: 613 operation = 'list' 614 615 main(operation, u, fields) 616
Note: See TracChangeset
for help on using the changeset viewer.