don't give 500 for mere stdout on a redirect
[invirt/packages/invirt-web.git] / code / webcommon.py
1 """Exceptions for the web interface."""
2
3 import time
4 from sipb_xen_database import Machine, MachineAccess
5
6 class MyException(Exception):
7     """Base class for my exceptions"""
8     pass
9
10 class InvalidInput(MyException):
11     """Exception for user-provided input is invalid but maybe in good faith.
12
13     This would include setting memory to negative (which might be a
14     typo) but not setting an invalid boot CD (which requires bypassing
15     the select box).
16     """
17     def __init__(self, err_field, err_value, expl=None):
18         MyException.__init__(self, expl)
19         self.err_field = err_field
20         self.err_value = err_value
21
22 class CodeError(MyException):
23     """Exception for internal errors or bad faith input."""
24     pass
25
26 import controls
27
28 def cachedproperty(func):
29     name = '__cache_' + func.__name__ + '_' + str(id(func))
30     def getter(self):
31         try:
32             return getattr(self, name)
33         except AttributeError:
34             value = func(self)
35             setattr(self, name, value)
36             return value
37     return property(getter)
38
39 class State(object):
40     """State for a request"""
41     def __init__(self, user, overlord=False):
42         self.username = user
43         self.overlord = overlord
44
45     def getMachines(self):
46         if self.overlord:
47             return Machine.select()
48         else:
49             return Machine.query().join('acl').select_by(user=self.username)
50
51     machines = cachedproperty(getMachines)
52     xmlist_raw = cachedproperty(lambda self: controls.getList())
53     xmlist = cachedproperty(lambda self:
54                                 dict((m, self.xmlist_raw[m.name])
55                                      for m in self.machines
56                                      if m.name in self.xmlist_raw))
57
58     def clear(self):
59         """Clear the state so future accesses reload it."""
60         for attr in list(self.__dict__):
61             if attr.startswith('__cache_'):
62                 delattr(self, attr)