Author: eallen
Date: 2008-11-15 17:36:31 -0500 (Sat, 15 Nov 2008)
New Revision: 2809
Modified:
mgmt/trunk/cumin/python/cumin/model.py
mgmt/trunk/cumin/python/cumin/pool.py
mgmt/trunk/cumin/python/cumin/pool.strings
mgmt/trunk/cumin/python/cumin/system.py
mgmt/trunk/cumin/python/cumin/system.strings
Log:
Added ability to click on Slot vis element and show the running job.
Changed the Show All Slots button on the slot vis to a StateSwitch.
Consolidate so shared code between the system slot vis and the pool slot vis.
Modified: mgmt/trunk/cumin/python/cumin/model.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/model.py 2008-11-15 22:34:09 UTC (rev 2808)
+++ mgmt/trunk/cumin/python/cumin/model.py 2008-11-15 22:36:31 UTC (rev 2809)
@@ -548,6 +548,72 @@
stat.title = "Load Avg"
stat.category = "general"
+class Visualization(CuminAction):
+ def __init__(self, cls, name):
+ super(Visualization, self).__init__(cls, name)
+
+ self.itemset = None
+
+ def get_xml_response(self, session, object, *args):
+ boxes = self.get_boxes(session, object, *args)
+ fields = self.get_field_tuples(session)
+
+ writer = Writer()
+ writer.write("<%ss>" % self.itemset.name)
+ for box in boxes:
+ writer.write("<%s id='%s'" % (self.itemset.name,
str(box["id"])))
+ for field, desc in fields:
+ writer.write(" %s='%s'" % (field, box[field]))
+ if fields:
+ extra = self.get_extra(session, box)
+ for name, value in extra:
+ writer.write(" %s='%s'" % (name, value))
+ writer.write(" color='%s'/>" %
self.get_color(session, box))
+ writer.write("</%ss>" %self.itemset.name)
+ return writer.to_string()
+
+ def get_boxes(self, session, object, *args):
+ if args:
+ self.itemset.set_args(session, *args)
+ cursor = self.itemset.get_items(session, object)
+ box_list = self.itemset.cursor_to_rows(cursor)
+ return box_list
+
+ def get_color(self, session, box):
+ return ""
+
+ def get_extra(self, session, box):
+ return list()
+
+ def get_colors(self):
+ return list()
+
+class SlotVisualization(Visualization):
+ # list of status/colors in the order we want them displayed
+ # in the legend
+ load_colors = [("Idle", "clear"),
+ ("Busy", "green"),
+ ("Suspended", "red"),
+ ("Vacating", "orange"),
+ ("Killing", "blue"),
+ ("Benchmarking", "yellow")]
+
+ def get_field_tuples(self, session):
+ return [("name", "Name"), ("machine",
"Machine"), ("job_id", "Job")]
+
+ def get_extra(self, session, slot):
+ return [("jid", slot["jid"])]
+
+ def get_color(self, session, slot):
+ activity = slot["activity"]
+ for status, color in self.load_colors:
+ if status == activity:
+ return color
+ return "black"
+
+ def get_colors(self):
+ return self.load_colors
+
from system import SystemSlotSet
class CuminSystem(RemoteClass):
def __init__(self, model):
@@ -572,7 +638,7 @@
prop = CuminProperty(self, "machine")
prop.title = "Architecture"
- action = self.VisSlots(self, "slots")
+ action = self.SystemSlotVisualization(self, "slots")
action.navigable = False
#action = CuminAction(self, "ping")
@@ -591,56 +657,18 @@
def get_object_name(self, object):
return object.nodeName
- class VisSlots(CuminAction):
- # list of status/colors in the order we want them displayed
- # in the legend
- load_colors = [("Idle", "clear"),
- ("Busy", "green"),
- ("Suspended", "red"),
- ("Vacating", "red"),
- ("Killing", "blue"),
- ("Benchmarking", "yellow")]
-
+ class SystemSlotVisualization(SlotVisualization):
def __init__(self, cls, name):
- super(CuminSystem.VisSlots, self).__init__(cls, name)
+ super(CuminSystem.SystemSlotVisualization, self).__init__(cls, name)
- self.slot_set = self.ModelSystemSlotSet(cls.model.app, name)
+ self.itemset = self.ModelSystemSlotSet(cls.model.app, "slot")
- def get_xml_response(self, session, system, *args):
- slots = self.get_slots(session, system)
- writer = Writer()
- writer.write("<slots>")
- for slot in slots:
- writer.write("<slot id='%i' name='%s'
machine='%s' job='%s' color='%s'/>" % \
- (slot["id"],
- slot["name"],
- slot["machine"],
- slot["job_id"],
- self.get_color(slot)))
- writer.write("</slots>")
- return writer.to_string()
-
- def get_slots(self, session, system):
- cursor = self.slot_set.do_get_items(session, system)
- slot_list = self.slot_set.cursor_to_rows(cursor)
- return slot_list
-
class ModelSystemSlotSet(SystemSlotSet):
def render_sql_limit(self, session, *args):
pass
def render_sql_orderby(self, session, *args):
- return "order by name asc"
-
- def get_color(self, slot):
- activity = slot["activity"]
- for status, color in self.load_colors:
- if status == activity:
- return color
- return "black"
-
- def get_colors(self):
- return self.load_colors
+ return "order by machine, name asc"
class SystemIdProperty(CuminProperty):
def value(self, session, object):
@@ -1841,43 +1869,6 @@
return Pool(coll)
get = classmethod(get)
-
-
-class Visualization(CuminAction):
- def __init__(self, cls, name, itemset):
- super(Visualization, self).__init__(cls, name)
-
- assert itemset
- self.itemset = itemset
-
- def get_xml_response(self, session, object, *args):
- boxes = self.get_boxes(session, object, *args)
- fields = self.get_field_tuples(session)
-
- writer = Writer()
- writer.write("<%ss>" % self.itemset.name)
- for box in boxes:
- writer.write("<%s id='%s'" % (self.itemset.name,
str(box["id"])))
- for field, desc in fields:
- writer.write(" %s='%s'" % (field, box[field]))
- if fields:
- writer.write(" color='%s'/>" % self.get_color(box))
- writer.write("</%ss>" %self.itemset.name)
- return writer.to_string()
-
- def get_boxes(self, session, object, *args):
- if args:
- self.itemset.set_args(session, *args)
- cursor = self.itemset.get_items(session, object)
- box_list = self.itemset.cursor_to_rows(cursor)
- return box_list
-
- def get_color(self, box):
- return ""
-
- def get_colors(self):
- return list()
-
from job import JobSet
from pool import PoolSlotSet, PoolMachineSet
@@ -1907,7 +1898,7 @@
stat = self.JobsPercentStat(self, "Jobs")
stat.title = "Total Jobs"
- action = self.VisSlots(self, "slots")
+ action = self.PoolSlotVisualization(self, "slots")
action.navigable = False
action = self.VisMachine(self, "machines")
@@ -1999,33 +1990,22 @@
return "(job.deletion_time is not null and job_status = %i)" % \
JobStatusInfo.get_status_int("Idle")
- class VisSlots(Visualization):
- # list of status/colors in the order we want them displayed
- # in the legend
- load_colors = [("Idle", "clear"),
- ("Busy", "green"),
- ("Suspended", "red"),
- ("Vacating", "orange"),
- ("Killing", "blue"),
- ("Benchmarking", "yellow")]
-
+ class PoolSlotVisualization(SlotVisualization):
def __init__(self, cls, name):
- self.slot_set = self.ModelPoolSlotSet(cls.model.app, "slot")
- super(CuminPool.VisSlots, self).__init__(cls, name, self.slot_set)
+ super(CuminPool.PoolSlotVisualization, self).__init__(cls, name)
+
+ self.itemset = self.ModelPoolSlotSet(cls.model.app, "slot")
- def get_field_tuples(self, session):
- return [("name", "Name"), ("machine",
"Machine"), ("job_id", "Job")]
-
def set_machine(self, session, machine):
- self.slot_set.set_machine(session, machine)
+ self.itemset.set_machine(session, machine)
def get_machine(self, session):
- return self.slot_set.get_machine(session)
+ return self.itemset.get_machine(session)
class ModelPoolSlotSet(PoolSlotSet):
def __init__(self, app, name):
- super(CuminPool.VisSlots.ModelPoolSlotSet, self).__init__(app, name)
-
+ super(CuminPool.PoolSlotVisualization.ModelPoolSlotSet,
self).__init__(app, name)
+
self.__machine = None
def set_args(self, session, machine):
@@ -2042,33 +2022,24 @@
elems.append("s.pool = %(pool)s")
if self.__machine:
elems.append("machine = %(machine)s")
-
+
return "where %s" % " and ".join(elems)
-
+
def get_sql_values(self, session, pool):
values = {"pool": pool.id}
machine = self.__machine
if machine:
values["machine"] = machine
return values
-
+
def render_sql_limit(self, session, *args):
pass
def render_sql_orderby(self, session, *args):
- return "order by name asc"
+ return "order by machine, name asc"
+
- def get_color(self, slot):
- activity = slot["activity"]
- for status, color in self.load_colors:
- if status == activity:
- return color
- return "black"
-
- def get_colors(self):
- return self.load_colors
-
- class VisMachine(VisSlots):
+ class VisMachine(Visualization):
load_colors = [("Idle", "clear"),
("> 0%", "green"),
("> 25%", "yellow"),
@@ -2076,13 +2047,14 @@
("> 75%", "green3")]
def __init__(self, cls, name):
- machine_set = PoolMachineSet(cls.model.app, "machine")
- super(CuminPool.VisSlots, self).__init__(cls, name, machine_set)
+ super(CuminPool.VisMachine, self).__init__(cls, name)
+ self.itemset = PoolMachineSet(cls.model.app, "machine")
+
def get_field_tuples(self, session):
return [("machine", "Machine"), ("busy",
"Busy Slots"), ("idle", "Idle Slots")]
- def get_color(self, machine):
+ def get_color(self, session, machine):
total = float(machine["total"])
busy = float(machine["busy"])
work = total > 0.0 and busy / total or 0.0
@@ -2093,6 +2065,9 @@
return self.load_colors[i][1]
return "black"
+ def get_colors(self):
+ return self.load_colors
+
class CuminLimit(CuminClass):
def __init__(self, model):
super(CuminLimit, self).__init__ \
@@ -2430,8 +2405,8 @@
return self.got_data
try:
- job.GetAd(self.model.data, completion, self.job_ads)
- except:
+ job.GetAd(self.model.data, completion, None)
+ except Exception, e:
return self.job_ads
# wait for up to 20 seconds for completion to be called
@@ -2819,8 +2794,8 @@
return self.got_data
try:
- negotiator.GetLimits(self.model.data, completion, self.lim)
- except:
+ negotiator.GetLimits(self.model.data, completion, None)
+ except Exception, e:
return self.lim
# wait for up to 5 seconds for completion to be called
Modified: mgmt/trunk/cumin/python/cumin/pool.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/pool.py 2008-11-15 22:34:09 UTC (rev 2808)
+++ mgmt/trunk/cumin/python/cumin/pool.py 2008-11-15 22:36:31 UTC (rev 2809)
@@ -297,25 +297,18 @@
self.machine_param = Parameter(app, "machine_param")
self.add_parameter(self.machine_param)
- self.show_all_slots = self.ShowAllSlots(app, "show_all_slots")
+ self.show_all_slots = self.SlotSwitch(app, "show_all_slots")
self.add_child(self.show_all_slots)
- class ShowAllSlots(Widget):
- def render(self, session):
- if self.parent.slot_grid.get_machine(session):
- if self.parent.all_fits.get(session):
- return super(PoolStats.ShowAllSlots, self).render(session)
-
- def render_href(self, session):
- branch = session.branch()
- self.parent.machine_param.set(branch, None)
- return branch.marshal()
-
def process(self, session):
super(PoolStats, self).process(session)
+ all_slots = self.show_all_slots.get(session)
machine = self.machine_param.get(session)
all_fits = True
+ if all_slots == "a":
+ machine = None
+
if not machine:
self.slot_grid.set_machine(session, None)
all_fits = self.slot_grid.will_it_fit(session)
@@ -331,13 +324,18 @@
return "Statistics"
def render_slot_title(self, session):
+ pool = self.frame.get_args(session)[0]
machine = self.slot_grid.get_machine(session)
- return machine and "Slots on (%s)" % machine or "Slot
Utilization"
+ return machine and "Slots on (%s)" % machine or "Slots on %s"
% pool.name
def render_machine_title(self, session):
pool = self.frame.get_args(session)[0]
return "Machines on %s" % pool.name
+ def render_slot_job_url(self, session):
+ job = Identifiable("XXX")
+ return self.page.main.pool.job.get_href(session, job)
+
class SlotVisualization(StatUtilizationGrid):
def __init__(self, app, name):
super(PoolStats.SlotVisualization, self).__init__(app, name)
@@ -364,18 +362,13 @@
def get_color(self, session, job):
action = self.app.model.pool.slots
- return action.get_color(job)
+ return action.get_color(session, job)
def get_contents(self, session, slot):
return ""
def get_href(self, session, slot):
- branch = session.branch()
- try:
- job = Job.select("custom_id = '%s'" % slot.JobId)[0]
- except Exception, e:
- return "#"
- return self.page.main.pool.job.get_href(branch, job)
+ return "#"
def get_url(self, session):
pool = self.parent.frame.get_args(session)[0]
@@ -407,7 +400,7 @@
def get_color(self, session, machine):
action = self.app.model.pool.machines
- return action.get_color(machine)
+ return action.get_color(session, machine)
def get_contents(self, session, machine):
return ""
@@ -416,6 +409,7 @@
machine = data["machine"]
branch = session.branch()
self.parent.machine_param.set(branch, machine)
+ self.parent.show_all_slots.set(branch, "m")
return branch.marshal()
def get_url(self, session):
@@ -426,6 +420,19 @@
action = self.app.model.pool.machines
return action.get_field_tuples(session)
+ class SlotSwitch(StateSwitch):
+ def __init__(self, app, name):
+ super(PoolStats.SlotSwitch, self).__init__(app, name)
+
+ self.add_state("a", "All Slots in Pool", hover="Show
all slots in this pool")
+ self.add_state("m", "Slots for This Machine",
hover="Show slots in this machine only")
+ self.param.default = "m"
+
+ def render(self, session):
+ if self.parent.slot_grid.get_machine(session):
+ if self.parent.all_fits.get(session):
+ return super(PoolStats.SlotSwitch, self).render(session)
+
class PoolStatSet(StatSet):
def render_rate_text(self, session, args):
return "Percentage"
Modified: mgmt/trunk/cumin/python/cumin/pool.strings
===================================================================
--- mgmt/trunk/cumin/python/cumin/pool.strings 2008-11-15 22:34:09 UTC (rev 2808)
+++ mgmt/trunk/cumin/python/cumin/pool.strings 2008-11-15 22:36:31 UTC (rev 2809)
@@ -44,6 +44,13 @@
div.vistats {
margin-bottom: 2em;
}
+div.vistats ul.radiotabs {
+ margin: 1em 0 0 1em;
+}
+div.machine_help {
+ color: #444;
+ font-size: 0.8em;
+}
[PoolStats.html]
<div style="width: 50%; float: left;">
@@ -55,6 +62,7 @@
<div style="float: left; margin-left: 4em;">
<div class="vistats">
<h2>{machine_title}</h2>
+ <div class="machine_help">Select a Machine to view its
slots</div>
{machine_grid}
</div>
<div class="vistats">
@@ -64,6 +72,9 @@
</div>
</div>
<div style="clear:left;"><!-- --></div>
+<script type="text/javascript">
+var show_slot_job_url = "{slot_job_url}";
+</script>
[ShowAllSlots.html]
<ul class="actions" style="margin: 1em;">
Modified: mgmt/trunk/cumin/python/cumin/system.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/system.py 2008-11-15 22:34:09 UTC (rev 2808)
+++ mgmt/trunk/cumin/python/cumin/system.py 2008-11-15 22:36:31 UTC (rev 2809)
@@ -58,11 +58,15 @@
def render_title(self, session):
return "Statistics"
+ def render_slot_job_url(self, session):
+ job = Identifiable("XXX")
+ return self.page.main.pool.job.get_href(session, job)
+
class SlotUtilizationGrid(StatUtilizationGrid):
def get_cells(self, session):
system = self.frame.get_args(session)[0]
action = self.app.model.system.slots
- return action.get_slots(session, system)
+ return action.get_boxes(session, system)
def render_title(self, session):
return "Slot Utilization"
@@ -73,7 +77,7 @@
def get_color(self, session, slot):
action = self.app.model.system.slots
- return action.get_color(slot)
+ return action.get_color(session, slot)
def get_contents(self, session, slot):
return ""
@@ -139,7 +143,7 @@
def render_sql_where(self, session, system):
elems = list()
elems.append("machine = %(nodeName)s")
- elems.append("deletion_time is null")
+ elems.append("s.deletion_time is null")
return "where %s" % " and ".join(elems)
def get_sql_values(self, session, system):
Modified: mgmt/trunk/cumin/python/cumin/system.strings
===================================================================
--- mgmt/trunk/cumin/python/cumin/system.strings 2008-11-15 22:34:09 UTC (rev 2808)
+++ mgmt/trunk/cumin/python/cumin/system.strings 2008-11-15 22:36:31 UTC (rev 2809)
@@ -32,7 +32,13 @@
if (oslot_Button) {
oslot_Button.className = "btn "+slot.color;
oslot_Button.onmouseover = over_cell;
- oslot_Button.onmouseout = out_cell
+ oslot_Button.onmouseout = out_cell;
+ if (slot.jid == "None") {
+ oslot_Button.onclick = function() { return false; };
+ } else {
+ oslot_Button.job = slot.jid;
+ oslot_Button.onclick = show_slot_job;
+ }
}
var oslot_Name = document.getElementById("cell_name_"+cell);
if (oslot_Name) {
@@ -42,14 +48,28 @@
if (oslot_Machine) {
oslot_Machine.innerHTML = slot.machine;
}
- var oslot_Job = document.getElementById("cell_job_"+cell);
+ var oslot_Job = document.getElementById("cell_job_id_"+cell);
if (oslot_Job) {
- oslot_Job.innerHTML = slot.job;
+ oslot_Job.innerHTML = slot.job_id;
}
}
- setTimeout("get_slot_grid()", 1000);
+ setTimeout("get_slot_grid()", 2500);
}
+function show_slot_job() {
+ if ( typeof show_slot_job_url != "undefined" ) {
+ var url = show_slot_job_url.replace("XXX", this.job);
+ window.location.href = url;
+ }
+ return false;
+}
+[SystemStats.html]
+{slot_grid}
+<script type="text/javascript">
+var show_slot_job_url = "{slot_job_url}";
+</script>
+
+
[SystemJobSet.html]
<div class="rfloat">{phase}</div>
<form id="{id}" style="clear:right;" method="post"
action="?">