Author: justi9
Date: 2010-06-30 10:00:08 -0400 (Wed, 30 Jun 2010)
New Revision: 4055
Modified:
mgmt/newdata/cumin/python/cumin/grid/submission.py
mgmt/newdata/cumin/python/cumin/objectframe.py
mgmt/newdata/cumin/python/cumin/objectframe.strings
mgmt/newdata/cumin/python/cumin/objecttask.py
mgmt/newdata/cumin/python/cumin/widgets.py
mgmt/newdata/mint/python/mint/session.py
mgmt/newdata/wooly/python/wooly/__init__.py
mgmt/newdata/wooly/python/wooly/pages.py
mgmt/newdata/wooly/python/wooly/pages.strings
mgmt/newdata/wooly/python/wooly/server.py
mgmt/newdata/wooly/python/wooly/widgets.py
Log:
* Restore submissions to working; more work remains here, however
* Make task invocations stick around until they are explicitly
dismissed
* Reuse a single read cursor per login_session
* Reverting a previous change, delete agents from the model in the
delAgent callback; deferring it caused agent collisions
* Add a top-level Page.service that encapsulates the
process/redirect?/render routine; use exceptions out of the service
method to signal redirects and auth failures
* Tuck debug messages into the bottom of the rendered html
* Fix class attr rendering in ItemSet
* Improve "none" value formatting in ObjectAttributes
* Add References to the details page; the values here are still not
getting set; that's a rosemary issue I intend to address in an
upcoming commit
Modified: mgmt/newdata/cumin/python/cumin/grid/submission.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/grid/submission.py 2010-06-29 20:20:12 UTC (rev 4054)
+++ mgmt/newdata/cumin/python/cumin/grid/submission.py 2010-06-30 14:00:08 UTC (rev 4055)
@@ -56,40 +56,39 @@
def do_invoke(self, invoc, scheduler,
description,
executable,
- args=None,
- iwd="/tmp",
+ arguments=None,
+ requirements=None,
+ iwd=None,
stdin=None,
stdout=None,
stderr=None,
- requirements="TRUE",
- universe="VANILLA"):
- user_name = invoc.user.name
+ universe=5):
+ # XXX
+ # user_name = invoc.user.name
+ user_name = "gridmonkey"
- ad = {
- "Submission": {"TYPE": self.STRING_TYPE,
- "VALUE": condor_string(description)},
- "Cmd": {"TYPE": self.STRING_TYPE,
- "VALUE": condor_string(executable)},
- "Args": {"TYPE": self.STRING_TYPE,
- "VALUE": condor_string(args)},
- "Requirements": {"TYPE": self.EXPR_TYPE,
- "VALUE": requirements},
- "JobUniverse": {"TYPE": self.INTEGER_TYPE,
- "VALUE": str(self.UNIVERSE[universe])},
- "Iwd": {"TYPE": self.STRING_TYPE,
- "VALUE": condor_string(iwd)},
- "Owner": {"TYPE": self.STRING_TYPE,
- "VALUE": "guest3"}
- }
+ ad = dict()
-# "User": {"TYPE": self.STRING_TYPE,
-# "VALUE":
condor_string("example(a)example.com")}
+ ad["Submission"] = description
+ ad["Cmd"] = executable
+ ad["Owner"] = user_name
- scheduler.Submit(completion, ad, None)
+ def put(name, value):
+ if value:
+ ad[name] = value
-def condor_string(string):
- return string
+ put("Args", arguments)
+ put("Iwd", iwd)
+ put("Requirements", requirements)
+ put("JobUniverse", universe)
+ descriptors = dict()
+ descriptors["Requirements"] = "com.redhat.grid.Expression"
+
+ ad["!!descriptors"] = descriptors
+
+ self.qmf_call(invoc, scheduler, "SubmitJob", ad)
+
class SubmissionAddForm(ObjectTaskForm):
def __init__(self, app, name, task):
super(SubmissionAddForm, self).__init__(app, name, task)
@@ -162,20 +161,18 @@
tokens = shlex.split(command)
executable = tokens[0]
- args = " ".join(tokens[1:])
+ arguments = " ".join(tokens[1:])
- if not requirements:
- requirements = "TRUE"
-
- self.task.invoke(session, scheduler, description,
+ self.task.invoke(session,
+ scheduler,
+ description,
executable,
- args=args,
+ arguments=arguments,
+ requirements=requirements,
iwd=directory,
stdin=stdin,
stdout=stdout,
- stderr=stderr,
- requirements=requirements)
-
+ stderr=stderr)
# universe=universe) # XXX
self.task.exit_with_redirect(session)
Modified: mgmt/newdata/cumin/python/cumin/objectframe.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/objectframe.py 2010-06-29 20:20:12 UTC (rev 4054)
+++ mgmt/newdata/cumin/python/cumin/objectframe.py 2010-06-30 14:00:08 UTC (rev 4055)
@@ -95,7 +95,7 @@
for attr in self.get_attributes(session):
name = attr.title
- value = getattr(obj, attr.name, fmt_none())
+ value = getattr(obj, attr.name, None)
writer.write(self.entry.render(session, name, value))
@@ -106,6 +106,9 @@
return name
def render_value(self, session, name, value):
+ if value is None:
+ return fmt_none()
+
return xml_escape(str(value))
class ObjectTasks(Widget):
@@ -263,18 +266,22 @@
self.object = object
- props = self.Headers(app, "headers", self.object)
- props.update_enabled = True
- self.add_child(props)
+ attrs = self.Headers(app, "headers", self.object)
+ attrs.update_enabled = True
+ self.add_child(attrs)
- props = self.Properties(app, "props", self.object)
- props.update_enabled = True
- self.add_child(props)
+ attrs = self.References(app, "refs", self.object)
+ attrs.update_enabled = True
+ self.add_child(attrs)
- stats = self.Statistics(app, "stats", self.object)
- stats.update_enabled = True
- self.add_child(stats)
+ attrs = self.Properties(app, "props", self.object)
+ attrs.update_enabled = True
+ self.add_child(attrs)
+ attrs = self.Statistics(app, "stats", self.object)
+ attrs.update_enabled = True
+ self.add_child(attrs)
+
def render_title(self, session):
return "Details"
@@ -286,6 +293,14 @@
def render_title(self, session):
return "QMF Headers"
+ class References(ObjectAttributes):
+ def get_attributes(self, session):
+ obj = self.object.get(session)
+ return obj._class._references
+
+ def render_title(self, session):
+ return "References"
+
class Properties(ObjectAttributes):
def get_attributes(self, session):
obj = self.object.get(session)
Modified: mgmt/newdata/cumin/python/cumin/objectframe.strings
===================================================================
--- mgmt/newdata/cumin/python/cumin/objectframe.strings 2010-06-29 20:20:12 UTC (rev
4054)
+++ mgmt/newdata/cumin/python/cumin/objectframe.strings 2010-06-30 14:00:08 UTC (rev
4055)
@@ -175,6 +175,8 @@
[ObjectDetails.html]
{headers}
+{refs}
+
{props}
{stats}
Modified: mgmt/newdata/cumin/python/cumin/objecttask.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/objecttask.py 2010-06-29 20:20:12 UTC (rev 4054)
+++ mgmt/newdata/cumin/python/cumin/objecttask.py 2010-06-30 14:00:08 UTC (rev 4055)
@@ -6,6 +6,7 @@
from wooly.resources import *
from wooly.widgets import *
+from formats import *
from main import *
from util import *
@@ -74,18 +75,18 @@
return invoc
- def invoke(self, session, obj, *args):
+ def invoke(self, session, obj, *args, **kwargs):
if obj:
assert isinstance(obj, RosemaryObject), obj
invoc = self.start(session, obj)
try:
- self.do_invoke(invoc, obj, *args)
+ self.do_invoke(invoc, obj, *args, **kwargs)
except Exception, e:
self.exception(invoc, e)
- def do_invoke(self, invoc, obj, *args):
+ def do_invoke(self, invoc, obj, *args, **kwargs):
pass
def qmf_call(self, invoc, obj, meth, *args):
@@ -144,23 +145,28 @@
def __init__(self, task, login_session):
self.task = task
- self.login_session = login_session
- self.login_session.task_invocations.append(self)
+ login_session = login_session
+ login_session.task_invocations.append(self)
+ self.user = login_session.user
+
self.start_time = None
self.end_time = None
self.update_time = None
+
self.status = None
self.exception = None
self.status_code = None
self.output_args = None
+ self.dismissed = False
+
def get_summary(self, session):
if self.exception:
return str(self.exception)
- return self.status
+ return "%s %r" % (self.status, self.output_args)
def end(self):
log.debug("Ending %s", self.task)
@@ -182,17 +188,26 @@
self.html_class = TaskInvocationSet.__name__
self.update_enabled = True
- def do_get_items(self, session):
- now = secs(datetime.now())
+ self.dismiss = IntegerParameter(app, "dismiss")
+ self.add_parameter(self.dismiss)
+ def get_items(self, session):
login = session.client_session.attributes["login_session"]
+ return [x for x in login.task_invocations if not x.dismissed]
- invocs = sorted_by(login.task_invocations, "update_time")
- invocs = [x for x in invocs
- if now - secs(x.update_time) < 10 or x.status == x.FAILED]
+ def do_process(self, session):
+ super(TaskInvocationSet, self).do_process(session)
- return invocs
+ dismiss = self.dismiss.get(session)
+ if dismiss:
+ for invoc in self.get_items(session):
+ if id(invoc) == dismiss:
+ invoc.dismissed = True
+ break
+
+ self.dismiss.unset(session)
+
def do_render(self, session):
items = self.get_items(session)
@@ -208,8 +223,14 @@
summary = item.get_summary(session)
- return ": ".join((description, summary))
+ # XXX oh honey
+ branch = session.branch()
+ self.dismiss.set(branch, id(item))
+ link = fmt_link(branch.marshal(), "Dismiss")
+
+ return ": ".join((description, summary, link))
+
class SelectionTask(Task):
def __init__(self, app, selector):
super(SelectionTask, self).__init__(app)
Modified: mgmt/newdata/cumin/python/cumin/widgets.py
===================================================================
--- mgmt/newdata/cumin/python/cumin/widgets.py 2010-06-29 20:20:12 UTC (rev 4054)
+++ mgmt/newdata/cumin/python/cumin/widgets.py 2010-06-30 14:00:08 UTC (rev 4055)
@@ -1322,12 +1322,31 @@
self.add_attribute(self.user)
def do_process(self, session):
- conn = self.app.database.get_connection()
- setattr(session, "cursor", conn.cursor())
+ session.cursor = self.get_cursor(session)
- if self.authorized(session):
- super(CuminPage, self).do_process(session)
+ if not self.authorized(session):
+ page = self.app.login_page
+ sess = Session(page)
+ page.origin.set(sess, session.marshal())
+
+ self.redirect.set(sess.marshal())
+
+ return
+
+ super(CuminPage, self).do_process(session)
+
+ def get_cursor(self, session):
+ try:
+ cursor = session.client_session.attributes["read_cursor"]
+ except KeyError:
+ conn = self.app.database.get_connection()
+ cursor = conn.cursor()
+
+ session.client_session.attributes["read_cursor"] = cursor
+
+ return cursor
+
def authorized(self, session):
if not self.protected:
return True
@@ -1351,13 +1370,6 @@
return True
- lpage = self.app.login_page
-
- lsess = Session(lpage)
- lpage.origin.set(lsess, session.marshal())
-
- self.redirect.set(session, lsess.marshal())
-
return False
class CuminFormPage(CuminPage):
Modified: mgmt/newdata/mint/python/mint/session.py
===================================================================
--- mgmt/newdata/mint/python/mint/session.py 2010-06-29 20:20:12 UTC (rev 4054)
+++ mgmt/newdata/mint/python/mint/session.py 2010-06-30 14:00:08 UTC (rev 4055)
@@ -78,6 +78,8 @@
except KeyError:
return
+ agent.delete()
+
if not self.model.app.update_thread.isAlive():
return
Modified: mgmt/newdata/wooly/python/wooly/__init__.py
===================================================================
--- mgmt/newdata/wooly/python/wooly/__init__.py 2010-06-29 20:20:12 UTC (rev 4054)
+++ mgmt/newdata/wooly/python/wooly/__init__.py 2010-06-30 14:00:08 UTC (rev 4055)
@@ -58,6 +58,9 @@
# XXX don't return the value
return session.set(self.path, value)
+ def unset(self, session):
+ session.unset(self.path)
+
def get_default(self, session):
return self.default
@@ -459,6 +462,16 @@
def enable_update(self, session, widget):
pass
+ def service(self, session):
+ self.process(session)
+
+ redirect = self.redirect.get(session)
+
+ if redirect:
+ raise PageRedirect(redirect)
+
+ return self.render(session)
+
def render_id(self, session, *args):
return self.name
@@ -466,6 +479,15 @@
def get_default(self, session):
return PageProfile(self)
+class PageRedirect(Exception):
+ def __init__(self, url):
+ super(PageRedirect, self).__init__()
+
+ self.url = url
+
+class PageForbidden(Exception):
+ pass
+
from parameters import DictParameter
class Application(object):
Modified: mgmt/newdata/wooly/python/wooly/pages.py
===================================================================
--- mgmt/newdata/wooly/python/wooly/pages.py 2010-06-29 20:20:12 UTC (rev 4054)
+++ mgmt/newdata/wooly/python/wooly/pages.py 2010-06-30 14:00:08 UTC (rev 4055)
@@ -5,6 +5,7 @@
from wooly import *
from wooly.parameters import ListParameter
from wooly.resources import StringCatalog
+from wooly.widgets import ItemSet
strings = StringCatalog(__file__)
@@ -93,6 +94,9 @@
self.defer_script.interval = 0
self.add_child(self.defer_script)
+ messages = HtmlPageMessages(app, "messages")
+ self.add_child(messages)
+
self.update_page = UpdatePage(app, self.base_name + ".update", self)
self.app.add_page(self.update_page)
@@ -141,6 +145,10 @@
def get_default(self, session):
return list()
+class HtmlPageMessages(ItemSet):
+ def do_get_items(self, session):
+ return session.messages
+
class AjaxScript(Widget):
def __init__(self, app, name, html_page):
super(AjaxScript, self).__init__(app, name)
Modified: mgmt/newdata/wooly/python/wooly/pages.strings
===================================================================
--- mgmt/newdata/wooly/python/wooly/pages.strings 2010-06-29 20:20:12 UTC (rev 4054)
+++ mgmt/newdata/wooly/python/wooly/pages.strings 2010-06-30 14:00:08 UTC (rev 4055)
@@ -23,9 +23,16 @@
</head>
<body class="{class}">
{content}
+ {messages}
</body>
</html>
+[HtmlPageMessages.css]
+ul.HtmlPageMessages {
+ font-size: 0.9em;
+ color: red;
+}
+
[AjaxScript.html]
<script type="text/javascript">
// <![CDATA[
Modified: mgmt/newdata/wooly/python/wooly/server.py
===================================================================
--- mgmt/newdata/wooly/python/wooly/server.py 2010-06-29 20:20:12 UTC (rev 4054)
+++ mgmt/newdata/wooly/python/wooly/server.py 2010-06-30 14:00:08 UTC (rev 4055)
@@ -106,46 +106,19 @@
if modified <= since:
return self.send_not_modified(response, headers)
except AttributeError:
- log.error("Exception in If Modified Since. ims=%s" % str(ims))
- pass
+ log.error("If-modified-since check failed; ims=%s" % str(ims))
self.adapt_request_to_session(env, session)
try:
- page.process(session)
-
- redirect = page.redirect.get(session)
-
- if redirect:
- return self.send_redirect(response, headers, redirect)
-
- content = page.render(session)
+ content = page.service(session)
+ except PageRedirect, e:
+ return self.send_redirect(response, headers, e.url)
+ except PageForbidden:
+ return self.send_forbidden(response, headers)
except:
- headers.append(("Content-Type", "text/plain"))
+ return self.send_error(response, headers, env, page, session)
- response("500 Internal Error", headers)
-
- writer = Writer()
- writer.write("APPLICATION ERROR\n\n")
-
- print_exc(None, writer)
-
- writer.write("\n")
-
- profile = page.profile.get(session)
-
- if profile:
- writer.write("Widget trace:\n\n")
- profile.print_stack_trace(writer)
- writer.write("\n")
-
- self.print_messages(session, writer)
- self.print_session(session, writer)
- self.print_url_vars(env["QUERY_STRING"], writer)
- self.print_environment(env, writer)
-
- return writer.to_string()
-
headers.append(("Content-Length", str(len(content))))
self.adapt_session_to_response(page, session, headers)
@@ -154,46 +127,6 @@
return (content,)
- def print_messages(self, session, writer):
- writer.write("Messages:\n\n")
-
- for message in session.messages:
- writer.write(" %s\n" % message)
-
- writer.write("\n")
-
- def print_session(self, session, writer):
- writer.write("Session:\n\n")
-
- for path in sorted(session.values_by_path):
- value = session.values_by_path[path]
-
- writer.write(" %-30s %s\n" % (path, value))
-
- writer.write("\n")
-
- def print_url_vars(self, query, writer):
- writer.write("URL variables:\n\n")
-
- if query:
- vars = query.split(";")
-
- for var in sorted(vars):
- key, value = var.split("=")
- writer.write(" %-30s %s\n" % (key, value))
-
- writer.write("\n")
-
- def print_environment(self, env, writer):
- writer.write("Environment:\n\n")
-
- for key in sorted(env):
- value = env[key]
-
- writer.write(" %-30s %s\n" % (key, value))
-
- writer.write("\n")
-
def adapt_request_to_session(self, env, session):
session.unmarshal_url_vars(env["QUERY_STRING"])
@@ -240,15 +173,6 @@
for header in session.marshal_cookies():
headers.append(("Set-Cookie", header))
- def send_not_found(self, response, headers):
- message = "404 Not Found"
-
- headers.append(("Content-Length", str(len(message))))
- headers.append(("Content-Type", "text/plain"))
-
- response(message, headers)
- return (message,)
-
def send_message(self, response, headers, message):
headers.append(("Content-Length", str(len(message))))
headers.append(("Content-Type", "text/plain"))
@@ -257,6 +181,12 @@
return (message,)
+ def send_not_found(self, response, headers):
+ return self.send_message(response, headers, "404 Not Found")
+
+ def send_forbidden(self, response, headers):
+ return self.send_message(response, headers, "403 Forbidden")
+
def send_redirect(self, response, headers, url):
headers.append(("Location", url))
headers.append(("Content-Length", "0"))
@@ -272,6 +202,72 @@
return ()
+ def send_error(self, response, headers, env, page, session):
+ headers.append(("Content-Type", "text/plain"))
+
+ response("500 Internal Error", headers)
+
+ writer = Writer()
+ writer.write("APPLICATION ERROR\n\n")
+
+ print_exc(None, writer)
+
+ writer.write("\n")
+
+ profile = page.profile.get(session)
+
+ if profile:
+ writer.write("Widget trace:\n\n")
+ profile.print_stack_trace(writer)
+ writer.write("\n")
+
+ self.print_messages(session, writer)
+ self.print_session(session, writer)
+ self.print_url_vars(env["QUERY_STRING"], writer)
+ self.print_environment(env, writer)
+
+ return writer.to_string()
+
+ def print_messages(self, session, writer):
+ writer.write("Messages:\n\n")
+
+ for message in session.messages:
+ writer.write(" %s\n" % message)
+
+ writer.write("\n")
+
+ def print_session(self, session, writer):
+ writer.write("Session:\n\n")
+
+ for path in sorted(session.values_by_path):
+ value = session.values_by_path[path]
+
+ writer.write(" %-30s %s\n" % (path, value))
+
+ writer.write("\n")
+
+ def print_url_vars(self, query, writer):
+ writer.write("URL variables:\n\n")
+
+ if query:
+ vars = query.split(";")
+
+ for var in sorted(vars):
+ key, value = var.split("=")
+ writer.write(" %-30s %s\n" % (key, value))
+
+ writer.write("\n")
+
+ def print_environment(self, env, writer):
+ writer.write("Environment:\n\n")
+
+ for key in sorted(env):
+ value = env[key]
+
+ writer.write(" %-30s %s\n" % (key, value))
+
+ writer.write("\n")
+
def __repr__(self):
return "%s(%s,%i)" % (self.__class__.__name__, self.host, self.port)
Modified: mgmt/newdata/wooly/python/wooly/widgets.py
===================================================================
--- mgmt/newdata/wooly/python/wooly/widgets.py 2010-06-29 20:20:12 UTC (rev 4054)
+++ mgmt/newdata/wooly/python/wooly/widgets.py 2010-06-30 14:00:08 UTC (rev 4055)
@@ -200,6 +200,9 @@
def render_item_content(self, session, item):
return item
+ def render_item_class(self, session, item):
+ return "_"
+
def render_none(self, session):
"""For producing a message when the set is
empty"""