Author: eallen
Date: 2008-09-25 11:25:36 -0400 (Thu, 25 Sep 2008)
New Revision: 2542
Modified:
mgmt/trunk/cumin/python/cumin/limits.py
mgmt/trunk/cumin/python/cumin/limits.strings
mgmt/trunk/cumin/python/cumin/model.py
Log:
Added SetLimit
Added Hold/Release/Remove methods to LimitJobSet
Modified: mgmt/trunk/cumin/python/cumin/limits.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/limits.py 2008-09-25 15:23:36 UTC (rev 2541)
+++ mgmt/trunk/cumin/python/cumin/limits.py 2008-09-25 15:25:36 UTC (rev 2542)
@@ -16,7 +16,48 @@
strings = StringCatalog(__file__)
log = logging.getLogger("cumin.Limits")
-class LimitsSet(ItemTable):
+class LimitActions(object):
+ def fetch_limits(self, session):
+ negotiator = self.get_negotiator(session)
+ if negotiator:
+ return self.get_raw_limits(session, negotiator)
+
+ def get_negotiator(self, session):
+#TODO: find better way to get the negotiator. from pool perhaps?
+ negotiators = Negotiator.select()
+ for negotiator in negotiators:
+ if negotiator.managedBroker:
+ return negotiator
+
+ def set_limit(self, session, limit):
+ negotiator = self.get_negotiator(session)
+ action = self.app.model.limit.setlimit
+ action.invoke(limit, negotiator)
+#TODO: this probably shouldn't be called until after the invoke completes
+ def completion():
+ pass
+ negotiator.Reconfig(self.app.model.data, completion)
+
+ def get_raw_limits(self, session, negotiator):
+ self.lim = dict()
+ self.got_data = False
+
+ def completion(status, data):
+ self.lim = data["Limits"]
+ self.got_data = True
+
+ def predicate():
+ return self.got_data
+
+ model = self.app.model
+ negotiator.GetLimits(model.data, completion, self.lim)
+
+ # wait for up to 20 seconds for completion to be called
+ wait(predicate, timeout=20)
+ return self.lim
+
+
+class LimitsSet(ItemTable, LimitActions):
def __init__(self, app, name):
super(LimitsSet, self).__init__(app, name)
@@ -47,33 +88,10 @@
def limit_count(self, session):
limits = self.limits.get(session)
if not limits:
-#TODO: fix this. Where do we get the correct negotiator???
- negotiators = Negotiator.select()
- for negotiator in negotiators:
- if negotiator.managedBroker:
-#TODO:
- limits = self.get_raw_limits(session, negotiator)
- self.limits.set(session, limits)
+ limits = self.fetch_limits(session)
+ self.limits.set(session, limits)
return len(limits)
- def get_raw_limits(self, session, negotiator):
- self.lim = dict()
- self.got_data = False
-
- def completion(status, data):
- self.lim = data["Limits"]
- self.got_data = True
-
- def predicate():
- return self.got_data
-
- model = self.app.model
- negotiator.GetLimits(model.data, completion, self.lim)
-
- # wait for up to 20 seconds for completion to be called
- wait(predicate, timeout=20)
- return self.lim
-
class NameColumn(ItemTableColumn):
def render_title(self, session, data):
return "Name"
@@ -96,7 +114,7 @@
def get_default(self, session):
return dict()
-class LimitsFrame(CuminFrame):
+class LimitsFrame(CuminFrame, JobSetFrame, LimitActions):
def __init__(self, app, name):
super(LimitsFrame, self).__init__(app, name)
@@ -107,19 +125,100 @@
self.add_mode(view)
self.set_view_mode(view)
- def show_job(self, session, job):
- return self.frame.show_job(session, job)
+ edit = LimitEdit(app, "edit")
+ self.add_mode(edit)
+ self.set_edit_mode(edit)
- def show_scheduler(self, session, sched):
- return self.frame.show_scheduler(session, sched)
+ def get_object(self, session):
+ obj = self.object.get(session)
+ if not getattr(obj, "name", None):
+ limits = self.fetch_limits(session)
+ obj.name = obj.id
+ obj.curr = limits[obj.id]["CURRENT"]
+ obj.max = limits[obj.id]["MAX"]
+ self.object.set(session, obj)
- def show_submitter(self, session, submitter):
- return self.frame.show_submitter(session, submitter)
+ return obj
+
- def show_job_group(self, session, job_group):
- return self.frame.show_job_group(session, job_group)
+class LimitEdit(CuminForm):
+ def __init__(self, app, name):
+ super(LimitEdit, self).__init__(app, name)
+ self.max = Parameter(app, "max")
+ self.add_parameter(self.max)
+ self.add_form_parameter(self.max)
+ self.error = self.Errors(self, "error")
+ self.add_attribute(self.error)
+
+ self.error_tmpl = Template(self, "error_html")
+
+ class Errors(Attribute):
+ def get_default(self, session):
+ return dict()
+
+ def get_args(self, session):
+ return self.frame.get_args(session)
+
+ def render_title(self, session, *args):
+ return "Edit Concurrency Limit '%s'" % args[0].id
+
+ def render_input_id(self, session, *args):
+ return self.max.path
+
+ def render_label(self, session, *args):
+ return "Maximum Allowance"
+
+ def render_input_name(self, session, *args):
+ return self.max.path
+
+ def render_input_value(self, session, *args):
+ max = self.max.get(session)
+ if not max:
+ max = args[0].max
+ return str(max)
+
+ def render_inline_help(self, session, *args):
+ return "Set the maximum number of jobs that can run concurrently using this
limiter."
+
+ def render_limit_error(self, session, *args):
+ error = self.error.get(session)
+ if "max" in error:
+ writer = Writer()
+ self.error_tmpl.render(writer, session, *args)
+ return writer.to_string()
+
+ def render_error(self, session, *args):
+ error = self.error.get(session)
+ if "max" in error:
+ return error["max"]
+
+ def render_original_value(self, session, *args):
+ error = self.error.get(session)
+ if "max" in error:
+ return "Original value was %s" % str(args[0].max)
+
+ def process_submit(self, session, *args):
+ max = self.max.get(session)
+ imax = 0
+ errors = False
+ try:
+ imax = int(max)
+ if imax < 1 or imax > 99999:
+ raise "out of bounds"
+ except:
+ errors = True
+ error = self.error.get(session)
+ error["max"] = "Numeric value between 1 and 99999
expected"
+ self.error.set(session, error)
+
+ if not errors:
+ limit = args[0]
+ limit.max = imax
+ self.frame.set_limit(session, limit)
+ self.process_cancel(session, *args)
+
class LimitsView(CuminView):
def __init__(self, app, name):
super(LimitsView, self).__init__(app, name)
@@ -139,15 +238,26 @@
class LimitsStatus(CuminStatus):
pass
-class LimitsJobSet(JobSet, Form):
+class LimitsJobSet(JobTab):
def get_visible_columns(self, session):
- return self.get_request_visible_columns(session, ["custom_group",
"scheduler", "submitter"])
+ return self.get_request_visible_columns(session,
+ ["custom_group",
+ "scheduler",
+ "submitter"])
def render_sql_where(self, session, limit):
phase_sql = self.get_phase_sql(session)
- Limits_sql = "j.concurrency_limits like '%%%s%%'" % limit.id
- return "where %s" % " and ".join([phase_sql, Limits_sql])
+ limits_sql = self.get_limits_sql(session, limit)
+ return "where %s" % " and ".join([phase_sql, limits_sql])
def render_title(self, session, limit):
- Limits_sql = "concurrency_limits like '%%%s%%'" % limit.id
- return "Jobs %s" % fmt_count(Job.select(Limits_sql).count())
+ limits_sql = self.get_limits_sql(session, limit)
+ return "Jobs %s" % fmt_count(Job.select(limits_sql).count())
+
+ def render_count(self, session, *args):
+ str = super(LimitsJobSet, self).render_count(session, *args)
+ return "%s with Concurrency Limit '%s'" % (str, args[0].id)
+
+ def get_limits_sql(self, session, limit):
+ x = limit.id
+ return "concurrency_limits similar to
'(%s|%s,%%|%%,%s|%%,%s,%%)'" % (x, x, x, x)
Modified: mgmt/trunk/cumin/python/cumin/limits.strings
===================================================================
--- mgmt/trunk/cumin/python/cumin/limits.strings 2008-09-25 15:23:36 UTC (rev 2541)
+++ mgmt/trunk/cumin/python/cumin/limits.strings 2008-09-25 15:25:36 UTC (rev 2542)
@@ -10,3 +10,82 @@
</thead>
<tbody>{items}</tbody>
</table>
+
+[LimitEdit.css]
+form.limitform {
+/* padding: 1em; */
+}
+form.limitform div.label, form.limitform div.input {
+ float: left;
+ height: 3em;
+ margin-left: 1em;
+}
+form.limitform div.input input {
+ position: relative;
+ top: -0.2em;
+ width: 4em;
+}
+form.limitform div.foot {
+ clear: left;
+}
+form.limitform div.help {
+ margin: 0.5em 1em 1em 0;
+}
+
+form.limitform div.original_value {
+ color: #333;
+ font-size: 0.9em;
+ font-style: italic;
+}
+
+[LimitEdit.html]
+<form id="{id}" class="mform limitform" method="post"
action="?">
+ <div class="head">
+ <h1>{title}</h1>
+ </div>
+ <div class="body">
+ <div class="help">
+ {inline_help}
+ </div>
+ <div class="label">
+ <label for="{input_id}">{label}</label>
+ </div>
+ <div class="input">
+ <input id="{input_id}" type="text"
name="{input_name}" value="{input_value}" />
+ <div class="original_value">{original_value}</div>
+ </div>{limit_error}
+ <div style="clear:both;"><!-- --></div>
+ </div>
+ <div class="foot">
+ {help} {submit} {cancel}
+ </div>
+ <div>{hidden_inputs}</div>
+</form>
+
+[LimitEdit.error_html]
+ <ul class="errors"><li>{error}</li></ul>
+
+[LimitsJobSet.html]
+ <div class="rfloat">{phase}</div>
+<form id="{id}" style="clear:right;" method="post"
action="?">
+
+ <div class="sactions">
+ <h2>Act on Selected Jobs:</h2>
+ {hold} {release} {remove}
+ </div>
+
+ <table class="mobjects">
+ <thead>
+ <tr>
+ <th class="setnav" colspan="{column_count}">
+ <div class="rfloat">{page}</div>
+ {count}
+ </th>
+ </tr>
+ <tr>{headers}</tr>
+ </thead>
+ <tbody>{items}</tbody>
+ </table>
+ <div>{hidden_inputs}</div>
+</form>
+
\ No newline at end of file
Modified: mgmt/trunk/cumin/python/cumin/model.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/model.py 2008-09-25 15:23:36 UTC (rev 2541)
+++ mgmt/trunk/cumin/python/cumin/model.py 2008-09-25 15:25:36 UTC (rev 2542)
@@ -1541,6 +1541,36 @@
super(CuminLimit, self).__init__ \
(model, "limit", Limit)
+ prop = CuminProperty(self, "name")
+ prop.title = "Name"
+
+ prop = CuminProperty(self, "curr")
+ prop.summary = True
+ prop.title = "Current"
+
+ prop = CuminProperty(self, "max")
+ prop.summary = True
+ prop.title = "Maximum"
+
+ action = self.Edit(self, "edit")
+ action.title = "Edit"
+ action.summary = True
+
+ action = self.SetLimit(self, "setlimit")
+ action.navigable = False
+ action.title = "Set Limit"
+
+ def show_object(self, session, limit):
+ frame = self.cumin_model.show_main(session)
+ frame = frame.children_by_name["pool"]
+ return frame.show_limit(session, limit)
+
+ class Edit(CuminAction):
+ def show(self, session, limit):
+ frame = self.cumin_class.show_object(session, limit)
+ frame = frame.show_edit(session)
+ return frame
+
def get_title(self, session):
return "Concurrency Limit"
@@ -1548,6 +1578,18 @@
title = self.get_title(session)
name = limit.id
return "%s '%s'" % (title, fmt_shorten(name))
+
+ class SetLimit(CuminAction):
+ def show(self, session, job):
+ pass
+
+ def get_title(self, session):
+ return "Set Limit for"
+
+ def do_invoke(self, limit, negotiator, completion):
+ Name = limit.id
+ Max = limit.max
+ negotiator.SetLimit(self.cumin_model.data, completion, Name, str(Max))
class CuminJobGroup(CuminClass):
def __init__(self, model):
@@ -1704,9 +1746,10 @@
prop.writable = False
######## Properties
- prop = CuminProperty(self, "AccountingGroup")
+ prop = self.GroupProperty(self, "CustomGroup")
+ prop.title = "Job Group"
prop.summary = True
- prop.title = "Group"
+ prop.escape = False
prop = self.SchedulerProperty(self, "scheduler")
prop.title = "Scheduler"
@@ -1718,6 +1761,9 @@
prop.summary = True
prop.escape = False
+ prop = CuminProperty(self, "AccountingGroup")
+ prop.title = "Accounting Group"
+
prop = CuminProperty(self, "Args")
prop.title = "Args"
@@ -1730,9 +1776,6 @@
prop = CuminProperty(self, "ConcurrencyLimits")
prop.title = "Concurrency Limits"
- prop = CuminProperty(self, "CustomGroup")
- prop.title = "Custom Group"
-
prop = CuminProperty(self, "CustomId")
prop.title = "Custom ID"
@@ -1797,6 +1840,18 @@
def render_status(self, session, status):
return JobStatusInfo.get_status_string(status)
+ class GroupProperty(CuminProperty):
+ def value(self, session, job):
+ branch = session.branch()
+ frame = self.cumin_class.get_pool_frame(branch)
+ try:
+ group = JobGroup(job.CustomGroup)
+ frame.show_job_group(branch, group)
+ return escape_amp(fmt_olink(branch, group, name=group.get_id()))
+ except Exception, e:
+ return "Unavailable"
+
+
class SubmitterProperty(CuminProperty):
def value(self, session, job):
branch = session.branch()