Use fcgi
authorEric Price <ecprice@mit.edu>
Tue, 3 Jun 2008 05:23:23 +0000 (01:23 -0400)
committerEric Price <ecprice@mit.edu>
Tue, 3 Jun 2008 05:23:23 +0000 (01:23 -0400)
svn path=/trunk/packages/sipb-xen-www/; revision=579

code/main.fcgi [new file with mode: 0755]
code/main.py

diff --git a/code/main.fcgi b/code/main.fcgi
new file mode 100755 (executable)
index 0000000..b2c7031
--- /dev/null
@@ -0,0 +1,3 @@
+#!/usr/bin/python
+import main
+main.main()
index 620c0b9..ec14236 100755 (executable)
@@ -472,11 +472,11 @@ console will suffer artifacts.
     return templates.help(searchList=[d])
 
 
-def badOperation(u, e):
+def badOperation(u, s, e):
     """Function called when accessing an unknown URI."""
     raise CodeError("Unknown operation")
 
-def infoDict(username, machine):
+def infoDict(username, state, machine):
     """Get the variables used by info.tmpl."""
     status = controls.statusInfo(machine)
     checkpoint.checkpoint('Getting status info')
@@ -572,7 +572,7 @@ def infoDict(username, machine):
 def info(username, state, fields):
     """Handler for info on a single VM."""
     machine = validation.Validate(username, state, machine_id=fields.getfirst('machine_id')).machine
-    d = infoDict(username, machine)
+    d = infoDict(username, state, machine)
     checkpoint.checkpoint('Got infodict')
     return templates.info(searchList=[d])
 
@@ -605,83 +605,88 @@ def getUser(environ):
         return None
     return email[:-8]
 
-def main(operation, username, state, fields):
-    start_time = time.time()
-    fun = mapping.get(operation, badOperation)
-
-    if fun not in (helpHandler, ):
-        connect('postgres://sipb-xen@sipb-xen-dev.mit.edu/sipb_xen')
-    try:
-        checkpoint.checkpoint('Before')
-        output = fun(username, state, fields)
-        checkpoint.checkpoint('After')
-
-        headers = dict(DEFAULT_HEADERS)
-        if isinstance(output, tuple):
-            new_headers, output = output
-            headers.update(new_headers)
-        e = revertStandardError()
-        if e:
-            if isinstance(output, basestring):
-                sys.stderr = StringIO()
-                x = str(output)
-                print >> sys.stderr, x
-                print >> sys.stderr, 'XXX'
-                print >> sys.stderr, e
-                raise Exception()
-            output.addError(e)
-        printHeaders(headers)
-        output_string =  str(output)
-        checkpoint.checkpoint('output as a string')
-        print output_string
+class App:
+    def __init__(self, environ, start_response):
+        self.environ = environ
+        self.start = start_response
+
+        self.username = getUser(environ)
+        self.state = State(self.username)
+
+    def __iter__(self):
+        fields = cgi.FieldStorage(fp=self.environ['wsgi.input'], environ=self.environ)
+        print >> sys.stderr, fields
+        operation = self.environ.get('PATH_INFO', '')
+        if not operation:
+            self.start("301 Moved Permanently", [('Location',
+                                                  os.environ['SCRIPT_NAME']+'/')])
+            return
+        if self.username is None:
+            operation = 'unauth'
+        if operation.startswith('/'):
+            operation = operation[1:]
+        if not operation:
+            operation = 'list'
+        print 'Starting', operation
+
+        start_time = time.time()
+        fun = mapping.get(operation, badOperation)
+        try:
+            checkpoint.checkpoint('Before')
+            output = fun(self.username, self.state, fields)
+            checkpoint.checkpoint('After')
+
+            headers = dict(DEFAULT_HEADERS)
+            if isinstance(output, tuple):
+                new_headers, output = output
+                headers.update(new_headers)
+            print 'MOO2'
+            e = revertStandardError()
+            if e:
+                if isinstance(output, basestring):
+                    sys.stderr = StringIO()
+                    x = str(output)
+                    print >> sys.stderr, x
+                    print >> sys.stderr, 'XXX'
+                    print >> sys.stderr, e
+                    raise Exception()
+                output.addError(e)
+            output_string =  str(output)
+            checkpoint.checkpoint('output as a string')
+        except Exception, err:
+            if not fields.has_key('js'):
+                if isinstance(err, CodeError):
+                    self.start('500 Internal Server Error', [('Content-Type', 'text/html')])
+                    e = revertStandardError()
+                    s = error(operation, self.username, fields, err, e)
+                    yield str(s)
+                    return
+                if isinstance(err, InvalidInput):
+                    self.start('200 OK', [('Content-Type', 'text/html')])
+                    e = revertStandardError()
+                    yield str(invalidInput(operation, self.username, fields, err, e))
+                    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.'
+----
+%s
+----
+%s
+----''' % (str(err), traceback.format_exc())
+        self.start('200 OK', headers.items())
+        yield output_string
         if fields.has_key('timedebug'):
-            print '<pre>%s</pre>' % cgi.escape(checkpoint)
-    except Exception, err:
-        if not fields.has_key('js'):
-            if isinstance(err, CodeError):
-                print 'Content-Type: text/html\n'
-                e = revertStandardError()
-                print error(operation, state.username, fields, err, e)
-                sys.exit(1)
-            if isinstance(err, InvalidInput):
-                print 'Content-Type: text/html\n'
-                e = revertStandardError()
-                print invalidInput(operation, state.username, fields, err, e)
-                sys.exit(1)
-        print 'Content-Type: text/plain\n'
-        print 'Uh-oh!  We experienced an error.'
-        print 'Please email xvm-dev@mit.edu with the contents of this page.'
-        print '----'
-        e = revertStandardError()
-        print e
-        print '----'
-        raise
+            yield '<pre>%s</pre>' % cgi.escape(str(checkpoint))
+
+def constructor():
+    connect('postgres://sipb-xen@sipb-xen-dev.mit.edu/sipb_xen')
+    return App
+
+def main():
+    from flup.server.fcgi_fork import WSGIServer
+    WSGIServer(constructor()).run()
 
 if __name__ == '__main__':
-    fields = cgi.FieldStorage()
-
-    if fields.has_key('sqldebug'):
-        import logging
-        logging.basicConfig()
-        logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
-        logging.getLogger('sqlalchemy.orm.unitofwork').setLevel(logging.INFO)
-
-    username = getUser(os.environ)
-    state = State(username)
-    operation = os.environ.get('PATH_INFO', '')
-    if not operation:
-        print "Status: 301 Moved Permanently"
-        print 'Location: ' + os.environ['SCRIPT_NAME']+'/\n'
-        sys.exit(0)
-    if username is None:
-        operation = 'unauth'
-    if operation.startswith('/'):
-        operation = operation[1:]
-    if not operation:
-        operation = 'list'
-
-    if os.getenv("SIPB_XEN_PROFILE"):
-        import profile
-        profile.run('main(operation, username, state, fields)', 'log-'+operation)
-    else:
-        main(operation, username, state, fields)
+    main()