r5547 - in branches/elephant/cumin: model python/cumin/grid-hadoop
by croberts@fedoraproject.org
Author: croberts
Date: 2012-11-16 16:17:51 +0000 (Fri, 16 Nov 2012)
New Revision: 5547
Modified:
branches/elephant/cumin/model/cumin.xml
branches/elephant/cumin/model/rosemary.xml
branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py
Log:
More useful name/data node tables.
Modified: branches/elephant/cumin/model/cumin.xml
===================================================================
--- branches/elephant/cumin/model/cumin.xml 2012-11-16 15:32:40 UTC (rev 5546)
+++ branches/elephant/cumin/model/cumin.xml 2012-11-16 16:17:51 UTC (rev 5547)
@@ -57,6 +57,12 @@
</class>
<class name="DataNode" storage="none">
<property name="Name" type="sstr"/>
+ <property name="ID" type="sstr"/>
+ <property name="Submitted" type="sstr"/>
+ <property name="Status" type="sstr"/>
+ <property name="Uptime" type="sstr"/>
+ <property name="Owner" type="sstr"/>
+ <property name="NameNode" type="sstr"/>
</class>
<class name="TaskTracker" storage="none">
<property name="Name" type="sstr"/>
Modified: branches/elephant/cumin/model/rosemary.xml
===================================================================
--- branches/elephant/cumin/model/rosemary.xml 2012-11-16 15:32:40 UTC (rev 5546)
+++ branches/elephant/cumin/model/rosemary.xml 2012-11-16 16:17:51 UTC (rev 5547)
@@ -64,6 +64,24 @@
<property name="Name">
<title>Name</title>
</property>
+ <property name="ID">
+ <title>Id</title>
+ </property>
+ <property name="Submitted">
+ <title>Submitted</title>
+ </property>
+ <property name="Status">
+ <title>Status</title>
+ </property>
+ <property name="Uptime">
+ <title>Uptime</title>
+ </property>
+ <property name="Owner">
+ <title>Owner</title>
+ </property>
+ <property name="NameNode">
+ <title>Name node</title>
+ </property>
</class>
<class name="TaskTracker">
Modified: branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py
===================================================================
--- branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py 2012-11-16 15:32:40 UTC (rev 5546)
+++ branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py 2012-11-16 16:17:51 UTC (rev 5547)
@@ -33,7 +33,7 @@
super(NameNodeSelector, self).__init__(app, name, cls)
- self.add_search_filter(self.table.name_col)
+ self.add_search_filter(self.table.loc_col)
self.table.adapter = HadoopAdapter(app, cls, None)
self.enable_csv_export()
@@ -54,7 +54,7 @@
super(DataNodeSelector, self).__init__(app, name, cls)
- self.add_search_filter(self.table.name_col)
+ self.add_search_filter(self.table.nn_col)
self.table.adapter = HadoopAdapter(app, cls, None)
self.enable_csv_export()
@@ -133,14 +133,16 @@
"Status":"Running", \
"Uptime":"2+00:54:56", \
"Owner":"croberts", \
- "Location":"http://mrg7.lab.bos.redhat.com:40222"}, \
+ "Location":"http://mrg7.lab.bos.redhat.com:40222",\
+ "NameNode":"796210 @ http://mrg16.lab.bos.redhat.com:50061"}, \
"node2":{"Name":"node2.lab.bos.redhat.com",\
"ID":"56789", \
"Submitted":"11/15/2012", \
"Status":"Running", \
"Uptime":"1+00:24:56", \
"Owner":"croberts", \
- "Location":"http://mrg8.lab.bos.redhat.com:40222"}}
+ "Location":"http://mrg8.lab.bos.redhat.com:40222",\
+ "NameNode":"720565 @ http://mrg14.lab.bos.redhat.com:44594"}}
return results
@@ -158,22 +160,20 @@
def __init__(self, app, name, cls):
super(NameNodeTable, self).__init__(app, name, cls)
- self.name_col = self.NameColumn(app, "name", cls.Name)
- self.add_column(self.name_col)
-
+ self.loc_col = ObjectTableColumn(app, "loccol", cls.Location)
self.id_col = ObjectTableColumn(app, "idcol", cls.ID)
self.sub_col = ObjectTableColumn(app, "sub", cls.Submitted)
self.status_col = ObjectTableColumn(app, "statuscol", cls.Status)
self.uptime_col = ObjectTableColumn(app, "uptimecol", cls.Uptime)
self.owner_col = ObjectTableColumn(app, "ownercol", cls.Owner)
- self.loc_col = ObjectTableColumn(app, "loccol", cls.Location)
+ self.add_column(self.loc_col)
self.add_column(self.id_col)
self.add_column(self.sub_col)
self.add_column(self.status_col)
self.add_column(self.uptime_col)
self.add_column(self.owner_col)
- self.add_column(self.loc_col)
+
class NameColumn(ObjectTableColumn):
def render_text_align(self, session):
@@ -183,9 +183,22 @@
class DataNodeTable(ObjectQmfTable):
def __init__(self, app, name, cls):
super(DataNodeTable, self).__init__(app, name, cls)
-
- self.name_col = self.NameColumn(app, "name", cls.Name)
- self.add_column(self.name_col)
+
+ self.nn_col = ObjectTableColumn(app, "nncol", cls.NameNode)
+ self.nn_col.width="20%"
+ self.id_col = ObjectTableColumn(app, "idcol", cls.ID)
+ self.sub_col = ObjectTableColumn(app, "sub", cls.Submitted)
+ self.status_col = ObjectTableColumn(app, "statuscol", cls.Status)
+ self.uptime_col = ObjectTableColumn(app, "uptimecol", cls.Uptime)
+ self.owner_col = ObjectTableColumn(app, "ownercol", cls.Owner)
+
+ self.add_column(self.nn_col)
+ self.add_column(self.id_col)
+ self.add_column(self.sub_col)
+ self.add_column(self.status_col)
+ self.add_column(self.uptime_col)
+ self.add_column(self.owner_col)
+
class NameColumn(ObjectTableColumn):
def render_text_align(self, session):
11 years, 5 months
r5546 - in branches/elephant/cumin: model python/cumin/grid-hadoop
by croberts@fedoraproject.org
Author: croberts
Date: 2012-11-16 15:32:40 +0000 (Fri, 16 Nov 2012)
New Revision: 5546
Modified:
branches/elephant/cumin/model/cumin.xml
branches/elephant/cumin/model/rosemary.xml
branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py
Log:
Additional skeleton work for demo.
Modified: branches/elephant/cumin/model/cumin.xml
===================================================================
--- branches/elephant/cumin/model/cumin.xml 2012-11-16 14:46:00 UTC (rev 5545)
+++ branches/elephant/cumin/model/cumin.xml 2012-11-16 15:32:40 UTC (rev 5546)
@@ -48,6 +48,12 @@
<package name="com.redhat.cumin.grid.hadoop">
<class name="NameNode" storage="none">
<property name="Name" type="sstr"/>
+ <property name="ID" type="sstr"/>
+ <property name="Submitted" type="sstr"/>
+ <property name="Status" type="sstr"/>
+ <property name="Uptime" type="sstr"/>
+ <property name="Owner" type="sstr"/>
+ <property name="Location" type="sstr"/>
</class>
<class name="DataNode" storage="none">
<property name="Name" type="sstr"/>
Modified: branches/elephant/cumin/model/rosemary.xml
===================================================================
--- branches/elephant/cumin/model/rosemary.xml 2012-11-16 14:46:00 UTC (rev 5545)
+++ branches/elephant/cumin/model/rosemary.xml 2012-11-16 15:32:40 UTC (rev 5546)
@@ -40,6 +40,24 @@
<property name="Name">
<title>Name</title>
</property>
+ <property name="ID">
+ <title>Id</title>
+ </property>
+ <property name="Submitted">
+ <title>Submitted</title>
+ </property>
+ <property name="Status">
+ <title>Status</title>
+ </property>
+ <property name="Uptime">
+ <title>Uptime</title>
+ </property>
+ <property name="Owner">
+ <title>Owner</title>
+ </property>
+ <property name="Location">
+ <title>Location</title>
+ </property>
</class>
<class name="DataNode">
Modified: branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py
===================================================================
--- branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py 2012-11-16 14:46:00 UTC (rev 5545)
+++ branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py 2012-11-16 15:32:40 UTC (rev 5546)
@@ -127,7 +127,20 @@
# TODO make some sage call and return the results
# Here, we call self.remoteDataMethod
results = MethodResult()
- results.data = {"node1": {"Name":"node1.lab.bos.redhat.com"}, "node2":{"Name":"node2.lab.bos.redhat.com"}}
+ results.data = {"node1":{"Name":"node1.lab.bos.redhat.com",\
+ "ID":"12345", \
+ "Submitted":"11/14/2012", \
+ "Status":"Running", \
+ "Uptime":"2+00:54:56", \
+ "Owner":"croberts", \
+ "Location":"http://mrg7.lab.bos.redhat.com:40222"}, \
+ "node2":{"Name":"node2.lab.bos.redhat.com",\
+ "ID":"56789", \
+ "Submitted":"11/15/2012", \
+ "Status":"Running", \
+ "Uptime":"1+00:24:56", \
+ "Owner":"croberts", \
+ "Location":"http://mrg8.lab.bos.redhat.com:40222"}}
return results
@@ -147,7 +160,21 @@
self.name_col = self.NameColumn(app, "name", cls.Name)
self.add_column(self.name_col)
-
+
+ self.id_col = ObjectTableColumn(app, "idcol", cls.ID)
+ self.sub_col = ObjectTableColumn(app, "sub", cls.Submitted)
+ self.status_col = ObjectTableColumn(app, "statuscol", cls.Status)
+ self.uptime_col = ObjectTableColumn(app, "uptimecol", cls.Uptime)
+ self.owner_col = ObjectTableColumn(app, "ownercol", cls.Owner)
+ self.loc_col = ObjectTableColumn(app, "loccol", cls.Location)
+
+ self.add_column(self.id_col)
+ self.add_column(self.sub_col)
+ self.add_column(self.status_col)
+ self.add_column(self.uptime_col)
+ self.add_column(self.owner_col)
+ self.add_column(self.loc_col)
+
class NameColumn(ObjectTableColumn):
def render_text_align(self, session):
return "left"
11 years, 5 months
r5545 - branches/elephant/cumin/python/cumin/grid-hadoop
by croberts@fedoraproject.org
Author: croberts
Date: 2012-11-16 14:46:00 +0000 (Fri, 16 Nov 2012)
New Revision: 5545
Modified:
branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py
branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.strings
Log:
Updating dummy search results.
Modified: branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py
===================================================================
--- branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py 2012-11-16 14:31:26 UTC (rev 5544)
+++ branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py 2012-11-16 14:46:00 UTC (rev 5545)
@@ -127,7 +127,7 @@
# TODO make some sage call and return the results
# Here, we call self.remoteDataMethod
results = MethodResult()
- results.data = {"namenode1": {"Name":"Namenode1"}}
+ results.data = {"node1": {"Name":"node1.lab.bos.redhat.com"}, "node2":{"Name":"node2.lab.bos.redhat.com"}}
return results
Modified: branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.strings
===================================================================
--- branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.strings 2012-11-16 14:31:26 UTC (rev 5544)
+++ branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.strings 2012-11-16 14:46:00 UTC (rev 5545)
@@ -1,59 +1 @@
-[TopSystemSet.sql]
-select
- s.id,
- s.node_name as name,
- c.load_average1_min as load_avg
-from sysimage s
-join sysimage_stats as c on s.stats_curr_id = c.id
-order by load_avg desc
-limit 5
-
-[TopSystemSet.count_sql]
---
-
-[SystemStats.html]
-<table class="twocol">
- <tbody>
- <tr>
- <td>
- <h2>Memory/Load</h2>
- {stats}
- <br/>
- </td>
- <td>
- {freemem}
- {loadavg}
- </td>
- </tr>
- </tbody>
-</table>
-<script type="text/javascript">
- // <![CDATA[
- var show_slot_job_url = "{slot_job_url}";
- // ]]>
-</script>
-
-[SystemServices.html]
-<h2>Services</h2>
-<table class="PropertySet">
- <tbody>{items}</tbody>
-</table>
-
-[SystemServices.item_html]
-<tr><th>{item_type}</th><td>{item_content}</td></tr>
-
-[SystemTagSet.html]
-<table id="{id}" class="{class} PropertySet TagPropertySet">
- <thead>
- <tr>
- <td>Property</td>
- <td>Value</td>
- </tr>
- </thead>
- <tbody>
- <tr class="item" title="">
- <th>Tags:</th>
- <td class="{class}">{tags}</td>
- </tr>
- </tbody>
-</table>
\ No newline at end of file
+[nothingyet]
\ No newline at end of file
11 years, 5 months
r5544 - in branches/elephant/cumin: model model/access python/cumin python/cumin/grid-hadoop
by croberts@fedoraproject.org
Author: croberts
Date: 2012-11-16 14:31:26 +0000 (Fri, 16 Nov 2012)
New Revision: 5544
Added:
branches/elephant/cumin/python/cumin/grid-hadoop/
branches/elephant/cumin/python/cumin/grid-hadoop/__init__.py
branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py
branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.strings
branches/elephant/cumin/python/cumin/grid-hadoop/main.py
branches/elephant/cumin/python/cumin/grid-hadoop/main.strings
Modified:
branches/elephant/cumin/model/access/persona.xml
branches/elephant/cumin/model/cumin.xml
branches/elephant/cumin/model/rosemary.xml
Log:
skeleton for "elephant" demo
Modified: branches/elephant/cumin/model/access/persona.xml
===================================================================
--- branches/elephant/cumin/model/access/persona.xml 2012-11-15 22:05:56 UTC (rev 5543)
+++ branches/elephant/cumin/model/access/persona.xml 2012-11-16 14:31:26 UTC (rev 5544)
@@ -29,6 +29,7 @@
<Module name="grid"/>
<Module name="inventory"/>
<Module name="usergrid"/>
+ <Module name="grid-hadoop"/>
<GroupAccess name="nogroup">
<MainPage name="login.html"/>
@@ -45,7 +46,29 @@
<ModuleAccess name="*"/>
</GroupAccess>
</Persona>
+
+ <Persona name="gridoop" auth="True">
+ <Module name="account"/>
+ <Module name="configuration"/>
+ <Module name="inventory"/>
+ <Module name="grid-hadoop"/>
+ <GroupAccess name="nogroup">
+ <MainPage name="login.html"/>
+ </GroupAccess>
+
+ <GroupAccess name="user">
+ <MainPage name="usergrid.html"/>
+ <ModuleAccess name="account"/>
+ <ModuleAccess name="usergrid"/>
+ </GroupAccess>
+
+ <GroupAccess name="admin">
+ <MainPage name="index.html"/>
+ <ModuleAccess name="*"/>
+ </GroupAccess>
+ </Persona>
+
<Persona name="messaging" auth="False">
<Module name="account"/>
<Module name="messaging"/>
Modified: branches/elephant/cumin/model/cumin.xml
===================================================================
--- branches/elephant/cumin/model/cumin.xml 2012-11-15 22:05:56 UTC (rev 5543)
+++ branches/elephant/cumin/model/cumin.xml 2012-11-16 14:31:26 UTC (rev 5544)
@@ -43,6 +43,20 @@
<property name="Features" type="sstr"/>
<property name="NumHosts" type="sstr"/>
</class>
-
</package>
+
+ <package name="com.redhat.cumin.grid.hadoop">
+ <class name="NameNode" storage="none">
+ <property name="Name" type="sstr"/>
+ </class>
+ <class name="DataNode" storage="none">
+ <property name="Name" type="sstr"/>
+ </class>
+ <class name="TaskTracker" storage="none">
+ <property name="Name" type="sstr"/>
+ </class>
+ <class name="JobTracker" storage="none">
+ <property name="Name" type="sstr"/>
+ </class>
+ </package>
</model>
Modified: branches/elephant/cumin/model/rosemary.xml
===================================================================
--- branches/elephant/cumin/model/rosemary.xml 2012-11-15 22:05:56 UTC (rev 5543)
+++ branches/elephant/cumin/model/rosemary.xml 2012-11-16 14:31:26 UTC (rev 5544)
@@ -34,6 +34,32 @@
</property>
</class>
</package>
+
+ <package name="com.redhat.cumin.grid.hadoop">
+ <class name="NameNode">
+ <property name="Name">
+ <title>Name</title>
+ </property>
+ </class>
+
+ <class name="DataNode">
+ <property name="Name">
+ <title>Name</title>
+ </property>
+ </class>
+
+ <class name="TaskTracker">
+ <property name="Name">
+ <title>Name</title>
+ </property>
+ </class>
+
+ <class name="JobTracker">
+ <property name="Name">
+ <title>Name</title>
+ </property>
+ </class>
+ </package>
<package name="org.apache.qpid.broker">
<class name="Binding">
Added: branches/elephant/cumin/python/cumin/grid-hadoop/__init__.py
===================================================================
--- branches/elephant/cumin/python/cumin/grid-hadoop/__init__.py (rev 0)
+++ branches/elephant/cumin/python/cumin/grid-hadoop/__init__.py 2012-11-16 14:31:26 UTC (rev 5544)
@@ -0,0 +1 @@
+from main import *
Property changes on: branches/elephant/cumin/python/cumin/grid-hadoop/__init__.py
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py
===================================================================
--- branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py (rev 0)
+++ branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py 2012-11-16 14:31:26 UTC (rev 5544)
@@ -0,0 +1,187 @@
+from operator import itemgetter
+
+from cumin.objectselector import ObjectSelector, ObjectLinkColumn, ObjectTable, ObjectTableColumn, ObjectQmfTable
+from cumin.objectframe import ObjectFrame
+from cumin.stat import StatSet, StatFlashChart
+from cumin.formats import fmt_bytes, fmt_datetime
+from cumin.model import CuminStatistic
+from cumin.parameters import RosemaryObjectParameter
+from cumin.sqladapter import ObjectSqlAdapter, ObjectSqlField
+from cumin.util import *
+from cumin.qmfadapter import ObjectQmfAdapter
+
+from sage.wallaby.wallabyoperations import WallabyOperations, WBTypes
+from sage.util import MethodResult
+
+from wooly import Session, Widget
+from wooly.datatable import *
+from wooly.util import StringCatalog, xml_escape
+
+strings = StringCatalog(__file__)
+
+class ObjectSelectorTableNoCheckboxes(ObjectSelector):
+ def __init__(self, app, name, cls):
+ super(ObjectSelectorTableNoCheckboxes, self).__init__(app, name, cls)
+
+ def create_table(self, app, name, cls):
+ return ObjectTable(app, name, cls)
+
+
+class NameNodeSelector(ObjectSelector):
+ def __init__(self, app, name):
+ cls = app.model.com_redhat_cumin_grid_hadoop.NameNode
+
+ super(NameNodeSelector, self).__init__(app, name, cls)
+
+ self.add_search_filter(self.table.name_col)
+ self.table.adapter = HadoopAdapter(app, cls, None)
+
+ self.enable_csv_export()
+
+ def create_table(self, app, name, cls):
+ return NameNodeTable(app, name, cls)
+
+ def render_title(self, session):
+ return "HDFS Name nodes"
+
+ def get_qmf_results(self, session):
+ values = self.get_data_values(session)
+ return self.table.adapter.get_sage_results(values)
+
+class DataNodeSelector(ObjectSelector):
+ def __init__(self, app, name):
+ cls = app.model.com_redhat_cumin_grid_hadoop.DataNode
+
+ super(DataNodeSelector, self).__init__(app, name, cls)
+
+ self.add_search_filter(self.table.name_col)
+ self.table.adapter = HadoopAdapter(app, cls, None)
+
+ self.enable_csv_export()
+
+ def create_table(self, app, name, cls):
+ return DataNodeTable(app, name, cls)
+
+ def render_title(self, session):
+ return "HDFS data nodes"
+
+ def get_qmf_results(self, session):
+ values = self.get_data_values(session)
+ return self.table.adapter.get_sage_results(values)
+
+class TaskTrackerSelector(ObjectSelector):
+ def __init__(self, app, name):
+ cls = app.model.com_redhat_cumin_grid_hadoop.TaskTracker
+
+ super(TaskTrackerSelector, self).__init__(app, name, cls)
+
+ self.add_search_filter(self.table.name_col)
+ self.table.adapter = HadoopAdapter(app, cls, None)
+
+ self.enable_csv_export()
+
+ def create_table(self, app, name, cls):
+ return TaskTrackerTable(app, name, cls)
+
+ def render_title(self, session):
+ return "Hadoop task trackers"
+
+ def get_qmf_results(self, session):
+ values = self.get_data_values(session)
+ return self.table.adapter.get_sage_results(values)
+
+class JobTrackerSelector(ObjectSelector):
+ def __init__(self, app, name):
+ cls = app.model.com_redhat_cumin_grid_hadoop.JobTracker
+
+ super(JobTrackerSelector, self).__init__(app, name, cls)
+
+ self.add_search_filter(self.table.name_col)
+ self.table.adapter = HadoopAdapter(app, cls, None)
+
+ self.enable_csv_export()
+
+ def create_table(self, app, name, cls):
+ return JobTrackerTable(app, name, cls)
+
+ def render_title(self, session):
+ return "Hadoop job trackers"
+
+ def get_qmf_results(self, session):
+ values = self.get_data_values(session)
+ return self.table.adapter.get_sage_results(values)
+
+
+class HadoopAdapter(ObjectQmfAdapter):
+ def __init__(self, app, cls, remoteDataMethod):
+ super(HadoopAdapter, self).__init__(app, cls)
+ self.remoteDataMethod = remoteDataMethod
+
+ def get_count(self, values):
+ data = self.do_get_data(values)
+ return len(data)
+
+ def get_sage_results(self, values):
+ session = values['session']
+
+ # TODO make some sage call and return the results
+ # Here, we call self.remoteDataMethod
+ results = MethodResult()
+ results.data = {"namenode1": {"Name":"Namenode1"}}
+
+ return results
+
+ def do_get_data(self, values):
+ results = self.get_sage_results(values)
+ namenodes = results.data
+
+ if namenodes is None or len(namenodes) == 0:
+ return {}
+
+ return namenodes
+
+
+class NameNodeTable(ObjectQmfTable):
+ def __init__(self, app, name, cls):
+ super(NameNodeTable, self).__init__(app, name, cls)
+
+ self.name_col = self.NameColumn(app, "name", cls.Name)
+ self.add_column(self.name_col)
+
+ class NameColumn(ObjectTableColumn):
+ def render_text_align(self, session):
+ return "left"
+
+
+class DataNodeTable(ObjectQmfTable):
+ def __init__(self, app, name, cls):
+ super(DataNodeTable, self).__init__(app, name, cls)
+
+ self.name_col = self.NameColumn(app, "name", cls.Name)
+ self.add_column(self.name_col)
+
+ class NameColumn(ObjectTableColumn):
+ def render_text_align(self, session):
+ return "left"
+
+class TaskTrackerTable(ObjectQmfTable):
+ def __init__(self, app, name, cls):
+ super(TaskTrackerTable, self).__init__(app, name, cls)
+
+ self.name_col = self.NameColumn(app, "name", cls.Name)
+ self.add_column(self.name_col)
+
+ class NameColumn(ObjectTableColumn):
+ def render_text_align(self, session):
+ return "left"
+
+class JobTrackerTable(ObjectQmfTable):
+ def __init__(self, app, name, cls):
+ super(JobTrackerTable, self).__init__(app, name, cls)
+
+ self.name_col = self.NameColumn(app, "name", cls.Name)
+ self.add_column(self.name_col)
+
+ class NameColumn(ObjectTableColumn):
+ def render_text_align(self, session):
+ return "left"
\ No newline at end of file
Property changes on: branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.py
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.strings
===================================================================
--- branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.strings (rev 0)
+++ branches/elephant/cumin/python/cumin/grid-hadoop/hadoop.strings 2012-11-16 14:31:26 UTC (rev 5544)
@@ -0,0 +1,59 @@
+[TopSystemSet.sql]
+select
+ s.id,
+ s.node_name as name,
+ c.load_average1_min as load_avg
+from sysimage s
+join sysimage_stats as c on s.stats_curr_id = c.id
+order by load_avg desc
+limit 5
+
+[TopSystemSet.count_sql]
+--
+
+[SystemStats.html]
+<table class="twocol">
+ <tbody>
+ <tr>
+ <td>
+ <h2>Memory/Load</h2>
+ {stats}
+ <br/>
+ </td>
+ <td>
+ {freemem}
+ {loadavg}
+ </td>
+ </tr>
+ </tbody>
+</table>
+<script type="text/javascript">
+ // <![CDATA[
+ var show_slot_job_url = "{slot_job_url}";
+ // ]]>
+</script>
+
+[SystemServices.html]
+<h2>Services</h2>
+<table class="PropertySet">
+ <tbody>{items}</tbody>
+</table>
+
+[SystemServices.item_html]
+<tr><th>{item_type}</th><td>{item_content}</td></tr>
+
+[SystemTagSet.html]
+<table id="{id}" class="{class} PropertySet TagPropertySet">
+ <thead>
+ <tr>
+ <td>Property</td>
+ <td>Value</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="item" title="">
+ <th>Tags:</th>
+ <td class="{class}">{tags}</td>
+ </tr>
+ </tbody>
+</table>
\ No newline at end of file
Added: branches/elephant/cumin/python/cumin/grid-hadoop/main.py
===================================================================
--- branches/elephant/cumin/python/cumin/grid-hadoop/main.py (rev 0)
+++ branches/elephant/cumin/python/cumin/grid-hadoop/main.py 2012-11-16 14:31:26 UTC (rev 5544)
@@ -0,0 +1,49 @@
+from wooly import *
+from wooly.widgets import *
+from wooly.resources import *
+
+from cumin.main import CuminModule
+from cumin.widgets import *
+from cumin.util import *
+
+from hadoop import *
+
+strings = StringCatalog(__file__)
+
+class Module(CuminModule):
+ def __init__(self, app, name):
+ super(Module, self).__init__(app, name)
+
+ self.frame = GridHadoopFrame(app, "gridhadoop")
+ self.app = app
+ self.frame.cumin_module = name
+
+ def init(self):
+ self.app.main_page.main.inventory = self.frame
+ self.app.main_page.main.add_tab(self.frame)
+
+class GridHadoopFrame(CuminFrame):
+ def __init__(self, app, name):
+ super(GridHadoopFrame, self).__init__(app, name)
+
+ self.view = GridHadoopView(app, "view")
+ self.add_mode(self.view)
+
+ def render_title(self, session):
+ return "Grid-hadoop"
+
+class GridHadoopView(Widget):
+ def __init__(self, app, name):
+ super(GridHadoopView, self).__init__(app, name)
+
+# heading = self.Heading(app, "heading")
+# self.add_child(heading)
+
+ self.tabs = TabbedModeSet(app, "tabs")
+ self.add_child(self.tabs)
+
+ self.tabs.add_tab(NameNodeSelector(app, "namenodes"))
+ self.tabs.add_tab(DataNodeSelector(app, "datanodes"))
+ self.tabs.add_tab(TaskTrackerSelector(app, "tasktrackers"))
+ self.tabs.add_tab(JobTrackerSelector(app, "jobtrackers"))
+
\ No newline at end of file
Property changes on: branches/elephant/cumin/python/cumin/grid-hadoop/main.py
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: branches/elephant/cumin/python/cumin/grid-hadoop/main.strings
===================================================================
--- branches/elephant/cumin/python/cumin/grid-hadoop/main.strings (rev 0)
+++ branches/elephant/cumin/python/cumin/grid-hadoop/main.strings 2012-11-16 14:31:26 UTC (rev 5544)
@@ -0,0 +1 @@
+[thisSpaceIntentionallyLeftBlank]
\ No newline at end of file
11 years, 5 months
r5543 - branches
by croberts@fedoraproject.org
Author: croberts
Date: 2012-11-15 22:05:56 +0000 (Thu, 15 Nov 2012)
New Revision: 5543
Added:
branches/elephant/
Log:
Branch for elephant-related work
11 years, 5 months
r5542 - in branches/croberts: cumin/resources wooly/resources
by croberts@fedoraproject.org
Author: croberts
Date: 2012-11-15 15:06:29 +0000 (Thu, 15 Nov 2012)
New Revision: 5542
Added:
branches/croberts/cumin/resources/mootree.gif
branches/croberts/wooly/resources/mootree.js
Log:
JavaScript and graphic for tree impl.
Added: branches/croberts/cumin/resources/mootree.gif
===================================================================
(Binary files differ)
Property changes on: branches/croberts/cumin/resources/mootree.gif
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: branches/croberts/wooly/resources/mootree.js
===================================================================
--- branches/croberts/wooly/resources/mootree.js (rev 0)
+++ branches/croberts/wooly/resources/mootree.js 2012-11-15 15:06:29 UTC (rev 5542)
@@ -0,0 +1,685 @@
+/*
+Script: mootree.js
+ My Object Oriented Tree
+ - Developed by Rasmus Schultz, <http://www.mindplay.dk>
+ - Tested with MooTools release 1.2, under Firefox 2, Opera 9 and Internet Explorer 6 and 7.
+
+License:
+ MIT-style license.
+
+Credits:
+ Inspired by:
+ - WebFX xTree, <http://webfx.eae.net/dhtml/xtree/>
+ - Destroydrop dTree, <http://www.destroydrop.com/javascripts/tree/>
+
+Changes:
+
+ rev.12:
+ - load() only worked once on the same node, fixed.
+ - the script would sometimes try to get 'R' from the server, fixed.
+ - the 'load' attribute is now supported in XML files (see example_5.html).
+
+ rev.13:
+ - enable() and disable() added - the adopt() and load() methods use these to improve performance by minimizing the number of visual updates.
+
+ rev.14:
+ - toggle() was using enable() and disable() which actually caused it to do extra work - fixed.
+
+ rev.15:
+ - adopt() now picks up 'href', 'target', 'title' and 'name' attributes of the a-tag, and stores them in the data object.
+ - adopt() now picks up additional constructor arguments from embedded comments, e.g. icons, colors, etc.
+ - documentation now generates properly with NaturalDocs, <http://www.naturaldocs.org/>
+
+ rev.16:
+ - onClick events added to MooTreeControl and MooTreeNode
+ - nodes can now have id's - <MooTreeControl.get> method can be used to find a node with a given id
+
+ rev.17:
+ - changed icon rendering to use innerHTML, making the control faster (and code size slightly smaller).
+
+ rev.18:
+ - migrated to MooTools 1.2 (previous versions no longer supported)
+
+*/
+
+var MooTreeIcon = ['I','L','Lminus','Lplus','Rminus','Rplus','T','Tminus','Tplus','_closed','_doc','_open','minus','plus'];
+
+/*
+Class: MooTreeControl
+ This class implements a tree control.
+
+Properties:
+ root - returns the root <MooTreeNode> object.
+ selected - returns the currently selected <MooTreeNode> object, or null if nothing is currently selected.
+
+Events:
+ onExpand - called when a node is expanded or collapsed: function(node, state) - where node is the <MooTreeNode> object that fired the event, and state is a boolean meaning true:expanded or false:collapsed.
+ onSelect - called when a node is selected or deselected: function(node, state) - where node is the <MooTreeNode> object that fired the event, and state is a boolean meaning true:selected or false:deselected.
+ onClick - called when a node is clicked: function(node) - where node is the <MooTreeNode> object that fired the event.
+
+Parameters:
+ The constructor takes two object parameters: config and options.
+ The first, config, contains global settings for the tree control - you can use the configuration options listed below.
+ The second, options, should contain options for the <MooTreeNode> constructor - please refer to the options listed in the <MooTreeNode> documentation.
+
+Config:
+ div - a string representing the div Element inside which to build the tree control.
+ mode - optional string, defaults to 'files' - specifies default icon behavior. In 'files' mode, empty nodes have a document icon - whereas, in 'folders' mode, all nodes are displayed as folders (a'la explorer).
+ grid - boolean, defaults to false. If set to true, a grid is drawn to outline the structure of the tree.
+
+ theme - string, optional, defaults to 'mootree.gif' - specifies the 'theme' GIF to use.
+
+ loader - optional, an options object for the <MooTreeNode> constructor - defaults to {icon:'mootree_loader.gif', text:'Loading...', color:'a0a0a0'}
+
+ onExpand - optional function (see Events above)
+ onSelect - optional function (see Events above)
+
+*/
+
+var MooTreeControl = new Class({
+
+ initialize: function(config, options) {
+
+ options.control = this; // make sure our new MooTreeNode knows who it's owner control is
+ options.div = config.div; // tells the root node which div to insert itself into
+ this.root = new MooTreeNode(options); // create the root node of this tree control
+
+ this.index = new Object(); // used by the get() method
+
+ this.enabled = true; // enable visual updates of the control
+
+ this.theme = config.theme || 'resource?name=mootree.gif';
+
+ this.loader = config.loader || {icon:'resource?name=mootree_loader.gif', text:'Loading...', color:'#a0a0a0'};
+
+ this.selected = null; // set the currently selected node to nothing
+ this.mode = config.mode; // mode can be "folders" or "files", and affects the default icons, setting this to null will result in no icons being used
+ this.grid = config.grid; // grid can be turned on (true) or off (false)
+
+ this.onExpand = config.onExpand || new Function(); // called when any node in the tree is expanded/collapsed
+ this.onSelect = config.onSelect || new Function(); // called when any node in the tree is selected/deselected
+ this.onClick = config.onClick || new Function(); // called when any node in the tree is clicked
+
+ this.root.update(true);
+
+ },
+
+ /*
+ Property: insert
+ Creates a new node under the root node of this tree.
+
+ Parameters:
+ options - an object containing the same options available to the <MooTreeNode> constructor.
+
+ Returns:
+ A new <MooTreeNode> instance.
+ */
+
+ insert: function(options) {
+ options.control = this;
+ return this.root.insert(options);
+ },
+
+ /*
+ Property: select
+ Sets the currently selected node.
+ This is called by <MooTreeNode> when a node is selected (e.g. by clicking it's title with the mouse).
+
+ Parameters:
+ node - the <MooTreeNode> object to select.
+ */
+
+ select: function(node) {
+ this.onClick(node); node.onClick(); // fire click events
+ if (this.selected === node) return; // already selected
+ if (this.selected) {
+ // deselect previously selected node:
+ this.selected.select(false);
+ this.onSelect(this.selected, false);
+ }
+ // select new node:
+ this.selected = node;
+ node.select(true);
+ this.onSelect(node, true);
+ },
+
+ /*
+ Property: expand
+ Expands the entire tree, recursively.
+ */
+
+ expand: function() {
+ this.root.toggle(true, true);
+ },
+
+ /*
+ Property: collapse
+ Collapses the entire tree, recursively.
+ */
+
+ collapse: function() {
+ this.root.toggle(true, false);
+ },
+
+ /*
+ Property: get
+ Retrieves the node with the given id - or null, if no node with the given id exists.
+
+ Parameters:
+ id - a string, the id of the node you wish to retrieve.
+
+ Note:
+ Node id can be assigned via the <MooTreeNode> constructor, e.g. using the <MooTreeNode.insert> method.
+ */
+
+ get: function(id) {
+ return this.index[id] || null;
+ },
+
+ /*
+ Property: adopt
+ Adopts a structure of nested ul/li/a elements as tree nodes, then removes the original elements.
+
+ Parameters:
+ id - a string representing the ul element to be adopted, or an element reference.
+ parentNode - optional, a <MooTreeNode> object under which to import the specified ul element. Defaults to the root node of the parent control.
+
+ Note:
+ The ul/li structure must be properly nested, and each li-element must contain one a-element, e.g.:
+
+ ><ul id="mytree">
+ > <li><a href="test.html">Item One</a></li>
+ > <li><a href="test.html">Item Two</a>
+ > <ul>
+ > <li><a href="test.html">Item Two Point One</a></li>
+ > <li><a href="test.html">Item Two Point Two</a></li>
+ > </ul>
+ > </li>
+ > <li><a href="test.html"><!-- icon:_doc; color:#ff0000 -->Item Three</a></li>
+ ></ul>
+
+ The "href", "target", "title" and "name" attributes of the a-tags are picked up and stored in the
+ data property of the node.
+
+ CSS-style comments inside a-tags are parsed, and treated as arguments for <MooTreeNode> constructor,
+ e.g. "icon", "openicon", "color", etc.
+ */
+
+ adopt: function(id, parentNode) {
+ if (parentNode === undefined) parentNode = this.root;
+ this.disable();
+ this._adopt(id, parentNode);
+ parentNode.update(true);
+ $(id).destroy();
+ this.enable();
+ },
+
+ _adopt: function(id, parentNode) {
+ /* adopts a structure of ul/li elements into this tree */
+ e = $(id);
+ var i=0, c = e.getChildren();
+ for (i=0; i<c.length; i++) {
+ if (c[i].nodeName == 'li') {
+ var con={text:''}, comment='', node=null, subul=null;
+ var n=0, z=0, se=null, s = c[i].getChildren();
+ for (n=0; n<s.length; n++) {
+ switch (s[n].nodeName) {
+ case 'A':
+ case 'a':
+ for (z=0; z<s[n].childNodes.length; z++) {
+ se = s[n].childNodes[z];
+ switch (se.nodeName) {
+ case '#text': con.text += se.nodeValue; break;
+ case '#comment': comment += se.nodeValue; break;
+ }
+ }
+ con.data = s[n].getProperties('href','target','title','name');
+ break;
+ case 'UL':
+ case 'ul':
+ subul = s[n];
+ break;
+ }
+ }
+ if (con.label != '') {
+ con.data.url = con.data['href']; // (for backwards compatibility)
+ if (comment != '') {
+ var bits = comment.split(';');
+ for (z=0; z<bits.length; z++) {
+ var pcs = bits[z].trim().split(':');
+ if (pcs.length == 2) con[pcs[0].trim()] = pcs[1].trim();
+ }
+ }
+ node = parentNode.insert(con);
+ if (subul) this._adopt(subul, node);
+ }
+ }
+ }
+ },
+
+ /*
+ Property: disable
+ Call this to temporarily disable visual updates -- if you need to insert/remove many nodes
+ at a time, many visual updates would normally occur. By temporarily disabling the control,
+ these visual updates will be skipped.
+
+ When you're done making changes, call <MooTreeControl.enable> to turn on visual updates
+ again, and automatically repaint all nodes that were changed.
+ */
+
+ disable: function() {
+ this.enabled = false;
+ },
+
+ /*
+ Property: enable
+ Enables visual updates again after a call to <MooTreeControl.disable>
+ */
+
+ enable: function() {
+ this.enabled = true;
+ this.root.update(true, true);
+ }
+
+});
+
+/*
+Class: MooTreeNode
+ This class implements the functionality of a single node in a <MooTreeControl>.
+
+Note:
+ You should not manually create objects of this class -- rather, you should use
+ <MooTreeControl.insert> to create nodes in the root of the tree, and then use
+ the similar function <MooTreeNode.insert> to create subnodes.
+
+ Both insert methods have a similar syntax, and both return the newly created
+ <MooTreeNode> object.
+
+Parameters:
+ options - an object. See options below.
+
+Options:
+ text - this is the displayed text of the node, and as such as is the only required parameter.
+ id - string, optional - if specified, must be a unique node identifier. Nodes with id can be retrieved using the <MooTreeControl.get> method.
+ color - string, optional - if specified, must be a six-digit hexadecimal RGB color code.
+
+ open - boolean value, defaults to false. Use true if you want the node open from the start.
+
+ icon - use this to customize the icon of the node. The following predefined values may be used: '_open', '_closed' and '_doc'. Alternatively, specify the URL of a GIF or PNG image to use - this should be exactly 18x18 pixels in size. If you have a strip of images, you can specify an image number (e.g. 'my_icons.gif#4' for icon number 4).
+ openicon - use this to customize the icon of the node when it's open.
+
+ data - an object containing whatever data you wish to associate with this node (such as an url and/or an id, etc.)
+
+Events:
+ onExpand - called when the node is expanded or collapsed: function(state) - where state is a boolean meaning true:expanded or false:collapsed.
+ onSelect - called when the node is selected or deselected: function(state) - where state is a boolean meaning true:selected or false:deselected.
+ onClick - called when the node is clicked (no arguments).
+*/
+
+var MooTreeNode = new Class({
+
+ initialize: function(options) {
+
+ this.text = options.text; // the text displayed by this node
+ this.id = options.id || null; // the node's unique id
+ this.nodes = new Array(); // subnodes nested beneath this node (MooTreeNode objects)
+ this.parent = null; // this node's parent node (another MooTreeNode object)
+ this.last = true; // a flag telling whether this node is the last (bottom) node of it's parent
+ this.control = options.control; // owner control of this node's tree
+ this.selected = false; // a flag telling whether this node is the currently selected node in it's tree
+
+ this.color = options.color || null; // text color of this node
+
+ this.data = options.data || {}; // optional object containing whatever data you wish to associate with the node (typically an url or an id)
+
+ this.onExpand = options.onExpand || new Function(); // called when the individual node is expanded/collapsed
+ this.onSelect = options.onSelect || new Function(); // called when the individual node is selected/deselected
+ this.onClick = options.onClick || new Function(); // called when the individual node is clicked
+
+ this.open = options.open ? true : false; // flag: node open or closed?
+
+ this.icon = options.icon;
+ this.openicon = options.openicon || this.icon;
+
+ // add the node to the control's node index:
+ if (this.id) this.control.index[this.id] = this;
+
+ // create the necessary divs:
+ this.div = {
+ main: new Element('div').addClass('mooTree_node'),
+ indent: new Element('div'),
+ gadget: new Element('div'),
+ icon: new Element('div'),
+ text: new Element('div').addClass('mooTree_text'),
+ sub: new Element('div')
+ }
+
+ // put the other divs under the main div:
+ this.div.main.adopt(this.div.indent);
+ this.div.main.adopt(this.div.gadget);
+ this.div.main.adopt(this.div.icon);
+ this.div.main.adopt(this.div.text);
+
+ // put the main and sub divs in the specified parent div:
+ $(options.div).adopt(this.div.main);
+ $(options.div).adopt(this.div.sub);
+
+ // attach event handler to gadget:
+ this.div.gadget._node = this;
+ this.div.gadget.onclick = this.div.gadget.ondblclick = function() {
+ this._node.toggle();
+ }
+
+ // attach event handler to icon/text:
+ this.div.icon._node = this.div.text._node = this;
+ this.div.icon.onclick = this.div.icon.ondblclick = this.div.text.onclick = this.div.text.ondblclick = function() {
+ this._node.control.select(this._node);
+ }
+
+ },
+
+ /*
+ Property: insert
+ Creates a new node, nested inside this one.
+
+ Parameters:
+ options - an object containing the same options available to the <MooTreeNode> constructor.
+
+ Returns:
+ A new <MooTreeNode> instance.
+ */
+
+ insert: function(options) {
+
+ // set the parent div and create the node:
+ options.div = this.div.sub;
+ options.control = this.control;
+ var node = new MooTreeNode(options);
+
+ // set the new node's parent:
+ node.parent = this;
+
+ // mark this node's last node as no longer being the last, then add the new last node:
+ var n = this.nodes;
+ if (n.length) n[n.length-1].last = false;
+ n.push(node);
+
+ // repaint the new node:
+ node.update();
+
+ // repaint the new node's parent (this node):
+ if (n.length == 1) this.update();
+
+ // recursively repaint the new node's previous sibling node:
+ if (n.length > 1) n[n.length-2].update(true);
+
+ return node;
+
+ },
+
+ /*
+ Property: remove
+ Removes this node, and all of it's child nodes. If you want to remove all the childnodes without removing the node itself, use <MooTreeNode.clear>
+ */
+
+ remove: function() {
+ var p = this.parent;
+ this._remove();
+ p.update(true);
+ },
+
+ _remove: function() {
+
+ // recursively remove this node's subnodes:
+ var n = this.nodes;
+ while (n.length) n[n.length-1]._remove();
+
+ // remove the node id from the control's index:
+ delete this.control.index[this.id];
+
+ // remove this node's divs:
+ this.div.main.destroy();
+ this.div.sub.destroy();
+
+ if (this.parent) {
+
+ // remove this node from the parent's collection of nodes:
+ var p = this.parent.nodes;
+ p.erase(this);
+
+ // in case we removed the parent's last node, flag it's current last node as being the last:
+ if (p.length) p[p.length-1].last = true;
+
+ }
+
+ },
+
+ /*
+ Property: clear
+ Removes all child nodes under this node, without removing the node itself.
+ To remove all nodes including this one, use <MooTreeNode.remove>
+ */
+
+ clear: function() {
+ this.control.disable();
+ while (this.nodes.length) this.nodes[this.nodes.length-1].remove();
+ this.control.enable();
+ },
+
+ /*
+ Property: update
+ Update the tree node's visual appearance.
+
+ Parameters:
+ recursive - boolean, defaults to false. If true, recursively updates all nodes beneath this one.
+ invalidated - boolean, defaults to false. If true, updates only nodes that have been invalidated while the control has been disabled.
+ */
+
+ update: function(recursive, invalidated) {
+
+ var draw = true;
+
+ if (!this.control.enabled) {
+ // control is currently disabled, so we don't do any visual updates
+ this.invalidated = true;
+ draw = false;
+ }
+
+ if (invalidated) {
+ if (!this.invalidated) {
+ draw = false; // this one is still valid, don't draw
+ } else {
+ this.invalidated = false; // we're drawing this item now
+ }
+ }
+
+ if (draw) {
+
+ var x;
+
+ // make selected, or not:
+ this.div.main.className = 'mooTree_node' + (this.selected ? ' mooTree_selected' : '');
+
+ // update indentations:
+ var p = this, i = '';
+ while (p.parent) {
+ p = p.parent;
+ i = this.getImg(p.last || !this.control.grid ? '' : 'I') + i;
+ }
+ this.div.indent.innerHTML = i;
+
+ // update the text:
+ x = this.div.text;
+ x.empty();
+ x.appendText(this.text);
+ if (this.color) x.style.color = this.color;
+
+ // update the icon or nothing if the control.mode is null:
+ this.div.icon.innerHTML = this.control.mode == null ? "" : (this.getImg( this.nodes.length ? ( this.open ? (this.openicon || this.icon || '_open') : (this.icon || '_closed') ) : ( this.icon || (this.control.mode == 'folders' ? '_closed' : '_doc') ) ));
+
+ // update the plus/minus gadget:
+ this.div.gadget.innerHTML = this.getImg( ( this.control.grid ? ( this.control.root == this ? (this.nodes.length ? 'R' : '') : (this.last?'L':'T') ) : '') + (this.nodes.length ? (this.open?'minus':'plus') : '') );
+
+ // show/hide subnodes:
+ this.div.sub.style.display = this.open ? 'block' : 'none';
+
+ }
+
+ // if recursively updating, update all child nodes:
+ if (recursive) this.nodes.forEach( function(node) {
+ node.update(true, invalidated);
+ });
+
+ },
+
+ /*
+ Property: getImg
+ Creates a new image, in the form of HTML for a DIV element with appropriate style.
+ You should not need to manually call this method. (though if for some reason you want to, you can)
+
+ Parameters:
+ name - the name of new image to create, defined by <MooTreeIcon> or located in an external file.
+
+ Returns:
+ The HTML for a new div Element.
+ */
+
+ getImg: function(name) {
+
+ var html = '<div class="mooTree_img"';
+
+ if (name != '') {
+ var img = this.control.theme;
+ var i = MooTreeIcon.indexOf(name);
+ if (i == -1) {
+ // custom (external) icon:
+ var x = name.split('#');
+ img = x[0];
+ i = (x.length == 2 ? parseInt(x[1])-1 : 0);
+ }
+ html += ' style="background-image:url(' + img + '); background-position:-' + (i*18) + 'px 0px;"';
+ }
+
+ html += "></div>";
+
+ return html;
+
+ },
+
+ /*
+ Property: toggle
+ By default (with no arguments) this function toggles the node between expanded/collapsed.
+ Can also be used to recursively expand/collapse all or part of the tree.
+
+ Parameters:
+ recursive - boolean, defaults to false. With recursive set to true, all child nodes are recursively toggle to this node's new state.
+ state - boolean. If undefined, the node's state is toggled. If true or false, the node can be explicitly opened or closed.
+ */
+
+ toggle: function(recursive, state) {
+
+ this.open = (state === undefined ? !this.open : state);
+ this.update();
+
+ this.onExpand(this.open);
+ this.control.onExpand(this, this.open);
+
+ if (recursive) this.nodes.forEach( function(node) {
+ node.toggle(true, this.open);
+ }, this);
+
+ },
+
+ /*
+ Property: select
+ Called by <MooTreeControl> when the selection changes.
+ You should not manually call this method - to set the selection, use the <MooTreeControl.select> method.
+ */
+
+ select: function(state) {
+ this.selected = state;
+ this.update();
+ this.onSelect(state);
+ },
+
+ /*
+ Property: load
+ Asynchronously load an XML structure into a node of this tree.
+
+ Parameters:
+ url - string, required, specifies the URL from which to load the XML document.
+ vars - query string, optional.
+ */
+
+ load: function(url, vars) {
+
+ if (this.loading) return; // if this node is already loading, return
+ this.loading = true; // flag this node as loading
+
+ this.toggle(false, true); // expand the node to make the loader visible
+
+ this.clear();
+
+ this.insert(this.control.loader);
+
+ var f = function() {
+ new Request({
+ method: 'GET',
+ url: url,
+ onSuccess: this._loaded.bind(this),
+ onFailure: this._load_err.bind(this)
+ }).send(url, vars || '');
+ }.bind(this).delay(20);
+
+ //window.setTimeout(f.bind(this), 20); // allowing a small delay for the browser to draw the loader-icon.
+
+ },
+
+ _loaded: function(text, xml) {
+ // called on success - import nodes from the root element:
+ this.control.disable();
+ this.clear();
+ this._import(xml.documentElement);
+ this.control.enable();
+ this.loading = false;
+ },
+
+ _import: function(e) {
+ // import childnodes from an xml element:
+ var n = e.childNodes;
+ for (var i=0; i<n.length; i++) if (n[i].tagName == 'node') {
+ var opt = {data:{}};
+ var a = n[i].attributes;
+ for (var t=0; t<a.length; t++) {
+ switch (a[t].name) {
+ case 'text':
+ case 'id':
+ case 'icon':
+ case 'openicon':
+ case 'color':
+ case 'open':
+ opt[a[t].name] = a[t].value;
+ break;
+ default:
+ opt.data[a[t].name] = a[t].value;
+ }
+ }
+ var node = this.insert(opt);
+ if (node.data.load) {
+ node.open = false; // can't have a dynamically loading node that's already open!
+ node.insert(this.control.loader);
+ node.onExpand = function(state) {
+ this.load(this.data.load);
+ this.onExpand = new Function();
+ }
+ }
+ // recursively import subnodes of this node:
+ if (n[i].childNodes.length) node._import(n[i]);
+ }
+ },
+
+ _load_err: function(req) {
+ window.alert('Error loading: ' + this.text);
+ }
+
+});
Property changes on: branches/croberts/wooly/resources/mootree.js
___________________________________________________________________
Added: svn:mime-type
+ text/plain
11 years, 5 months
r5541 - in branches/croberts: cumin/python/cumin cumin/python/cumin/grid cumin/resources wooly/python/wooly
by croberts@fedoraproject.org
Author: croberts
Date: 2012-11-15 15:03:29 +0000 (Thu, 15 Nov 2012)
New Revision: 5541
Modified:
branches/croberts/cumin/python/cumin/grid/dashboard.py
branches/croberts/cumin/python/cumin/grid/dashboard.strings
branches/croberts/cumin/python/cumin/stat.py
branches/croberts/cumin/python/cumin/stat.strings
branches/croberts/cumin/resources/app.css
branches/croberts/cumin/resources/app.js
branches/croberts/wooly/python/wooly/pages.strings
Log:
More changes to include tree navigation for hierarchical accounting groups on the accounting usage chart.
Modified: branches/croberts/cumin/python/cumin/grid/dashboard.py
===================================================================
--- branches/croberts/cumin/python/cumin/grid/dashboard.py 2012-11-06 21:34:31 UTC (rev 5540)
+++ branches/croberts/cumin/python/cumin/grid/dashboard.py 2012-11-15 15:03:29 UTC (rev 5541)
@@ -1,4 +1,5 @@
import logging
+import re
from wooly import Widget, Attribute
from wooly.util import StringCatalog, Writer
@@ -7,6 +8,7 @@
from wooly.widgets import RadioModeSet, WidgetSet
from wooly.template import WidgetTemplate
from wooly.forms import StringInput
+from wooly.sql import SqlOperation
from parsley.stringex import rpartition
from rosemary.sqlquery import SqlQueryOptions
@@ -80,15 +82,11 @@
# chart.duration.param.default= "86400"
# charts.add_child(chart)
- chart = self.AccountingChart(app, "accuse", app.model.com_redhat_grid_plumage.Accountant)
- chart.max_samples = 250
- chart.chart_type = "genusechart"
- chart.duration.param.default = "86400"
- chart.leftlegend = False
- chart.height = 150
- chart.width = 400
- charts.add_child(chart)
+ chartholder = AccountingChartWidget(app, "accchart")
+ charts.add_child(chartholder)
+
+
def render_title(self, session):
return "Accounting"
@@ -106,7 +104,99 @@
class AccountingChart(ReportingChart):
def render_title(self, session):
- return "Usage by accounting group (cpus)"
+ return "Usage by accounting group (cpus)"
+
+class AccountingChartWidget(Widget):
+ def __init__(self, app, name):
+ super(AccountingChartWidget, self).__init__(app, name)
+
+ control = self.AccountingChartControl(app, "actrl")
+ self.add_child(control)
+
+ chart = self.AccountingChart(app, "accuse", app.model.com_redhat_grid_plumage.Accountant)
+ chart.max_samples = 250
+ chart.chart_type = "genusechart"
+ chart.duration.param.default = "86400"
+ chart.leftlegend = False
+ chart.height = 150
+ chart.width = 400
+ self.add_child(chart)
+
+ class AccountingChartControl(Widget):
+ def __init__(self, app, name):
+ super(AccountingChartWidget.AccountingChartControl, self).__init__(app, name)
+ self.app = app
+ self.groupLoader = AccGroupSqlOperation(app)
+
+ def render_chart_div_name(self, session):
+ return self.parent.children_by_name['accuse'].path
+
+ def render_accounting_groups(self, session):
+ display_groups = []
+ trees = {}
+ groups_string = ""
+ groups = self.groupLoader.execute(self.app.session).fetchall()
+ groups = [g[0] for g in groups]
+ top_groups = self.groupLoader.getTopLevelGroups(groups)
+ for t_group in top_groups:
+ trees[t_group] = self.groupLoader.build_tree(groups, t_group)
+
+ groups_string = self.processSubTree(trees, "", True)
+
+ return groups_string
+
+ def processSubTree(self, subtree, startString, initialUL=False):
+ if initialUL:
+ subtree_string = "%s <ul id=\"%s\">" % (startString, self.path)
+ else:
+ subtree_string = "%s <ul>" % startString
+ for node in subtree:
+ if len(subtree[node]) > 0:
+ subtree_string += """<li><a href="#">%s</a>""" % node.replace("<", "<").replace(">", ">")
+ subtree_string = self.processSubTree(subtree[node], subtree_string)
+ subtree_string += "</li>"
+ else:
+ subtree_string += """<li><a href="#">%s</a></li>""" % node.replace("<", "<").replace(">", ">")
+ subtree_string += "</ul>"
+ return subtree_string
+
+
+ class AccountingChart(ReportingChart):
+ def render_title(self, session):
+ return "Usage by accounting group (cpus)"
+
+class AccGroupSqlOperation(SqlOperation):
+ def __init__(self, app):
+ super(AccGroupSqlOperation, self).__init__(app)
+
+ def get_connection(self, session):
+ return self.app.database.get_read_connection()
+
+ def getTopLevelGroups(self, groups):
+ topLevelGroups = []
+ for group in groups:
+ split_name = group.split(".",1)
+ if split_name[0] not in topLevelGroups:
+ topLevelGroups.append(split_name[0])
+ return topLevelGroups
+
+ def build_tree(self, nodes, topNode):
+ tree = {}
+ self.build_tree_recursive(tree, topNode, nodes)
+
+ return tree
+
+ def build_tree_recursive(self, tree, parent, nodes):
+ children = []
+ for n in nodes:
+ (nparent, sep, leaf) = n.rpartition(".")
+ if nparent == parent:
+ children.append(n)
+
+ for child in children:
+ tree[child] = {}
+ self.build_tree_recursive(tree[child], child, nodes)
+
class DashboardSummary(Widget):
def __init__(self, app, name, collector):
Modified: branches/croberts/cumin/python/cumin/grid/dashboard.strings
===================================================================
--- branches/croberts/cumin/python/cumin/grid/dashboard.strings 2012-11-06 21:34:31 UTC (rev 5540)
+++ branches/croberts/cumin/python/cumin/grid/dashboard.strings 2012-11-15 15:03:29 UTC (rev 5541)
@@ -317,6 +317,14 @@
</div>
</div>
+
+
+[DashboardAccounting.html]
+<div class="{class}">
+ {charts}
+</div>
+<div style="clear:both;"></div>
+
[DashboardAccounting.css]
div.DashboardAccounting ul.WidgetSet {
padding: 0;
@@ -324,13 +332,74 @@
list-style: none;
}
-div.DashboardAccounting ul.WidgetSet li {
- display: inline;
- float: left;
-}
-[DashboardAccounting.html]
+[AccountingChartWidget.html]
<div class="{class}">
- {charts}
+ {actrl}
+ {accuse}
</div>
-<div style="clear:both;"></div>
+
+[AccountingChartWidget.css]
+div.AccountingChartWidget>div {
+ float: left;
+}
+
+
+[AccountingChartControl.html]
+<div id="controlTree" class="{class}"></div>
+<div style="display:none;">
+ {accounting_groups}
+</div>
+
+<script type="text/javascript">
+//<![CDATA[
+var controlTree;
+window.addEvent('domready', function () {
+ controlTree = new MooTreeControl({
+ div: 'controlTree',
+ mode: null,
+ grid: true,
+ onSelect: function(node, state) {
+ //do nothing
+ },
+ onExpand: function(node, state) {
+ var exposed_nodes = [];
+ for(i=0; i < node.nodes.length; i++) {
+ exposed_nodes[i] = node.nodes[i].text;
+ }
+ var chart = cumin.getChart("{chart_div_name}");
+ var chart_url = chart.getParent().getElement("a").getAttribute("href");
+ var nodes = [];
+ getExposedNodes(nodes, this.root);
+ var new_url = get_new_chart_url("{chart_div_name}", chart_url, "groupex", nodes);
+ chart.getParent().getElements('a')[chart_href].set('href', new_url);
+ drawSingleChart(chart, true);
+ }
+ },{
+ text: 'Accounting Groups',
+ open: true
+ });
+ controlTree.adopt('{id}');
+
+});
+
+function getExposedNodes(nodeList, node) {
+ if(node.open == true) {
+ for(var i=0, count=node.nodes.length; i < count; i++) {
+ getExposedNodes(nodeList, node.nodes[i]);
+ }
+ } else {
+ nodeList.push(node.text);
+ }
+}
+//]]>
+</script>
+
+[AccountingChartControl.css]
+div.AccountingChartControl {
+ width : 300px;
+}
+
+[AccGroupSqlOperation.sql]
+select distinct(agroup) from "com.redhat.grid.plumage"."Accountant_samples"
+ order by agroup asc;
Modified: branches/croberts/cumin/python/cumin/stat.py
===================================================================
--- branches/croberts/cumin/python/cumin/stat.py 2012-11-06 21:34:31 UTC (rev 5540)
+++ branches/croberts/cumin/python/cumin/stat.py 2012-11-15 15:03:29 UTC (rev 5541)
@@ -902,13 +902,13 @@
duration = self.get_duration(session)
end_seconds_ago = self.get_end_seconds(session)
delta = self.get_delta(session)
-
+
interval = self.page.get_interval(session, duration, width)
msg = "Chart parameters: duration: %s end_secends_ago: %s interval: %s" % (str(duration), str(end_seconds_ago), str(interval))
log.debug(msg)
# get the most recent samples
- samples = self.fetch_samples(adapter, duration, interval,
+ samples = self.fetch_samples(session, adapter, duration, interval,
self.fix_method(method, mode),
mode, delta, stats,
end_seconds_ago=end_seconds_ago)
@@ -925,7 +925,7 @@
if axis_max != max_of_axiis:
msg = "Y-Axis changed. New chart parameters: time_span: %s end_secends_ago: %s interval: %s" % (str(time_span), str(end_seconds_ago), str(interval))
log.debug(msg)
- samples = self.fetch_samples(adapter, time_span, interval,
+ samples = self.fetch_samples(session, adapter, time_span, interval,
self.fix_method(method, mode),
mode, False, stats,
end_seconds_ago=end_seconds_ago)
@@ -1003,7 +1003,7 @@
return y_axis, y_axis_right
- def fetch_samples(self, adapter, dur, interval, method, mode, delta, stats, end_seconds_ago=0):
+ def fetch_samples(self, session, adapter, dur, interval, method, mode, delta, stats, end_seconds_ago=0):
return dict()
def get_max_min(self, session, stats, samples):
@@ -1022,7 +1022,7 @@
# get more samples than needed to allow chart to clip correctly (explains the + 600)
samples[stat] = adapter[stat].samples(stat, dur+600, interval, method, secs2=end_seconds_ago, delta=delta)
- def fetch_samples(self, adapter, dur, interval, method, mode, delta, stats, end_seconds_ago=0):
+ def fetch_samples(self, session, adapter, dur, interval, method, mode, delta, stats, end_seconds_ago=0):
samples = dict()
if mode == "rate":
for stat in stats:
@@ -1182,18 +1182,29 @@
self.accGroups = self.AccGroupSqlOperation(app)
self.accUse = self.AccGroupUseSqlOperation(app, self)
- def fetch_samples(self, adapter, dur, interval, method, mode, delta, stats, end_seconds_ago=0):
+ def fetch_samples(self, session, adapter, dur, interval, method, mode, delta, stats, end_seconds_ago=0):
samples = dict()
- groups = self.accGroups.execute(self.app.session).fetchall()
+ groups_expanded = self.page.group_expand.get(session)
+ #use groups from url, if present, otherwise grab "all" form database
+ groups = groups_expanded if len(groups_expanded) > 0 else self.getTopLevelGroups(self.accGroups.execute(self.app.session).fetchall())
for group in groups:
- group_name = group[0]
+ group_name = group if isinstance(group, unicode) or isinstance(group, str) else group[0]
result = self.accUse.execute(self.app.session, group_name, dur, interval).fetchall()
if len(result) > 0:
samples[group_name] = result
return samples
+ def getTopLevelGroups(self, groups):
+ topLevelGroups = []
+ for group in groups:
+ group = group if isinstance(group, unicode) else group[0]
+ split_name = group.split(".",1)
+ if split_name[0] not in topLevelGroups:
+ topLevelGroups.append(split_name[0])
+ return topLevelGroups
+
def get_line_title(self, stat):
return stat.replace("<", "").replace(">", "")
@@ -1401,6 +1412,13 @@
self.group_selection = Parameter(app, "groupc")
self.group_selection.default = None
self.add_parameter(self.group_selection)
+
+ groupex_val = Parameter(app, "gp")
+ self.add_parameter(groupex_val)
+
+ self.group_expand = ListParameter(app, "groupex", groupex_val)
+ self.group_expand.default = []
+ self.add_parameter(self.group_expand)
def get_content_type(self, session):
return "text/plain"
Modified: branches/croberts/cumin/python/cumin/stat.strings
===================================================================
--- branches/croberts/cumin/python/cumin/stat.strings 2012-11-06 21:34:31 UTC (rev 5540)
+++ branches/croberts/cumin/python/cumin/stat.strings 2012-11-15 15:03:29 UTC (rev 5541)
@@ -286,27 +286,13 @@
setTimeout(function () {changeDuration(state, a, id, attempt+1);}, 100);
return false;
}
- newurl = get_chart_url(id, $(chart).getParent().getElements('a')[chart_href].get('href'), state);
+ newurl = get_new_chart_url(id, $(chart).getParent().getElements('a')[chart_href].get('href'), 'duration', state);
$(chart).getParent().getElements('a')[chart_href].set('href', newurl);
drawSingleChart(chart, true);
}
return false;
}
-// called by open-flash-chart.swf in response to chart.geturl()
-function get_chart_url(id, url, state) {
- var chart = cumin.getChart(id);
- if (chart == null)
- return false;
- var branch = wooly.session.branch(url);
- var now = new Date().getTime();
- branch['elapsed'] = now; // force an entire update
- branch['duration'] = state;
- url = branch.marshal();
-
- return url;
-}
-
function gotChartPoints(text, oImg) {
var mImg = $(oImg);
mImg.store('points', eval("("+text+")"));
@@ -436,20 +422,6 @@
return false;
}
-function get_new_chart_url(id, url, param, value) {
- var chart = cumin.getChart(id);
- if (chart == null)
- return false;
-
- var branch = wooly.session.branch(url);
- var now = new Date().getTime();
- branch['elapsed'] = now; // force an entire update
- branch[param] = value;
- url = branch.marshal();
-
- return url;
-}
-
[FilterInput.html]
<!-- <input id="{id}" type="text" name="{name}"></input><input type="button" value="Update filter" {onclick}/> -->
{title}: <select {onchange}>{user_list}</select>
@@ -482,8 +454,8 @@
[AccGroupUseSqlOperation.sql]
select max("Accountant_samples"."ts") as interval_end,
-cast(avg("Accountant_samples"."resused") as integer) as value,
+cast(max("Accountant_samples"."resused") as integer) as value,
stddev("Accountant_samples"."resused") as dev from "com.redhat.grid.plumage"."Accountant_samples"
-where ("Accountant_samples"."user" like '{accgroup}') and "Accountant_samples"."ts" >= now() - interval '{duration} seconds'
+where ("Accountant_samples"."user" like '{accgroup}%') and "Accountant_samples"."ts" >= now() - interval '{duration} seconds'
group by floor(extract(epoch from "Accountant_samples"."ts") / {interval}) order by interval_end desc limit all offset 0;
\ No newline at end of file
Modified: branches/croberts/cumin/resources/app.css
===================================================================
--- branches/croberts/cumin/resources/app.css 2012-11-06 21:34:31 UTC (rev 5540)
+++ branches/croberts/cumin/resources/app.css 2012-11-15 15:03:29 UTC (rev 5541)
@@ -824,3 +824,29 @@
{
color: #9FCFFF;
}
+
+
+.mooTree_node {
+ font-family: Verdana, Arial, Helvetica;
+ font-size: 10px;
+ white-space: nowrap;
+}
+
+.mooTree_text {
+ padding-top: 3px;
+ height: 15px;
+ cursor: pointer;
+}
+
+.mooTree_img {
+ float: left;
+ width: 18px;
+ height: 18px;
+ overflow: hidden;
+}
+
+.mooTree_selected {
+ background-color: #e0f0ff;
+ font-weight: bold;
+}
+
Modified: branches/croberts/cumin/resources/app.js
===================================================================
--- branches/croberts/cumin/resources/app.js 2012-11-06 21:34:31 UTC (rev 5540)
+++ branches/croberts/cumin/resources/app.js 2012-11-15 15:03:29 UTC (rev 5541)
@@ -634,7 +634,7 @@
gridPadding: dataContainer['gridPadding'],
grid: { background: '#FFFFFF' },
legend: {
- show: true,
+ show: dataContainer['labels'][0] == "No data" ? false:true,
location: dataContainer['legendLocation'],
renderer: $j.jqplot.EnhancedLegendRenderer,
yoffset: 0,
@@ -671,7 +671,7 @@
fillAndStroke:dataContainer['fillAndStroke'],
fillAlpha: dataContainer['fillAlpha'],
rendererOptions: {
- highlightMouseOver: false,
+ highlightMouseOver: true,
highlightMouseDown: false,
highlightColor: null,
markerRenderer: $j.jqplot.MarkerRenderer,
@@ -720,6 +720,7 @@
// if the chart already exists, perform a "replot()" on the chart, otherwise, draw the chart from scratch
if(allCharts[divName] != undefined) {
if(allCharts[divName]["forceRedraw"] == true) {
+ //console.log("Data is: " + JSON.stringify(dataContainer['y_coordinate_values']));
allCharts[divName].destroy();
allCharts[divName] = $j.jqplot(holder, dataContainer['y_coordinate_values'],chartOptionsObject);
} else {
@@ -736,14 +737,20 @@
} else {
$j.jqplot.preDrawHooks.push(cuminChartPreDraw);
$j.jqplot.postDrawHooks.push(cuminChartPostDraw);
+ //$j.jqplot.eventListenerHooks.push(['jqplotClick', plot1ClickHandler]);
allCharts[divName] = $j.jqplot(holder, dataContainer['y_coordinate_values'],chartOptionsObject);
allCharts[divName].target.bind('jqplotResetZoom', cuminChartResetZoom);
allCharts[divName].target.bind('jqplotZoom', cuminChartZoom);
+ allCharts[divName].target.bind('jqplotDataHighlight', cuminChartDataClick);
startChartMonitor(divName);
}
} // end function drawChart
+cuminChartDataClick = function (ev, seriesIndex, pointIndex, data) {
+ console.log('series: '+seriesIndex+', point: '+pointIndex+', data: '+data);
+}
+
// called on the jqplotZoom event
cuminChartZoom = function(gridpos, datapos, plot, cursor) {
// console.log("cuminZoom");
@@ -764,6 +771,17 @@
// console.log("customPreDraw");
}
+function plot1ClickHandler(ev, gridpos, datapos, neighbor, plot) {
+ if(plot.targetId == "#bargraph") {
+
+ var column = getColumnLocation(plot,gridpos,line1.length);
+
+ //make2nd('doc'+plot.data[0][parseInt(column)][2], plot.data[0][parseInt(column)][0]);
+
+ }
+}
+
+
// used to let us tweak the contents of the tooltip according to our whim, gets called from highlighter plugin showTooltip function
customTooltip = function(str, seriesIndex, pointIndex, plot) {
value = plot.series[seriesIndex].data[pointIndex][1];
@@ -899,3 +917,16 @@
return "anonymous";
}
+function get_new_chart_url(id, url, param, value) {
+ var chart = cumin.getChart(id);
+ if (chart == null)
+ return false;
+
+ var branch = wooly.session.branch(url);
+ var now = new Date().getTime();
+ branch['elapsed'] = now; // force an entire update
+ branch[param] = value;
+ url = branch.marshal();
+
+ return url;
+}
Modified: branches/croberts/wooly/python/wooly/pages.strings
===================================================================
--- branches/croberts/wooly/python/wooly/pages.strings 2012-11-06 21:34:31 UTC (rev 5540)
+++ branches/croberts/wooly/python/wooly/pages.strings 2012-11-15 15:03:29 UTC (rev 5541)
@@ -23,12 +23,14 @@
<script type="text/javascript" src="resource?name=jquery.js"></script>
<script type="text/javascript" src="resource?name=jquery.jqplot.js"></script>
<script type="text/javascript" src="resource?name=jqplot.pieRenderer.js"></script>
+ <script type="text/javascript" src="resource?name=jqplot.barRenderer.js"></script>
<script type="text/javascript" src="resource?name=jqplot.donutRenderer.min.js"></script>
<script type="text/javascript" src="resource?name=jqplot.categoryAxisRenderer.js"></script>
<script type="text/javascript" src="resource?name=jqplot.enhancedLegendRenderer.js"></script>
<script type="text/javascript" src="resource?name=jqplot.highlighter.js"></script>
<script type="text/javascript" src="resource?name=jqplot.cursor.js"></script>
<script type="text/javascript" src="resource?name=jqplot.dateAxisRenderer.js"></script>
+ <script type="text/javascript" src="resource?name=mootree.js"></script>
<script type="text/javascript">
$j = jQuery.noConflict();
11 years, 5 months
r5540 - trunk/cumin/model/upgrades
by tmckay@fedoraproject.org
Author: tmckay
Date: 2012-11-06 21:34:31 +0000 (Tue, 06 Nov 2012)
New Revision: 5540
Added:
trunk/cumin/model/upgrades/1.1_to_1.1a
trunk/cumin/model/upgrades/create_1.1a
Log:
Upgrade scripts left out of the commit in revision 5482
BZ846345
Added: trunk/cumin/model/upgrades/1.1_to_1.1a
===================================================================
--- trunk/cumin/model/upgrades/1.1_to_1.1a (rev 0)
+++ trunk/cumin/model/upgrades/1.1_to_1.1a 2012-11-06 21:34:31 UTC (rev 5540)
@@ -0,0 +1,114 @@
+#!/usr/bin/python
+import sys
+import shutil
+import os
+import re
+import pwd
+from subprocess import PIPE, Popen
+
+PG_HBA_CONF = "/var/lib/pgsql/data/pg_hba.conf"
+PG_HBA_CONF_SHORT = "pg_hba.conf"
+PG_HBA_CONF_BACK = PG_HBA_CONF + ".backup"
+
+def confirm(prompt, resp=False):
+ if resp:
+ prompt = '%s [%s]|%s: ' % (prompt, 'yes', 'no')
+ else:
+ prompt = '%s [%s]|%s: ' % (prompt, 'no', 'yes')
+
+ while True:
+ ans = raw_input(prompt)
+ if not ans:
+ return resp
+ ans = ans.lower()
+ if ans not in ['y', 'n', 'yes', 'no']:
+ print 'Please enter yes or no.'
+ continue
+ return ans in ('y', 'yes')
+
+def get_backup_name(path):
+ count = 1
+ name = path
+ while True:
+ if not os.path.exists(name):
+ return name
+ name = path + "." + str(count)
+ count += 1
+
+def main():
+
+ # If our real uid is root, we can do what we need to do
+ # regardles of what our current effective uid is
+ uids = (os.getuid(), os.geteuid())
+ if uids[0] != 0:
+ print "\nError: This upgrade script must be run as root."
+ sys.exit(1)
+
+ # Make us root for the upgrade
+ elif uids[1] != 0:
+ os.seteuid(0)
+
+ print "\nChecking database authentication for the cumin user in %s\n" \
+ % PG_HBA_CONF
+
+ altered_file = False
+
+ # Search for the cumin auth lines.
+ # We want to eliminate 'trust' auth for the cumin
+ # user on the cumin database and use default ident on local
+ old = re.compile("^\s*(local|host|hostssl|hostnossl)\s*cumin\s*cumin.*trust\s*$")
+
+ old_lines = []
+ count = 1
+ lines = file(PG_HBA_CONF).readlines()
+ for l in lines:
+ if old.match(l):
+ # Things we want to get rid of
+ old_lines.append(count)
+ count += 1
+
+ # If we have old lines, we need to alter the file.
+ if old_lines:
+ print "Removing 'trust' authentication for cumin."
+
+ # Backup existing
+ shutil.move(PG_HBA_CONF, PG_HBA_CONF_BACK)
+ stats = os.stat(PG_HBA_CONF_BACK)
+ fd = os.open(PG_HBA_CONF, os.O_WRONLY|os.O_CREAT, stats.st_mode)
+
+ # Write the file with the old lines missing
+ count = 1
+ for l in lines:
+ if count not in old_lines:
+ os.write(fd, l)
+ count += 1
+
+ os.chown(PG_HBA_CONF, stats.st_uid, stats.st_gid)
+ os.close(fd)
+
+ print "\nThe %s file has been changed.\nThe previous version is in %s."\
+ % (PG_HBA_CONF_SHORT, PG_HBA_CONF_BACK)
+ altered_file = True
+ else:
+ print "Leaving %s unchanged." % PG_HBA_CONF_SHORT
+
+ # Changes won't take effect until postgres is restarted
+ if altered_file:
+ if confirm("\nPostgres must be restarted for changes to take effect. "\
+ "Restart now?", True):
+
+ cmd = "service postgresql restart"
+ if Popen(cmd, shell=True).wait():
+ print "Failed to restart Postgres"
+
+ else:
+ print ""
+ else:
+ print ""
+
+ # And finish the way we started
+ os.seteuid(uids[1])
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
Property changes on: trunk/cumin/model/upgrades/1.1_to_1.1a
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/cumin/model/upgrades/create_1.1a
===================================================================
--- trunk/cumin/model/upgrades/create_1.1a (rev 0)
+++ trunk/cumin/model/upgrades/create_1.1a 2012-11-06 21:34:31 UTC (rev 5540)
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+import subprocess
+import os
+import re
+
+PG_HBA_CONF = "/var/lib/pgsql/data/pg_hba.conf"
+
+home = os.environ.get("CUMIN_HOME", os.path.normpath("/usr/share/cumin"))
+
+old = re.compile("^\s*(local|host|hostssl|hostnossl)\s*cumin\s*cumin.*trust\s*$")
+lines = file(PG_HBA_CONF).readlines()
+for l in lines:
+ if old.match(l):
+ # Okay, we have old config lines to get rid of.
+ subprocess.Popen(os.path.join(home, "model/upgrades/1.1_to_1.1a"),
+ shell=True).wait()
+ break
Property changes on: trunk/cumin/model/upgrades/create_1.1a
___________________________________________________________________
Added: svn:executable
+ *
11 years, 6 months
r5539 - in branches/croberts/cumin: bin python/cumin python/cumin/grid
by croberts@fedoraproject.org
Author: croberts
Date: 2012-11-05 22:00:06 +0000 (Mon, 05 Nov 2012)
New Revision: 5539
Modified:
branches/croberts/cumin/bin/cumin-web
branches/croberts/cumin/python/cumin/config.py
branches/croberts/cumin/python/cumin/grid/dashboard.py
branches/croberts/cumin/python/cumin/grid/dashboard.strings
branches/croberts/cumin/python/cumin/model.py
branches/croberts/cumin/python/cumin/stat.py
branches/croberts/cumin/python/cumin/stat.strings
Log:
Changes to detect plumage presence (or lack thereof). The dashboard summary will display a plumage-based chart if available.
Modified: branches/croberts/cumin/bin/cumin-web
===================================================================
--- branches/croberts/cumin/bin/cumin-web 2012-11-05 19:14:12 UTC (rev 5538)
+++ branches/croberts/cumin/bin/cumin-web 2012-11-05 22:00:06 UTC (rev 5539)
@@ -74,6 +74,10 @@
cumin.kerberos_server = values.kerberos_server
cumin.kerberos_realm = values.kerberos_realm
+def set_plumage_configs(cumin, values):
+ cumin.plumage_host = values.plumage_host
+ cumin.plumage_port = values.plumage_port
+
def check_cert_files(opts):
# If a certificate or key file has been specified,
# check to make sure that both exist and that the
@@ -219,6 +223,7 @@
set_wallaby_configs(cumin, values, broker_uris)
set_ldap_configs(cumin, values)
set_kerberos_configs(cumin, values)
+ set_plumage_configs(cumin, values)
# Not used right now
#cumin.auth_create_ondemand = values.auth_create_ondemand
Modified: branches/croberts/cumin/python/cumin/config.py
===================================================================
--- branches/croberts/cumin/python/cumin/config.py 2012-11-05 19:14:12 UTC (rev 5538)
+++ branches/croberts/cumin/python/cumin/config.py 2012-11-05 22:00:06 UTC (rev 5539)
@@ -161,6 +161,14 @@
param = ConfigParameter(self, "debug", bool)
param.default = False
+
+ param = ConfigParameter(self, "plumage_host", str)
+ param.default = "localhost"
+
+ param = ConfigParameter(self, "plumage_port", int)
+ param.default = 27017
+
+
class BrokeredConfigSection(CuminConfigSection):
def __init__(self, config, name, strict_section=False):
@@ -289,12 +297,6 @@
super(CuminReportConfigSection, self).__init__(config, name,
strict_section)
- param = ConfigParameter(self, "plumage_host", str)
- param.default = "localhost"
-
- param = ConfigParameter(self, "plumage_port", int)
- param.default = 27017
-
class CuminOptionParser(OptionParser,object):
def __init__(self):
OptionParser.__init__(self)
Modified: branches/croberts/cumin/python/cumin/grid/dashboard.py
===================================================================
--- branches/croberts/cumin/python/cumin/grid/dashboard.py 2012-11-05 19:14:12 UTC (rev 5538)
+++ branches/croberts/cumin/python/cumin/grid/dashboard.py 2012-11-05 22:00:06 UTC (rev 5539)
@@ -17,7 +17,9 @@
ObjectLinkColumn, CsvStatsExporter, ExportButton, MonitorSelfAgeColumn
from cumin.parameters import YoungestAttribute
from cumin.util import rgb_to_string, xml_escape
+from cumin.model import PlumageChecker
+
strings = StringCatalog(__file__)
log = logging.getLogger("cumin.dashboard")
@@ -94,10 +96,6 @@
def render_title(self, session):
return "Pool memory"
- class PoolCpuChart(ReportingChart):
- def render_title(self, session):
- return "Pool cpus"
-
class PoolEfficiencyChart(ReportingChart):
def render_title(self, session):
return "Pool efficiency"
@@ -117,8 +115,19 @@
job_data = DashboardOverviewJobSummary(app, "job_info")
self.add_child(job_data)
- slot_data = GridSlotsSummary(app, "host_info", collector)
- self.add_child(slot_data)
+ plumageChecker = PlumageChecker(app)
+ havePlumage = plumageChecker.isPlumageAvailable()
+
+ if havePlumage:
+ chart = self.PoolCpuChart(app, "host_info", app.model.com_redhat_grid_plumage.OSUtil)
+ chart.stats = [ "usedcpu", "freecpu"]
+ chart.max_samples = 250
+ chart.duration.param.default = "86400"
+ chart.chart_type = "stacked"
+ self.add_child(chart)
+ else:
+ slot_data = GridSlotsSummary(app, "host_info", collector)
+ self.add_child(slot_data)
neg_through = NegotiatorJobThroughput(app, "negotiator_throughput")
self.add_child(neg_through)
@@ -135,6 +144,10 @@
def render_title(self, session):
return "Summary"
+ class PoolCpuChart(ReportingChart):
+ def render_title(self, session):
+ return "Pool cpus"
+
class DashboardPerformance(Widget):
def __init__(self, app, name):
super(DashboardPerformance, self).__init__(app, name)
Modified: branches/croberts/cumin/python/cumin/grid/dashboard.strings
===================================================================
--- branches/croberts/cumin/python/cumin/grid/dashboard.strings 2012-11-05 19:14:12 UTC (rev 5538)
+++ branches/croberts/cumin/python/cumin/grid/dashboard.strings 2012-11-05 22:00:06 UTC (rev 5539)
@@ -7,6 +7,11 @@
</div>
<div style="clear:both;"></div>
+[DashboardSummary.css]
+div.DashboardSummary div.ReportingStatValueChart {
+ float:left;
+}
+
[MonitorSelfStats.css]
div.MonitorSelfStats div.data {
margin-left: 2em;
Modified: branches/croberts/cumin/python/cumin/model.py
===================================================================
--- branches/croberts/cumin/python/cumin/model.py 2012-11-05 19:14:12 UTC (rev 5538)
+++ branches/croberts/cumin/python/cumin/model.py 2012-11-05 22:00:06 UTC (rev 5539)
@@ -962,3 +962,18 @@
class NegotiatorStaticGroupConfigValuesStore(NegotiatorGroupConfigValuesStore):
def __init__(self, model, negotiator, groups, config):
super(NegotiatorStaticGroupConfigValuesStore, self).__init__(model, negotiator, groups, config)
+
+# Utility class to check for the plumage (data store)
+class PlumageChecker(object):
+ def __init__(self, app):
+ self.app = app
+
+ def isPlumageAvailable(self):
+ plumageAvail = False
+ try:
+ from pymongo import Connection
+ self.connection = Connection(self.app.plumage_host, self.app.plumage_port)
+ plumageAvail = True
+ except:
+ log.info("No plumage data store connection achieved.")
+ return plumageAvail
\ No newline at end of file
Modified: branches/croberts/cumin/python/cumin/stat.py
===================================================================
--- branches/croberts/cumin/python/cumin/stat.py 2012-11-05 19:14:12 UTC (rev 5538)
+++ branches/croberts/cumin/python/cumin/stat.py 2012-11-05 22:00:06 UTC (rev 5539)
@@ -313,6 +313,11 @@
return "leftlegend"
return ""
+ def render_legendmargin(self, session):
+ if not self.leftlegend:
+ return "legendmargin"
+ return ""
+
def render_filters(self, session):
filtertext = ""
for f in self.filters:
@@ -1277,14 +1282,14 @@
return self.app.database.get_read_connection()
class StackedAreaChart(AreaChart):
- colors = ('#FFABAB', '#ABABFF', '#ABFFAB', '#FFABFF', '#FFFFAB', '#ABFFFF', '#ABABAB')
def __init__(self, app, name, page):
super(StackedAreaChart, self).__init__(app, name, page)
self.points = self.Points(app, "points")
self.add_attribute(self.points)
- self.alpha = 1
+ self.fillAlpha = 0.7
+ self.fillAndStroke = False
self.stackSeries = True
# removed get_vals method since the new way of rendering stacked charts
Modified: branches/croberts/cumin/python/cumin/stat.strings
===================================================================
--- branches/croberts/cumin/python/cumin/stat.strings 2012-11-05 19:14:12 UTC (rev 5538)
+++ branches/croberts/cumin/python/cumin/stat.strings 2012-11-05 22:00:06 UTC (rev 5539)
@@ -137,6 +137,30 @@
}
[StatValueChart.css]
+/* This gives us a left justified 'n' position for our legend, just have the container div use the leftlegend class */
+div.leftlegend>table.jqplot-table-legend{
+ left:0px !important;
+}
+
+.jqplot-cursor-tooltip {
+ border: 1px solid #cccccc;
+ font-size: 0.75em;
+ white-space: nowrap;
+ background: rgba(255,255,255,0.9);
+ padding: 1px;
+ z-index:10;
+}
+
+.jqplot-highlighter-tooltip, .jqplot-canvasOverlay-tooltip {
+ border: 1px solid #cccccc;
+ font-size: 0.75em;
+ white-space: nowrap;
+ background: rgba(255,255,255,0.9);
+ padding: 1px;
+ z-index:10;
+}
+
+
div.StatValueChart {
font-size: 0.9em;
margin: 0 0 1.5em 0;
@@ -349,7 +373,7 @@
<div>
<!-- don't put this data url inside the holder div, jqplot will kill it on a zoom -->
<a rel="api" type="application/json" href="{href}" style="display:none">Data</a>
- <div id="{id_nodots}_chart" class="jqplotgraph {leftlegend}" style="height:{height}px;width:{width}px;">
+ <div id="{id_nodots}_chart" class="jqplotgraph {leftlegend} {legendmargin}" style="height:{height}px;width:{width}px;">
<div class="loading" style="display:none;"><span>Loading...</span></div>
</div>
</div>
@@ -360,7 +384,7 @@
</div>
[ReportingChart.css]
-div.ReportingStatValueChart div.jqplotgraph table.jqplot-table-legend {
+div.ReportingStatValueChart div.legendmargin table.jqplot-table-legend {
margin-left: 30px;
}
11 years, 6 months
r5538 - trunk/wooly/python/wooly
by tmckay@fedoraproject.org
Author: tmckay
Date: 2012-11-05 19:14:12 +0000 (Mon, 05 Nov 2012)
New Revision: 5538
Modified:
trunk/wooly/python/wooly/server.py
Log:
Generalize exception handler even further, suppress all ssl exceptions on
wrap()
Modified: trunk/wooly/python/wooly/server.py
===================================================================
--- trunk/wooly/python/wooly/server.py 2012-11-05 17:38:04 UTC (rev 5537)
+++ trunk/wooly/python/wooly/server.py 2012-11-05 19:14:12 UTC (rev 5538)
@@ -19,10 +19,7 @@
try:
s, env = super(PatchBuiltinSSLAdapter, self).wrap(sock)
except ssl.SSLError, e:
- if e.errno != ssl.SSL_ERROR_SSL:
- raise
- else:
- log.debug("Supressing ssl exception", exc_info=True)
+ log.debug("Supressing ssl exception", exc_info=True)
s, env = None, {}
return s, env
except:
11 years, 6 months