id of the CD (e.g. 'gutsy_i386')
"""
if cdtype is not None:
- remctl('control', machine.name, 'create',
- cdtype)
+ out, err = remctl('control', machine.name, 'create',
+ cdtype, err=True)
else:
- remctl('control', machine.name, 'create')
+ out, err = remctl('control', machine.name, 'create',
+ err=True)
+ if 'already exists' in out:
+ raise InvalidInput('action', 'create',
+ 'VM %s is already on' % machine.name)
+ elif err:
+ raise CodeError('"%s" on "control %s create %s'
+ % (err, machine.name, cdtype))
+ else:
+ raise CodeError('"%s" on "control %s create %s'
+ % (err, machine.name, cdtype))
def registerMachine(machine):
"""Register a machine to be controlled by the web interface"""
def commandResult(user, fields):
start_time = 0
- print >> sys.stderr, time.time()-start_time
machine = validation.testMachineId(user, fields.getfirst('machine_id'))
action = fields.getfirst('action')
cdrom = fields.getfirst('cdrom')
- 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',
raise CodeError('ERROR on remctl')
elif action == 'Delete VM':
deleteVM(machine)
- print >> sys.stderr, time.time()-start_time
d = dict(user=user,
command=action,
import templates
from Cheetah.Template import Template
-from sipb_xen_database import Machine, CDROM, ctx, connect
+from sipb_xen_database import Machine, CDROM, ctx, connect, MachineAccess
import validation
from webcommon import InvalidInput, CodeError, g
import controls
def getListDict(user):
- machines = [m for m in Machine.select()
- if validation.haveAccess(user, m)]
+ machines = g.machines
checkpoint.checkpoint('Got my machines')
on = {}
has_vnc = {}
except InvalidInput, err:
if not back:
raise
- print >> sys.stderr, err
- result = None
+ #print >> sys.stderr, err
+ result = err
else:
result = 'Success!'
if not back:
d['result'] = result
return templates.info(searchList=[d])
else:
- raise InvalidInput
- ('back', back, 'Not a known back page.')
+ raise InvalidInput('back', back, 'Not a known back page.')
def modifyDict(user, fields):
olddisk = {}
"""Exceptions for the web interface."""
-from sipb_xen_database import Machine
+from sipb_xen_database import Machine, MachineAccess
class MyException(Exception):
"""Base class for my exceptions"""
import controls
+def cachedproperty(func):
+ name = '__cache_' + func.__name__ + '_' + str(id(func))
+ def getter(self):
+ try:
+ return getattr(self, name)
+ except AttributeError:
+ value = func(self)
+ setattr(self, name, value)
+ return value
+ return property(getter)
+
class Global(object):
"""Global state of the system, to avoid duplicate remctls to get state"""
def __init__(self, user):
self.user = user
-
- def __get_uptimes(self):
- if not hasattr(self, '_uptimes'):
- self._uptimes = controls.getUptimes(Machine.select())
- return self._uptimes
- uptimes = property(__get_uptimes)
+
+ machines = cachedproperty(lambda self:
+ [ma.machine for ma in
+ MachineAccess.select_by(user=self.user)])
+ uptimes = cachedproperty(lambda self:
+ controls.getUptimes(self.machines))
def clear(self):
"""Clear the state so future accesses reload it."""
- for attr in ('_uptimes', ):
- if hasattr(self, attr):
+ for attr in self.__dict__:
+ if attr.startswith('__cache_'):
delattr(self, attr)
g = Global(None)