Index: /package_branches/invirt-web/cherrypy-rebased/code/main.py
===================================================================
--- /package_branches/invirt-web/cherrypy-rebased/code/main.py	(revision 2677)
+++ /package_branches/invirt-web/cherrypy-rebased/code/main.py	(revision 2678)
@@ -150,4 +150,29 @@
         return {'request': cherrypy.request, 'kwargs': kwargs}
     helloworld._cp_config['tools.require_login.on'] = False
+
+    class MachineView(View):
+        # This is hairy. Fix when CherryPy 3.2 is out. (rename to
+        # _cp_dispatch, and parse the argument as a list instead of
+        # string
+
+        def __getattr__(self, name):
+            try:
+                machine_id = int(name)
+                cherrypy.request.params['machine_id'] = machine_id
+                return self
+            except ValueError:
+                return None
+
+        @cherrypy.expose
+        @cherrypy.tools.mako(filename="/info.mako")
+        def info(self, machine_id):
+            """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)
+            checkpoint.checkpoint('Got infodict')
+            return d
+        index = info
+
+    machine = MachineView()
 
 def pathSplit(path):
@@ -606,11 +631,4 @@
     return d
 
-def info(username, state, path, fields):
-    """Handler for info on a single VM."""
-    machine = validation.Validate(username, state, machine_id=fields.getfirst('machine_id')).machine
-    d = infoDict(username, state, machine)
-    checkpoint.checkpoint('Got infodict')
-    return templates.info(searchList=[d])
-
 def unauthFront(_, _2, _3, fields):
     """Information for unauth'd users."""
@@ -637,5 +655,4 @@
                command=command,
                modify=modify,
-               info=info,
                create=create,
                unauth=unauthFront,
Index: /package_branches/invirt-web/cherrypy-rebased/code/templates/info.mako
===================================================================
--- /package_branches/invirt-web/cherrypy-rebased/code/templates/info.mako	(revision 2678)
+++ /package_branches/invirt-web/cherrypy-rebased/code/templates/info.mako	(revision 2678)
@@ -0,0 +1,102 @@
+<%page expression_filter="h"/>
+<%inherit file="skeleton.mako" />
+
+<%def name="title()">
+Info on ${machine.name}
+</%def>
+
+<%def name="infoTable()">
+<h2>Info</h2>
+<table>
+  % for key, value in fields:
+  <tr><td>${key}:</td><td>${value}</td></tr>
+  % endfor
+</table>
+</%def>
+
+<%def name="commands()">
+% if on:
+ % if not machine.type.hvm:
+  Console access: type
+  <tt>ssh ${machine.name}@${config.console.hostname}</tt>
+  on Athena. <a href="https://xvm.scripts.mit.edu/wiki/SerialConsole">(more info)</a>
+ % elif has_vnc:
+  <strong><a href="machine/${machine.machine_id}/vnc">Get Console</a></strong>
+ % else:
+  VNC console not enabled; still booting?
+ % endif
+% endif
+<form action="command" method="POST">
+  <input type="hidden" name="back" value="info"/>
+  <input type="hidden" name="machine_id" value="${machine.machine_id}"/>
+  <div>
+	% if on:
+	<button type="submit" class="button" name="action" value="Power off">Power off (hard)</button>
+	<button type="submit" class="button" name="action" value="Shutdown">Shut down</button>
+	<input type="submit" class="button" name="action" value="Reboot"/>
+	% else:
+	<input type="submit" class="button" name="action" value="Power on"/>
+	% endif
+  </div>
+  <div>
+    Boot CD:
+${self.fn.cdromList()}
+  </div>
+  <div>
+      <input type="submit" class="button" name="action" value="Delete VM" onclick="return confirm('Are you sure that you want to delete this VM?');"/>
+  </div>
+</form>
+</%def>
+
+<%def name="modifyForm()">
+% if err:
+<p class="error">We had a problem with your request:</p>
+% elif new_machine:
+<p>Successfully modified.</p>
+% endif
+% if on:
+(To edit ram, disk size, or machine name, turn off the machine first.)
+% endif
+<form action="modify" method="POST">
+  <input type="hidden" name="machine_id" value="${defaults.machine_id}"/>
+  <table>
+    <tr><td>Description:</td><td colspan="2"><textarea name="description" rows="4" cols="60">${defaults.description}</textarea></td></tr>
+    <tr><td>Owner${self.fn.helppopup("Owner")}:</td><td><input type="text" name="owner", value="${defaults.owner}"/></td></tr>
+${self.fn.errorRow('owner', err)}
+    <tr><td>Administrator${self.fn.helppopup("Administrator")}:</td><td><input type="text" name="admin", value="${defaults.administrator}"/></td></tr>
+${self.fn.errorRow('administrator', err)}
+    <tr><td>Contact email:</td><td><input type="text" name="contact" value="${defaults.contact}"/></td></tr>
+${self.fn.errorRow('contact', err)}
+% if not on:
+    <tr><td>Machine Name:</td><td><input type="text" name="name" value="${defaults.name}"/>.${config.dns.domains[0]}</td></tr>
+${self.fn.errorRow('name', err)}
+    <tr>
+      <td>HVM/ParaVM${self.fn.helppopup('HVM/ParaVM')}</td>
+      <td>${self.fn.vmTypeList(defaults.type)}</td>
+    </tr>
+    <tr><td>Ram:</td><td><input type="text" size=3 name="memory" value="${defaults.memory}"/>MiB (max ${max_mem})</td></tr>
+${self.fn.errorRow('memory', err)}
+    <tr><td>Disk:</td><td><input type="text" size=3 name="disksize" value="${defaults.disk}"/>GiB (max ${max_disk})</td><td>WARNING: Modifying disk size may corrupt your data.</td></tr>
+${self.fn.errorRow('disk', err)}
+% else:
+${self.fn.errorRow('name', err)}
+${self.fn.errorRow('memory', err)}
+${self.fn.errorRow('disk', err)}
+% endif
+    <tr><td><input type="submit" class="button" name="action" value="Change"/></td></tr>
+  </table>
+</form>
+</%def>
+
+<div id="info">
+  ${infoTable()}
+</div>
+
+<h2>Commands</h2>
+<div id="commands">
+  ${commands()}
+</div>
+<h2>Settings</h2>
+<div id="modify">
+  ${modifyForm()}
+</div>
Index: ckage_branches/invirt-web/cherrypy-rebased/code/templates/info.tmpl
===================================================================
--- /package_branches/invirt-web/cherrypy-rebased/code/templates/info.tmpl	(revision 2677)
+++ 	(revision )
@@ -1,142 +1,0 @@
-#from skeleton import skeleton
-#extends skeleton
-
-#def title
-Info on $machine.name
-#end def
-
-#def infoTable()
-<h2>Info</h2>
-<table>
-  #for $key, $value in $fields
-  <tr><td>$key:</td><td>$value</td></tr>
-  #end for
-</table>
-#end def
-
-#def commands()
-#if $on
- #if not $machine.type.hvm
-  Console access: type
-  <tt>ssh $machine.name@$config.console.hostname</tt>
-  on Athena. <a href="https://xvm.scripts.mit.edu/wiki/SerialConsole">(more info)</a>
- #elif $has_vnc
-  <strong><a href="vnc?machine_id=$machine.machine_id">Get Console</a></strong>
- #else
-  VNC console not enabled; still booting?
- #end if
-#end if
-<form action="command" method="POST">
-  <input type="hidden" name="back" value="info"/>
-  <input type="hidden" name="machine_id" value="$machine.machine_id"/>
-  <div>
-	#if $on
-	<button type="submit" class="button" name="action" value="Power off">Power off (hard)</button>
-	<button type="submit" class="button" name="action" value="Shutdown">Shut down</button>
-	<input type="submit" class="button" name="action" value="Reboot"/>
-	#else
-	<input type="submit" class="button" name="action" value="Power on"/>
-	#end if
-  </div>
-  <div>
-    Boot CD:
-#filter None
-$cdromList()#slurp
-#end filter
-  </div>
-  <div>
-      <input type="submit" class="button" name="action" value="Delete VM" onclick="return confirm('Are you sure that you want to delete this VM?');"/>
-  </div>
-</form>
-#end def
-
-#def modifyForm()
-#if $err
-<p class="error">We had a problem with your request:</p>
-#else if $varExists('new_machine')
-<p>Successfully modified.</p>
-#end if
-#if $on
-(To edit ram, disk size, or machine name, turn off the machine first.)
-#end if
-<form action="modify" method="POST">
-  <input type="hidden" name="machine_id" value="$defaults.machine_id"/>
-  <table>
-    <tr><td>Description:</td><td colspan="2"><textarea name="description" rows="4" cols="60">$defaults.description</textarea></td></tr>
-    <tr><td>Owner#slurp
-#filter None
-$helppopup("Owner")#slurp
-#end filter
-:</td><td><input type="text" name="owner", value="$defaults.owner"/></td></tr>
-#filter None
-$errorRow('owner', $err)
-#end filter
-    <tr><td>Administrator#slurp
-#filter None
-$helppopup("Administrator")#slurp
-#end filter
-:</td><td><input type="text" name="admin", value="$defaults.administrator"/></td></tr>
-#filter None
-$errorRow('administrator', $err)
-#end filter
-    <tr><td>Contact email:</td><td><input type="text" name="contact" value="$defaults.contact"/></td></tr>
-#filter None
-$errorRow('contact', $err)
-#end filter
-#if not $on
-    <tr><td>Machine Name:</td><td><input type="text" name="name" value="$defaults.name"/>.${config.dns.domains[0]}</td></tr>
-#filter None
-$errorRow('name', $err)
-#end filter
-    <tr>
-      <td>HVM/ParaVM#slurp
-#filter None
-$helppopup('HVM/ParaVM')#slurp
-#end filter
-</td>
-      <td>#slurp
-#filter None
-$vmTypeList($defaults.type)#slurp
-#end filter
-</td>
-    </tr>
-    <tr><td>Ram:</td><td><input type="text" size=3 name="memory" value="$defaults.memory"/>MiB (max $max_mem)</td></tr>
-#filter None
-$errorRow('memory', $err)
-#end filter
-    <tr><td>Disk:</td><td><input type="text" size=3 name="disksize" value="$defaults.disk"/>GiB (max $max_disk)</td><td>WARNING: Modifying disk size may corrupt your data.</td></tr>
-#filter None
-$errorRow('disk', $err)
-#end filter
-#else
-#filter None
-$errorRow('name', $err)
-$errorRow('memory', $err)
-$errorRow('disk', $err)
-#end filter
-#end if
-    <tr><td><input type="submit" class="button" name="action" value="Change"/></td></tr>
-  </table>
-</form>
-#end def
-
-#def body
-<div id="info">
-#filter None
-  $infoTable()
-#end filter
-</div>
-
-<h2>Commands</h2>
-<div id="commands">
-#filter None
-  $commands()
-#end filter
-</div>
-<h2>Settings</h2>
-<div id="modify">
-#filter None
-  $modifyForm()
-#end filter
-</div>
-#end def
Index: /package_branches/invirt-web/cherrypy-rebased/code/templates/list.mako
===================================================================
--- /package_branches/invirt-web/cherrypy-rebased/code/templates/list.mako	(revision 2677)
+++ /package_branches/invirt-web/cherrypy-rebased/code/templates/list.mako	(revision 2678)
@@ -96,5 +96,5 @@
 	  </form>
 	</td>
-	<td><a href="info?machine_id=${machine.machine_id}">${machine.name}</a></td>
+	<td><a href="machine/${machine.machine_id}">${machine.name}</a></td>
 	<td>${machine.memory}M</td>
 	<td>${machine.owner}</td>
@@ -112,5 +112,7 @@
 	<td>\
 % if has_vnc[machine] == True:
-<a href="vnc?machine_id=${machine.machine_id}">Console</a>\
+<a href="machine/${machine.machine_id}/vnc">Console</a>\
+% elif has_vnc[machine] == 'ParaVM':
+ParaVM${self.fn.helppopup("ParaVM Console")}
 % elif has_vnc[machine] != 'Off':
 ${has_vnc[machine]}
Index: /package_branches/invirt-web/cherrypy-rebased/code/templates/skeleton.mako
===================================================================
--- /package_branches/invirt-web/cherrypy-rebased/code/templates/skeleton.mako	(revision 2677)
+++ /package_branches/invirt-web/cherrypy-rebased/code/templates/skeleton.mako	(revision 2678)
@@ -6,4 +6,5 @@
 <html>
 <head><title>${self.title()} &mdash; XVM</title>
+  <base href="${cherrypy.request.base}" />
   <link href="static/favicon.ico" type="image/x-icon" rel="shortcut icon">
   <link rel="stylesheet" href="static/style.css" type="text/css" />
@@ -54,6 +55,6 @@
 <li><a href="list">List</a></li>
 % if machine:
-<li><a href="info?machine_id=${machine.machine_id}">Info</a></li>
-<li><a href="vnc?machine_id=${machine.machine_id}">Console</a></li>
+<li><a href="machine/${machine.machine_id}">Info</a></li>
+<li><a href="machine/${machine.machine_id}/vnc">Console</a></li>
 % endif
 <li><a href="help">Help</a></li>
