VNC: Catch the error when the VM is off and there is no host
[invirt/packages/invirt-web.git] / code / main.py
index 2740a74..7af4ecc 100755 (executable)
@@ -6,6 +6,7 @@ import cPickle
 import cgi
 import datetime
 import hmac
+import random
 import sha
 import simplejson
 import sys
@@ -40,6 +41,8 @@ import cache_acls
 from webcommon import InvalidInput, CodeError, State
 import controls
 from getafsgroups import getAfsGroupMembers
+import invirt.config
+invirt_config = invirt.config.load()
 
 def pathSplit(path):
     if path.startswith('/'):
@@ -254,6 +257,12 @@ def vnc(username, state, path, fields):
     token = {'data': pickled_data, 'digest': m.digest()}
     token = cPickle.dumps(token)
     token = base64.urlsafe_b64encode(token)
+    host = controls.listHost(machine)
+    if host:
+        port = 10003 + [config_host["hostname"] for config_host in invirt_config["hosts"]
+            ].index(controls.listHost(machine))
+    else:
+        port = 5900 # dummy
 
     status = controls.statusInfo(machine)
     has_vnc = hasVnc(status)
@@ -263,6 +272,7 @@ def vnc(username, state, path, fields):
              has_vnc=has_vnc,
              machine=machine,
              hostname=state.environ.get('SERVER_NAME', 'localhost'),
+             port=port,
              authtoken=token)
     return templates.vnc(searchList=[d])
 
@@ -341,7 +351,7 @@ def command(username, state, path, fields):
     elif back == 'info':
         machine = validation.Validate(username, state, machine_id=fields.getfirst('machine_id')).machine
         return ({'Status': '303 See Other',
-                 'Location': '/info?machine_id=%d' % machine.machine_id},
+                 'Location': 'info?machine_id=%d' % machine.machine_id},
                 "You shouldn't see this message.")
     else:
         raise InvalidInput('back', back, 'Not a known back page.')
@@ -490,6 +500,7 @@ def infoDict(username, state, machine):
         cputime = None
     else:
         main_status = dict(status[1:])
+        main_status['host'] = controls.listHost(machine)
         start_time = float(main_status.get('start_time', 0))
         uptime = datetime.timedelta(seconds=int(time.time()-start_time))
         cpu_time_float = float(main_status.get('cpu_time', 0))
@@ -506,6 +517,7 @@ def infoDict(username, state, machine):
                       'NIC_INFO',
                       ('uptime', 'uptime'),
                       ('cputime', 'CPU usage'),
+                      ('host', 'Hosted on'),
                       ('memory', 'RAM'),
                       'DISK_INFO',
                       ('state', 'state (xen format)'),
@@ -585,6 +597,10 @@ def unauthFront(_, _2, _3, fields):
     return templates.unauth(searchList=[{'simple' : True}])
 
 def overlord(username, state, path, fields):
+    if path == '':
+        return ({'Status': '303 See Other',
+                 'Location': 'overlord/'},
+                "You shouldn't see this message.")
     if not username in getAfsGroupMembers('system:xvm', 'athena.mit.edu'):
         raise InvalidInput('username', username, 'Not an overlord.')
     newstate = State(username, overlord=True)
@@ -659,6 +675,8 @@ class App:
         self.state = State(self.username)
         self.state.environ = environ
 
+        random.seed() #sigh
+
     def __iter__(self):
         start_time = time.time()
         sipb_xen_database.clear_cache()
@@ -666,8 +684,7 @@ class App:
         fields = cgi.FieldStorage(fp=self.environ['wsgi.input'], environ=self.environ)
         operation = self.environ.get('PATH_INFO', '')
         if not operation:
-            self.start("301 Moved Permanently", [('Location',
-                                                  self.environ['SCRIPT_NAME']+'/')])
+            self.start("301 Moved Permanently", [('Location', './')])
             return
         if self.username is None:
             operation = 'unauth'
@@ -683,14 +700,12 @@ class App:
                 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)
+                if hasattr(output, 'addError'):
+                    output.addError(e)
+                else:
+                    # This only happens on redirects, so it'd be a pain to get
+                    # the message to the user.  Maybe in the response is useful.
+                    output = output + '\n\nstderr:\n' + e
             output_string =  str(output)
             checkpoint.checkpoint('output as a string')
         except Exception, err: