Author: tmckay
Date: 2012-02-08 17:28:17 +0000 (Wed, 08 Feb 2012)
New Revision: 5207
Modified:
trunk/cumin/python/cumin/grid/job.py
trunk/cumin/python/cumin/objectframe.py
trunk/cumin/python/cumin/objectselector.py
trunk/wooly/python/wooly/__init__.py
trunk/wooly/python/wooly/pages.py
trunk/wooly/python/wooly/server.py
trunk/wooly/resources/wooly.js
Log:
These changes sanely handle conditions that arise from deleted
submissions when the schedd publishes QMF submission objects
(QMF_PUBLISH_SUBMISSIONS is True) while eliminating unnecessary
redirects when the jobserver process publishes QMF objects.
* Add a mechanism that optionally allows a redirect on a failed ajax update.
Redirects at this point must be specified widget by widget.
* Redirect updates of the job summary page and the job details page
to the submission list when an update fails because the submission
object is missing.
* Change redirect from "Remove job" link on the job details page
to the job list instead of the submission list.
* Remove redirect from job summary page when the last running job
in a submission is removed.
BZ783139
Modified: trunk/cumin/python/cumin/grid/job.py
===================================================================
--- trunk/cumin/python/cumin/grid/job.py 2012-02-06 19:34:41 UTC (rev 5206)
+++ trunk/cumin/python/cumin/grid/job.py 2012-02-08 17:28:17 UTC (rev 5207)
@@ -296,6 +296,17 @@
(app, "id", cls.JobId, self.ids)
self.add_column(self.checkbox_column)
+ def do_render(self, session):
+ # Set redirect if the submission object we depend on is missing
+ if self.frame.object.get(session) is None:
+ nsession = session.branch()
+ frame = self.frame.parent
+ frame.view.show(nsession)
+ submission_list_url = nsession.marshal()
+ self.page.redirect.set(session, submission_list_url)
+ else:
+ return super(JobSelectorTable, self).do_render(session)
+
class JobObjectSelectorTask(ObjectSelectorTask):
def __init__(self, app, selector, verb):
super(JobObjectSelectorTask, self).__init__(app, selector)
@@ -342,29 +353,6 @@
def get_title(self, session):
return "Remove"
- def _get_running_jobs(self, osession):
- running = []
- records = self.selector.get_qmf_results(osession)
- if records and hasattr(records, "data"):
- for rec in records.data:
- if "JobStatus" in rec and rec["JobStatus"] ==
"RUNNING":
- running.append("%s.%s" %
(rec["ClusterId"],rec["ProcId"]))
- return running
-
- def do_enter(self, session, osession):
- super(JobSelectionRemove, self).do_enter(session, osession)
-
- # if all the running jobs in this submission are to be removed
- # return to the submission list instead of this submission page.
- running = self._get_running_jobs(osession)
- selected = self.selector.table.ids.get(osession)
- if len(set(running) - set(selected)) == 0:
- nsession = osession.branch()
- frame = self.selector.frame.parent
- frame.view.show(nsession)
- submission_list_url = nsession.marshal()
- self.form.return_url.set(session, submission_list_url)
-
class JobObjectSelectorTaskForm(ObjectSelectorTaskForm):
def __init__(self, app, name, task, verb):
super(JobObjectSelectorTaskForm, self).__init__(app, name, task)
@@ -650,6 +638,17 @@
self.defer_enabled = True
self.update_enabled = True
+ def do_render(self, session):
+ # Set redirect if the submission object we depend on is missing
+ if self.frame.object.get(session) is None:
+ nsession = session.branch()
+ frame = self.frame.parent.parent
+ frame.view.show(nsession)
+ submission_list_url = nsession.marshal()
+ self.page.redirect.set(session, submission_list_url)
+ else:
+ return super(JobAdsViewer, self).do_render(session)
+
def render_edit_button(self, session):
_, error = self.do_get_items(session)
render = True
@@ -1172,10 +1171,9 @@
nsession = osession.branch()
- # return to the submission list page
+ # return to the job list page
job_list = self.frame.parent
- submission_list = job_list.parent
- submission_list.view.show(nsession)
+ job_list.view.show(nsession)
self.form.return_url.set(session, nsession.marshal())
Modified: trunk/cumin/python/cumin/objectframe.py
===================================================================
--- trunk/cumin/python/cumin/objectframe.py 2012-02-06 19:34:41 UTC (rev 5206)
+++ trunk/cumin/python/cumin/objectframe.py 2012-02-08 17:28:17 UTC (rev 5207)
@@ -69,8 +69,20 @@
super(ObjectFrame, self).do_process(session)
+ def _allow_none(self, session):
+ try:
+ return self.page.allow_object_not_found.get(session)
+ except:
+ pass
+ return False
+
def get_object(self, session, id):
- return self.cls.get_object_by_id(session.cursor, id)
+ try:
+ return self.cls.get_object_by_id(session.cursor, id)
+ except:
+ if self._allow_none(session):
+ return None
+ raise
def get_view(self, app, name, obj):
return ObjectView(app, name, obj)
Modified: trunk/cumin/python/cumin/objectselector.py
===================================================================
--- trunk/cumin/python/cumin/objectselector.py 2012-02-06 19:34:41 UTC (rev 5206)
+++ trunk/cumin/python/cumin/objectselector.py 2012-02-08 17:28:17 UTC (rev 5207)
@@ -580,7 +580,10 @@
export_session = wooly.Session(page)
page.modes.show_child(export_session, self.exporter)
- page.set_parameters(export_session, session, self.object_attributes,
self.file_name)
+ try:
+ page.set_parameters(export_session, session, self.object_attributes,
self.file_name)
+ except:
+ return ""
return escape_entity(export_session.marshal())
class QmfDetails(Widget):
Modified: trunk/wooly/python/wooly/__init__.py
===================================================================
--- trunk/wooly/python/wooly/__init__.py 2012-02-06 19:34:41 UTC (rev 5206)
+++ trunk/wooly/python/wooly/__init__.py 2012-02-08 17:28:17 UTC (rev 5207)
@@ -401,6 +401,10 @@
self.redirect = Attribute(app, "redirect")
self.add_attribute(self.redirect)
+ self.allow_object_not_found = Attribute(app, "allow_object_not_found")
+ self.allow_object_not_found.required = False
+ self.add_attribute(self.allow_object_not_found)
+
self.error = Attribute(app, "error")
self.add_attribute(self.error)
@@ -502,6 +506,10 @@
class PageRedirect(Exception):
pass
+class UpdateRedirect(Exception):
+ def __init__(self, url):
+ self.url = url
+
class PageError(object):
def __init__(self, page, session):
self.page = page
Modified: trunk/wooly/python/wooly/pages.py
===================================================================
--- trunk/wooly/python/wooly/pages.py 2012-02-06 19:34:41 UTC (rev 5206)
+++ trunk/wooly/python/wooly/pages.py 2012-02-08 17:28:17 UTC (rev 5207)
@@ -110,8 +110,9 @@
value = session.request_environment.get("HTTP_USER_AGENT")
if (value and value.find("MSIE 6") != -1) or (value and
value.find("MSIE 9") != -1):
- # sadly, although msie 9 handles application/xhtml+xml, the version of
swfobject (2.2)
- # that we are using does not support that content type (by their design), so
we fall back to text/html
+ # sadly, although msie 9 handles application/xhtml+xml, the version
+ # of swfobject (2.2) that we are using does not support that content
+ # type (by their design), so we fall back to text/html
content_type = self.html_content_type
else:
content_type = self.xhtml_content_type
@@ -215,13 +216,31 @@
def do_process(self, session):
# get the session for the main page
sess = self.session.get(session)
+
+ # Allow object frames to have None as an object
+ # during the process pass.
+ self.allow_object_not_found.set(sess, True)
+
self.html_page.process(sess)
- # if the main page set it's redirect attribute in it's session
+ # if the main page set its redirect attribute in its session
redirect = self.html_page.redirect.get(sess)
# pass that redirect on to the the update page
if redirect:
self.redirect.set(session, redirect)
+ def service(self, session):
+ self.process(session)
+
+ # Skip the render if a redirect has been set
+ if not self.redirect.get(session):
+ res = self.render(session)
+ # Check for a redirect from either process or render
+ url = self.redirect.get(session)
+ if url:
+ # Send the url to the ajax script in the update response
+ raise UpdateRedirect(url)
+ return res
+
def render_widgets(self, session):
writer = Writer()
sess = self.session.get(session)
@@ -230,7 +249,12 @@
for widget in widgets:
self.widget_tmpl.render(writer, sess, widget)
-
+ # If a widget generated a redirect url,
+ # there is no sense finishing the render
+ redirect = self.redirect.get(sess)
+ if redirect:
+ self.redirect.set(session, redirect)
+ break
return writer.to_string()
def render_widget_id(self, session, widget):
Modified: trunk/wooly/python/wooly/server.py
===================================================================
--- trunk/wooly/python/wooly/server.py 2012-02-06 19:34:41 UTC (rev 5206)
+++ trunk/wooly/python/wooly/server.py 2012-02-08 17:28:17 UTC (rev 5207)
@@ -126,6 +126,12 @@
except PageRedirect:
status = "303 See Other"
headers.append(("Location", page.redirect.get(session)))
+ except UpdateRedirect as e:
+ # This will optionally allow a failed ajax update to
+ # process a location change. Javascript code in the
+ # update handler will look for the header.
+ status = "200 OK"
+ headers.append(("Location", e.url))
except:
content = page.service_error(session)
status = "500 Internal Error"
Modified: trunk/wooly/resources/wooly.js
===================================================================
--- trunk/wooly/resources/wooly.js 2012-02-06 19:34:41 UTC (rev 5206)
+++ trunk/wooly/resources/wooly.js 2012-02-08 17:28:17 UTC (rev 5207)
@@ -459,16 +459,25 @@
function update() {
try {
- if (req.readyState == 4 && req.status == 200) {
+ // The location header provides away to recover from a
+ // failed update
+ var checkForRedirect = req.getResponseHeader("Location")
+ if (checkForRedirect){
+ if (checkForRedirect == "reload") {
+ location.reload()
+ } else {
+ location.href = checkForRedirect
+ }
+ } else if (req.readyState == 4 && req.status == 200) {
if (astext == true)
callback(req.responseText, passback);
else
callback(req.responseXML, passback);
} else {
- if(req.readyState == 4) {
- //readyState == 4 means that the call is done...a non-200 status
means that something bad happened, call the callback with null for the XML
- callback(null, passback);
- }
+ if(req.readyState == 4) {
+ //readyState == 4 means that the call is done...a non-200 status
means that something bad happened, call the callback with null for the XML
+ callback(null, passback);
+ }
}
} catch (e) {
log(e);