import cgi
import datetime
import hmac
+import os
import random
import sha
import sys
from view import View, revertStandardError
+
+static_dir = os.path.join(os.path.dirname(__file__), 'static')
+InvirtStatic = cherrypy.tools.staticdir.handler(
+ root=static_dir,
+ dir=static_dir,
+ section='/static')
+
class InvirtUnauthWeb(View):
+ static = InvirtStatic
+
@cherrypy.expose
@cherrypy.tools.mako(filename="/unauth.mako")
def index(self):
- return {'simple': True}
+ return dict(simple=True)
class InvirtWeb(View):
def __init__(self):
'from invirt import database']
self._cp_config['request.error_response'] = self.handle_error
+ static = InvirtStatic
+
@cherrypy.expose
@cherrypy.tools.mako(filename="/invalid.mako")
def invalidInput(self):
@cherrypy.expose
@cherrypy.tools.mako(filename="/error.mako")
def error(self):
- #op, username, fields, err, emsg, traceback):
"""Print an error page when an exception occurs"""
op = cherrypy.request.prev.path_info
username = cherrypy.request.login
err = cherrypy.request.prev.params["err"]
emsg = cherrypy.request.prev.params["emsg"]
traceback = cherrypy.request.prev.params["traceback"]
- d = dict(op = op, user=username, fields=cherrypy.request.prev.params,
+ d = dict(op=op, user=username, fields=cherrypy.request.prev.params,
errorMessage=str(err), stderr=emsg, traceback=traceback)
error_raw = cherrypy.request.lookup.get_template("/error_raw.mako")
details = error_raw.render(**d)
def __getattr__(self, name):
if name in ("admin", "overlord"):
- if not cherrypy.request.login in getAfsGroupMembers(config.adminacl, config.authz[0].cell):
+ if not cherrypy.request.login in getAfsGroupMembers(config.adminacl, config.authz.afs.cells[0].cell):
raise InvalidInput('username', cherrypy.request.login,
'Not in admin group %s.' % config.adminacl)
cherrypy.request.state = State(cherrypy.request.login, isadmin=True)
def handle_error(self):
err = sys.exc_info()[1]
if isinstance(err, InvalidInput):
- e = revertStandardError()
cherrypy.request.params['err'] = err
- cherrypy.request.params['emsg'] = e
+ cherrypy.request.params['emsg'] = revertStandardError()
raise cherrypy.InternalRedirect('/invalidInput')
if not cherrypy.request.prev or 'err' not in cherrypy.request.prev.params:
- e = revertStandardError()
cherrypy.request.params['err'] = err
- cherrypy.request.params['emsg'] = e
+ cherrypy.request.params['emsg'] = revertStandardError()
cherrypy.request.params['traceback'] = _cperror.format_exc()
raise cherrypy.InternalRedirect('/error')
# fall back to cherrypy default error page
@cherrypy.tools.mako(filename="/list.mako")
def list(self, result=None):
"""Handler for list requests."""
- checkpoint.checkpoint('Getting list dict')
d = getListDict(cherrypy.request.login, cherrypy.request.state)
if result is not None:
d['result'] = result
- checkpoint.checkpoint('Got list dict')
return d
index=list
help._cp_config['tools.require_login.on'] = False
def parseCreate(self, fields):
- kws = dict([(kw, fields.get(kw)) for kw in 'name description owner memory disksize vmtype cdrom autoinstall'.split() if fields.get(kw)])
- validate = validation.Validate(cherrypy.request.login, cherrypy.request.state, strict=True, **kws)
- return dict(contact=cherrypy.request.login, name=validate.name, description=validate.description, memory=validate.memory,
- disksize=validate.disksize, owner=validate.owner, machine_type=getattr(validate, 'vmtype', Defaults.type),
+ kws = dict([(kw, fields[kw]) for kw in
+ 'name description owner memory disksize vmtype cdrom autoinstall'.split()
+ if fields[kw]])
+ validate = validation.Validate(cherrypy.request.login,
+ cherrypy.request.state,
+ strict=True, **kws)
+ return dict(contact=cherrypy.request.login, name=validate.name,
+ description=validate.description, memory=validate.memory,
+ disksize=validate.disksize, owner=validate.owner,
+ machine_type=getattr(validate, 'vmtype', Defaults.type),
cdrom=getattr(validate, 'cdrom', None),
autoinstall=getattr(validate, 'autoinstall', None))
"""Handler for create requests."""
try:
parsed_fields = self.parseCreate(fields)
- machine = controls.createVm(cherrypy.request.login, cherrypy.request.state, **parsed_fields)
+ machine = controls.createVm(cherrypy.request.login,
+ cherrypy.request.state, **parsed_fields)
except InvalidInput, err:
pass
else:
d = getListDict(cherrypy.request.login, cherrypy.request.state)
d['err'] = err
if err:
- for field in fields.keys():
- setattr(d['defaults'], field, fields.get(field))
+ for field, value in fields.items():
+ setattr(d['defaults'], field, value)
else:
d['new_machine'] = parsed_fields['name']
return d
raise RuntimeError("test of the emergency broadcast system")
class MachineView(View):
- # This is hairy. Fix when CherryPy 3.2 is out. (rename to
- # _cp_dispatch, and parse the argument as a list instead of
- # string
-
def __getattr__(self, name):
+ """Synthesize attributes to allow RESTful URLs like
+ /machine/13/info. This is hairy. CherryPy 3.2 adds a
+ method called _cp_dispatch that allows you to explicitly
+ handle URLs that can't be mapped, and it allows you to
+ rewrite the path components and continue processing.
+
+ This function gets the next path component being resolved
+ as a string. _cp_dispatch will get an array of strings
+ representing any subsequent path components as well."""
+
try:
- machine_id = int(name)
- cherrypy.request.params['machine_id'] = machine_id
+ cherrypy.request.params['machine_id'] = int(name)
return self
except ValueError:
return None
@cherrypy.tools.mako(filename="/info.mako")
def info(self, machine_id):
"""Handler for info on a single VM."""
- machine = validation.Validate(cherrypy.request.login, cherrypy.request.state, machine_id=machine_id).machine
+ machine = validation.Validate(cherrypy.request.login,
+ cherrypy.request.state,
+ machine_id=machine_id).machine
d = infoDict(cherrypy.request.login, cherrypy.request.state, machine)
- checkpoint.checkpoint('Got infodict')
return d
index = info
def modify(self, machine_id, **fields):
"""Handler for modifying attributes of a machine."""
try:
- modify_dict = modifyDict(cherrypy.request.login, cherrypy.request.state, machine_id, fields)
+ modify_dict = modifyDict(cherrypy.request.login,
+ cherrypy.request.state,
+ machine_id, fields)
except InvalidInput, err:
result = None
- machine = validation.Validate(cherrypy.request.login, cherrypy.request.state, machine_id=machine_id).machine
+ machine = validation.Validate(cherrypy.request.login,
+ cherrypy.request.state,
+ machine_id=machine_id).machine
else:
machine = modify_dict['machine']
result = 'Success!'
err = None
- info_dict = infoDict(cherrypy.request.login, cherrypy.request.state, machine)
+ info_dict = infoDict(cherrypy.request.login,
+ cherrypy.request.state, machine)
info_dict['err'] = err
if err:
- for field in fields.keys():
- setattr(info_dict['defaults'], field, fields.get(field))
+ for field, value in fields.items():
+ setattr(info_dict['defaults'], field, value)
info_dict['result'] = result
return info_dict
Remember to enable iptables!
echo 1 > /proc/sys/net/ipv4/ip_forward
"""
- machine = validation.Validate(cherrypy.request.login, cherrypy.request.state, machine_id=machine_id).machine
-
+ machine = validation.Validate(cherrypy.request.login,
+ cherrypy.request.state,
+ machine_id=machine_id).machine
token = controls.vnctoken(machine)
host = controls.listHost(machine)
if host:
port=port,
authtoken=token)
return d
+
@cherrypy.expose
@cherrypy.tools.mako(filename="/command.mako")
@cherrypy.tools.require_POST()
def command(self, command_name, machine_id, **kwargs):
"""Handler for running commands like boot and delete on a VM."""
- back = kwargs.get('back', None)
+ back = kwargs.get('back')
+ if command_name == 'delete':
+ back = 'list'
try:
- d = controls.commandResult(cherrypy.request.login, cherrypy.request.state, command_name, machine_id, kwargs)
- if d['command'] == 'Delete VM':
- back = 'list'
+ d = controls.commandResult(cherrypy.request.login,
+ cherrypy.request.state,
+ command_name, machine_id, kwargs)
except InvalidInput, err:
if not back:
raise
return d
if back == 'list':
cherrypy.request.state.clear() #Changed global state
- raise cherrypy.InternalRedirect('/list?result=%s' % urllib.quote(result))
+ raise cherrypy.InternalRedirect('/list?result=%s'
+ % urllib.quote(result))
elif back == 'info':
- raise cherrypy.HTTPRedirect(cherrypy.request.base + '/machine/%d/' % machine_id, status=303)
+ raise cherrypy.HTTPRedirect(cherrypy.request.base
+ + '/machine/%d/' % machine_id,
+ status=303)
else:
raise InvalidInput('back', back, 'Not a known back page.')
machine = MachineView()
-class Checkpoint:
- def __init__(self):
- self.start_time = time.time()
- self.checkpoints = []
-
- def checkpoint(self, s):
- self.checkpoints.append((s, time.time()))
-
- def __str__(self):
- return ('Timing info:\n%s\n' %
- '\n'.join(['%s: %s' % (d, t - self.start_time) for
- (d, t) in self.checkpoints]))
-
-checkpoint = Checkpoint()
class Defaults:
"""Class to store default values for fields."""
def getListDict(username, state):
"""Gets the list of local variables used by list.tmpl."""
- checkpoint.checkpoint('Starting')
machines = state.machines
- checkpoint.checkpoint('Got my machines')
on = {}
has_vnc = {}
installing = {}
xmlist = state.xmlist
- checkpoint.checkpoint('Got uptimes')
for m in machines:
if m not in xmlist:
has_vnc[m] = 'Off'
m.uptime = None
else:
m.uptime = xmlist[m]['uptime']
+ installing[m] = bool(xmlist[m].get('autoinstall'))
if xmlist[m]['console']:
has_vnc[m] = True
elif m.type.hvm:
has_vnc[m] = "WTF?"
else:
has_vnc[m] = "ParaVM"
- if xmlist[m].get('autoinstall'):
- installing[m] = True
- else:
- installing[m] = False
max_memory = validation.maxMemory(username, state)
max_disk = validation.maxDisk(username)
- checkpoint.checkpoint('Got max mem/disk')
defaults = Defaults(max_memory=max_memory,
max_disk=max_disk,
owner=username)
- checkpoint.checkpoint('Got defaults')
def sortkey(machine):
return (machine.owner != username, machine.owner, machine.name)
machines = sorted(machines, key=sortkey)
olddisk = {}
session.begin()
try:
- kws = dict([(kw, fields.get(kw)) for kw in 'owner admin contact name description memory vmtype disksize'.split() if fields.get(kw)])
+ kws = dict((kw, fields[kw]) for kw in
+ 'owner admin contact name description memory vmtype disksize'.split()
+ if fields.get(kw))
kws['machine_id'] = machine_id
validate = validation.Validate(username, state, **kws)
machine = validate.machine
def infoDict(username, state, machine):
"""Get the variables used by info.tmpl."""
status = controls.statusInfo(machine)
- checkpoint.checkpoint('Getting status info')
has_vnc = hasVnc(status)
if status is None:
main_status = dict(name=machine.name,
uptime = datetime.timedelta(seconds=int(time.time()-start_time))
cpu_time_float = float(main_status.get('cpu_time', 0))
cputime = datetime.timedelta(seconds=int(cpu_time_float))
- checkpoint.checkpoint('Status')
display_fields = [('name', 'Name'),
('description', 'Description'),
('owner', 'Owner'),
pass
#fields.append((disp, None))
- checkpoint.checkpoint('Got fields')
-
-
max_mem = validation.maxMemory(machine.owner, state, machine, False)
- checkpoint.checkpoint('Got mem')
max_disk = validation.maxDisk(machine.owner, machine)
defaults = Defaults()
for name in 'machine_id name description 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=username,
on=status is not None,
machine=machine,
p.stdin.close()
p.wait()
-random.seed()
+random.seed() #sigh