send mail on non-CodeError exceptions
[invirt/packages/invirt-web.git] / code / main.py
index ec14236..5874928 100755 (executable)
@@ -6,7 +6,6 @@ import cPickle
 import cgi
 import datetime
 import hmac
-import os
 import sha
 import simplejson
 import sys
@@ -262,7 +261,7 @@ def vnc(username, state, fields):
              on=status,
              has_vnc=has_vnc,
              machine=machine,
-             hostname=os.environ.get('SERVER_NAME', 'localhost'),
+             hostname=state.environ.get('SERVER_NAME', 'localhost'),
              authtoken=token)
     return templates.vnc(searchList=[d])
 
@@ -340,7 +339,7 @@ def command(username, state, fields):
         return templates.list(searchList=[d])
     elif back == 'info':
         machine = validation.Validate(username, state, machine_id=fields.getfirst('machine_id')).machine
-        return ({'Status': '302',
+        return ({'Status': '303 See Other',
                  'Location': '/info?machine_id=%d' % machine.machine_id},
                 "You shouldn't see this message.")
     else:
@@ -378,7 +377,7 @@ def modifyDict(username, state, fields):
             machine.owner = validate.owner
             update_acl = True
         if hasattr(validate, 'name'):
-            machine.name = name
+            machine.name = validate.name
         if hasattr(validate, 'admin') and validate.admin != machine.administrator:
             machine.administrator = validate.admin
             update_acl = True
@@ -412,7 +411,7 @@ def modify(username, state, fields):
         machine = modify_dict['machine']
         result = 'Success!'
         err = None
-    info_dict = infoDict(username, machine)
+    info_dict = infoDict(username, state, machine)
     info_dict['err'] = err
     if err:
         for field in fields.keys():
@@ -580,6 +579,10 @@ def unauthFront(_, _2, fields):
     """Information for unauth'd users."""
     return templates.unauth(searchList=[{'simple' : True}])
 
+def throwError(_, __, ___):
+    """Throw an error, to test the error-tracing mechanisms."""
+    raise RuntimeError("This is a test of the emergency broadcast system.")
+
 mapping = dict(list=listVms,
                vnc=vnc,
                command=command,
@@ -587,7 +590,8 @@ mapping = dict(list=listVms,
                info=info,
                create=create,
                help=helpHandler,
-               unauth=unauthFront)
+               unauth=unauthFront,
+               errortest=throwError)
 
 def printHeaders(headers):
     """Print a dictionary as HTTP headers."""
@@ -595,6 +599,20 @@ def printHeaders(headers):
         print '%s: %s' % (key, value)
     print
 
+def send_error_mail(subject, body):
+    import subprocess
+
+    to = 'xvm@mit.edu'
+    mail = """To: %s
+From: root@xvm.mit.edu
+Subject: %s
+
+%s
+""" % (to, subject, body)
+    p = subprocess.Popen(['/usr/sbin/sendmail', to], stdin=subprocess.PIPE)
+    p.stdin.write(mail)
+    p.stdin.close()
+    p.wait()
 
 def getUser(environ):
     """Return the current user based on the SSL environment variables"""
@@ -612,6 +630,7 @@ class App:
 
         self.username = getUser(environ)
         self.state = State(self.username)
+        self.state.environ = environ
 
     def __iter__(self):
         fields = cgi.FieldStorage(fp=self.environ['wsgi.input'], environ=self.environ)
@@ -619,7 +638,7 @@ class App:
         operation = self.environ.get('PATH_INFO', '')
         if not operation:
             self.start("301 Moved Permanently", [('Location',
-                                                  os.environ['SCRIPT_NAME']+'/')])
+                                                  self.environ['SCRIPT_NAME']+'/')])
             return
         if self.username is None:
             operation = 'unauth'
@@ -668,14 +687,23 @@ class App:
                     return
             self.start('500 Internal Server Error', [('Content-Type', 'text/plain')])
             import traceback
-            yield '''Uh-oh!  We experienced an error.'
-Please email xvm-dev@mit.edu with the contents of this page.'
+            send_error_mail('xvm error: %s' % (err,),
+                            '%s\n' % (traceback.format_exc(),))
+            yield '''Uh-oh!  We experienced an error.
+Sorry about that.  We've gotten mail about it.
+
+Feel free to poke us at xvm@mit.edu if this bug is
+consistently biting you and we don't seem to be fixing it.
+
+In case you're curious, the gory details are here.
 ----
 %s
 ----
 %s
 ----''' % (str(err), traceback.format_exc())
-        self.start('200 OK', headers.items())
+        status = headers.setdefault('Status', '200 OK')
+        del headers['Status']
+        self.start(status, headers.items())
         yield output_string
         if fields.has_key('timedebug'):
             yield '<pre>%s</pre>' % cgi.escape(str(checkpoint))