[rhmessaging-commits] rhmessaging commits: r2806 - mgmt/trunk/cumin/python/cumin.

rhmessaging-commits at lists.jboss.org rhmessaging-commits at lists.jboss.org
Fri Nov 14 19:38:08 EST 2008


Author: eallen
Date: 2008-11-14 19:38:08 -0500 (Fri, 14 Nov 2008)
New Revision: 2806

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/slot.py
   mgmt/trunk/cumin/python/cumin/slot.strings
   mgmt/trunk/cumin/python/cumin/stat.py
   mgmt/trunk/cumin/python/cumin/stat.strings
   mgmt/trunk/cumin/python/cumin/system.py
   mgmt/trunk/cumin/python/cumin/system.strings
Log:
Removed Job vis on Pool staticsics page.
Added Machine vis.
Added Slot vis.
Show all slots by default if they will fit.
Show slots for 1st machine if all don't fit.
Show slots for machine when that machine is selected.
Made vis elements lighter weight. Using divs instead of buttons.

Modified: mgmt/trunk/cumin/python/cumin/model.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/model.py	2008-11-14 20:12:00 UTC (rev 2805)
+++ mgmt/trunk/cumin/python/cumin/model.py	2008-11-15 00:38:08 UTC (rev 2806)
@@ -1841,8 +1841,45 @@
             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
+from pool import PoolSlotSet, PoolMachineSet
 
 class CuminPool(CuminClass):
     def __init__(self, model):
@@ -1858,22 +1895,22 @@
         stat = self.PercentStat(self, "Completed")
         stat.title = "Completed Jobs"
 
-        stat = self.PercentStat(self, "Idle")
+        stat = self.IdlePercentStat(self, "Idle")
         stat.title = "Idle Jobs"
 
         stat = self.PercentStat(self, "Held")
         stat.title = "Held Jobs"
 
-        stat = self.PercentStat(self, "Removed")
+        stat = self.RemovedPercentStat(self, "Removed")
         stat.title = "Removed Jobs"
 
-        stat = self.PercentStat(self, "Jobs")
+        stat = self.JobsPercentStat(self, "Jobs")
         stat.title = "Total Jobs"
 
-        action = self.VisJobs(self, "jobs")
+        action = self.VisSlots(self, "slots")
         action.navigable = False
 
-        action = self.VisSlots(self, "slots")
+        action = self.VisMachine(self, "machines")
         action.navigable = False
 
     def init(self):
@@ -1893,30 +1930,40 @@
     class PercentStat(CuminStat):
         def value_text(self, pool):
             state = self.name
-
-            if state == "Jobs":
-                return str(Job.select().count())
             value = self.get_value(pool, state)
             return str(value)
             
+        def get_sql_and_elem(self):
+            pass
+        
+        def get_sql_or_elem(self):
+            pass
+        
+        def get_status_elem(self, state):
+            istate = JobStatusInfo.get_status_int(state)
+            return "job_status = %i" % istate
+
         def get_value(self, pool, state):
             elems = list()
-            istate = JobStatusInfo.get_status_int(state)
-            elems.append("job_status = %i" % istate)
-            elems.append("s.pool = '%s'" % pool.id)
+            status_elem = self.get_status_elem(state)
+            if status_elem:
+                elems.append(status_elem)
     
-            # manually removed jobs will have a state of Idle
-            # with a deletion_time
-            if state == "Idle":
-                elems.append("job.deletion_time is null")
-            where = " and ".join(elems)
-    
-            # manually removed jobs will have a state of Idle
-            # with a deletion_time
-            if state == "Removed":
-                removed = "(job.deletion_time is not null and job_status = %i)" % JobStatusInfo.get_status_int("Idle") 
-                where = " or ".join((where, removed))
-                
+            and_elem = self.get_sql_and_elem()
+            if and_elem:
+                elems.append(and_elem)
+
+            or_elem = self.get_sql_or_elem()
+            
+            return self.do_select(pool, elems, or_elem)
+
+        def do_select(self, pool, and_elems, or_elem):
+            and_elems.append("s.pool = '%s'" % pool.id)
+            where = " and ".join(and_elems)
+            
+            if or_elem:
+                where = " or ".join((where, or_elem))
+            
             jn = "inner join scheduler as s on s.id = scheduler_id"
             return Job.select(where, join=jn).count()
     
@@ -1925,51 +1972,86 @@
             return self.get_item_rate(pool, state)
             
         def get_item_rate(self, pool, state):
-            jobs = Job.select().count()
+            jobs = self.do_select(pool, list(), None)
 
-            if state == "Jobs":
-                value = jobs
-            else:
-                value = self.get_value(pool, state)
+            value = self.get_value(pool, state)
             if jobs:
-                percent = (value*1.0) / (jobs*1.0) * 100.0
+                percent = float(value) / float(jobs) * 100.0
             return jobs and "%2.2f" % percent or "-"
         
-    class VisSlots(CuminAction):
+
+    class JobsPercentStat(PercentStat):
+        def get_status_elem(self, state):
+            return None
+        
+        def rate_text(self, pool):
+            return "100.00"
+
+    class IdlePercentStat(PercentStat):
+        def get_sql_and_elem(self):
+            # manually removed jobs will have a state of Idle
+            # with a deletion_time
+            return "job.deletion_time is null"
+
+    class RemovedPercentStat(PercentStat): 
+        def get_sql_or_elem(self):
+            # if a job is idle, but has a deletion_time, it's actually Removed
+            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", "red"),
+                       ("Vacating", "orange"),
                        ("Killing", "blue"),
                        ("Benchmarking", "yellow")]
 
         def __init__(self, cls, name):
-            super(CuminPool.VisSlots, self).__init__(cls, name)
-            
-            self.slot_set = self.ModelPoolSlotSet(cls.model.app, name)
-            
-        def get_xml_response(self, session, pool, *args):
-            slots = self.get_slots(session, pool)
-            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()
+            self.slot_set = self.ModelPoolSlotSet(cls.model.app, "slot")
+            super(CuminPool.VisSlots, self).__init__(cls, name, self.slot_set)
 
-        def get_slots(self, session, pool):
-            cursor = self.slot_set.do_get_items(session, pool)
-            slot_list = self.slot_set.cursor_to_rows(cursor)
-            return slot_list
+        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)
+        
+        def get_machine(self, session):
+            return self.slot_set.get_machine(session)
+        
         class ModelPoolSlotSet(PoolSlotSet):
+            def __init__(self, app, name):
+                super(CuminPool.VisSlots.ModelPoolSlotSet, self).__init__(app, name)
+
+                self.__machine = None
+                
+            def set_args(self, session, machine):
+                self.set_machine(session, machine)
+                
+            def set_machine(self, session, machine):
+                self.__machine= machine
+                
+            def get_machine(self, session):
+                return self.__machine
+            
+            def render_sql_where(self, session, pool):
+                elems = list()
+                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
             
@@ -1986,54 +2068,31 @@
         def get_colors(self):
             return self.load_colors
         
-    class VisJobs(CuminAction):
+    class VisMachine(VisSlots):
+        load_colors = [("Idle", "clear"), 
+                       ("> 0%", "green"),
+                       ("> 25%", "yellow"),
+                       ("> 50%", "blue"),
+                       ("> 75%", "green3")]
+
         def __init__(self, cls, name):
-            super(CuminPool.VisJobs, self).__init__(cls, name)
-            
-            self.job_set = self.ModelSystemJobSet(cls.model.app, name)
-            
-        def get_xml_response(self, session, pool, *args):
-            jobs = self.get_jobs(session, pool)
-            writer = Writer()
-            writer.write("<jobs>")
-            for job in jobs:
-                status = self.get_status(job)
-                writer.write("<job id='%i' name='%s' submitter='%s' status='%s' color='%s'/>" % \
-                    (job["id"], 
-                     job["custom_id"],
-                     job["submitter"], 
-                     JobStatusInfo.get_status_string(status), 
-                     self.get_color(job)))
-            writer.write("</jobs>")
-            return writer.to_string()
+            machine_set = PoolMachineSet(cls.model.app, "machine")
+            super(CuminPool.VisSlots, self).__init__(cls, name, machine_set)
 
-        def get_jobs(self, session, pool):
-            cursor = self.job_set.do_get_items(session, pool)
-            return self.job_set.cursor_to_rows(cursor)
-
-        class ModelSystemJobSet(JobSet):
-            def render_sql_limit(self, session, *args):
-                pass
-
-            def render_sql_orderby(self, session, *args):
-                return "order by custom_id asc"
-
-        def get_status(self, job):
-            status = job["job_status"]
-            if status != JobStatusInfo.get_status_int("Completed") and job["deletion_time"]:
-                status = JobStatusInfo.get_status_int("Removed")
-            return status
+        def get_field_tuples(self, session):
+            return [("machine", "Machine"), ("busy", "Busy Slots"), ("idle", "Idle Slots")]
         
-        def get_color(self, job):
-            status = self.get_status(job)
-            color = JobStatusInfo.get_status_color(status) 
-            if "Idle" == JobStatusInfo.get_status_string(status):
-                color = "clear" # instead of green  
-            return color
+        def get_color(self, machine):
+            total = float(machine["total"])
+            busy = float(machine["busy"])
+            work = total > 0.0 and busy / total or 0.0
+            
+            percents = [0.0, 0.25, 0.5, 0.75, 1.0]
+            for i in range(len(percents)):
+                if work <= percents[i]:
+                    return self.load_colors[i][1]
+            return "black"  
 
-        def get_colors(self):
-            return JobStatusInfo.get_zipped_colors()
-        
 class CuminLimit(CuminClass):
     def __init__(self, model):
         super(CuminLimit, self).__init__ \
@@ -2829,12 +2888,8 @@
         xargs = self.__args.get(session)
 
         if cls:
-            try:
-                object = cls.mint_class.get(id)
-            except:
-                object = None
+            object = cls.mint_class.get(id)
             method = self.__method.get(session)
-            #self.app.model.write_xml(writer, objects)
             for action in cls.actions:
                 if action.name == method:
                     args = xargs and xargs.split("&") or list()

Modified: mgmt/trunk/cumin/python/cumin/pool.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/pool.py	2008-11-14 20:12:00 UTC (rev 2805)
+++ mgmt/trunk/cumin/python/cumin/pool.py	2008-11-15 00:38:08 UTC (rev 2806)
@@ -17,7 +17,7 @@
 from collector import CollectorSet, CollectorFrame, CollectorStart, CollectorStop
 from negotiator import NegotiatorSet, NegotiatorFrame, NegStart, NegStop
 from limits import LimitsSet, LimitsFrame
-from slot import SlotSet
+from slot import SlotSet, MachineSet
 
 strings = StringCatalog(__file__)
 log = logging.getLogger("cumin.pool")
@@ -265,6 +265,19 @@
         count = self.get_item_count(session, pool)
         return "Slots %s" % fmt_count(count)
 
+class PoolMachineSet(MachineSet):
+    def get_args(self, session):
+        return self.frame.get_args(session)
+
+    def render_sql_where(self, session, pool):
+        return "where s.pool = %(pool)s"
+
+    def get_sql_values(self, session, pool):
+        return {"pool": pool.id}
+    
+    def render_sql_orderby(self, session, pool):
+        return "order by machine asc"
+
 class PoolStats(Widget):
     def __init__(self, app, name):
         super(PoolStats, self).__init__(app, name)
@@ -272,81 +285,146 @@
         stats = PoolStatSet(app, "general", "general")
         self.add_child(stats)
 
-        #self.grid = self.JobUtilizationGrid(app, "job_grid")
-        #self.add_child(self.grid)
-
         self.slot_grid = self.SlotVisualization(app, "slot_grid")
         self.add_child(self.slot_grid)
 
+        self.machine_grid = self.MachineVisualization(app, "machine_grid")
+        self.add_child(self.machine_grid)
+
+        self.all_fits = Attribute(app, "can_show_all")
+        self.add_attribute(self.all_fits)
+        
+        self.machine_param = Parameter(app, "machine_param")
+        self.add_parameter(self.machine_param)
+    
+        self.show_all_slots = self.ShowAllSlots(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)
+        machine = self.machine_param.get(session)
+        all_fits = True
+        
+        if not machine:
+            self.slot_grid.set_machine(session, None)
+            all_fits = self.slot_grid.will_it_fit(session)
+            if not all_fits:
+                machine = self.machine_grid.get_1st_machine(session)
+            else:
+                machine = ""
+
+        self.all_fits.set(session, all_fits)
+        self.slot_grid.set_machine(session, machine)
+        
     def render_title(self, session):
         return "Statistics"
     
-    class JobUtilizationGrid(StatUtilizationGrid):
+    def render_slot_title(self, session):
+        machine = self.slot_grid.get_machine(session)
+        return machine and "Slots on (%s)" % machine or "Slot Utilization"
+
+    def render_machine_title(self, session):
+        pool = self.frame.get_args(session)[0]
+        return "Machines on %s" % pool.name
+    
+    class SlotVisualization(StatUtilizationGrid):
+        def __init__(self, app, name):
+            super(PoolStats.SlotVisualization, self).__init__(app, name)
+
         def get_cells(self, session):
             pool = self.frame.get_args(session)[0]
-            action = self.app.model.pool.jobs
-            return action.get_jobs(session, pool)
+            action = self.app.model.pool.slots
+            return action.get_boxes(session, pool)
         
         def render_title(self, session):
             return ""
 
+        def set_machine(self, session, machine):
+            action = self.app.model.pool.slots
+            action.set_machine(session, machine)
+            
+        def get_machine(self, session):
+            action = self.app.model.pool.slots
+            return action.get_machine(session)
+            
         def get_colors(self, session):
-            action = self.app.model.pool.jobs
+            action = self.app.model.pool.slots
             return action.get_colors()
             
         def get_color(self, session, job):
-            action = self.app.model.pool.jobs
+            action = self.app.model.pool.slots
             return action.get_color(job)
     
-        def get_contents(self, session, job):
+        def get_contents(self, session, slot):
             return ""
 
-        def get_href(self, session, job):
+        def get_href(self, session, slot):
             branch = session.branch()
-            ojob = Job.get(job["id"])
-            return self.page.main.pool.job.get_href(branch, ojob)
+            try:
+                job = Job.select("custom_id = '%s'" % slot.JobId)[0]
+            except Exception, e:
+                return "#"
+            return self.page.main.pool.job.get_href(branch, job)
 
         def get_url(self, session):
             pool = self.parent.frame.get_args(session)[0]
-            return "call.xml?class=pool;id=%s;method=jobs" % pool.id
+            machine = self.get_machine(session)
+            return "call.xml?class=pool;id=%s;method=slots;xargs=%s" % (pool.id, machine)
         
         def get_sticky_info(self, session):
-            return [("name", "ID"), ("submitter", "Submitter"), ("status", "Status")]
+            action = self.app.model.pool.slots
+            return action.get_field_tuples(session)
 
-    class SlotVisualization(StatUtilizationGrid):
+    class MachineVisualization(StatUtilizationGrid):
         def get_cells(self, session):
             pool = self.frame.get_args(session)[0]
-            action = self.app.model.pool.slots
-            return action.get_slots(session, pool)
+            action = self.app.model.pool.machines
+            return action.get_boxes(session, pool)
         
         def render_title(self, session):
             return ""
 
+        def get_1st_machine(self, session):
+            pool = self.frame.get_args(session)[0]
+            action = self.app.model.pool.machines
+            boxes = action.get_boxes(session, pool)
+            return boxes[0]["machine"]
+        
         def get_colors(self, session):
-            action = self.app.model.pool.slots
+            action = self.app.model.pool.machines
             return action.get_colors()
             
-        def get_color(self, session, job):
-            action = self.app.model.pool.slots
-            return action.get_color(job)
+        def get_color(self, session, machine):
+            action = self.app.model.pool.machines
+            return action.get_color(machine)
     
-        def get_contents(self, session, slot):
+        def get_contents(self, session, machine):
             return ""
 
-        def get_href(self, session, slot):
+        def get_href(self, session, data):
+            machine = data["machine"]
             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)
+            self.parent.machine_param.set(branch, machine)
+            return branch.marshal()
 
         def get_url(self, session):
             pool = self.parent.frame.get_args(session)[0]
-            return "call.xml?class=pool;id=%s;method=slots" % pool.id
+            return "call.xml?class=pool;id=%s;method=machines" % pool.id
         
         def get_sticky_info(self, session):
-            return [("name", "Name"), ("machine", "Machine"), ("job", "Job")]
+            action = self.app.model.pool.machines
+            return action.get_field_tuples(session)
 
 class PoolStatSet(StatSet):
     def render_rate_text(self, session, args):

Modified: mgmt/trunk/cumin/python/cumin/pool.strings
===================================================================
--- mgmt/trunk/cumin/python/cumin/pool.strings	2008-11-14 20:12:00 UTC (rev 2805)
+++ mgmt/trunk/cumin/python/cumin/pool.strings	2008-11-15 00:38:08 UTC (rev 2806)
@@ -53,35 +53,47 @@
   </div>
 </div>
 <div style="float: left; margin-left: 4em;">
-   <div class="vistats">
-  <h2>Slot Utilization</h2>
-  {slot_grid}
-  </div>
+   	<div class="vistats">
+  		<h2>{machine_title}</h2>
+		{machine_grid}
+	</div>
+	<div class="vistats">
+   		<h2>{slot_title}</h2>
+   		{show_all_slots}
+		{slot_grid}
+  	</div>
 </div>
 <div style="clear:left;"><!-- --></div>
 
+[ShowAllSlots.html]
+	<ul class="actions" style="margin: 1em;">
+	  <li><a class="nav" href="{href}">Show All Slots</a></li>
+	</ul>
 
-[JobUtilizationGrid.javascript]
-function got_job_grid(obj, id) {
-	for (var cell in obj.jobs.job) {
-		var job = obj.jobs.job[cell]
-		var ojob_Button = document.getElementById("button_"+cell);
-		if (ojob_Button) {
-			ojob_Button.className = "btn "+job.color;
+
+[MachineVisualization.javascript]
+function got_machine_grid(obj, id) {
+	for (var cell in obj.machines.machine) {
+		var machine = obj.machines.machine[cell]
+		var o_Button = document.getElementById("button_"+cell);
+		if (o_Button) {
+			o_Button.className = "btn "+machine.color;
+			o_Button.onmouseover = over_cell;
+			o_Button.onmouseout = out_cell
 		}
-		var ojob_Name = document.getElementById("cell_name_"+cell);
-		if (ojob_Name) {
-			ojob_Name.innerHTML = job.name;
+		var o_Machine = document.getElementById("cell_machine_"+cell);
+		if (o_Machine) {
+			o_Machine.innerHTML = machine.machine;
 		}
-		var ojob_Machine = document.getElementById("cell_submitter_"+cell);
-		if (ojob_Machine) {
-			ojob_Machine.innerHTML = job.submitter;
+		var o_Busy = document.getElementById("cell_busy_"+cell);
+		if (o_Busy) {
+			o_Busy.innerHTML = machine.busy;
 		}
-		var ojob_Job = document.getElementById("cell_status_"+cell);
-		if (ojob_Job) {
-			ojob_Job.innerHTML = job.status;
+		var o_Idle = document.getElementById("cell_idle_"+cell);
+		if (o_Idle) {
+			o_Idle.innerHTML = machine.idle;
 		}
 	}
-	setTimeout("get_job_grid()", 1000);
+	setTimeout("get_machine_grid()", 1000);
 }
 

Modified: mgmt/trunk/cumin/python/cumin/slot.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/slot.py	2008-11-14 20:12:00 UTC (rev 2805)
+++ mgmt/trunk/cumin/python/cumin/slot.py	2008-11-15 00:38:08 UTC (rev 2806)
@@ -22,3 +22,6 @@
         def render_title(self, session, data):
             return "Name"
 
+class MachineSet(CuminTable):
+    pass
+

Modified: mgmt/trunk/cumin/python/cumin/slot.strings
===================================================================
--- mgmt/trunk/cumin/python/cumin/slot.strings	2008-11-14 20:12:00 UTC (rev 2805)
+++ mgmt/trunk/cumin/python/cumin/slot.strings	2008-11-15 00:38:08 UTC (rev 2806)
@@ -5,7 +5,7 @@
   s.machine,
   s.system,
   s.job_id,
-  c.activity as activity
+  c.activity
 from slot as s
 left outer join slot_stats as c on c.id = s.stats_curr_id
 left outer join slot_stats as p on p.id = s.stats_prev_id
@@ -17,3 +17,21 @@
 select count(*)
 from slot as s
 {sql_where}
+
+[MachineSet.sql]
+select 
+  machine as id,
+  machine, 
+    sum(case c.activity when 'Busy' then 1 else 0 end) as busy, 
+    sum(case c.activity when 'Idle' then 1 else 0 end) as idle,
+    sum(1) as total 
+from slot as s
+left outer join slot_stats as c on c.id = s.stats_curr_id
+{sql_where}
+group by machine
+{sql_orderby}  
+
+[MachineSet.count_sql]
+select count(*)
+from
+  (select 1 from slot group by machine) as l

Modified: mgmt/trunk/cumin/python/cumin/stat.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/stat.py	2008-11-14 20:12:00 UTC (rev 2805)
+++ mgmt/trunk/cumin/python/cumin/stat.py	2008-11-15 00:38:08 UTC (rev 2806)
@@ -144,17 +144,44 @@
     def __init__(self, app, name):
         super(StatUtilizationGrid, self).__init__(app, name)
 
-        cells = self.GridCells(app, "grid")
-        self.add_child(cells)
+        self.cells = self.GridCells(app, "grid")
+        self.add_child(self.cells)
         
         legend = self.Legend(app, "grid_legend")
         self.add_child(legend)
         
         ajax = self.Updater(app, "grid_updater")
         self.add_child(ajax)
+        
+        self.ems = 480.0
+        self.max_item_em = 28.0
+        self.max_columns = 20.0
 
     def render_title(self, session):
         return "Utilization"
+    
+    def render_name(self, session):
+        return self.name
+    
+    def will_it_fit(self, session):
+        count = len(self.cells.get_items(session))
+        columns = self.cells.calculate_columns(count)
+        return columns <= self.max_columns
+    
+    def get_grid_width(self, session):
+        count = len(self.cells.get_items(session))
+        columns = self.cells.calculate_columns(count)
+        # we have approx 15em to work with
+        # we'd like each column to be between 1em and 2em
+        width = float(columns) * self.max_item_em
+        if width > self.ems:
+            width = self.ems
+        extra = 3.0 * columns # left right border plus 1 right margin
+        return width + extra
+    
+    def render_grid_width(self, session):
+        width = self.get_grid_width(session)
+        return "%fpx" % width
 
     class GridCells(ItemSet):
         def __init__(self, app, name):
@@ -167,7 +194,8 @@
             self.add_child(self.sticky)
 
         def do_get_items(self, session):
-            cells = self.parent.get_cells(session) 
+            cells = self.parent.get_cells(session)
+            self.items.set(session, cells)
             self.width.set(session, 
                            self.calculate_cell_width(len(cells)))
             return cells 
@@ -178,16 +206,20 @@
         def render_cell_width(self, session, cell):
             return self.width.get(session)
         
-        def calculate_cell_width(self, count):
+        def calculate_columns(self, count):
             sq = sqrt(count)
             isq = int(sq)
             if sq > isq:
                 isq = isq + 1
-                
-            if count > 0:
-                return int(100 / isq)
-            else:
-                return 100
+            return isq
+            
+        def calculate_cell_width(self, count):
+            columns = self.calculate_columns(count)
+            width = self.parent.max_item_em
+            if columns:
+                min = self.parent.ems / float(columns)
+                width = min > self.parent.max_item_em and self.parent.max_item_em or min
+            return "%fpx" % width
 
         def render_href(self, session, cell):
             return self.parent.get_href(session, cell)

Modified: mgmt/trunk/cumin/python/cumin/stat.strings
===================================================================
--- mgmt/trunk/cumin/python/cumin/stat.strings	2008-11-14 20:12:00 UTC (rev 2805)
+++ mgmt/trunk/cumin/python/cumin/stat.strings	2008-11-15 00:38:08 UTC (rev 2806)
@@ -166,31 +166,7 @@
 </li>
 
 [StatUtilizationGrid.javascript]
-/* called on page resize to make sure
-   the grid popup notes don't go
-   off the edge of the page */
-function ensure_notes_visible() {
-	// see if the current rule will show the note off the page
-
-	this.find_rule = function() {
-		if (document.styleSheets) {
-			for (var i=0; i<document.styleSheets.length; i++) {
-				var sheet = document.styleSheets[i];
-				if (sheet.href.indexOf("cumin.css") != -1) {
-					if (sheet.cssRules) {
-						var rules = sheet.cssRules;
-						for (var j=0; j<rules.length; j++) {
-							if (rules[j].cssText.indexOf("div.sticky_note") != -1) {
-								return rules[j];
-							}
-						}			
-					}
-				}
-			}
-		}
-		return null;
-	}
-	
+function over_cell() {
 	this.get_left = function (o) {
 		var p = o.offsetParent;  
 		var true_left = o.offsetLeft;       
@@ -208,62 +184,60 @@
 		return true_left;				
 	}	
 
-	var oGrid = document.getElementById("StatGrid");
-	if (oGrid) {
-		var left = this.get_left(oGrid);
-		var right = left + oGrid.offsetWidth;
-		var wwidth = 9999;
-		if (window.innerWidth)
-			wwidth = window.innerWidth;
-		if (right + 310 > wwidth) {
-			var rule = this.find_rule();
-			if (rule) {
-				rule.style.left = "";
-				rule.style.right = "50%";
+	var id = this.id;
+	var onote = document.getElementById("note_"+id);
+	if (onote) {
+		if (document.all) {
+			this.title = onote.innerText;
+		} else {
+			onote.style.visibility = "hidden";
+			onote.style.display = "block";
+			if (onote.style.left.indexOf("px") == -1) {
+				var left = this.get_left(onote);
+				var right = left + onote.offsetWidth;
+				if (window.innerWidth) {
+					wwidth = window.innerWidth;
+					if (right > wwidth) {
+						oparent = onote.offsetParent;
+						pleft = this.get_left(oparent);
+						onote.style.left = "-" + (onote.offsetWidth - (wwidth - pleft) + 4) + "px";
+					} else {
+						onote.style.left = "50%";
+					}
+				}
 			}
+			onote.style.visibility = "visible";
 		}
 	}
-
-	
 }
-
-function over_cell(me) {
-	var id = me.id;
+function out_cell() {
+	var id = this.id;
 	var onote = document.getElementById("note_"+id);
-	onote.style.display = "block";
-	if (document.all) {
-		me.title = onote.innerText;
+	if (onote) {
+		onote.style.display = "none";
 	}
-
 }
-function out_cell(me) {
-	var id = me.id;
-	document.getElementById("note_"+id).style.display = "none";
-}
-addEvent(window, "resize", ensure_notes_visible);
-addEvent(window, "load", ensure_notes_visible);
 
 [StatUtilizationGrid.css]
-div.StatGrid{
-	width: 10em;
-	height: 10em;
-}
-div.grid_cell {
+div.StatGrid a {
 	float:left;
+	border:1px solid #EAEAEA;
+	margin: 0 1px 1px 0;
 	position: relative;
+	color: black;
 }
-div.grid_cell button {
-	width:95%;
-	height:95%;
-}
+div.StatGrid a:hover { border: 1px solid #a00; }
 .btn.yellow { background: #ffc; }
 .btn.green { background: #cfc; }
 .btn.blue { background: #ccf; }
 .btn.red { background: #fcc; }
+.btn.orange { background: #ffbb5e; }
 .btn.black { background: #444; }
 .btn.clear { background: white; }
-.btn:hover { border: 1px solid #a00; }
-.btn:active { background-color: #444; }
+.btn.green1 { background: #9f9; }
+.btn.green2 { background: #6c6; }
+.btn.green3 { background: #393; }
+
 .btn[class] {  background-image: url(resource?name=shade1.png); background-position: bottom; }
 
 div.visualization {
@@ -275,7 +249,7 @@
 	margin-left: 1em;
 }
 
-div.grid_cell div.sticky_note {
+div.sticky_note {
 	display: none;
 	font-size: 0.8em;
 	position: absolute;
@@ -300,12 +274,13 @@
 td.sticky_values {
 	line-height: 1em;
 }
-div#cell_legend {
-	margin: 1em;
+div.cell_legend {
+	margin: 1em 0;
 	font-size: 0.8em;
 	color: #000;
+	position: relative;
 }
-div#cell_legend button {
+div.cell_legend button {
 	position: relative;
 	top: -2px;
 }
@@ -314,33 +289,32 @@
 <div class="StatUtilizationGrid" id="{id}">
 	<div class="visualization">
 		<h2>{title}</h2>
-		<div id="StatGrid" class="StatGrid">
+		<div id="StatGrid" class="StatGrid" style="width:{grid_width};">
 			{grid}
+			<div style="clear:left;"><!-- --></div>
 		</div>
-		<div style="clear:left;"><!-- --></div>
 	</div>
+	<div id="legend_{name}" class="cell_legend">
+		{grid_legend}
+	</div>
 </div>
-<div id="cell_legend">
-	{grid_legend}
-</div>
 {grid_updater}
 
 [GridCells.html]
 {items}
 
 [GridCells.item_html]
-	<div id="{cell_id}" class="grid_cell" 
-		style="width:{cell_width}%; height:{cell_width}%;" 
-		onmouseover="over_cell(this)"
-		onmouseout="out_cell(this)" >
-		<a href="{href}"><button id="button_{cell_id}" class="btn {color}" >{contents}</button></a>
-		<div id="note_{cell_id}" class="sticky_note">
+	<a href="{href}">
+		<div id="button_{cell_id}" class="btn {color}" style="width:{cell_width}; height:{cell_width};">
+			{contents}
+		</div>
+		<div id="note_button_{cell_id}" class="sticky_note">
 			<table class="sticky_table">
 				{sticky_rows}
 			</table>
 		</div>
-	</div>
- 
+	</a>
+ 	
 [Sticky.item_html]
 <tr>
 	<td class="sticky_names" nowrap="nowrap">{sticky_title}: </td>

Modified: mgmt/trunk/cumin/python/cumin/system.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/system.py	2008-11-14 20:12:00 UTC (rev 2805)
+++ mgmt/trunk/cumin/python/cumin/system.py	2008-11-15 00:38:08 UTC (rev 2806)
@@ -91,7 +91,8 @@
             return "call.xml?class=system;id=%i;method=slots" % system.id
         
         def get_sticky_info(self, session):
-            return [("name", "Name"), ("machine", "Machine"), ("job", "Job")]
+            action = self.app.model.system.slots
+            return action.get_field_tuples()
 
 class SystemView(CuminView):
     def __init__(self, app, name):
@@ -119,7 +120,7 @@
 
     def render_sql_where(self, session, system):
         elems = list()
-        #elems.append("s.system = %(nodeName)s")
+        elems.append("s.system = %(nodeName)s")
         elems.append(self.get_phase_sql(session))
         return "where %s" % " and ".join(elems)
 
@@ -137,7 +138,7 @@
 
     def render_sql_where(self, session, system):
         elems = list()
-        #elems.append("machine = %(nodeName)s")
+        elems.append("machine = %(nodeName)s")
         elems.append("deletion_time is null")
         return "where %s" % " and ".join(elems)
 

Modified: mgmt/trunk/cumin/python/cumin/system.strings
===================================================================
--- mgmt/trunk/cumin/python/cumin/system.strings	2008-11-14 20:12:00 UTC (rev 2805)
+++ mgmt/trunk/cumin/python/cumin/system.strings	2008-11-15 00:38:08 UTC (rev 2806)
@@ -31,6 +31,8 @@
 		var oslot_Button = document.getElementById("button_"+cell);
 		if (oslot_Button) {
 			oslot_Button.className = "btn "+slot.color;
+			oslot_Button.onmouseover = over_cell;
+			oslot_Button.onmouseout = out_cell
 		}
 		var oslot_Name = document.getElementById("cell_name_"+cell);
 		if (oslot_Name) {




More information about the rhmessaging-commits mailing list