From 28e240eb7def09d695bff401226193faffbbd59a Mon Sep 17 00:00:00 2001 From: Stephen Soltesz <soltesz@cs.princeton.edu> Date: Thu, 25 Jun 2009 23:01:59 +0000 Subject: [PATCH] added references to google gadgets added sitesummary and summary controls for gadgets clarified sitehistory, and other history views simplified controllers.py in many places, trying to make node() faster. --- web/MonitorWeb/monitorweb/controllers.py | 74 +++++++++++++++++-- .../monitorweb/static/css/style.css | 5 +- .../monitorweb/static/xml/gadget.xml | 4 +- .../monitorweb/static/xml/sitemonitor.xml | 4 +- web/MonitorWeb/monitorweb/templates/links.py | 2 + .../monitorweb/templates/nodehistory.kid | 29 +------- .../monitorweb/templates/pcuhistory.kid | 31 ++------ .../monitorweb/templates/sitehistory.kid | 9 ++- .../monitorweb/templates/sitesummary.kid | 41 ++++++++++ .../monitorweb/templates/summary.kid | 38 ++++++++++ .../monitorweb/templates/welcome.kid | 11 ++- 11 files changed, 179 insertions(+), 69 deletions(-) create mode 100644 web/MonitorWeb/monitorweb/templates/sitesummary.kid create mode 100644 web/MonitorWeb/monitorweb/templates/summary.kid diff --git a/web/MonitorWeb/monitorweb/controllers.py b/web/MonitorWeb/monitorweb/controllers.py index a1746c8..60bdbcc 100644 --- a/web/MonitorWeb/monitorweb/controllers.py +++ b/web/MonitorWeb/monitorweb/controllers.py @@ -108,12 +108,16 @@ def prep_pcu_for_display(pcu): class NodeWidget(widgets.Widget): pass -def prep_node_for_display(node): +def prep_node_for_display(node, pcuhash=None): agg = aggregate() agg.node = node if node.plc_pcuid: - pcu = FindbadPCURecord.get_latest_by(plc_pcuid=node.plc_pcuid) + if pcuhash: + pcu = pcuhash[node.plc_pcuid] + else: + pcu = FindbadPCURecord.get_latest_by(plc_pcuid=node.plc_pcuid) + if pcu: agg.pcu_status = pcu.reboot_trial_status agg.pcu_short_status = format_pcu_shortstatus(pcu) @@ -167,6 +171,31 @@ class Root(controllers.RootController, MonitorXmlrpcServer): flash("Welcome To MyOps!") return dict(now=time.ctime()) + @expose(template="monitorweb.templates.nodelist") + def node2(self, filter='boot'): + + fbquery = FindbadNodeRecord.get_all_latest() + fbpcus = FindbadPCURecord.get_all_latest() + def fbtohash(fbpculist): + h = {} + for p in fbpculist: + h[p.plc_pcuid] = p + + pcuhash = fbtohash(fbpcus) + + query = [] + for node in fbquery: + # NOTE: reformat some fields. + agg = prep_node_for_display(node, pcuhash) + + if not agg.history: + continue + + query.append(agg) + + widget = NodeWidget(template='monitorweb.templates.node_template') + return dict(now=time.ctime(), query=query, nodewidget=widget) + @expose(template="monitorweb.templates.nodelist") def node(self, filter='boot'): print "NODE------------------" @@ -181,9 +210,6 @@ class Root(controllers.RootController, MonitorXmlrpcServer): # NOTE: reformat some fields. agg = prep_node_for_display(node) - #node.history.status - #print node.hostname - if not agg.history: continue @@ -197,9 +223,6 @@ class Root(controllers.RootController, MonitorXmlrpcServer): elif agg.history.status in ['debug', 'monitordebug']: filtercount['debug'] += 1 else: - # TODO: need a better fix. filtercount - # doesn't maps to GetBootStates() on - # 4.3 so this one fails quite often. if filtercount.has_key(agg.history.status): filtercount[agg.history.status] += 1 @@ -462,6 +485,41 @@ class Root(controllers.RootController, MonitorXmlrpcServer): query.append(site) return dict(query=query, fc=filtercount) + @expose(template="monitorweb.templates.sitesummary") + def sitesummary(self, loginbase="princeton"): + nodequery = [] + for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase): + agg = prep_node_for_display(node) + nodequery += [agg] + + return dict(nodequery=nodequery, loginbase=loginbase) + + @expose(template="monitorweb.templates.summary") + def summary(self, since=7): + sumdata = {} + sumdata['nodes'] = {} + sumdata['sites'] = {} + sumdata['pcus'] = {} + + def summarize(query, type): + for o in query: + if o.status not in sumdata[type]: + sumdata[type][o.status] = 0 + sumdata[type][o.status] += 1 + + fbquery = HistorySiteRecord.query.all() + summarize(fbquery, 'sites') + fbquery = HistoryPCURecord.query.all() + summarize(fbquery, 'pcus') + fbquery = HistoryNodeRecord.query.all() + summarize(fbquery, 'nodes') + + if 'monitordebug' in sumdata['nodes']: + d = sumdata['nodes']['monitordebug'] + del sumdata['nodes']['monitordebug'] + sumdata['nodes']['failboot'] = d + + return dict(sumdata=sumdata, setorder=['good', 'offline', 'down', 'online']) @expose(template="monitorweb.templates.actionsummary") def actionsummary(self, since=7): diff --git a/web/MonitorWeb/monitorweb/static/css/style.css b/web/MonitorWeb/monitorweb/static/css/style.css index d3a365c..ac85b33 100644 --- a/web/MonitorWeb/monitorweb/static/css/style.css +++ b/web/MonitorWeb/monitorweb/static/css/style.css @@ -108,6 +108,9 @@ a.right { float: right; } #site-offline { background-color: red; } #site-down { background-color: indianred; } +#site-True { background-color : darkseagreen; } +#site-False { background-color: indianred; } + #node-online { background-color : lightgreen; } #node-good { background-color : darkseagreen; } #node-offline { background-color: red; } @@ -118,7 +121,7 @@ a.right { float: right; } #pcu-offline { background-color: red; } #pcu-down { background-color: indianred; } -/*#site-0 { background-color : white; }*/ +#site-0 { background-color : darkseagreen ; } #site-1 { background-color: gold; } #site-2 { background-color: indianred; } diff --git a/web/MonitorWeb/monitorweb/static/xml/gadget.xml b/web/MonitorWeb/monitorweb/static/xml/gadget.xml index 8a3c79a..bae4356 100644 --- a/web/MonitorWeb/monitorweb/static/xml/gadget.xml +++ b/web/MonitorWeb/monitorweb/static/xml/gadget.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Module> -<ModulePrefs title="Monitor Node Count" title_url="http://www.planet-lab.org"> +<ModulePrefs title="MyOps Summary" title_url="http://www.planet-lab.org"> <Require feature="dynamic-height"/> </ModulePrefs> <Content type="html"><![CDATA[ @@ -10,7 +10,7 @@ var displaycontent = function (responseText) { _gel('content_div').innerHTML = responseText; _IG_AdjustIFrameHeight(); }; -_IG_FetchContent('http://monitor.planet-lab.org/monitor/actionsummary', displaycontent, { refreshInterval: 300 }); +_IG_FetchContent('http://monitor.planet-lab.org/monitor/summary', displaycontent, { refreshInterval: 300 }); </script> ]]></Content> </Module> diff --git a/web/MonitorWeb/monitorweb/static/xml/sitemonitor.xml b/web/MonitorWeb/monitorweb/static/xml/sitemonitor.xml index 0bb0b02..2b2c4ad 100644 --- a/web/MonitorWeb/monitorweb/static/xml/sitemonitor.xml +++ b/web/MonitorWeb/monitorweb/static/xml/sitemonitor.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Module> - <ModulePrefs title="PlanetLab Site Status" title_url="http://www.planet-lab.org"> + <ModulePrefs title="MyOps Site Status" title_url="http://www.planet-lab.org"> <Require feature="dynamic-height"/> </ModulePrefs> <UserPref name="loginBase" display_name="Site Login Base" @@ -13,7 +13,7 @@ var displaycontent = function (responseText) { _gel('content_div').innerHTML = responseText; _IG_AdjustIFrameHeight(); }; -var url = 'http://monitor.planet-lab.org/monitor/actionlist?loginbase=' + prefs.getString("loginBase"); +var url = 'http://monitor.planet-lab.org/monitor/sitesummary?loginbase=' + prefs.getString("loginBase"); _IG_FetchContent(url, displaycontent, { refreshInterval: 1200 }); </script> ]]></Content> diff --git a/web/MonitorWeb/monitorweb/templates/links.py b/web/MonitorWeb/monitorweb/templates/links.py index 95f192e..1a951bd 100644 --- a/web/MonitorWeb/monitorweb/templates/links.py +++ b/web/MonitorWeb/monitorweb/templates/links.py @@ -2,6 +2,8 @@ from monitor import config import turbogears as tg import urllib +def plc_myops_uri(): + return "http://" + config.MONITOR_HOSTNAME def plc_mail_uri(ticketid): return config.RT_WEB_SERVER + "/Ticket/Display.html?id=" + str(ticketid) def plc_node_uri(hostname): diff --git a/web/MonitorWeb/monitorweb/templates/nodehistory.kid b/web/MonitorWeb/monitorweb/templates/nodehistory.kid index de60dd9..e63d957 100644 --- a/web/MonitorWeb/monitorweb/templates/nodehistory.kid +++ b/web/MonitorWeb/monitorweb/templates/nodehistory.kid @@ -18,37 +18,16 @@ from links import * <table id="sortable_table" class="datagrid" border="1" width="100%"> <thead> <tr> - <th mochi:format="int"></th> - <!--th>Site</th> - <th>pcu</th--> - <th>date</th> + <th>Last Check</th> + <th>Last Change</th> <th>hostname</th> - <th>last_contact</th> + <th>Status</th> </tr> </thead> <tbody> <tr py:for="i,node in enumerate(query)" class="${i%2 and 'odd' or 'even'}" > - <td></td> - <!--td id="site-${node.site.status}"> - <a href="${link('pcuview', loginbase=node.loginbase)}">${node.loginbase}</a> - </td> - <td width="20%" nowrap='true' align='center' id="status-${node.pcu_short_status}"> - <div id="links"> - <a class="info" py:if="'error' in node.pcu_short_status" - href="${link('pcuview', pcuid=node.plc_pcuid)}"> - Error<span><pre>${node.pcu.reboot_trial_status}</pre></span></a> - <a py:if="'error' not in node.pcu_short_status and 'none' not in node.pcu_short_status" - href="${link('pcuview', pcuid=node.plc_pcuid)}" - py:content="node.pcu_short_status">Reboot Status</a> - <span py:if="'none' in node.pcu_short_status" - py:content="node.pcu_short_status">Reboot Status</span> - </div> - </td--> - <!--td id="node-${node.observed_status}" nowrap="true"> - <a target="_top" href="${link('pcuview', hostname=node.hostname)}" py:content="node.hostname">your.host.org</a></td--> - <!--td nowrap="true" py:content="node.kernel"></td--> - <!--td py:content="node.date_checked"></td--> <td py:content="node.last_checked"></td> + <td py:content="diff_time(mktime(node.last_changed.timetuple()))"></td> <td nowrap="true"> <a target="_top" href="${link('pcuview', hostname=node.hostname)}" py:content="node.hostname">your.host.org</a></td> <td id="node-${node.status}" py:content="node.status"></td> diff --git a/web/MonitorWeb/monitorweb/templates/pcuhistory.kid b/web/MonitorWeb/monitorweb/templates/pcuhistory.kid index 79fd07b..d809609 100644 --- a/web/MonitorWeb/monitorweb/templates/pcuhistory.kid +++ b/web/MonitorWeb/monitorweb/templates/pcuhistory.kid @@ -10,7 +10,7 @@ from links import * xmlns:mochi="http://www.mochi.org"> <div py:match="item.tag == 'content'"> - <h3>Node History : ${pcu_id}</h3> + <h3>PCU History for pcu_id : <a href="${plc_pcu_uri_id(pcu_id)}">${pcu_id}</a></h3> <table width="100%"> <tbody> <tr> @@ -18,37 +18,16 @@ from links import * <table id="sortable_table" class="datagrid" border="1" width="100%"> <thead> <tr> - <th mochi:format="int"></th> - <!--th>Site</th> - <th>pcu</th--> - <th>date</th> + <th>Last Check</th> + <th>Last Change</th> <th>pcu_id</th> - <th>last_contact</th> + <th>Status</th> </tr> </thead> <tbody> <tr py:for="i,pcu in enumerate(query)" class="${i%2 and 'odd' or 'even'}" > - <td></td> - <!--td id="site-${node.site.status}"> - <a href="${link('pcuview', loginbase=node.loginbase)}">${node.loginbase}</a> - </td> - <td width="20%" nowrap='true' align='center' id="status-${node.pcu_short_status}"> - <div id="links"> - <a class="info" py:if="'error' in node.pcu_short_status" - href="${link('pcuview', pcuid=node.plc_pcuid)}"> - Error<span><pre>${node.pcu.reboot_trial_status}</pre></span></a> - <a py:if="'error' not in node.pcu_short_status and 'none' not in node.pcu_short_status" - href="${link('pcuview', pcuid=node.plc_pcuid)}" - py:content="node.pcu_short_status">Reboot Status</a> - <span py:if="'none' in node.pcu_short_status" - py:content="node.pcu_short_status">Reboot Status</span> - </div> - </td--> - <!--td id="node-${node.observed_status}" nowrap="true"> - <a target="_top" href="${link('pcuview', hostname=node.hostname)}" py:content="node.hostname">your.host.org</a></td--> - <!--td nowrap="true" py:content="node.kernel"></td--> - <!--td py:content="node.date_checked"></td--> <td py:content="pcu.last_checked"></td> + <td py:content="diff_time(mktime(pcu.last_changed.timetuple()))"></td> <td nowrap="true"> <a target="_top" href="${link('pcuview', pcuid=pcu.plc_pcuid)}" py:content="pcu.plc_pcuid">your.host.org</a></td> <td id="pcu-${pcu.status}" py:content="pcu.status"></td> diff --git a/web/MonitorWeb/monitorweb/templates/sitehistory.kid b/web/MonitorWeb/monitorweb/templates/sitehistory.kid index 8dfb823..6040d83 100644 --- a/web/MonitorWeb/monitorweb/templates/sitehistory.kid +++ b/web/MonitorWeb/monitorweb/templates/sitehistory.kid @@ -20,9 +20,10 @@ from links import * <tr> <th mochi:format="int"></th> <th>Site name</th> + <th mochi:format="int">Slices/Max</th> <th>Enabled</th> <th>Penalty</th> - <th mochi:format="int">Slices/Max</th> + <th>Last Change</th> <th mochi:format="int">Nodes/Total</th> <th>Date Checked</th> </tr> @@ -37,11 +38,11 @@ from links import * <img style='display: inline' border='0' src="static/images/extlink.gif" align='right'/></a> </div> </td> - <td py:content="site.enabled"></td> - <td id="site-${site.penalty_level}">${site.penalty_level}</td> <td>${site.slices_used}/${site.slices_total}</td> - <td>${site.nodes_up} / ${site.nodes_total}</td> + <td id="site-${site.enabled}" py:content="site.enabled"></td> + <td id="site-${site.penalty_level}">${site.penalty_level}</td> <td id="site-${site.status}" py:content="diff_time(mktime(site.last_changed.timetuple()))"></td> + <td id="site-${site.nodes_up >= 2}">${site.nodes_up} / ${site.nodes_total}</td> <td py:content="site.timestamp"></td> </tr> </tbody> diff --git a/web/MonitorWeb/monitorweb/templates/sitesummary.kid b/web/MonitorWeb/monitorweb/templates/sitesummary.kid new file mode 100644 index 0000000..37e0541 --- /dev/null +++ b/web/MonitorWeb/monitorweb/templates/sitesummary.kid @@ -0,0 +1,41 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<?python +layout_params['page_title'] = "MyOps Detail View" +from monitor.util import diff_time +from monitor import config +from time import mktime +from pcucontrol.reboot import pcu_name, model_to_object +from links import * +?> +<html xmlns:py="http://purl.org/kid/ns#" + xmlns:mochi="http://www.mochi.org"> + <head> + <link href="http://monitor.planet-lab.org/monitor/static/css/style.css" type="text/css" rel="stylesheet" /> + </head> + + <h3>Nodes for site ${loginbase}</h3> + <p>Working on the color...</p> + <p py:if="len(nodequery) == 0"> + There are no registered nodes for this site. + </p> + <table py:if="len(nodequery) > 0" id="sortable_table" class="datagrid" border="1" width="100%"> + <thead> + <tr> + <th>History</th> + <th>Hostname</th> + <th>Status</th> + </tr> + </thead> + <tbody> + <tr py:for="i,agg in enumerate(nodequery)" class="${i%2 and 'odd' or 'even'}" > + <td><a target="_blank" href="nodehistory?hostname=${agg.node.hostname}">history</a></td> + <td id="node-${agg.node.observed_status}" nowrap="true" > + <a class="ext-link" target="_blank" href="${plc_node_uri_id(agg.node.plc_node_stats['node_id'])}"> + <span class="icon">${agg.node.hostname}</span></a> + </td> + <td py:content="agg.node.observed_status" nowrap="true" ></td> + </tr> + </tbody> + </table> + +</html> diff --git a/web/MonitorWeb/monitorweb/templates/summary.kid b/web/MonitorWeb/monitorweb/templates/summary.kid new file mode 100644 index 0000000..27b888c --- /dev/null +++ b/web/MonitorWeb/monitorweb/templates/summary.kid @@ -0,0 +1,38 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<?python +layout_params['page_title'] = "MyOps Summary" +from monitor.util import diff_time +from monitor import config +from time import mktime +from links import * +?> +<html + xmlns:py="http://purl.org/kid/ns#" + xmlns:mochi="http://www.mochi.org"> + + <?python orig=True ?> + <table> + <tbody> + <span py:for="primarykey in ['sites', 'nodes', 'pcus']"> + <tr> + <td width="50" rowspan="2">${primarykey.capitalize()}</td> + <span py:for="i,key in enumerate(setorder + [s for s in set(sumdata[primarykey].keys())-set(setorder)]) "> + <th valign="top" py:if="orig and i<4" py:content="key.capitalize()"></th> + <th valign="top" py:if="orig and i>3" py:content="key.capitalize()"></th> + <th valign="top" py:if="not orig and i>3" py:content="key.capitalize()"></th> + <th valign="top" py:if="not orig and i<4" py:content=""></th> + </span> + </tr> + <?python orig=False ?> + <tr> + <span py:for="key in setorder + [s for s in set(sumdata[primarykey].keys())-set(setorder)]"> + <td bgcolor="lightgrey" valign="top" align="center" py:content="sumdata[primarykey][key]"></td> + </span> + </tr> + </span> + </tbody> + </table> +<div py:match="item.tag == 'content'"> +</div> + +</html> diff --git a/web/MonitorWeb/monitorweb/templates/welcome.kid b/web/MonitorWeb/monitorweb/templates/welcome.kid index 43fdc21..af7b007 100644 --- a/web/MonitorWeb/monitorweb/templates/welcome.kid +++ b/web/MonitorWeb/monitorweb/templates/welcome.kid @@ -1,4 +1,7 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<?python +from links import * +?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#" py:extends="'master.kid'"> <head> @@ -32,7 +35,13 @@ <p> All nodes: <a href="node">Nodes</a> <br/> </p> </li> </ol> - <!--div class="notice"> If you create something cool, please <a href="http://groups.google.com/group/turbogears">let people know</a>, and consider contributing something back to the <a href="http://groups.google.com/group/turbogears">community</a>.</div--> + <p>If you'd like to track things a little more informally, you can install + these Google Gadgets for summaries of the entire system or a specific + site.</p> + <ul class="links"> + <li><a href="http://fusion.google.com/add?source=atgs&moduleurl=${plc_myops_uri()}/monitor/gadget.xml">MyOps Summary</a></li> + <li><a href="http://fusion.google.com/add?source=atgs&moduleurl=${plc_myops_uri()}/monitor/sitemonitor.xml">Site Summary</a></li> + </ul> </div> <!-- End of getting_started --> </body> -- 2.47.0