Changeset 209


Ignore:
Timestamp:
Oct 21, 2007, 1:35:13 AM (17 years ago)
Author:
ecprice
Message:

Split main.py in four.

Location:
trunk/web/templates
Files:
3 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/web/templates/getafsgroups.py

    r177 r209  
    4040def checkLockerOwner(user, locker, verbose=False):
    4141    """
    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.
    4346    """
    4447    p = subprocess.Popen(["fs", "whichcell", "/mit/" + locker],
     
    6265            if entry[0] == user or (entry[0][0:6] == "system" and
    6366                                    checkAfsGroup(user, entry[0], cell)):
     67                if verbose:
     68                    return None
    6469                return True
    6570    if verbose:
  • trunk/web/templates/main.py

    r207 r209  
    66import cgi
    77import datetime
    8 import getafsgroups
    98import hmac
    109import os
    11 import random
    12 import re
    1310import sha
    1411import simplejson
    15 import string
    16 import subprocess
    1712import sys
    1813import time
     
    4237
    4338from 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
     39from sipb_xen_database import Machine, CDROM, ctx, connect
     40import validation
     41from webcommon import InvalidInput, CodeError, g
     42import controls
    6543
    6644def helppopup(subj):
     
    6947            '&simple=true" target="_blank" ' +
    7048            '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 = user
    76 
    77     def __get_uptimes(self):
    78         if not hasattr(self, '_uptimes'):
    79             self._uptimes = getUptimes(Machine.select())
    80         return self._uptimes
    81     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 = None
    9049
    9150class User:
     
    14099
    141100
    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)
     101DEFAULT_HEADERS = {'Content-Type': 'text/html'}
    227102
    228103def error(op, user, fields, err, emsg):
     
    230105    d = dict(op=op, user=user, errorMessage=str(err),
    231106             stderr=emsg)
    232     return Template(file='error.tmpl', searchList=[d]);
     107    return Template(file='error.tmpl', searchList=[d])
    233108
    234109def invalidInput(op, user, fields, err, emsg):
     
    237112             err_value=str(err.err_value), stderr=emsg,
    238113             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])
    373115
    374116def hasVnc(status):
     
    382124    return False
    383125
    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 table
    387     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 = id
    403         machine.name = name
    404         machine.memory = memory
    405         machine.owner = user.username
    406         machine.administrator = user.username
    407         machine.contact = user.email
    408         machine.uuid = uuidToString(randomUUID())
    409         machine.boot_off_cd = True
    410         machine_type = Type.get_by(hvm=is_hvm)
    411         machine.type_id = machine_type.type_id
    412         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_id
    421         nic.hostname = name
    422         ctx.current.save(nic)   
    423         ctx.current.save(disk)
    424         transaction.commit()
    425     except:
    426         transaction.rollback()
    427         raise
    428     registerMachine(machine)
    429     makeDisks(machine)
    430     # tell it to boot with cdrom
    431     bootMachine(machine, cdrom)
    432 
    433     return machine
    434 
    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 is
    439     switched on.
    440     """
    441     try:
    442         memory = int(memory)
    443         if memory < MIN_MEMORY_SINGLE:
    444             raise ValueError
    445     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 memory
    452 
    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 ValueError
    463     except ValueError:
    464         raise InvalidInput('disk', disk,
    465                            "Minimum %s GB" % MIN_DISK_SINGLE)
    466     return disk
    467 
    468126def parseCreate(user, fields):
    469127    name = fields.getfirst('name')
    470     if not validMachineName(name):
     128    if not validation.validMachineName(name):
    471129        raise InvalidInput('name', name, 'You must provide a machine name.')
    472130    name = name.lower()
     
    477135   
    478136    memory = fields.getfirst('memory')
    479     memory = validMemory(user, memory, on=True)
     137    memory = validation.validMemory(user, memory, on=True)
    480138   
    481139    disk = fields.getfirst('disk')
    482     disk = validDisk(user, disk)
     140    disk = validation.validDisk(user, disk)
    483141
    484142    vm_type = fields.getfirst('vmtype')
     
    497155    try:
    498156        parsed_fields = parseCreate(user, fields)
    499         machine = createVm(**parsed_fields)
     157        machine = controls.createVm(**parsed_fields)
    500158    except InvalidInput, err:
    501159        pass
     
    514172
    515173def 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)]   
    517176    on = {}
    518177    has_vnc = {}
     
    526185        else:
    527186            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)
    534189    defaults = Defaults(max_memory=max_memory,
    535190                        max_disk=max_disk,
    536191                        cdrom='gutsy-i386')
    537192    d = dict(user=user,
    538              cant_add_vm=cantAddVm(user),
     193             cant_add_vm=validation.cantAddVm(user),
    539194             max_memory=max_memory,
    540195             max_disk=max_disk,
     
    551206    return Template(file='list.tmpl', searchList=[d])
    552207           
    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 machine
    570 
    571208def vnc(user, fields):
    572209    """VNC applet page.
     
    589226    echo 1 > /proc/sys/net/ipv4/ip_forward
    590227    """
    591     machine = testMachineId(user, fields.getfirst('machine_id'))
     228    machine = validation.testMachineId(user, fields.getfirst('machine_id'))
    592229   
    593230    TOKEN_KEY = "0M6W0U1IXexThi5idy8mnkqPKEq1LtEnlK/pZSn0cDrN"
     
    604241    token = base64.urlsafe_b64encode(token)
    605242   
    606     status = statusInfo(machine)
     243    status = controls.statusInfo(machine)
    607244    has_vnc = hasVnc(status)
    608245   
     
    653290    return disk_fields
    654291
    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 = None
    664             nic.hostname = None
    665             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         raise
    673     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_time
    679     machine = testMachineId(user, fields.getfirst('machine_id'))
    680     action = fields.getfirst('action')
    681     cdrom = fields.getfirst('cdrom')
    682     print >> sys.stderr, time.time()-start_time
    683     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, err
    702                 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, err
    719                 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, err
    729                 raise CodeError('ERROR on remctl')
    730     elif action == 'Delete VM':
    731         deleteVM(machine)
    732     print >> sys.stderr, time.time()-start_time
    733 
    734     d = dict(user=user,
    735              command=action,
    736              machine=machine)
    737     return d
    738 
    739292def command(user, fields):
    740293    """Handler for running commands like boot and delete on a VM."""
    741294    back = fields.getfirst('back')
    742295    try:
    743         d = commandResult(user, fields)
     296        d = controls.commandResult(user, fields)
    744297        if d['command'] == 'Delete VM':
    745298            back = 'list'
     
    759312        return Template(file='list.tmpl', searchList=[d])
    760313    elif back == 'info':
    761         machine = testMachineId(user, fields.getfirst('machine_id'))
     314        machine = validation.testMachineId(user, fields.getfirst('machine_id'))
    762315        d = infoDict(user, machine)
    763316        d['result'] = result
     
    765318    else:
    766319        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 None
    771     if admin == user.username:
    772         return admin
    773     if getafsgroups.checkAfsGroup(user.username, admin, 'athena.mit.edu'):
    774         return admin
    775     if getafsgroups.checkAfsGroup(user.username, 'system:'+admin,
    776                                   'athena.mit.edu'):
    777         return 'system:'+admin
    778     return admin
    779     #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 None
    785     value = getafsgroups.checkLockerOwner(user.username, owner, verbose=True)
    786     if value == True:
    787         return owner
    788     raise InvalidInput('owner', owner, value)
    789 
    790 def testContact(user, contact, machine=None):
    791     if contact in (None, machine.contact):
    792         return None
    793     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 contact
    796 
    797 def testDisk(user, disksize, machine=None):
    798     return disksize
    799 
    800 def testName(user, name, machine=None):
    801     if name in (None, machine.name):
    802         return None
    803     if not Machine.select_by(name=name):
    804         return name
    805     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 hostname
    811     # check if doesn't already exist
    812     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 hostname
    819320
    820321def modifyDict(user, fields):
     
    822323    transaction = ctx.current.create_transaction()
    823324    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)
    830334        oldname = machine.name
    831335        command = "modify"
     
    833337        memory = fields.getfirst('memory')
    834338        if memory is not None:
    835             memory = validMemory(user, memory, machine, on=False)
     339            memory = validation.validMemory(user, memory, machine, on=False)
    836340            machine.memory = memory
    837341 
    838         disksize = testDisk(user, fields.getfirst('disk'))
     342        disksize = validation.testDisk(user, fields.getfirst('disk'))
    839343        if disksize is not None:
    840             disksize = validDisk(user, disksize, machine)
     344            disksize = validation.validDisk(user, disksize, machine)
    841345            disk = machine.disks[0]
    842346            if disk.size != disksize:
     
    866370        raise
    867371    for diskname in olddisk:
    868         remctl("web", "lvresize", oldname, diskname, str(olddisk[diskname]))
     372        controls.resizeDisk(oldname, diskname, str(olddisk[diskname]))
    869373    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)
    873375    return dict(user=user,
    874376                command=command,
     
    881383    except InvalidInput, err:
    882384        result = None
    883         machine = testMachineId(user, fields.getfirst('machine_id'))
     385        machine = validation.testMachineId(user, fields.getfirst('machine_id'))
    884386    else:
    885387        machine = modify_dict['machine']
    886         result='Success!'
     388        result = 'Success!'
    887389        err = None
    888390    info_dict = infoDict(user, machine)
     
    943445
    944446def infoDict(user, machine):
    945     status = statusInfo(machine)
     447    status = controls.statusInfo(machine)
    946448    has_vnc = hasVnc(status)
    947449    if status is None:
     
    1006508            pass
    1007509            #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()
    1011513    for name in 'machine_id name administrator owner memory contact'.split():
    1012514        setattr(defaults, name, getattr(machine, name))
     
    1030532def info(user, fields):
    1031533    """Handler for info on a single VM."""
    1032     machine = testMachineId(user, fields.getfirst('machine_id'))
     534    machine = validation.testMachineId(user, fields.getfirst('machine_id'))
    1033535    d = infoDict(user, machine)
    1034536    return Template(file='info.tmpl', searchList=[d])
     
    1056558        return User('moo', 'nobody')
    1057559
    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 
     560def main(operation, user, fields):   
    1076561    fun = mapping.get(operation, badOperation)
    1077562
     
    1081566        output = fun(u, fields)
    1082567
    1083         headers = dict(default_headers)
     568        headers = dict(DEFAULT_HEADERS)
    1084569        if isinstance(output, tuple):
    1085570            new_headers, output = output
     
    1111596        print '----'
    1112597        raise
     598
     599if __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.