r5300 - trunk/sage/python/sage/aviary
by tmckay@fedoraproject.org
Author: tmckay
Date: 2012-04-12 22:33:53 +0000 (Thu, 12 Apr 2012)
New Revision: 5300
Modified:
trunk/sage/python/sage/aviary/aviaryoperations.py
Log:
Turn off suds caching for schemas.
Modified: trunk/sage/python/sage/aviary/aviaryoperations.py
===================================================================
--- trunk/sage/python/sage/aviary/aviaryoperations.py 2012-04-12 20:27:12 UTC (rev 5299)
+++ trunk/sage/python/sage/aviary/aviaryoperations.py 2012-04-12 22:33:53 UTC (rev 5300)
@@ -683,12 +683,12 @@
Instantiate a Client object with an OverridesPlugin and
retain a pointer to the plugin so that it can be controlled.
'''
- def __init__(self, *args):
+ def __init__(self, *args, **kwargs):
self.override = OverridesPlugin()
try:
- super(OverrideClient, self).__init__(plugins=[self.override], *args)
+ super(OverrideClient, self).__init__(plugins=[self.override], *args, **kwargs)
except:
- super(OverrideClient, self).__init__(*args)
+ super(OverrideClient, self).__init__(*args, **kwargs)
def set_enable_attributes(self, truth):
'''
@@ -718,7 +718,7 @@
self.job_wsdl = job_wsdl
def create_object(self):
- return OverrideClient(self.job_wsdl)
+ return OverrideClient(self.job_wsdl, cache=None)
class QueryClientPool(ObjectPool):
def __init__(self, query_wsdl, max_size):
@@ -726,4 +726,4 @@
self.query_wsdl = query_wsdl
def create_object(self):
- return OverrideClient(self.query_wsdl)
+ return OverrideClient(self.query_wsdl, cache=None)
12 years, 1 month
r5299 - in branches/play_plumage/cumin: python/cumin python/cumin/grid resources
by croberts@fedoraproject.org
Author: croberts
Date: 2012-04-12 20:27:12 +0000 (Thu, 12 Apr 2012)
New Revision: 5299
Modified:
branches/play_plumage/cumin/python/cumin/grid/dashboard.py
branches/play_plumage/cumin/python/cumin/grid/dashboard.strings
branches/play_plumage/cumin/python/cumin/model.py
branches/play_plumage/cumin/python/cumin/stat.py
branches/play_plumage/cumin/python/cumin/stat.strings
branches/play_plumage/cumin/resources/app.js
Log:
Initial cut at changes for the reporting grid utilization chart, BZ 807838.
Modified: branches/play_plumage/cumin/python/cumin/grid/dashboard.py
===================================================================
--- branches/play_plumage/cumin/python/cumin/grid/dashboard.py 2012-04-12 20:21:01 UTC (rev 5298)
+++ branches/play_plumage/cumin/python/cumin/grid/dashboard.py 2012-04-12 20:27:12 UTC (rev 5299)
@@ -11,7 +11,7 @@
from rosemary.sqlquery import SqlQueryOptions
from cumin.sqladapter import ObjectSqlAdapter
-from cumin.stat import StatSet, PieChartPage, StatFlashChart
+from cumin.stat import StatSet, PieChartPage, StatFlashChart, ReportingChart
from cumin.objectselector import ObjectSelector, MonitorSelfStatColumn, ObjectTableColumn, ObjectTable,\
ObjectLinkColumn, CsvStatsExporter, ExportButton, MonitorSelfAgeColumn
from cumin.parameters import YoungestAttribute
@@ -93,9 +93,21 @@
os_data = GridOSBreakdown(app, "os_breakdown")
self.add_child(os_data)
+
+ chart = self.UtilChart(app, "util", app.model.com_redhat_grid_plumage.OSUtil)
+ chart.stats = ["total", "avail", "used"]
+ # these titles are a temporary requirement. Eventually, we will have an "aggregate" class available that will
+ # let us store queries or other info in the rosemary.xml model but NOT have an actual column in the database
+ chart.titles = ["Total", "Available", "Used"]
+ chart.duration.param.default = "3600"
+ self.add_child(chart)
def render_title(self, session):
return "Slot capacity"
+
+ class UtilChart(ReportingChart):
+ def render_title(self, session):
+ return "Grid utilization"
class DefinitionSet(StatSet):
def __init__(self, app, name, object, title):
Modified: branches/play_plumage/cumin/python/cumin/grid/dashboard.strings
===================================================================
--- branches/play_plumage/cumin/python/cumin/grid/dashboard.strings 2012-04-12 20:21:01 UTC (rev 5298)
+++ branches/play_plumage/cumin/python/cumin/grid/dashboard.strings 2012-04-12 20:27:12 UTC (rev 5299)
@@ -76,6 +76,8 @@
<div id="{id}" class="{class}">
{slot_capacity}
{os_breakdown}
+ <div style="clear:both;"></div>
+ {util}
</div>
[DefinitionSet.css]
Modified: branches/play_plumage/cumin/python/cumin/model.py
===================================================================
--- branches/play_plumage/cumin/python/cumin/model.py 2012-04-12 20:21:01 UTC (rev 5298)
+++ branches/play_plumage/cumin/python/cumin/model.py 2012-04-12 20:27:12 UTC (rev 5299)
@@ -420,6 +420,53 @@
samples = self.get_data({}, options)
return len(samples) and samples[0][0] or None
+class AggregateSamplesSqlAdapter(SamplesSqlAdapter):
+ def __init__(self, app, cls, sig):
+ super(AggregateSamplesSqlAdapter, self).__init__(app, cls, sig)
+ self.querymap = {"used":"sum(case when state = 'Claimed' then 1 else 0 end) as value",
+ "avail":"sum(case when state = 'Claimed' or state = 'Available' then 1 else 0 end) as value",
+ "total":"sum(case when state = 'Claimed' or state = 'Available' or state = 'Unavailable' then 1 else 0 end) as value",
+ "unavail":"sum(case when state = 'Unavailable' then 1 else 0 end) as value"}
+
+
+ def avg_samples(self, stat, secs, interval, secs2):
+ updated_col = self.table._columns_by_name[self.update_col]
+
+ org_filters = list(self.query.filters)
+ max_col = "max(%s) as interval_end" % updated_col.identifier
+ value_col = self.querymap[stat.name]
+ dev_col = "count(1) as dev"
+
+ columns = list()
+ columns.append(max_col)
+ columns.append(value_col)
+ columns.append(dev_col)
+ self.columns = columns
+
+ when = "now() - interval '%i seconds'" % int(secs + secs2)
+ filter = SqlComparisonFilter(updated_col, when, ">=")
+ self.query.add_filter(filter)
+ when2 = ""
+ filter2 = None
+ if secs2:
+ when2 = "now() - interval '%i seconds'" % int(secs2)
+ filter2 = SqlComparisonFilter(updated_col, when2, "<=")
+ self.query.add_filter(filter2)
+
+ options = SqlQueryOptions()
+ options.sort_column = "interval_end"
+ options.sort_ascending = False
+ options.group_column = "floor(extract(epoch from %s) / %i)" % (updated_col.identifier, interval)
+
+ samples = self.get_data({}, options)
+
+ # reset the filters in case we need to re-run the query in this same request
+ del self.query.filters[:]
+ self.query.filters = org_filters
+
+ return samples
+
+
class CuminStatistic(object):
formatters = {
NoneType: lambda x: fmt_none(),
Modified: branches/play_plumage/cumin/python/cumin/stat.py
===================================================================
--- branches/play_plumage/cumin/python/cumin/stat.py 2012-04-12 20:21:01 UTC (rev 5298)
+++ branches/play_plumage/cumin/python/cumin/stat.py 2012-04-12 20:27:12 UTC (rev 5299)
@@ -11,7 +11,7 @@
BooleanParameter
from cumin.formats import fmt_bytes, fmt_duration_brief
-from cumin.model import CuminStatistic, SamplesSqlAdapter
+from cumin.model import CuminStatistic, SamplesSqlAdapter, AggregateSamplesSqlAdapter
from cumin.widgets import StateSwitch
from wooly.template import WidgetTemplate
from cumin.util import calc_rate, secs, nvl, xml_escape
@@ -172,7 +172,7 @@
if self.mode:
params.append("mode=%s" % self.mode)
-
+
if self.chart_type:
params.append("type=%s" % self.chart_type)
@@ -202,6 +202,33 @@
def render_height(self, session):
return 100
+class ReportingStatValueChart(StatValueChart):
+ def __init__(self, app, name, cls):
+ super(ReportingStatValueChart, self).__init__(app, name, None)
+
+ self.cls = cls
+ self.duration.add_state("2592000", "1 month")
+ self.duration.add_state("31557600", "1 year")
+
+ def get_href_params(self, session):
+ params = list()
+
+ params.append("chart_id=%s" % self.render_id(session, None))
+ params.append("duration=%s" % self.duration.get(session))
+ params.append("rpkg=%s" % self.cls._package._name)
+ params.append("rcls=%s" % self.cls._name)
+ params.append("type=%s" % "reportarea")
+
+ for i, stat in enumerate(self.stats):
+ params.append("stat=%s|%s" % (stat, self.titles[i]))
+
+ if self.mode:
+ params.append("mode=%s" % self.mode)
+
+ params.append("interval=60") #may need to experiment on computing this on the fly or use a value that matches the plumage sample rate
+
+ return params
+
class StatStackedChart(StatValueChart):
def __init__(self, app, name):
super(StatStackedChart, self).__init__(app, name)
@@ -244,7 +271,37 @@
def render_id_nodots(self, session):
return self.render_id(session).replace(".", "_")
+
+class ReportingChart(ReportingStatValueChart):
+ def get_flash_name(self, session):
+ return "chart.json"
+ def render_img_href(self, session):
+ return super(ReportingChart, self).render_href(session)
+
+ def render_img_width(self, session):
+ return super(ReportingChart, self).render_width(session)
+
+ def render_img_height(self, session):
+ return super(ReportingChart, self).render_height(session)
+
+ def render_href(self, session):
+ params = self.get_href_params(session)
+ return escape_entity("%s?" % self.get_flash_name(session) + ";".join(params))
+
+ def render_fullpage_href(self, session):
+ params = self.get_href_params(session)
+ return escape_entity("flashpage.html?" + ";".join(params))
+
+ def render_width(self, session):
+ return 360
+
+ def render_height(self, session):
+ return 120
+
+ def render_id_nodots(self, session):
+ return self.render_id(session).replace(".", "_")
+
class ImageCache(object):
def __init__(self):
self.__files = dict() # {name: {"time": time_created, "file": file object, "cookie": (cookie values)}}
@@ -409,11 +466,27 @@
rosemary_class = rosemary_package._classes_by_name[rclass]
signature = self.object_signature.get(session)
- adapter = SamplesSqlAdapter(self.app, rosemary_class, signature)
+
+ if(session.get("type") == "reportarea"):
+ # the stats here are not RosemaryStatistics, so we need a specialized sql adapter
+ # for the time being. Eventually we will have a Rosemary class available for
+ # things like these
+ adapter = AggregateSamplesSqlAdapter(self.app, rosemary_class, signature)
+ stats = [self.Pseudostat(x) for x in self.stats.get(session)]
+ else:
+ adapter = SamplesSqlAdapter(self.app, rosemary_class, signature)
+ stats = [getattr(rosemary_class, x) for x in self.stats.get(session)]
- stats = [getattr(rosemary_class, x) for x in self.stats.get(session)]
-
return (adapter, stats)
+
+ # builds an object that is similar to a RosemaryStatistic that can
+ # be used later in the chart rendering to give values to the chart items
+ class Pseudostat(object):
+ def __init__(self, statname):
+ name, title = statname.split('|')
+ self.name = name
+ self.title = title
+ self.short_title = None
def get_cache_control(self, session):
return "no-cache"
@@ -1030,6 +1103,9 @@
last_val = value
new_samples.append((dt, value, dev))
samples[stat] = new_samples
+
+class ReportAreaChart(AreaChart):
+ pass
class StackedAreaChart(AreaChart):
colors = ('#FFABAB', '#ABABFF', '#ABFFAB', '#FFABFF', '#FFFFAB', '#ABFFFF', '#ABABAB')
@@ -1175,6 +1251,9 @@
chart_obj = PercentAreaChart(self.app, chart_type, self)
elif chart_type == "pie":
chart_obj = FlashPieChart(self.app, chart_type, self)
+ elif chart_type == "reportarea":
+ chart_obj = ReportAreaChart(self.app, chart_type, self)
+
return chart_obj
Modified: branches/play_plumage/cumin/python/cumin/stat.strings
===================================================================
--- branches/play_plumage/cumin/python/cumin/stat.strings 2012-04-12 20:21:01 UTC (rev 5298)
+++ branches/play_plumage/cumin/python/cumin/stat.strings 2012-04-12 20:27:12 UTC (rev 5299)
@@ -106,6 +106,33 @@
<td class="ralign"> {item_value}</td>
</tr>
+[ReportingStatValueChart.css]
+div.ReportingStatValueChart {
+ font-size: 0.9em;
+ margin: 0 0 1.5em 0;
+ position: relative;
+ width: 33em;
+}
+
+div.ReportingStatValueChart div.duration {
+ margin: 1em 0 0.5em 1em;
+ width:400px;
+}
+
+div.ReportingStatValueChart ul.radiotabs {
+ margin: 0;
+}
+
+div.ReportingStatValueChart img,
+div.ReportingStatValueChart object {
+ margin: 0 0 0 1em;
+}
+
+div.ReportingStatValueChart>p.fullpageIcon {
+ top:49px;
+}
+
+
[StatValueChart.css]
div.StatValueChart {
font-size: 0.9em;
@@ -310,6 +337,23 @@
</div>
+[ReportingChart.html]
+<div>
+ <div class="ReportingStatValueChart{fullpageable}" id="{id}">
+ <h2>{title}</h2>
+ <div class="duration" style="float:left;">{duration}</div>
+ <div style="clear:both;"></div>
+ <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:150px;width:400px;">
+ <div class="loading" style="display:none;"><span>Loading...</span></div>
+ </div>
+ </div>
+ </div>
+
+</div>
+
[GenericChart.css]
div.FullpageChart {
margin: 1.5em;
@@ -322,6 +366,7 @@
<img id="{id}" src="{img_href}" height="{height}" width="{width}" alt="stats" />
<div class="loading" style="display:none;"><span>Loading...</span></div>
</div>
+ YOU ARE HERE!
</div>
<script type="text/javascript">
//<![CDATA[
Modified: branches/play_plumage/cumin/resources/app.js
===================================================================
--- branches/play_plumage/cumin/resources/app.js 2012-04-12 20:21:01 UTC (rev 5298)
+++ branches/play_plumage/cumin/resources/app.js 2012-04-12 20:27:12 UTC (rev 5299)
@@ -518,6 +518,14 @@
dataContainer['x_axis_normalizer'] = 3600;
dataContainer['x_axis_unit_label'] = "hr";
break;
+ case 2592000:
+ dataContainer['x_axis_normalizer'] = 86400;
+ dataContainer['x_axis_unit_label'] = "day";
+ break;
+ case 31557600:
+ dataContainer['x_axis_normalizer'] = 2592000;
+ dataContainer['x_axis_unit_label'] = "mo";
+ break;
}
for ( var i = 0; i < json.x_axis.labels.labels.length; i++) {
@@ -531,6 +539,7 @@
for ( var j = 0; j < json.elements[i].values.length; j++) {
dataContainer['x_coordinate_values'][i]
.append([ json.elements[i].values[j].dt / dataContainer['x_axis_normalizer'] ]);
+ //console.log("X-coordinate value of: " + json.elements[i].values[j].dt + " going to divide by " + dataContainer['x_axis_normalizer']);
}
}
@@ -696,12 +705,20 @@
// when called to render a popup tooltip, the caller is named "g"...not sure why. Whattup, g?
if(arguments.callee.caller.getName() == 'g') {
var tempTime = allCharts['chartNowTime'].clone();
+ //console.log("Using tempTime (chartNowTime) of: " + tempTime);
+ //console.log("Input offset timestamp of: "+ val);
+ //console.log("Subtract offset in months from temptime: " + tempTime.increment('month', val));
timeFormat = "%b %e, %T";
if(format.search(/min/) > -1) {
- return (tempTime.increment('minute', val).format(timeFormat));
- } else {
- return (tempTime.increment('hour', val).format(timeFormat));
+ modifier = 60 * val;
+ } else if (format.search(/day/) > -1) {
+ modifier = 86400 * val;
+ } else if (format.search(/mo/) > -1) {
+ modifier = 2592000 * val;
+ } else {
+ modifier = 3600 * val;
}
+ return (tempTime.increment('second', modifier).format(timeFormat));
}
return ($j.jqplot.sprintf(format, val)).replace(/-/,""); // hack to prevent negative axis labels, which we don't have
}
12 years, 1 month
r5298 - trunk/sage/rpc-defs/aviary
by tmckay@fedoraproject.org
Author: tmckay
Date: 2012-04-12 20:21:01 +0000 (Thu, 12 Apr 2012)
New Revision: 5298
Modified:
trunk/sage/rpc-defs/aviary/aviary-common.xsd
trunk/sage/rpc-defs/aviary/aviary-query.wsdl
trunk/sage/rpc-defs/aviary/aviary-query.xsd
Log:
Update aviary definition files
Modified: trunk/sage/rpc-defs/aviary/aviary-common.xsd
===================================================================
--- trunk/sage/rpc-defs/aviary/aviary-common.xsd 2012-04-11 21:09:33 UTC (rev 5297)
+++ trunk/sage/rpc-defs/aviary/aviary-common.xsd 2012-04-12 20:21:01 UTC (rev 5298)
@@ -105,6 +105,7 @@
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="0"/>
<xs:element name="owner" type="xs:string" minOccurs="0"/>
+ <xs:element name="qdate" type="xs:int" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="JobID">
@@ -153,7 +154,6 @@
<xs:sequence>
<xs:element name="id" type="tns:SubmissionID"/>
<xs:element name="status" type="tns:Status"/>
- <xs:element name="qdate" type="xs:int"/>
<xs:element name="completed" type="xs:int"/>
<xs:element name="held" type="xs:int"/>
<xs:element name="idle" type="xs:int"/>
@@ -209,4 +209,12 @@
<xs:element name="location" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
+ <xs:simpleType name="ScanMode">
+ <!-- a set of options for selecting how we scan a contiguous set of ids -->
+ <!-- only meaningful when used with an offset -->
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AFTER"/>
+ <xs:enumeration value="BEFORE"/>
+ </xs:restriction>
+ </xs:simpleType>
</xs:schema>
Modified: trunk/sage/rpc-defs/aviary/aviary-query.wsdl
===================================================================
--- trunk/sage/rpc-defs/aviary/aviary-query.wsdl 2012-04-11 21:09:33 UTC (rev 5297)
+++ trunk/sage/rpc-defs/aviary/aviary-query.wsdl 2012-04-12 20:21:01 UTC (rev 5298)
@@ -52,6 +52,12 @@
<wsdl:message name="GetSubmissionSummaryResponse">
<wsdl:part name="parameters" element="qry:GetSubmissionSummaryResponse"/>
</wsdl:message>
+ <wsdl:message name="GetSubmissionIDRequest">
+ <wsdl:part name="parameters" element="qry:GetSubmissionID"/>
+ </wsdl:message>
+ <wsdl:message name="GetSubmissionIDResponse">
+ <wsdl:part name="parameters" element="qry:GetSubmissionIDResponse"/>
+ </wsdl:message>
<wsdl:portType name="AviaryQuery">
<wsdl:operation name="getJobSummary">
<wsdl:input message="tns:GetJobSummaryRequest"/>
@@ -73,6 +79,10 @@
<wsdl:input message="tns:GetSubmissionSummaryRequest"/>
<wsdl:output message="tns:GetSubmissionSummaryResponse"/>
</wsdl:operation>
+ <wsdl:operation name="getSubmissionID">
+ <wsdl:input message="tns:GetSubmissionIDRequest"/>
+ <wsdl:output message="tns:GetSubmissionIDResponse"/>
+ </wsdl:operation>
</wsdl:portType>
<wsdl:binding name="AviaryQuerySOAPBinding" type="tns:AviaryQuery">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
@@ -121,6 +131,15 @@
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
+ <wsdl:operation name="getSubmissionID">
+ <soap:operation soapAction="http://grid.redhat.com/aviary-query/job/submission/id"/>
+ <wsdl:input>
+ <soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
</wsdl:binding>
<wsdl:service name="AviaryQueryService">
<wsdl:port name="AviaryQuerySOAPPort" binding="tns:AviaryQuerySOAPBinding">
Modified: trunk/sage/rpc-defs/aviary/aviary-query.xsd
===================================================================
--- trunk/sage/rpc-defs/aviary/aviary-query.xsd 2012-04-11 21:09:33 UTC (rev 5297)
+++ trunk/sage/rpc-defs/aviary/aviary-query.xsd 2012-04-12 20:21:01 UTC (rev 5298)
@@ -103,4 +103,23 @@
</xs:sequence>
</xs:complexType>
</xs:element>
+ <xs:element name="GetSubmissionID">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="size" type="xs:int"/>
+ <!-- declare how we want to search for ids-->
+ <xs:element name="mode" type="mrg:ScanMode" minOccurs="0"/>
+ <!-- the submission id offset is our "iterator" pointer -->
+ <xs:element name="offset" type="mrg:SubmissionID" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetSubmissionIDResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ids" type="mrg:SubmissionID" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="remaining" type="xs:int"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
</xs:schema>
12 years, 1 month
r5297 - trunk/cumin/python/cumin
by croberts@fedoraproject.org
Author: croberts
Date: 2012-04-11 21:09:33 +0000 (Wed, 11 Apr 2012)
New Revision: 5297
Modified:
trunk/cumin/python/cumin/widgets.py
Log:
Fixing the about page by closing the <li> tag for each browser.
Modified: trunk/cumin/python/cumin/widgets.py
===================================================================
--- trunk/cumin/python/cumin/widgets.py 2012-04-11 19:46:24 UTC (rev 5296)
+++ trunk/cumin/python/cumin/widgets.py 2012-04-11 21:09:33 UTC (rev 5297)
@@ -1675,7 +1675,7 @@
def render_browser_list(self, session):
browser_list_items = ""
for browser in self.browsers:
- browser_list_items += "<li class='browseritem'>%s" % browser
+ browser_list_items += "<li class='browseritem'>%s</li>" % browser
return browser_list_items
12 years, 1 month
r5296 - trunk/cumin
by tmckay@fedoraproject.org
Author: tmckay
Date: 2012-04-11 19:46:24 +0000 (Wed, 11 Apr 2012)
New Revision: 5296
Removed:
trunk/cumin/metadata/
Log:
Get rid of cumin/metadata
12 years, 1 month
r5295 - in trunk: cumin cumin/bin cumin/etc cumin/model cumin/model/access cumin/python/cumin cumin/python/cumin/account cumin/python/cumin/grid cumin/python/cumin/inventory cumin/python/cumin/messaging cumin/python/cumin/usergrid wooly/python/wooly
by tmckay@fedoraproject.org
Author: tmckay
Date: 2012-04-11 19:36:57 +0000 (Wed, 11 Apr 2012)
New Revision: 5295
Added:
trunk/cumin/model/access/
trunk/cumin/model/access/persona.xml
trunk/cumin/python/cumin/persona.py
Modified:
trunk/cumin/Makefile
trunk/cumin/bin/cumin-admin
trunk/cumin/bin/cumin-web
trunk/cumin/etc/cumin.conf
trunk/cumin/python/cumin/account/widgets.py
trunk/cumin/python/cumin/account/widgets.strings
trunk/cumin/python/cumin/admin.py
trunk/cumin/python/cumin/config.py
trunk/cumin/python/cumin/grid/main.py
trunk/cumin/python/cumin/grid/pool.py
trunk/cumin/python/cumin/inventory/main.py
trunk/cumin/python/cumin/inventory/system.py
trunk/cumin/python/cumin/main.py
trunk/cumin/python/cumin/messaging/main.py
trunk/cumin/python/cumin/usergrid/main.py
trunk/cumin/python/cumin/widgets.py
trunk/wooly/python/wooly/__init__.py
trunk/wooly/python/wooly/pages.py
trunk/wooly/python/wooly/table.py
trunk/wooly/python/wooly/widgets.py
Log:
Provide enforcement in the UI for user roles.
BZ769753
Modified: trunk/cumin/Makefile
===================================================================
--- trunk/cumin/Makefile 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/Makefile 2012-04-11 19:36:57 UTC (rev 5295)
@@ -27,8 +27,10 @@
install -pm 0644 ../wooly/LICENSE-for-wsgiserver ${CUMIN_HOME}/doc
install -pm 0644 ../wooly/COPYING-for-wsgiserver ${CUMIN_HOME}/doc
install -d ${CUMIN_HOME}/model/upgrades
+ install -d ${CUMIN_HOME}/model/access
install -pm 0644 model/*.xml ${CUMIN_HOME}/model
- install -pm 0755 model/upgrades/* ${CUMIN_HOME}/model/upgrades/
+ install -pm 0644 model/access/* ${CUMIN_HOME}/model/access/
install -d ${CUMIN_HOME}/resources
install -pm 0644 ../wooly/resources/*.css ${CUMIN_HOME}/resources
install -pm 0644 ../wooly/resources/*.js ${CUMIN_HOME}/resources
Modified: trunk/cumin/bin/cumin-admin
===================================================================
--- trunk/cumin/bin/cumin-admin 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/bin/cumin-admin 2012-04-11 19:36:57 UTC (rev 5295)
@@ -77,7 +77,7 @@
# cumin-admin is the mechanism for fixing the schema so we
# have to avoid the check here!
try:
- app.init(schema_version_check=False)
+ app.db_init(schema_version_check=False)
except OperationalError:
print "Can't talk to the database"
error("Run 'cumin-database check' as root for more information")
@@ -402,6 +402,26 @@
print("\nNo users removed.")
+def handle_add_role(app, cursor, opts, args):
+ print("\nNot implemented.")
+ return
+
+ # We may allow this later
+ try:
+ name = args[0]
+ except IndexError:
+ error("ROLE is required")
+
+ if app.admin.get_role(cursor, name):
+ error("A role called '%s' already exists" % name)
+
+ try:
+ app.admin.add_role(cursor, name)
+ except IntegrityError:
+ error("A role called '%s' already exists" % name)
+
+ print "Role '%s' is added" % name
+
def handle_add_user(app, cursor, opts, args):
try:
name = args[0]
@@ -542,7 +562,6 @@
def handle_remove_assignment(app, cursor, opts, args):
user, role = get_user_and_role(app, cursor, args)
-
assignment = app.admin.get_assignment(cursor, user, role)
if not assignment:
Modified: trunk/cumin/bin/cumin-web
===================================================================
--- trunk/cumin/bin/cumin-web 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/bin/cumin-web 2012-04-11 19:36:57 UTC (rev 5295)
@@ -41,7 +41,24 @@
cumin.wallaby_refresh = values.wallaby_refresh
if cumin.wallaby_refresh == 0:
cumin.wallaby_refresh = None
-
+
+def set_authorize_config(cumin, values, access_root):
+
+ # Allow this to be turned on/off.
+ # Default will be off.
+ cumin.do_authorize = values.authorize
+
+ # Allow this to be disabled via "None"
+ if values.auth_path == "None":
+ cumin.access_path = None
+ else:
+ # If there is no initial dir, prepend home
+ dir_name = os.path.split(values.auth_path)[0]
+ if len(dir_name) == 0:
+ cumin.access_path = os.path.join(access_root, values.auth_path)
+ else:
+ cumin.access_path = values.auth_path
+
def adjust_return(passed_init, ret):
# Shift non-zer0 return codes left 1 bit
# and OR in whether or not init passed
@@ -138,6 +155,15 @@
set_aviary_configs(cumin, values)
set_wallaby_configs(cumin, values, broker_uris)
+ # Not used right now
+ #cumin.auth_create_ondemand = values.auth_create_ondemand
+ #cumin.auth_proxy = values.auth_proxy
+
+ # Someday we may let this be configurable, for now it will
+ # be hardwired
+ values.auth_path = "persona.xml"
+ set_authorize_config(cumin, values, config.get_access_root())
+
cumin.debug = opts.debug
cumin.user = values.user
cumin.update_interval = values.update_interval
Modified: trunk/cumin/etc/cumin.conf
===================================================================
--- trunk/cumin/etc/cumin.conf 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/etc/cumin.conf 2012-04-11 19:36:57 UTC (rev 5295)
@@ -96,6 +96,7 @@
# update-interval: 10
# max-qmf-table-sort: 1000
# persona: grid
+# authorize: False
#notification-timeout: 180
# Number of seconds that a message in the yellow notification banner
@@ -248,6 +249,13 @@
## The "default" persona contains content for both grid and
## messaging.
+## authorize: False
+## Controls whether or not roles are enforced.
+## Roles are assigned to users with cumin-admin.
+## If roles are enforced, users with only the 'user'
+## role will not see the 'Administrator' tab.
+## The default role for a new user is 'user'.
+
## [data]
## expire-enabled: True
Copied: trunk/cumin/model/access/persona.xml (from rev 5294, branches/roles_II/cumin/model/access/persona.xml)
===================================================================
--- trunk/cumin/model/access/persona.xml (rev 0)
+++ trunk/cumin/model/access/persona.xml 2012-04-11 19:36:57 UTC (rev 5295)
@@ -0,0 +1,54 @@
+<PersonaMap>
+ <Persona name="default" auth="True">
+ <Module name="account"/>
+ <Module name="configuration"/>
+ <Module name="grid"/>
+ <Module name="inventory"/>
+ <Module name="messaging"/>
+ <Module name="usergrid"/>
+
+ <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="grid" auth="True">
+ <Module name="account"/>
+ <Module name="configuration"/>
+ <Module name="grid"/>
+ <Module name="inventory"/>
+ <Module name="usergrid"/>
+
+ <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="inventory"/>
+ <Module name="messaging"/>
+ </Persona>
+</PersonaMap>
\ No newline at end of file
Modified: trunk/cumin/python/cumin/account/widgets.py
===================================================================
--- trunk/cumin/python/cumin/account/widgets.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/python/cumin/account/widgets.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -124,19 +124,27 @@
user = cls.get_object(cursor, name=name)
if not user:
- self.login_invalid.set(session, True)
+ self.login_invalid.set(session, "credentials")
return
authenticated = self.app.authenticator.authenticate(name,password)
if authenticated:
- # You're in!
- login = LoginSession(self.app, user)
+ # You're in! almost...
+ # Check for a valid group if group authorization is on
+ if self.app.authorizator.is_enforcing():
+ roles = self.app.admin.get_roles_for_user(cursor, user)
+ if not self.app.authorizator.contains_valid_group(roles):
+ self.login_invalid.set(session, "roles")
+ return
+ else:
+ roles = []
+ login = LoginSession(self.app, user, roles)
session.client_session.attributes["login_session"] = login
url = self.page.origin.get(session)
self.page.redirect.set(session, url)
else:
- self.login_invalid.set(session, True)
+ self.login_invalid.set(session, "credentials")
def render_operator_link(self, session):
email = self.app.operator_email
@@ -147,7 +155,10 @@
return "site operator"
def render_login_invalid(self, session):
- if self.login_invalid.get(session):
+ reason = self.login_invalid.get(session)
+ if reason == "roles":
+ return self.get_string("roles_invalid")
+ elif reason == "credentials":
return self.get_string("login_invalid")
class Submit(FormButton):
Modified: trunk/cumin/python/cumin/account/widgets.strings
===================================================================
--- trunk/cumin/python/cumin/account/widgets.strings 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/python/cumin/account/widgets.strings 2012-04-11 19:36:57 UTC (rev 5295)
@@ -77,3 +77,7 @@
<p class="login_invalid">The user name and password you entered do not
match any account.</p>
+[LoginForm.roles_invalid]
+<p class="login_invalid">There are no valid roles
+configured for this account.</p>
+
Modified: trunk/cumin/python/cumin/admin.py
===================================================================
--- trunk/cumin/python/cumin/admin.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/python/cumin/admin.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -1,6 +1,8 @@
from StringIO import StringIO
from util import *
+from rosemary.sqlquery import SqlQuery, SqlInnerJoin
+from rosemary.sqlfilter import SqlComparisonFilter
from psycopg2 import IntegrityError, ProgrammingError
log = logging.getLogger("cumin.admin")
@@ -135,3 +137,26 @@
return mapping
+ def get_roles_for_user(self, cursor, user):
+ user_cls = self.app.model.com_redhat_cumin.User
+ role_cls = self.app.model.com_redhat_cumin.Role
+ mapping_cls = self.app.model.com_redhat_cumin.UserRoleMapping
+
+ query = SqlQuery(role_cls.sql_table)
+
+ SqlInnerJoin(query,
+ mapping_cls.sql_table,
+ mapping_cls.role.sql_column,
+ role_cls._id.sql_column)
+
+ SqlInnerJoin(query,
+ user_cls.sql_table,
+ user_cls._id.sql_column,
+ mapping_cls.user.sql_column)
+ #TODO: one column ?
+ cols = [ role_cls.name.sql_column ]
+ filt = SqlComparisonFilter(user_cls._id.sql_column, user._id, '=')
+ query.add_filter(filt)
+ sql = query.emit(cols)
+ cursor.execute(sql)
+ return [x[0] for x in cursor.fetchall()]
Modified: trunk/cumin/python/cumin/config.py
===================================================================
--- trunk/cumin/python/cumin/config.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/python/cumin/config.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -51,7 +51,7 @@
param = ConfigParameter(web, "persona", str)
param.default = "grid"
-
+
param = ConfigParameter(web, "fast-view-attributes", str)
param.default = "JobStatus,Cmd,Args,ExitStatus,JobStartDate,LastRemoteHost,LastJobStatus,Owner"
@@ -64,6 +64,23 @@
param = ConfigParameter(web, "force-html-doctype", bool)
param.default = False
+ # Turn this into a boolean, default is off for introduction.
+ # Hardwire the path to persona.xml unless/until we allow overriding
+ param = ConfigParameter(web, "authorize", bool)
+ param.default = False
+
+ # Turn these off for now...
+
+# param = ConfigParameter(web, "authz-provider", str)
+# param.default = "internal"
+
+# param = ConfigParameter(web, "auth-create-ondemand", bool)
+# param.default = False
+
+# param = ConfigParameter(web, "auth-proxy", bool)
+# param.default = False
+
+
def create_data_section(self, name, strict_section):
data = CuminConfigSection(self, name, strict_section)
data.log_file.default = os.path.join(self.home, "log", name + ".log")
@@ -103,6 +120,9 @@
def get_home(self):
return self.home
+ def get_access_root(self):
+ return os.path.join(self.home, "model/access/")
+
def parse(self):
paths = list()
Modified: trunk/cumin/python/cumin/grid/main.py
===================================================================
--- trunk/cumin/python/cumin/grid/main.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/python/cumin/grid/main.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -24,6 +24,8 @@
super(Module, self).init()
self.frame = PoolFrame(self.app, "grid")
+ self.frame.cumin_module = self.name
+
self.app.main_page.main.grid = self.frame
self.app.main_page.main.add_tab(self.frame)
Modified: trunk/cumin/python/cumin/grid/pool.py
===================================================================
--- trunk/cumin/python/cumin/grid/pool.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/python/cumin/grid/pool.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -78,6 +78,7 @@
self.tag = TagsFrame(app, "tag")
self.add_mode(self.tag)
+ self.tag.cumin_module = "configuration"
dashboard = PoolDashboard(app, "dashboard", self.object)
self.view.add_tab(dashboard)
Modified: trunk/cumin/python/cumin/inventory/main.py
===================================================================
--- trunk/cumin/python/cumin/inventory/main.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/python/cumin/inventory/main.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -16,6 +16,7 @@
self.frame = InventoryFrame(app, "inventory")
self.app = app
+ self.frame.cumin_module = name
def init(self):
self.app.main_page.main.inventory = self.frame
Modified: trunk/cumin/python/cumin/inventory/system.py
===================================================================
--- trunk/cumin/python/cumin/inventory/system.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/python/cumin/inventory/system.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -46,9 +46,11 @@
col = SystemTagsColumn(app, "Tags", app.model.com_redhat_cumin_grid.Node.Tags, "Tags")
self.add_column(col)
+ col.cumin_module = "configuration"
col = SystemCheckinColumn(app, "Checkin", app.model.com_redhat_cumin_grid.Node.Checkin, "Checkin")
self.add_column(col)
+ col.cumin_module = "configuration"
self.enable_csv_export()
@@ -73,6 +75,7 @@
configuration = SystemTags(app, "configuration", self.object)
self.view.add_tab(configuration)
+ configuration.cumin_module = "configuration"
def do_process(self, session):
try:
@@ -380,6 +383,7 @@
self.attr = attr
self.title = title
self.format_method = getattr(attr, "unit", None)
+ self.cumin_module = "configuration"
def get_field(self):
field = CheckinField(self.table.adapter, self.name)
Modified: trunk/cumin/python/cumin/main.py
===================================================================
--- trunk/cumin/python/cumin/main.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/python/cumin/main.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -21,6 +21,7 @@
from util import *
from widgets import *
from authenticator import *
+from persona import CuminAuthorizator
from sage.catalog import Catalog
from sage.qmf.qmfoperations import QmfOperations
from sage.wallaby.wallabyoperations import WallabyOperations
@@ -56,6 +57,14 @@
self.modules = list()
self.modules_by_name = dict()
+ # This is an argument to CuminAuthorizator in init()
+ self.access_path = None
+ self.do_authorize = False
+
+ # Currently turned off in config, but maybe used in the future
+ self.auth_proxy = None
+ self.auth_create_ondemand = None
+
self.tasks = list()
self.user = None
@@ -69,14 +78,10 @@
self.form_defaults = self.CuminFormDefaults()
- # Persona methods are used to control what pages and/or
- # modules are present
-
+ # Persona value maps to xml definitions handled
+ # in persona.py
self.persona = persona
- self.personas = dict()
- self.personas["default"] = self._init_default_persona
- self.personas["grid"] = self._init_grid_persona
- self.personas["messaging"] = self._init_messaging_persona
+
self._page_links = list()
# self.model.sql_logging_enabled = True
@@ -113,61 +118,65 @@
self.model.check()
self.database.check()
+
+ def _init_persona(self, modules):
- def _init_grid_persona(self):
- self.main_page = GridMainPage(self, "index.html")
+ # Determine the view based on which modules are enabled
+ if "messaging" in modules:
+ if "grid" in modules:
+ view = MainView(self, "main")
+ else:
+ view = MessagingMainView(self, "main")
+ else:
+ view = GridMainView(self, "main")
+
+ self.main_page = MainPage(self, "index.html", view)
self.add_page(self.main_page, add_to_link_set=True)
self.set_default_page(self.main_page)
-
- self.add_common_pages()
- import account
- import grid
- import inventory
- import usergrid
+ self.form_page = CuminFormPage(self, "form.html")
+ self.add_page(self.form_page)
- account.Module(self, "account")
- grid.Module(self, "grid")
- inventory.Module(self, "inventory")
- usergrid.Module(self, "usergrid")
+ self.add_page(StatFlashPage(self, "chart.json"))
+ self.add_page(FlashFullPage(self, "flashpage.html"))
- def _init_messaging_persona(self):
- self.main_page = MessagingMainPage(self, "index.html")
- self.add_page(self.main_page, add_to_link_set=True)
- self.set_default_page(self.main_page)
+ self.export_page = CuminExportPage(self, "csv")
+ self.add_page(self.export_page)
+
+ self.about_page = AboutPage(self, "about.html")
+ self.add_page(self.about_page)
- self.add_common_pages()
+ self.resource_page.protected = False
- import account
- import messaging
- import inventory
+ # Enable the modules that are associated with the
+ # persona (from persona.py)
+ for name in modules:
+ try:
+ m = __import__(name, globals())
+ m.Module(self, name)
+ except:
+ pass
- account.Module(self, "account")
- messaging.Module(self, "messaging")
- inventory.Module(self, "inventory")
+ def db_init(self, schema_version_check=True):
+ self.model.init()
+ self.database.init(schema_version_check)
- def _init_default_persona(self):
- self.main_page = MainPage(self, "index.html")
- self.add_page(self.main_page, add_to_link_set=True)
- self.set_default_page(self.main_page)
-
- self.add_common_pages()
-
- import account
- import messaging
- import grid
- import inventory
- import usergrid
-
- account.Module(self, "account")
- messaging.Module(self, "messaging")
- grid.Module(self, "grid")
- inventory.Module(self, "inventory")
- usergrid.Module(self, "usergrid")
-
def init(self, schema_version_check=True):
log.info("Initializing %s", self)
+ # Do this initialization as late as possible so that
+ # the application can set a value for self.access_path.
+ # Alternatively, it can be an argument to the constructor.
+ self.authorizator = CuminAuthorizator(self, self.access_path, self.do_authorize)
+ try:
+ self.authorizator.set_persona(self.persona)
+ except:
+ msg = "Persona is not defined '%s'"
+ raise Exception(msg % self.persona)
+
+ self.authorize_cb = self.authorizator.authorize
+ self.mainpage_cb = self.authorizator.find_mainpage
+
# Create RPC interfaces for QMF and aviary.
# These service have overlapping functionality,
# so they are wrapped in a sage.Catalog object
@@ -221,11 +230,9 @@
self.database.init(schema_version_check)
self.server.init()
- # Create the correct persona
- if self.persona in self.personas:
- self.personas[self.persona]()
- else:
- self._init_default_persona()
+ # This will set up the main view and enable the
+ # modules that are associated with the persona
+ self._init_persona(self.authorizator.get_enabled_modules())
for module in self.modules:
module.init()
@@ -235,21 +242,6 @@
super(Cumin, self).init()
- def add_common_pages(self):
- self.form_page = CuminFormPage(self, "form.html")
- self.add_page(self.form_page)
-
- self.add_page(StatFlashPage(self, "chart.json"))
- self.add_page(FlashFullPage(self, "flashpage.html"))
-
- self.export_page = CuminExportPage(self, "csv")
- self.add_page(self.export_page)
-
- self.about_page = AboutPage(self, "about.html")
- self.add_page(self.about_page)
-
- self.resource_page.protected = False
-
def start(self):
log.info("Starting %s", self)
@@ -291,9 +283,8 @@
def __init__(self, app, name):
self.app = app
self.name = name
-
self.tasks = list()
-
+ log.debug("Init cumin module %s", name )
assert not hasattr(app, self.name), self.name
self.app.modules.append(self)
@@ -306,45 +297,10 @@
def init_test(self, test):
pass
-class GridMainPage(CuminPage, ModeSet):
- def __init__(self, app, name):
- super(GridMainPage, self).__init__(app, name)
-
- self.main = GridMainView(app, "main")
- self.add_mode(self.main)
- self.set_default_frame(self.main)
-
- self.page_html_class = "Cumin"
-
- def render_title(self, session):
- return self.get_title(session)
-
- def get_title(self, session):
- return "Administrator"
-
class GridMainView(CuminMainView):
def __init__(self, app, name):
super(GridMainView, self).__init__(app, name)
- #self.overview = GridOverviewFrame(app, "overview")
- #self.add_tab(self.overview)
-
-class MessagingMainPage(CuminPage, ModeSet):
- def __init__(self, app, name):
- super(MessagingMainPage, self).__init__(app, name)
-
- self.main = MessagingMainView(app, "main")
- self.add_mode(self.main)
- self.set_default_frame(self.main)
-
- self.page_html_class = "Cumin"
-
- def render_title(self, session):
- return self.get_title(session)
-
- def get_title(self, session):
- return "Administrator"
-
class MessagingMainView(CuminMainView):
def __init__(self, app, name):
super(MessagingMainView, self).__init__(app, name)
@@ -352,13 +308,21 @@
self.overview = MessagingOverviewFrame(app, "overview")
self.add_tab(self.overview)
-class MainPage(CuminPage, ModeSet):
+class MainView(CuminMainView):
def __init__(self, app, name):
+ super(MainView, self).__init__(app, name)
+
+ self.overview = OverviewFrame(app, "overview")
+ self.add_tab(self.overview)
+
+class MainPage(CuminPage, ModeSet):
+ def __init__(self, app, name, main_view):
super(MainPage, self).__init__(app, name)
- self.main = MainView(app, "main")
+ self.main = main_view
self.add_mode(self.main)
self.set_default_frame(self.main)
+ self.cumin_module = ["messaging", "grid"]
self.page_html_class = "Cumin"
@@ -368,13 +332,6 @@
def get_title(self, session):
return "Administrator"
-class MainView(CuminMainView):
- def __init__(self, app, name):
- super(MainView, self).__init__(app, name)
-
- self.overview = OverviewFrame(app, "overview")
- self.add_tab(self.overview)
-
# XXX Add qmf tab
class OverviewFrame(CuminFrame):
@@ -412,46 +369,12 @@
systems = TopSystemTable(app, "systems")
self.add_child(systems)
+ systems.cumin_module = "inventory"
submissions = TopSubmissionTable(app, "submissions")
self.add_child(submissions)
+ submissions.cumin_module = "grid"
- # XXX
-
- #queues = messaging.queue.TopQueueSet(app, "queues")
- #self.add_child(queues)
-
- #submissions = grid.submission.TopSubmissionSet(app, "submissions")
- #self.add_child(submissions)
-
- #systems = inventory.system.TopSystemSet(app, "systems")
- #self.add_child(systems)
-
-# don't appear to need this....
- # class Heading(CuminHeading):
- # def render_title(self, session):
- # return "Overview"
-
- # def render_icon_href(self, session):
- # return "resource?name=action-36.png"
-
-class GridOverviewFrame(OverviewFrame):
- def __init__(self, app, name):
- super(GridOverviewFrame, self).__init__(app, name)
-
- def get_overview_view(self, app):
- return GridOverviewView(app, "view")
-
-class GridOverviewView(Widget):
- def __init__(self, app, name):
- super(GridOverviewView, self).__init__(app, name)
-
- systems = TopSystemTable(app, "systems")
- self.add_child(systems)
-
- submissions = TopSubmissionTable(app, "submissions")
- self.add_child(submissions)
-
class MessagingOverviewFrame(OverviewFrame):
def __init__(self, app, name):
super(MessagingOverviewFrame, self).__init__(app, name)
Modified: trunk/cumin/python/cumin/messaging/main.py
===================================================================
--- trunk/cumin/python/cumin/messaging/main.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/python/cumin/messaging/main.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -16,6 +16,7 @@
super(Module, self).__init__(app, name)
self.frame = MessagingFrame(self.app, "messaging")
+ self.frame.cumin_module = name
def init(self):
super(Module, self).init()
Copied: trunk/cumin/python/cumin/persona.py (from rev 5294, branches/roles_II/cumin/python/cumin/persona.py)
===================================================================
--- trunk/cumin/python/cumin/persona.py (rev 0)
+++ trunk/cumin/python/cumin/persona.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -0,0 +1,170 @@
+#!/usr/bin/env python
+import logging
+import os.path
+import re
+
+try:
+ import xml.etree.ElementTree as etree
+except ImportError:
+ import elementtree.ElementTree as etree
+
+log = logging.getLogger("cumin.authorize")
+
+class CuminGroup(object):
+ def __init__(self, name):
+ self.name = name
+ self.mainpage = "index.html"
+ self.allowed = [] # which modules the group can access
+
+class CuminPersona(object):
+ def __init__(self, name, auth):
+ self.name = name # may be handy to have this here
+
+ self.auth = auth.lower() == "true" # should groups be checked?
+ self.modules = [] # which modules are enabled
+ self.mapping = {} # dictionary of CuminGroup objects
+
+ def find_mainpage(self, group):
+ return self.mapping[group].mainpage
+
+ def lookup(self, group, module):
+ try:
+ if type(module) in (list, tuple):
+ return len(set(module) & \
+ set(self.mapping[group].allowed)) > 0
+ else:
+ return module in self.mapping[group].allowed
+ except KeyError:
+ return False
+
+class CuminPersonaMap(object):
+ def __init__(self):
+ log.info("Initializing %s", self.__class__.__name__)
+ self.personas = {}
+ self.filepath = None
+
+ def __repr__(self):
+ return ("%s %s" % ( self.__class__.__name__, self.filepath ))
+
+ def parse_personafile(self, filepath):
+ #TODO: handle exceptions during parsing
+ acctree = etree.ElementTree().parse(filepath)
+ for prec in acctree.getiterator('Persona'):
+ pkey = prec.attrib["name"]
+ auth = prec.attrib["auth"]
+ persona = CuminPersona(pkey, auth)
+ self.personas[pkey] = persona
+
+ for pchild in prec.getchildren():
+ if pchild.tag == "Module":
+ persona.modules.append(pchild.attrib["name"])
+ elif pchild.tag == "GroupAccess":
+ gkey = pchild.attrib["name"]
+ group = CuminGroup(gkey)
+ persona.mapping[gkey] = group
+ for gchild in pchild.getchildren():
+ if gchild.tag == "MainPage":
+ group.mainpage = gchild.attrib["name"]
+ elif gchild.tag == "ModuleAccess":
+ if gchild.attrib["name"] == "*":
+ group.allowed.extend(persona.modules)
+ else:
+ group.allowed.append(gchild.attrib["name"])
+
+class CuminAuthorizator(object):
+ def __init__(self, app, access_path, do_authorize):
+ self.app = app
+ self.access_path = access_path
+ log.info("Initializing %s", self)
+ self.personas = CuminPersonaMap()
+ self.persona = None
+ self.do_authorize = do_authorize
+
+ log.debug("Access file path is %s", access_path)
+ if os.path.isdir(access_path):
+ files = [os.path.join(access_path, x) \
+ for x in os.listdir(access_path)]
+ elif os.path.isfile(access_path):
+ files = [access_path]
+ else:
+ files = []
+ log.error("Path '%s' for access files does not exist!" % access_path)
+
+ for accfile in files:
+ if os.path.isfile(accfile) and \
+ os.path.splitext(accfile)[1] == ".xml":
+ try:
+ self.personas.parse_personafile(accfile)
+ except:
+ log.error("Access file '%s' does not parse!" % accfile)
+
+ def set_persona(self, name):
+ self.persona = self.personas.personas[name]
+
+ def is_enforcing(self):
+ return self.do_authorize and self.persona.auth
+
+ def find_mainpage(self, web_session):
+ # Find a main page for the current login session.
+ # If user is in the admin group, prefer that one.
+ # If we have multiple groups someday beyond user/admin,
+ # we may have to have a priority scheme here (or find
+ # a way to NOT have more than one mainpage).
+ try:
+ group = web_session.client_session.attributes['login_session'].group
+ except KeyError:
+ group = "nogroup"
+ if type(group) == type([]):
+ if "admin" in group:
+ group = "admin"
+ else:
+ group = group[0]
+ return self.persona.find_mainpage(group)
+
+ def get_enabled_modules(self):
+ return self.persona.modules
+
+ def contains_valid_group(self, groups):
+ for g in groups:
+ if g in self.persona.mapping:
+ return True
+ return False
+
+ def authorize(self, web_session, widget):
+ if not hasattr(widget, "cumin_module") or \
+ widget.cumin_module is None:
+ # no module for this widget, we have to allow it
+ return True
+
+ # We can't logically be authorized for a module we haven't even
+ # enabled! This may occur when parts of a display have
+ # associated themselves with a module explicitly.
+ # (like a column in a table that is only valid if a
+ # particular module has been loaded).
+ if type(widget.cumin_module) in (list, tuple):
+ if len(set(widget.cumin_module) & set(self.persona.modules)) == 0:
+ return False
+ elif not widget.cumin_module in self.persona.modules:
+ return False
+
+ if not self.is_enforcing():
+ # Auth checks against group are off.
+ return True
+
+ try:
+ group = web_session.client_session.attributes['login_session'].group
+ except KeyError:
+ group = "nogroup"
+
+ if type(group) == type([]):
+ for g in group:
+ if self.persona.lookup(g, widget.cumin_module):
+ log.debug("Allowing %s authorization for %s ",
+ widget.cumin_module, group)
+ return True
+ else:
+ return self.persona.lookup(group, widget.cumin_module)
+
+ log.debug("Denying %s authorization for %s ", widget.my_name, group)
+ return False
+
Modified: trunk/cumin/python/cumin/usergrid/main.py
===================================================================
--- trunk/cumin/python/cumin/usergrid/main.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/python/cumin/usergrid/main.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -11,3 +11,4 @@
self.app.user_grid_page = MainPage(self.app, "usergrid.html")
self.app.add_page(self.app.user_grid_page, add_to_link_set=True)
+ self.app.user_grid_page.cumin_module = self.name
Modified: trunk/cumin/python/cumin/widgets.py
===================================================================
--- trunk/cumin/python/cumin/widgets.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/cumin/python/cumin/widgets.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -81,7 +81,7 @@
return branch.marshal()
else:
return super(CuminMainView, self).render_tab_href(session, tab)
-
+
def render_about_href(self, session):
page = self.app.about_page
lsess = Session(page)
@@ -90,29 +90,24 @@
class CuminPageLinks(ItemSet):
def __init__(self, app, name):
super(CuminPageLinks, self).__init__(app, name)
-
+ self.app = app
self.html_class = CuminPageLinks.__name__
- self.check_admin = self.CheckAdmin(app)
-
def do_get_items(self, session):
return self.app.page_links
def render_item_content(self, session, page):
href = Session(page).marshal()
title = page.render_title(session)
+ if self.app.authorize_cb(session, page):
+ return fmt_link(href, title)
- return fmt_link(href, title)
-
def render_item_class(self, session, page):
if page is session.page:
return "selected"
else:
return "_"
- class CheckAdmin(CuminSqlDataSet):
- pass
-
class CuminFrame(Frame, ModeSet):
def __init__(self, app, name):
super(CuminFrame, self).__init__(app, name)
@@ -156,7 +151,6 @@
def render_href(self, session, *args):
branch = session.branch()
-
if hasattr(self, "view"):
self.view.show(branch)
@@ -1175,12 +1169,11 @@
# XXX this should move somewhere else
class LoginSession(object):
- def __init__(self, app, user):
+ def __init__(self, app, user, group):
self.app = app
self.user = user
-
+ self.group = group
self.created = datetime.now()
-
self.notifications = list()
class NotificationSet(Widget):
@@ -1281,58 +1274,98 @@
self.error_tmpl = WidgetTemplate(self, "error_html")
self.not_found_tmpl = WidgetTemplate(self, "not_found_html")
- def do_process(self, session):
+ def _redirect_to_login(self, session):
session.cursor = self.app.database.get_read_cursor()
-
if not self.authorized(session):
page = self.app.login_page
-
sess = Session(page)
page.origin.set(sess, session.marshal())
-
self.redirect.set(session, sess.marshal())
+ return True
+ return False
- return
+ def redirect_on_not_authorized(self, session):
+ # If the user is not logged in, then it doesn't have a
+ # a group identity yet. Check to see if we should
+ # redirect to the login page before looking for a
+ # valid page to redirect to based on group
+ if not self._redirect_to_login(session):
+ super(CuminPage, self).redirect_on_not_authorized(session)
- super(CuminPage, self).do_process(session)
+ def do_process(self, session):
+ if not self._redirect_to_login(session):
+ super(CuminPage, self).do_process(session)
def authorized(self, session):
if not self.protected:
return True
login = session.client_session.attributes.get("login_session")
-
if login:
when = datetime.now() - timedelta(hours=24)
-
if login.created > when:
return True
- elif self.app.user:
- cls = self.app.model.com_redhat_cumin.User
- users = cls.get_selection(session.cursor, name=self.app.user)
- if not users:
- raise Exception("User '%s' not found" % self.app.user)
+ elif self.app.auth_proxy or self.app.user:
+ username = self.app.user
+ # proxy user overrides app defined user
+ try:
+ username = session.request_environment['HTTP_REMOTE_USER']
+ except KeyError:
+ log.debug("Proxy auth enabled but no remote user set")
+ pass
- login = LoginSession(self.app, users[0])
- session.client_session.attributes["login_session"] = login
+ if username:
+ cls = self.app.model.com_redhat_cumin.User
+ users = cls.get_selection(session.cursor, name=username)
+ if not users:
+ if not self.app.auth_proxy:
+ log.info("User '%s' not found" % username)
+ else:
+ log.info("User %s not found in db, "\
+ "using auth proxy", username )
+ #Hmmm, what is users here? For now just let it return
+ # to the login page
+ return False
- return True
+#TODO prehodit do authenticatora
+# ondemand -> authenticator.create_user
+# user -> authenticator.force_login
+ # Check for valid group
+ if self.app.authorizator.is_enforcing():
+ cursor = self.app.database.get_read_cursor()
+ roles = self.app.admin.get_roles_for_user(cursor, users[0])
+ if not self.app.authorizator.contains_valid_group(roles):
+ log.info("No valid roles for '%s'" % username)
+ return False # go to login page
+ else:
+ roles = []
+
+ login = LoginSession(self.app, users[0], roles)
+ session.client_session.attributes["login_session"] = login
+ return True
return False
def redirect_on_exception(self, session):
# If we have an exception from a missing object, redirect to the
# main page with a notice instead of using the not_found_tmpl below.
- # Test for presence on the index.html page already to avoid any possibility
+ # Test for presence on the main page already to avoid any possibility
# of an infinite redirect loop.
cls, value, traceback = sys.exc_info()
+ if self.app.authorizator.is_enforcing():
+ mainpage = self.app.authorizator.find_mainpage(session)
+ if not mainpage.startswith("/"):
+ mainpage = "/" + mainpage
+ else:
+ mainpage = "/index.html"
+
if cls is RosemaryNotFound and \
- session.request_environment["REQUEST_URI"] != "/index.html":
+ session.request_environment["REQUEST_URI"] != mainpage:
+ session.add_notice(Notice(
+ "An object being displayed became unavailable"))
+ return mainpage
- session.add_notice(Notice("An object being displayed became unavailable"))
- return "/index.html"
-
def render_error(self, session):
cls, value, traceback = sys.exc_info()
Modified: trunk/wooly/python/wooly/__init__.py
===================================================================
--- trunk/wooly/python/wooly/__init__.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/wooly/python/wooly/__init__.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -2,7 +2,7 @@
from resources import ResourceFinder
from template import *
from util import *
-
+from traceback import print_exception
log = logging.getLogger("wooly")
strings = StringCatalog(__file__)
@@ -125,6 +125,8 @@
self.__defer_tmpl = WidgetTemplate(self, "deferred_html")
self.nocontent_tmpl = WidgetTemplate(self, "nocontent")
+ self.my_name = self.__class__.__module__ + '.' + self.__class__.__name__
+
def init(self):
log.debug("Initializing %s" % self)
@@ -285,26 +287,36 @@
for child in self.children:
child.save_parameters(session, params)
+ def redirect_on_not_authorized(self, session):
+ # Give an opportunity to redirect to a valid page
+ # when a user is not authorized for this widget.
+ pass
+
def process(self, session, *args):
- if self.update_enabled:
- self.page.enable_update(session, self)
+ if not self.app.authorize_cb(session, self):
+ self.redirect_on_not_authorized(session)
+ else:
+ if self.update_enabled:
+ self.page.enable_update(session, self)
- if self.defer_enabled:
- self.page.enable_defer(session, self)
+ if self.defer_enabled:
+ self.page.enable_defer(session, self)
- if self.app.debug:
- profile = self.page.profile.get(session)
+ if self.app.debug:
+ profile = self.page.profile.get(session)
- call = ProcessCall(profile, self, args)
- call.do(session)
- else:
- self.do_process(session, *args)
+ call = ProcessCall(profile, self, args)
+ call.do(session)
+ else:
+ self.do_process(session, *args)
def do_process(self, session, *args):
for child in self.children:
child.process(session)
def render(self, session, *args):
+ if not self.app.authorize_cb(session, self):
+ return ""
if self.app.debug:
profile = self.page.profile.get(session)
@@ -487,7 +499,12 @@
return None
def service_error(self, session):
- self.error.set(session, PageError(self, session))
+ # Well, we can have other handled exceptions pop up before
+ # we actually get to the render so we want to record here
+ # what the root cause was.
+ cls, value, traceback = sys.exc_info()
+ self.error.set(session, PageError(self, session,
+ cls, value, traceback))
return self.render(session)
@@ -515,15 +532,18 @@
self.url = url
class PageError(object):
- def __init__(self, page, session):
+ def __init__(self, page, session, cls, value, traceback):
self.page = page
self.session = session
+ self.cls = cls
+ self.value = value
+ self.traceback = traceback
def render(self):
writer = Writer()
writer.write("APPLICATION ERROR\n\n")
- print_exc(None, writer)
+ print_exception(self.cls, self.value, self.traceback, None, writer)
writer.write("\n")
Modified: trunk/wooly/python/wooly/pages.py
===================================================================
--- trunk/wooly/python/wooly/pages.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/wooly/python/wooly/pages.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -149,6 +149,14 @@
return sess.marshal()
+ def redirect_on_not_authorized(self, session):
+ mainpage = self.app.mainpage_cb(session)
+ if mainpage in self.app.pages_by_name:
+ log.debug("Not authorized, redirecting to %s", mainpage)
+ page = self.app.pages_by_name[mainpage]
+ sess = Session(page)
+ self.redirect.set(session, sess.marshal())
+
def do_process(self, session):
self.update_script.process(session)
self.defer_script.process(session)
Modified: trunk/wooly/python/wooly/table.py
===================================================================
--- trunk/wooly/python/wooly/table.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/wooly/python/wooly/table.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -70,6 +70,7 @@
writer = Writer()
for column in self.get_visible_columns(session):
+
writer.write(column.render(session))
return writer.to_string()
@@ -272,7 +273,8 @@
writer = Writer()
for column in self.table.get_visible_columns(session):
- writer.write(column.header.render(session))
+ if self.app.authorize_cb(session, column):
+ writer.write(column.header.render(session))
return writer.to_string()
@@ -285,7 +287,8 @@
writer = Writer()
for column in self.table.get_visible_columns(session):
- writer.write(column.cell.render(session, record))
+ if self.app.authorize_cb(session, column):
+ writer.write(column.cell.render(session, record))
return writer.to_string()
Modified: trunk/wooly/python/wooly/widgets.py
===================================================================
--- trunk/wooly/python/wooly/widgets.py 2012-04-11 18:09:44 UTC (rev 5294)
+++ trunk/wooly/python/wooly/widgets.py 2012-04-11 19:36:57 UTC (rev 5295)
@@ -58,7 +58,8 @@
writer = Writer()
for tab in self.__tabs:
- self.__tab_tmpl.render(writer, session, tab)
+ if self.app.authorize_cb(session, tab):
+ self.__tab_tmpl.render(writer, session, tab)
return writer.to_string()
12 years, 1 month
r5294 - branches/play_plumage/mint/python/mint/plumage
by croberts@fedoraproject.org
Author: croberts
Date: 2012-04-11 18:09:44 +0000 (Wed, 11 Apr 2012)
New Revision: 5294
Modified:
branches/play_plumage/mint/python/mint/plumage/session.py
Log:
Fixing-up the dummy data for cumin-report to match the upated plumage schema.
Modified: branches/play_plumage/mint/python/mint/plumage/session.py
===================================================================
--- branches/play_plumage/mint/python/mint/plumage/session.py 2012-04-11 18:07:49 UTC (rev 5293)
+++ branches/play_plumage/mint/python/mint/plumage/session.py 2012-04-11 18:09:44 UTC (rev 5294)
@@ -94,11 +94,32 @@
# some number of available used
os.used = randrange(0, os.avail+1)
+
+ machines = ["croberts.redhat.com", "tmckay.redhat.com", "shadowman.redhat.com"]
+ os.machine = machines[randrange(0,3)]
+ os.slot = "%d@%s" % (randrange(1, 16), os.machine)
+
+ architectures = ["X86_64", "X86", "Itanium"]
+ os.architecture = architectures[randrange(0,3)]
+
+ oses = ["LINUX", "WINDOWS", "MAC"]
+ os.os = oses[randrange(0,3)]
+
+ os.kbidle = randrange(0, 100)
+
+ os.lastactive = randrange(0, 100)
+
+ states = ["Claimed", "Available", "Unavailable"]
+ os.state = states[randrange(0,3)]
+
+ os.cpu = randrange(0,65)
+
+ os.mem = randrange(0, 100000)
obj = ObjectUpdate(self.app.model, os, self.cls)
self.app.update_thread.enqueue(obj)
- sleep(1)
+ sleep(30)
# five machines
uuid = (uuid + 1) % 6
12 years, 1 month
r5293 - in branches/roles_II/cumin: bin etc model/access python/cumin
by tmckay@fedoraproject.org
Author: tmckay
Date: 2012-04-11 18:07:49 +0000 (Wed, 11 Apr 2012)
New Revision: 5293
Removed:
branches/roles_II/cumin/model/access/usergrid.xml
Modified:
branches/roles_II/cumin/bin/cumin-admin
branches/roles_II/cumin/bin/cumin-web
branches/roles_II/cumin/etc/cumin.conf
branches/roles_II/cumin/python/cumin/config.py
branches/roles_II/cumin/python/cumin/main.py
branches/roles_II/cumin/python/cumin/persona.py
branches/roles_II/cumin/python/cumin/widgets.py
Log:
Finish up intial version of role enforcement.
* Change 'authorize' cumin.conf parameter to boolean and default to False.
This flag will leave role enforcement off out of the box. The path to
the xml file describing persona and roles will be hardwired for now.
* Turn off unused config parameters
* Disable cumin-admin add-role. For now we will have only user/admin.
* Prefer the admin group when looking for the main page if a user is
a member of multiple groups.
* Give cumin-admin a short init routine to call so that it doesn't need
to initialize all of the Cumin() object. Avoids issues.
Modified: branches/roles_II/cumin/bin/cumin-admin
===================================================================
--- branches/roles_II/cumin/bin/cumin-admin 2012-04-11 15:37:22 UTC (rev 5292)
+++ branches/roles_II/cumin/bin/cumin-admin 2012-04-11 18:07:49 UTC (rev 5293)
@@ -77,7 +77,7 @@
# cumin-admin is the mechanism for fixing the schema so we
# have to avoid the check here!
try:
- app.init(schema_version_check=False)
+ app.db_init(schema_version_check=False)
except OperationalError:
print "Can't talk to the database"
error("Run 'cumin-database check' as root for more information")
@@ -125,7 +125,6 @@
lines.append("User commands:")
lines.append("")
lines.append(" add-user USER [PASSWORD] Add USER")
- lines.append(" add-role ROLE Add ROLE")
lines.append(" external-user USER Add USER with external authentication")
lines.append(" external-sync AUTH [VERBOSE] Batch import users with external authentication")
lines.append(" AUTH is the name of a mechanism like 'ldap' or 'script'")
@@ -404,6 +403,10 @@
def handle_add_role(app, cursor, opts, args):
+ print("\nNot implemented.")
+ return
+
+ # We may allow this later
try:
name = args[0]
except IndexError:
Modified: branches/roles_II/cumin/bin/cumin-web
===================================================================
--- branches/roles_II/cumin/bin/cumin-web 2012-04-11 15:37:22 UTC (rev 5292)
+++ branches/roles_II/cumin/bin/cumin-web 2012-04-11 18:07:49 UTC (rev 5293)
@@ -43,16 +43,21 @@
cumin.wallaby_refresh = None
def set_authorize_config(cumin, values, access_root):
+
+ # Allow this to be turned on/off.
+ # Default will be off.
+ cumin.do_authorize = values.authorize
+
# Allow this to be disabled via "None"
- if values.authorize == "None":
+ if values.auth_path == "None":
cumin.access_path = None
else:
# If there is no initial dir, prepend home
- dir_name = os.path.split(values.authorize)[0]
+ dir_name = os.path.split(values.auth_path)[0]
if len(dir_name) == 0:
- cumin.access_path = os.path.join(access_root, values.authorize)
+ cumin.access_path = os.path.join(access_root, values.auth_path)
else:
- cumin.access_path = values.authorize
+ cumin.access_path = values.auth_path
def adjust_return(passed_init, ret):
# Shift non-zer0 return codes left 1 bit
@@ -150,10 +155,15 @@
set_aviary_configs(cumin, values)
set_wallaby_configs(cumin, values, broker_uris)
- cumin.auth_create_ondemand = values.auth_create_ondemand
- cumin.auth_proxy = values.auth_proxy
+ # Not used right now
+ #cumin.auth_create_ondemand = values.auth_create_ondemand
+ #cumin.auth_proxy = values.auth_proxy
+
+ # Someday we may let this be configurable, for now it will
+ # be hardwired
+ values.auth_path = "persona.xml"
set_authorize_config(cumin, values, config.get_access_root())
-
+
cumin.debug = opts.debug
cumin.user = values.user
cumin.update_interval = values.update_interval
Modified: branches/roles_II/cumin/etc/cumin.conf
===================================================================
--- branches/roles_II/cumin/etc/cumin.conf 2012-04-11 15:37:22 UTC (rev 5292)
+++ branches/roles_II/cumin/etc/cumin.conf 2012-04-11 18:07:49 UTC (rev 5293)
@@ -96,6 +96,7 @@
# update-interval: 10
# max-qmf-table-sort: 1000
# persona: grid
+# authorize: False
#notification-timeout: 180
# Number of seconds that a message in the yellow notification banner
@@ -248,6 +249,13 @@
## The "default" persona contains content for both grid and
## messaging.
+## authorize: False
+## Controls whether or not roles are enforced.
+## Roles are assigned to users with cumin-admin.
+## If roles are enforced, users with only the 'user'
+## role will not see the 'Administrator' tab.
+## The default role for a new user is 'user'.
+
## [data]
## expire-enabled: True
Deleted: branches/roles_II/cumin/model/access/usergrid.xml
===================================================================
--- branches/roles_II/cumin/model/access/usergrid.xml 2012-04-11 15:37:22 UTC (rev 5292)
+++ branches/roles_II/cumin/model/access/usergrid.xml 2012-04-11 18:07:49 UTC (rev 5293)
@@ -1,39 +0,0 @@
-<AccessMap>
- <GroupAccess name="nogroup">
- <WidgetAccess reg="cumin.account.widgets.LoginForm"/>
- <WidgetAccess reg="cumin.account.widgets.LoginPage"/>
- <WidgetAccess reg="cumin.account.widgets.Submit"/>
- <FallbackPage name="login.html"/>
- </GroupAccess>
- <GroupAccess name="user">
- <SubGroupAccess name="nogroup"/>
- <WidgetAccess reg="cumin.usergrid.*" />
- <WidgetAccess reg="cumin.account.*" />
- <WidgetAccess reg="cumin.task.*" />
- <WidgetAccess reg="cumin.widgets.CuminPageLinks"/>
- <WidgetAccess reg="cumin.widgets.CuminHeartBeat"/>
- <WidgetAccess reg="cumin.objectselector.*"/>
- <WidgetAccess reg="cumin.widgets.About*" />
- <WidgetAccess reg="cumin.widgets.CuminFormPage" />
- <WidgetAccess reg="cumin.grid.submission.*" />
- <WidgetAccess reg="cumin.objectframe.*" />
- <WidgetAccess reg="cumin.widgets.Notification*" />
- <WidgetAccess reg="cumin.grid.job.*" />
- <FallbackPage name="usergrid.html"/>
- </GroupAccess>
- <GroupAccess name="admin">
- <WidgetAccess reg=".*"/>
- </GroupAccess>
- <GroupAccess name="genericadmin">
- <SubGroupAccess name="user"/>
- <WidgetAccess reg="cumin.main.Main*"/>
- <WidgetAccess reg="cumin.main.Overview*"/>
- <WidgetAccess reg="cumin.main.Top*"/>
- <WidgetAccess reg="cumin.widgets.Top*"/>
- </GroupAccess>
- <GroupAccess name="messagingadmin">
- <SubGroupAccess name="user"/>
- <WidgetAccess reg="cumin.main.Main*"/>
- <WidgetAccess reg="cumin.main.MessagingView"/>
- </GroupAccess>
-</AccessMap>
Modified: branches/roles_II/cumin/python/cumin/config.py
===================================================================
--- branches/roles_II/cumin/python/cumin/config.py 2012-04-11 15:37:22 UTC (rev 5292)
+++ branches/roles_II/cumin/python/cumin/config.py 2012-04-11 18:07:49 UTC (rev 5293)
@@ -64,15 +64,19 @@
param = ConfigParameter(web, "force-html-doctype", bool)
param.default = False
- param = ConfigParameter(web, "authorize", str)
- param.default = os.path.join(self.get_access_root(), "usergrid.xml")
+ # Turn this into a boolean, default is off for introduction.
+ # Hardwire the path to persona.xml unless/until we allow overriding
+ param = ConfigParameter(web, "authorize", bool)
+ param.default = False
- param = ConfigParameter(web, "authz-provider", str)
- param.default = "internal"
+ # Turn these off for now...
- param = ConfigParameter(web, "auth-create-ondemand", bool)
- param.default = False
+# param = ConfigParameter(web, "authz-provider", str)
+# param.default = "internal"
+# param = ConfigParameter(web, "auth-create-ondemand", bool)
+# param.default = False
+
param = ConfigParameter(web, "auth-proxy", bool)
param.default = False
Modified: branches/roles_II/cumin/python/cumin/main.py
===================================================================
--- branches/roles_II/cumin/python/cumin/main.py 2012-04-11 15:37:22 UTC (rev 5292)
+++ branches/roles_II/cumin/python/cumin/main.py 2012-04-11 18:07:49 UTC (rev 5293)
@@ -62,7 +62,12 @@
# This is an argument to CuminAuthorizator in init()
self.access_path = None
+ self.do_authorize = False
+ # Currently turned off in config, but maybe used in the future
+ self.auth_proxy = None
+ self.auth_create_ondemand = None
+
self.tasks = list()
self.user = None
@@ -156,13 +161,17 @@
except:
pass
+ def db_init(self, schema_version_check=True):
+ self.model.init()
+ self.database.init(schema_version_check)
+
def init(self, schema_version_check=True):
log.info("Initializing %s", self)
# Do this initialization as late as possible so that
# the application can set a value for self.access_path.
# Alternatively, it can be an argument to the constructor.
- self.authorizator = CuminAuthorizator(self, self.access_path)
+ self.authorizator = CuminAuthorizator(self, self.access_path, self.do_authorize)
try:
self.authorizator.set_persona(self.persona)
except:
@@ -225,11 +234,6 @@
self.database.init(schema_version_check)
self.server.init()
-
-# Find a way to mark the pages, so that index.html is not
-# seeable by user in grid or default mode,
-# and so that usergrid is not visible in messaging mode.
-
# This will set up the main view and enable the
# modules that are associated with the persona
self._init_persona(self.authorizator.get_enabled_modules())
Modified: branches/roles_II/cumin/python/cumin/persona.py
===================================================================
--- branches/roles_II/cumin/python/cumin/persona.py 2012-04-11 15:37:22 UTC (rev 5292)
+++ branches/roles_II/cumin/python/cumin/persona.py 2012-04-11 18:07:49 UTC (rev 5293)
@@ -72,12 +72,13 @@
group.allowed.append(gchild.attrib["name"])
class CuminAuthorizator(object):
- def __init__(self, app, access_path):
+ def __init__(self, app, access_path, do_authorize):
self.app = app
self.access_path = access_path
log.info("Initializing %s", self)
self.personas = CuminPersonaMap()
self.persona = None
+ self.do_authorize = do_authorize
log.debug("Access file path is %s", access_path)
if os.path.isdir(access_path):
@@ -101,19 +102,23 @@
self.persona = self.personas.personas[name]
def is_enforcing(self):
- return self.persona.auth
+ return self.do_authorize and self.persona.auth
def find_mainpage(self, web_session):
# Find a main page for the current login session.
- # If the user is part of multiple groups, just pick the
- # first one. There may be a way to make a priority scheme here,
- # but does it really matter?
+ # If user is in the admin group, prefer that one.
+ # If we have multiple groups someday beyond user/admin,
+ # we may have to have a priority scheme here (or find
+ # a way to NOT have more than one mainpage).
try:
group = web_session.client_session.attributes['login_session'].group
except KeyError:
group = "nogroup"
if type(group) == type([]):
- group = group[0]
+ if "admin" in group:
+ group = "admin"
+ else:
+ group = group[0]
return self.persona.find_mainpage(group)
def get_enabled_modules(self):
Modified: branches/roles_II/cumin/python/cumin/widgets.py
===================================================================
--- branches/roles_II/cumin/python/cumin/widgets.py 2012-04-11 15:37:22 UTC (rev 5292)
+++ branches/roles_II/cumin/python/cumin/widgets.py 2012-04-11 18:07:49 UTC (rev 5293)
@@ -1323,7 +1323,7 @@
log.debug("Proxy auth enabled but no remote user set")
pass
- if username:
+ if username:
cls = self.app.model.com_redhat_cumin.User
users = cls.get_selection(session.cursor, name=username)
if not users:
@@ -1370,8 +1370,8 @@
if cls is RosemaryNotFound and \
session.request_environment["REQUEST_URI"] != mainpage:
-
- session.add_notice(Notice("An object being displayed became unavailable"))
+ session.add_notice(Notice(
+ "An object being displayed became unavailable"))
return mainpage
def render_error(self, session):
12 years, 1 month
r5292 - branches/play_plumage/cumin/model/plumage
by croberts@fedoraproject.org
Author: croberts
Date: 2012-04-11 15:37:22 +0000 (Wed, 11 Apr 2012)
New Revision: 5292
Modified:
branches/play_plumage/cumin/model/plumage/plumage.xml
branches/play_plumage/cumin/model/plumage/rosemary.xml
Log:
Slightly enhanced plumage.xml and rosemary.xml to get closer to the real data model.
Modified: branches/play_plumage/cumin/model/plumage/plumage.xml
===================================================================
--- branches/play_plumage/cumin/model/plumage/plumage.xml 2012-04-11 14:56:35 UTC (rev 5291)
+++ branches/play_plumage/cumin/model/plumage/plumage.xml 2012-04-11 15:37:22 UTC (rev 5292)
@@ -6,9 +6,19 @@
<property name="osName"
type="sstr" access="RO" desc="Operating System Name" />
-
- <statistic name="avail" type="uint32" unit="uint32" />
- <statistic name="used" type="uint32" unit="uint32" />
- <statistic name="update_time" type="absTime" unit="uint32" />
+
+ <statistic name="update_time" type="absTime" unit="uint32" />
+ <statistic name="machine" type="sstr" optional="y" default=""/>
+ <statistic name="slot" type="sstr" optional="y" default="" />
+ <statistic name="architecture" type="sstr" optional="y" default=""/>
+ <statistic name="os" type="sstr" optional="y" default=""/>
+ <statistic name="kbidle" type="uint32" uint="uint32" optional="y" default="0"/>
+ <statistic name="lastactive" type="uint32" uint="uint32" optional="y" default="0"/>
+ <statistic name="state" type="sstr" optional="y" default=""/>
+ <statistic name="cpu" type="uint32" uint="uint32" optional="y" default="0" />
+ <statistic name="mem" type="uint32" uint="uint32" optional="y" default="0"/>
+ <statistic name="avail" type="uint32" unit="uint32" optional="y" default="0"/>
+ <statistic name="used" type="uint32" unit="uint32" optional="y" default="0"/>
+
</class>
</schema>
Modified: branches/play_plumage/cumin/model/plumage/rosemary.xml
===================================================================
--- branches/play_plumage/cumin/model/plumage/rosemary.xml 2012-04-11 14:56:35 UTC (rev 5291)
+++ branches/play_plumage/cumin/model/plumage/rosemary.xml 2012-04-11 15:37:22 UTC (rev 5292)
@@ -2,9 +2,9 @@
<package name="com.redhat.grid.plumage" persistent="time">
<class name="OSUtil">
<source>some stuff goes here about a query</source>
- <property name="osName">
- <title>OS</title>
- </property>
+
+ <statistic name="update_time" timestamp="y">
+ </statistic>
<statistic name="used">
<title>Used</title>
@@ -13,10 +13,43 @@
<statistic name="avail">
<title>Available</title>
</statistic>
+
+ <statistic name="machine">
+ <title>Machine</title>
+ </statistic>
+
+ <statistic name="slot">
+ <title>Slot</title>
+ </statistic>
+
+ <statistic name="architecture">
+ <title>Architecture</title>
+ </statistic>
+
+ <statistic name="os">
+ <title>OS</title>
+ </statistic>
+
+ <statistic name="kbidle">
+ <title>KB idle</title>
+ </statistic>
+
+ <statistic name="lastactive">
+ <title>Last active</title>
+ </statistic>
+
+ <statistic name="state">
+ <title>State</title>
+ </statistic>
+
+ <statistic name="cpu">
+ <title>CPU</title>
+ </statistic>
+
+ <statistic name="mem">
+ <title>Memory</title>
+ </statistic>
- <statistic name="update_time" timestamp="y">
- </statistic>
-
</class>
</package>
12 years, 1 month
r5291 - branches/play_plumage/rosemary/python/rosemary
by croberts@fedoraproject.org
Author: croberts
Date: 2012-04-11 14:56:35 +0000 (Wed, 11 Apr 2012)
New Revision: 5291
Modified:
branches/play_plumage/rosemary/python/rosemary/model.py
Log:
Added get_sample_filters_by_signature to the base RosemaryClass. It just returns an empty list and should probably be overridden by derived classes.
Modified: branches/play_plumage/rosemary/python/rosemary/model.py
===================================================================
--- branches/play_plumage/rosemary/python/rosemary/model.py 2012-04-11 14:17:47 UTC (rev 5290)
+++ branches/play_plumage/rosemary/python/rosemary/model.py 2012-04-11 14:56:35 UTC (rev 5291)
@@ -606,6 +606,10 @@
columns = self.sql_table._columns
self.sql_samples_insert.execute(cursor, obj.__dict__, columns=columns)
+
+ def get_sample_filters_by_signature(self, sig):
+ # by default, there are no sample_filters, if you need them, please override this
+ return []
def delete_object(self, cursor, obj):
assert isinstance(obj, RosemaryObject)
@@ -817,7 +821,7 @@
if not values:
raise RosemaryNotFound()
self._set_object_attributes(obj, self.sql_table._columns, values)
-
+
class RosemaryAttribute(object):
def __init__(self, cls, name):
self.cls = cls
12 years, 1 month