Change VM creation auth failure message
[invirt/packages/invirt-web.git] / code / main.py
index cf0aca2..b4e659e 100755 (executable)
@@ -194,9 +194,9 @@ your machine will run just fine, but the applet's display of the
 console will suffer artifacts.
 """,
             'Windows': """
-<strong>Windows 7:</strong> The Windows 7 image is licensed for all MIT students and will automatically activate off the network. The installer requires 512 MiB RAM and at least 15 GiB disk space (20 GiB or more recommended).<br>
+<strong>Windows 7:</strong> The Windows 7 image is licensed for all MIT students and will automatically activate off the network; see <a href="/static/msca-7.txt">the licensing agreement</a> for details. The installer requires 512 MiB RAM and at least 15 GiB disk space (20 GiB or more recommended).<br>
 <strong>Windows Vista:</strong> The Vista image is licensed for all MIT students and will automatically activate off the network; see <a href="/static/msca-email.txt">the licensing confirmation e-mail</a> for details. The installer requires 512 MiB RAM and at least 7.5 GiB disk space (15 GiB or more recommended).<br>
-<strong>Windows XP:</strong> This is the volume license CD image. You will need your own volume license key to complete the install. We do not have these available for the general MIT community; ask your department if they have one, or visit <a href="http://msca.mit.edu/">http://msca.mit.edu/</a> if you are staff/faculty to request one. 
+<strong>Windows XP:</strong> This is the volume license CD image. You will need your own volume license key to complete the install. We do not have these available for the general MIT community; ask your department if they have one, or visit <a href="http://msca.mit.edu/">http://msca.mit.edu/</a> if you are staff/faculty to request one.
 """
             }
 
@@ -279,12 +279,14 @@ console will suffer artifacts.
 
         @cherrypy.expose
         @cherrypy.tools.mako(filename="/info.mako")
-        def info(self, machine_id):
+        def info(self, machine_id, result=None):
             """Handler for info on a single VM."""
             machine = validation.Validate(cherrypy.request.login,
                                           cherrypy.request.state,
                                           machine_id=machine_id).machine
             d = infoDict(cherrypy.request.login, cherrypy.request.state, machine)
+            if result:
+                d['result'] = result
             return d
         index = info
 
@@ -318,7 +320,18 @@ console will suffer artifacts.
         @cherrypy.expose
         @cherrypy.tools.mako(filename="/vnc.mako")
         def vnc(self, machine_id):
-            """VNC applet page.
+            """VNC applet page"""
+            return self._vnc(machine_id)
+
+        @cherrypy.expose
+        @cherrypy.tools.response_headers(headers=[('Content-Disposition', 'attachment; filename=vnc.jnlp')])
+        @cherrypy.tools.mako(filename="/vnc_jnlp.mako", content_type="application/x-java-jnlp-file")
+        def vnc_jnlp(self, machine_id):
+            """VNC applet exposed as a Java Web Start app (JNLP file)"""
+            return self._vnc(machine_id)
+
+        def _vnc(self, machine_id):
+            """VNC applet page functionality.
 
             Note that due to same-domain restrictions, the applet connects to
             the webserver, which needs to forward those requests to the xen
@@ -377,6 +390,8 @@ console will suffer artifacts.
                 result = str(err)
             else:
                 result = 'Success!'
+                if 'result' in d:
+                    result = d['result']
                 if not back:
                     return d
             if back == 'list':
@@ -384,8 +399,10 @@ console will suffer artifacts.
                 raise cherrypy.InternalRedirect('/list?result=%s'
                                                 % urllib.quote(result))
             elif back == 'info':
-                raise cherrypy.HTTPRedirect(cherrypy.request.base
-                                            + '/machine/%d/' % machine_id,
+                url = cherrypy.request.base + '/machine/%d/' % machine_id
+                if result:
+                    url += '?result='+urllib.quote(result)
+                raise cherrypy.HTTPRedirect(url,
                                             status=303)
             else:
                 raise InvalidInput('back', back, 'Not a known back page.')
@@ -488,6 +505,8 @@ def getNicInfo(data_dict, machine):
     nic_fields_template = [('nic%s_hostname', 'NIC %s Hostname'),
                            ('nic%s_mac', 'NIC %s MAC Addr'),
                            ('nic%s_ip', 'NIC %s IP'),
+                           ('nic%s_netmask', 'NIC %s Netmask'),
+                           ('nic%s_gateway', 'NIC %s Gateway'),
                            ]
     nic_fields = []
     for i in range(len(machine.nics)):
@@ -495,6 +514,23 @@ def getNicInfo(data_dict, machine):
         data_dict['nic%s_hostname' % i] = getHostname(machine.nics[i])
         data_dict['nic%s_mac' % i] = machine.nics[i].mac_addr
         data_dict['nic%s_ip' % i] = machine.nics[i].ip
+        data_dict['nic%s_netmask' % i] = machine.nics[i].netmask
+        data_dict['nic%s_gateway' % i] = machine.nics[i].gateway
+        if machine.nics[i].other_ip:
+            nic_fields.append(('nic%s_other' % i, 'NIC %s Other Address' % i))
+            other = '%s/%s via %s' % (machine.nics[i].other_ip, machine.nics[i].other_netmask, machine.nics[i].other_gateway)
+            other_action = machine.nics[i].other_action
+            if other_action == 'dnat':
+                other += " (NAT to primary IP)"
+            elif other_action == 'renumber':
+                other += " (cold boot or renew DHCP lease to swap)"
+            elif other_action == 'renumber_dhcp':
+                other += " (renew DHCP lease to swap)"
+            elif other_action == 'remove':
+                other += " (will be removed at next cold boot or DHCP lease renewal)"
+            else:
+                other += " (pending assignment)"
+            data_dict['nic%s_other' % i] = other
     if len(machine.nics) == 1:
         nic_fields = [(x, y.replace('NIC 0 ', '')) for x, y in nic_fields]
     return nic_fields
@@ -549,7 +585,7 @@ def modifyDict(username, state, machine_id, fields):
         if hasattr(validate, 'contact'):
             machine.contact = validate.contact
 
-        session.save_or_update(machine)
+        session.add(machine)
         session.commit()
     except:
         session.rollback()
@@ -563,10 +599,10 @@ def modifyDict(username, state, machine_id, fields):
             if disk.size != disksize:
                 olddisk[disk.guest_device_name] = disksize
                 disk.size = disksize
-                session.save_or_update(disk)
+                session.add(disk)
         for diskname in olddisk:
             controls.resizeDisk(oldname, diskname, str(olddisk[diskname]))
-        session.save_or_update(machine)
+        session.add(machine)
         session.commit()
     except:
         session.rollback()
@@ -581,7 +617,7 @@ def modifyDict(username, state, machine_id, fields):
                     n.hostname = validate.name
         if hasattr(validate, 'name'):
             controls.renameMachine(machine, oldname, validate.name)
-        session.save_or_update(machine)
+        session.add(machine)
         session.commit()
     except:
         session.rollback()
@@ -594,7 +630,11 @@ def modifyDict(username, state, machine_id, fields):
 
 def infoDict(username, state, machine):
     """Get the variables used by info.tmpl."""
-    status = controls.statusInfo(machine)
+    try:
+        status = controls.statusInfo(machine)
+    except CodeError, e:
+        # machine was shut down in between the call to listInfoDict and this
+        status = None
     has_vnc = hasVnc(status)
     if status is None:
         main_status = dict(name=machine.name,
@@ -645,6 +685,11 @@ def infoDict(username, state, machine):
     display_fields = (display_fields[:disk_point] + disk_fields +
                       display_fields[disk_point+1:])
 
+    renumber = False
+    for n in machine.nics:
+        if n.other_action == 'renumber_dhcp':
+            renumber = True
+
     main_status['memory'] += ' MiB'
     for field, disp in display_fields:
         if field in ('uptime', 'cputime') and locals()[field] is not None:
@@ -667,6 +712,7 @@ def infoDict(username, state, machine):
     defaults.disk = "%0.2f" % (machine.disks[0].size/1024.)
     d = dict(user=username,
              on=status is not None,
+             renumber=renumber,
              machine=machine,
              defaults=defaults,
              has_vnc=has_vnc,