Make commands work from list and info pages
authorQuentin Smith <quentin@mit.edu>
Mon, 10 Aug 2009 01:07:28 +0000 (21:07 -0400)
committerQuentin Smith <quentin@mit.edu>
Mon, 10 Aug 2009 01:07:28 +0000 (21:07 -0400)
svn path=/package_branches/invirt-web/cherrypy-rebased/; revision=2684

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

index e32b1c2..c51a6ba 100644 (file)
@@ -204,17 +204,18 @@ def deleteVM(machine):
         session.rollback()
         raise
 
-def commandResult(username, state, fields):
+def commandResult(username, state, command_name, machine_id, fields):
     start_time = 0
-    machine = validation.Validate(username, state, machine_id=fields.getfirst('machine_id')).machine
-    action = fields.getfirst('action')
-    cdrom = fields.getfirst('cdrom')
+    machine = validation.Validate(username, state, machine_id=machine_id).machine
+    action = command_name
+    cdrom = fields.get('cdrom')
+    if not cdrom:
+        cdrom = None
     if cdrom is not None and not CDROM.query().filter_by(cdrom_id=cdrom).one():
         raise CodeError("Invalid cdrom type '%s'" % cdrom)    
-    if action not in ('Reboot', 'Power on', 'Power off', 'Shutdown', 
-                      'Delete VM'):
+    if action not in "reboot create destroy shutdown delete".split(" "):
         raise CodeError("Invalid action '%s'" % action)
-    if action == 'Reboot':
+    if action == 'reboot':
         if cdrom is not None:
             out, err = remctl('control', machine.name, 'reboot', cdrom,
                               err=True)
@@ -230,13 +231,13 @@ def commandResult(username, state, fields):
                 print >> sys.stderr, err
                 raise CodeError('ERROR on remctl')
                 
-    elif action == 'Power on':
+    elif action == 'create':
         if validation.maxMemory(username, state, machine) < machine.memory:
             raise InvalidInput('action', 'Power on',
                                "You don't have enough free RAM quota "
                                "to turn on this machine.")
         bootMachine(machine, cdrom)
-    elif action == 'Power off':
+    elif action == 'destroy':
         out, err = remctl('control', machine.name, 'destroy', err=True)
         if err:
             if re.match("machine '.*' is not on", err):
@@ -246,7 +247,7 @@ def commandResult(username, state, fields):
                 print >> sys.stderr, 'Error on power off:'
                 print >> sys.stderr, err
                 raise CodeError('ERROR on remctl')
-    elif action == 'Shutdown':
+    elif action == 'shutdown':
         out, err = remctl('control', machine.name, 'shutdown', err=True)
         if err:
             if re.match("machine '.*' is not on", err):
@@ -256,7 +257,7 @@ def commandResult(username, state, fields):
                 print >> sys.stderr, 'Error on Shutdown:'
                 print >> sys.stderr, err
                 raise CodeError('ERROR on remctl')
-    elif action == 'Delete VM':
+    elif action == 'delete':
         deleteVM(machine)
 
     d = dict(user=username,
index d938450..ba892bf 100755 (executable)
@@ -58,10 +58,12 @@ class InvirtWeb(View):
 
     @cherrypy.expose
     @cherrypy.tools.mako(filename="/list.mako")
-    def list(self):
+    def list(self, result=None):
         """Handler for list requests."""
         checkpoint.checkpoint('Getting list dict')
         d = getListDict(cherrypy.request.login, cherrypy.request.state)
+        if result is not None:
+            d['result'] = result
         checkpoint.checkpoint('Got list dict')
         return d
     index=list
@@ -214,6 +216,33 @@ console will suffer artifacts.
                      port=port,
                      authtoken=token)
             return d
+        @cherrypy.expose
+        @cherrypy.tools.mako(filename="/command.mako")
+        def command(self, command_name, machine_id, **kwargs):
+            """Handler for running commands like boot and delete on a VM."""
+            if cherrypy.request.method != "POST":
+                raise InvalidInput("request.method", command_name, "You must execute commands via POST")
+            back = kwargs.get('back', None)
+            try:
+                d = controls.commandResult(cherrypy.request.login, cherrypy.request.state, command_name, machine_id, kwargs)
+                if d['command'] == 'Delete VM':
+                    back = 'list'
+            except InvalidInput, err:
+                if not back:
+                    raise
+                print >> sys.stderr, err
+                result = err
+            else:
+                result = 'Success!'
+                if not back:
+                    return d
+            if back == 'list':
+                cherrypy.request.state.clear() #Changed global state
+                raise cherrypy.InternalRedirect('/list?result=%s' % urllib.quote(result))
+            elif back == 'info':
+                raise cherrypy.HTTPRedirect(cherrypy.request.base + '/machine/%d/' % machine_id, status=303)
+            else:
+                raise InvalidInput('back', back, 'Not a known back page.')
 
     machine = MachineView()
 
@@ -431,35 +460,6 @@ def getDiskInfo(data_dict, machine):
         data_dict['%s_size' % name] = "%0.1f GiB" % (disk.size / 1024.)
     return disk_fields
 
-def command(username, state, path, fields):
-    """Handler for running commands like boot and delete on a VM."""
-    back = fields.getfirst('back')
-    try:
-        d = controls.commandResult(username, state, fields)
-        if d['command'] == 'Delete VM':
-            back = 'list'
-    except InvalidInput, err:
-        if not back:
-            raise
-        print >> sys.stderr, err
-        result = err
-    else:
-        result = 'Success!'
-        if not back:
-            return templates.command(searchList=[d])
-    if back == 'list':
-        state.clear() #Changed global state
-        d = getListDict(username, state)
-        d['result'] = result
-        return templates.list(searchList=[d])
-    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},
-                "You shouldn't see this message.")
-    else:
-        raise InvalidInput('back', back, 'Not a known back page.')
-
 def modifyDict(username, state, fields):
     """Modify a machine as specified by CGI arguments.
 
@@ -651,7 +651,6 @@ def throwError(_, __, ___, ____):
     raise RuntimeError("test of the emergency broadcast system")
 
 mapping = dict(
-               command=command,
                modify=modify,
                create=create,
                unauth=unauthFront,
diff --git a/code/templates/command.mako b/code/templates/command.mako
new file mode 100644 (file)
index 0000000..17a16ed
--- /dev/null
@@ -0,0 +1,9 @@
+<%page expression_filter="h" />
+<%inherit file="skeleton.mako" />
+
+<%def name="title()">
+$command ${machine.name}
+</%def>
+
+<p>${command} ${machine.name} was successful.</p>
+<p><a href="list">Return</a></p>
diff --git a/code/templates/command.tmpl b/code/templates/command.tmpl
deleted file mode 100644 (file)
index 904cba7..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#from skeleton import skeleton
-#extends skeleton
-
-#def title
-$command $machine.name
-#end def
-
-
-#def body
-<p>$command ${machine.name} was successful.</p>
-#if $command == "Delete VM" or True
-<p><a href="list">Return</a></p>
-#else
-<p><a href="info?machine_id=${machine.machine_id}">Return</a></p>
-#end if
-#end def
index b98e7c2..d6a1cfb 100644 (file)
@@ -28,7 +28,7 @@ Info on ${machine.name}
 % endif
 <%def name="command_button(title, value, cdrom=False, extra='')">
 <form action="machine/${machine.machine_id}/command/${value}" method="POST">
-  <input type="hidden" name="back" value="machine/${machine.machine_id}/info" />
+  <input type="hidden" name="back" value="info" />
   <input type="submit" class="button" name="action" value="${title}" ${extra | n}/>
 % if cdrom:
   Boot CD: ${self.fn.cdromList()}
index 71afd55..176fe14 100644 (file)
@@ -84,11 +84,11 @@ ${self.fn.cdromList(defaults.cdrom, "$('cd_or_auto_cd').checked = true;$('autoin
 <%def name="machineRow(machine)">
       <tr> 
        <td rowspan="2">
-         <form action="command" method="post">
+         <form action="machine/${machine.machine_id}/command/${'shutdown' if machine.uptime else 'create'}" method="post">
            <input type="hidden" name="back" value="list"/>
            <input type="hidden" name="machine_id"
                   value="${machine.machine_id}"/>
-<input type="submit" class="power ${'on' if machine.uptime else 'off'}" name="action" value="${'Power off' if machine.uptime else 'Power on'}"\
+<input type="submit" class="power ${'on' if machine.uptime else 'off'}" name="action" value="${'Shutdown' if machine.uptime else 'Power on'}"\
 % if machine.uptime:
  onclick="return confirm('Are you sure you want to power off this VM?');"
 % endif