Upgrade info page to Mako, and use REST-style URLs.
authorQuentin Smith <quentin@mit.edu>
Sun, 9 Aug 2009 22:45:35 +0000 (18:45 -0400)
committerQuentin Smith <quentin@mit.edu>
Sun, 9 Aug 2009 22:45:35 +0000 (18:45 -0400)
svn path=/package_branches/invirt-web/cherrypy-rebased/; revision=2678

code/main.py
code/templates/info.mako [new file with mode: 0644]
code/templates/info.tmpl [deleted file]
code/templates/list.mako
code/templates/skeleton.mako

index 47f9b01..656c209 100755 (executable)
@@ -150,6 +150,31 @@ console will suffer artifacts.
         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):
     if path.startswith('/'):
         path = path[1:]
@@ -605,13 +630,6 @@ def infoDict(username, state, machine):
              fields = fields)
     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."""
     return templates.unauth(searchList=[{'simple' : True, 
@@ -636,7 +654,6 @@ def throwError(_, __, ___, ____):
 mapping = dict(vnc=vnc,
                command=command,
                modify=modify,
-               info=info,
                create=create,
                unauth=unauthFront,
                admin=admin,
diff --git a/code/templates/info.mako b/code/templates/info.mako
new file mode 100644 (file)
index 0000000..5af29bb
--- /dev/null
@@ -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>
diff --git a/code/templates/info.tmpl b/code/templates/info.tmpl
deleted file mode 100644 (file)
index d872fce..0000000
+++ /dev/null
@@ -1,142 +0,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 b03a04f..e500896 100644 (file)
@@ -95,7 +95,7 @@ ${self.fn.cdromList(defaults.cdrom, "$('cd_or_auto_cd').checked = true;$('autoin
 />
          </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>
        <td>${machine.administrator}</td>
@@ -111,7 +111,9 @@ ${datetime.timedelta(seconds=int(machine.uptime))}\
 </td>
        <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]}
 % endif
index a619a67..9c60c56 100644 (file)
@@ -5,6 +5,7 @@ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <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" />
   <link rel="stylesheet" href="static/layout.css" type="text/css" media="screen" />
@@ -53,8 +54,8 @@ function helppopup(name){
 <ul class="navigation">
 <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>
 </ul>