from monitorweb.templates.links import *
+class ObjectQueryFields(widgets.WidgetsList):
+ """The WidgetsList defines the fields of the form."""
+ pass
+
+
+
+class NodeQueryFields(widgets.WidgetsList):
+ """The WidgetsList defines the fields of the form."""
+
+ object = widgets.RadioButtonList(label="Query Type", options=[('nodes', 'All Nodes'),
+ ('nodehistory', 'Single Node History'),
+ #('sites', 'All Sites'),
+ #('sitehistory', 'Single Site History'),
+ ], default="nodes")
+ nodehistory_hostname = widgets.TextField(label="Hostname Node History", attrs={'size':30})
+
+ hostname = widgets.CheckBox(label="Hostname")
+ firewall = widgets.CheckBox(label="Firewall?")
+ dns_status = widgets.CheckBox(label="DNS Status")
+ external_dns_status = widgets.CheckBox(label="Hostname Resolves?")
+ kernel_version = widgets.CheckBox(label="Kernel")
+ observed_status = widgets.CheckBox(label="Observed Status")
+ port_status = widgets.CheckBox(label="Port Status")
+ rpms = widgets.CheckBox(label="RPM")
+ rpmvalue = widgets.TextField(label="RPM Pattern")
+
+class QueryForm(widgets.TableForm):
+ template = """
+ <form xmlns:py="http://purl.org/kid/ns#"
+ name="${name}"
+ action="${action}"
+ method="${method}"
+ class="tableform"
+ py:attrs="form_attrs"
+ >
+ <div py:for="field in hidden_fields"
+ py:replace="field.display(value_for(field), **params_for(field))"
+ />
+ <table border="0" cellspacing="0" cellpadding="2" py:attrs="table_attrs">
+ <tr py:for="i, field in enumerate(fields)"
+ class="${i%2 and 'odd' or 'even'}"
+ >
+ <th>
+ <label class="fieldlabel" for="${field.field_id}" py:content="field.label" />
+ </th>
+ <td>
+ <span py:replace="field.display(value_for(field), **params_for(field))" />
+ <span py:if="error_for(field)" class="fielderror" py:content="error_for(field)" />
+ <span py:if="field.help_text" class="fieldhelp" py:content="field.help_text" />
+ </td>
+ </tr>
+ <tr>
+ <td> </td>
+ <td py:content="submit.display(submit_text)" />
+ </tr>
+ </table>
+ </form>
+ """
+
+def getNodeQueryForm():
+ return QueryForm(fields=NodeQueryFields(), action="query")
# make it easier group objects without invoking the elixir auto-write feature.
class aggregate: pass
class NodeWidget(widgets.Widget):
pass
+def prep_nodehist(node):
+ agg = aggregate()
+ agg.node = node
+ agg.loginbase = "unknown"
+ try:
+ agg.loginbase = PlcSite.query.get(node.plc_siteid).plc_site_stats['login_base']
+ except:
+ agg.loginbase = "exception"
+
+
+ return agg
+
def prep_node_for_display(node, pcuhash=None, preppcu=True, asofdate=None):
agg = aggregate()
agg.node = node
agg = prep_node_for_display(fb)
rquery.append(agg)
- #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
-#
-# if filter:
-# if agg.history.status == filter:
-# query.append(agg)
-# else:
-# query.append(agg)
-
widget = NodeWidget(template='monitorweb.templates.node_template')
return dict(now=time.ctime(), query=rquery, nodewidget=widget)
+ @expose(template="monitorweb.templates.query", allow_json=True)
+ def query(self, **data):
+ query = []
+
+ for k in data:
+ print k, data[k]
+
+ fbquery = None
+
+ if 'object' in data and data['object'] == "nodes":
+ fbquery = FindbadNodeRecord.get_all_latest()
+ elif 'object' in data and data['object'] == "nodehistory":
+ hostname = data['nodehistory_hostname']
+ data['date_checked'] = 'date_checked'
+ fbrecord = FindbadNodeRecord.get_by(hostname=hostname)
+ fbquery = fbrecord.versions[-500:]
+
+ if fbquery:
+ for node in fbquery:
+ # NOTE: reformat some fields.
+ if type(node) is not type(FindbadNodeRecord):
+ agg = node.__dict__.copy()
+ else:
+ agg = node.to_dict()
+ agg.update(agg['plc_node_stats'])
+ if 'rpmvalue' in data and 'rpms' in data:
+ if agg['rpms']:
+ rpm_list = agg['rpms'].split()
+ rpm_list = filter(lambda x: data['rpmvalue'] in x, rpm_list)
+ agg['rpms'] = " ".join(rpm_list)
+
+ query.append(agg)
+
+ fields=data.copy()
+
+ try:
+ del fields['object']
+ del fields['rpmvalue']
+ del fields['nodehistory_hostname']
+ except: pass
+ return dict(now=time.ctime(), query=query, fields=fields, data=data, queryform=getNodeQueryForm())
+
+ @expose(template="monitorweb.templates.nodefast", allow_json=True)
+ def node(self, filter=None):
+ nhquery = HistoryNodeRecord.query.all()
+ query = []
+ for nh in nhquery:
+ if filter:
+ if nh.status == filter:
+ agg = prep_nodehist(nh)
+ query.append(agg)
+ else:
+ agg = prep_nodehist(nh)
+ query.append(agg)
+
+ return dict(now=time.ctime(), query=query)
+
@expose(template="monitorweb.templates.nodelist")
- def node(self, filter='boot'):
+ def nodeslow(self, filter='boot'):
print "NODE------------------"
print "befor-len: ", len( [ i for i in session] )
session.flush(); session.clear()
session.flush(); session.clear()
loginbase=None
+ loginbase_list=[]
hostname=None
pcuid=None
since=20
+ # if objtype is not None, then treat 'hostname' or 'loginbase' as a search pattern
+ objtype=None
exceptions = None
sitequery=[]
nodequery=[]
pcuquery=[]
actions=[]
+ actions_list=[]
for key in data:
print key, data[key]
if 'query' in data:
obj = data['query']
- if len(obj.split(".")) > 1: hostname = obj
- else: loginbase=obj
+ fields = obj.split(":")
+ if len(fields) > 1:
+ objtype = fields[0]
+ obj = fields[1].replace("*", "%")
+ print "obj: %s"% obj
+
+ if len(obj.split(".")) > 1 or objtype == "node":
+ hostname = obj
+ else:
+ loginbase = obj
if 'loginbase' in data:
loginbase = data['loginbase']
if pcuid:
print "pcuid: %s" % pcuid
pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
- loginbase = PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base']
+ loginbase_list += [ PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base'] ]
if hostname:
- node = FindbadNodeRecord.get_latest_by(hostname=hostname)
- loginbase = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
-
- if loginbase:
- actions = ActionRecord.query.filter_by(loginbase=loginbase
- ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
- ).order_by(ActionRecord.date_created.desc())
- actions = [ a for a in actions ]
- sitequery = [HistorySiteRecord.by_loginbase(loginbase)]
- # NOTE: because a single pcu may be assigned to multiple hosts,
- # track unique pcus by their plc_pcuid, then turn dict into list
- pcus = {}
- for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
- # NOTE: reformat some fields.
- agg = prep_node_for_display(node)
- nodequery += [agg]
- if agg.pcu:
- pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
+ if not objtype:
+ nodes = [ FindbadNodeRecord.get_latest_by(hostname=hostname) ]
+ else:
+ nodes = FindbadNodeRecord.query.filter(FindbadNodeRecord.hostname.like(hostname))
- for pcuid_key in pcus:
- pcuquery += [pcus[pcuid_key]]
+ for node in nodes:
+ lb = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
+ if lb not in loginbase_list:
+ loginbase_list += [ lb ]
- return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions, since=since, exceptions=exceptions)
+ if loginbase:
+ if not objtype:
+ loginbase_list = [ loginbase ]
+ else:
+ loginbase_list = HistorySiteRecord.query.filter(HistorySiteRecord.loginbase.like(loginbase))
+ loginbase_list = [ l.loginbase for l in loginbase_list ]
+
+
+ if loginbase_list:
+ for loginbase in loginbase_list:
+ actions = ActionRecord.query.filter_by(loginbase=loginbase
+ ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
+ ).order_by(ActionRecord.date_created.desc())
+ actions_list += [ a for a in actions ]
+ site = HistorySiteRecord.by_loginbase(loginbase)
+ if site:
+ sitequery.append(site)
+ # NOTE: because a single pcu may be assigned to multiple hosts,
+ # track unique pcus by their plc_pcuid, then turn dict into list
+ pcus = {}
+ for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
+ # NOTE: reformat some fields.
+ agg = prep_node_for_display(node)
+ nodequery += [agg]
+ if agg.pcu:
+ pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
+
+ for pcuid_key in pcus:
+ pcuquery += [pcus[pcuid_key]]
+
+ return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions_list, since=since, exceptions=exceptions)
# TODO: add form validation
#node-good { background-color : darkseagreen; }\r
#node-offline { background-color: red; }\r
#node-down { background-color: indianred; }\r
+#node-failboot { background-color: gold; }\r
+#node-safeboot { background-color: lightyellow; }\r
+#node-disabled { background-color: grey; }\r
\r
#pcu-online { background-color : lightgreen; }\r
#pcu-good { background-color : darkseagreen; }\r
color: black;\r
font-size: 127%;\r
background-color: white;\r
- width: 757px;\r
+ /*width: 757px;*/\r
margin: 0 auto 0 auto;\r
border-left: 1px solid #aaa;\r
border-right: 1px solid #aaa;\r
margin: 0.5em;\r
padding: 1em;\r
float: right;\r
- width: 200px;\r
+ /*width: 200px;*/\r
font-size: 88%;\r
}\r
\r
padding: 10px;\r
font-size: 80%;\r
text-align: center;\r
- width: 765px;\r
+ /*width: 765px;*/\r
margin: 0 auto 1em auto;\r
}\r
\r
padding: 15px 10px 15px 55px;\r
background: #cec URL('../images/ok.png') left center no-repeat;\r
border: 1px solid #9c9;\r
- width: 450px;\r
+ /*width: 450px;*/\r
font-size: 120%;\r
font-weight: bolder;\r
}\r
.notice {\r
margin: 0.5em auto 0.5em auto;\r
padding: 15px 10px 15px 55px;\r
- width: 450px;\r
+ /*width: 450px;*/\r
background: #eef URL('../images/info.png') left center no-repeat;\r
border: 1px solid #cce;\r
}\r
.error {\r
margin: 0.5em auto 0.5em auto;\r
padding: 15px 10px 15px 55px;\r
- width: 450px;\r
+ /*width: 450px;*/\r
background: #e30 URL('../images/widgets.png') left center no-repeat;\r
border: 1px solid #c00;\r
}\r
<th>History (scan)</th>
<th>Status Since</th>
<th>Hostname</th>
- <th>DNS</th>
+ <th>Resolves?</th>
<th>SSH</th>
<th>last_contact (cached)</th>
<th>Last Checked</th>
<th nowrap='true'>Port Status</th>
- <th>Firewall</th>
+ <th>Blocked Ports?</th>
</tr>
</thead>
<tbody>
- <tr py:for="i,agg in enumerate(nodequery)" class="${i%2 and 'odd' or 'even'}" >
+ <span py:for="i,agg in enumerate(nodequery)">
+ <tr class="${i%2 and 'odd' or 'even'}" >
<td><a href="nodehistory?hostname=${agg.node.hostname}">status</a>
(<a href="nodescanhistory?hostname=${agg.node.hostname}">scan</a>)</td>
<td id="site-${agg.history.status}" py:content="diff_time(mktime(agg.history.last_changed.timetuple()))"></td>
id="port${state}" py:content="'%s, ' % port">80</span>
</td>
<td py:content="agg.node.firewall"></td>
- <td>
- <!-- TODO: add some values/code to authenticate the operation. -->
- <!--form action="${link('pcuview', hostname=agg.node.hostname)}" name="externalscan${i}" method='post'>
- <input type='hidden' name='hostname' value='${agg.node.hostname}'/>
- <input type='hidden' name='type' value='ExternalScan' />
- </form>
- <a onclick='document.externalscan${i}.submit();' href="javascript: void(1);">ExternalScan</a-->
- </td>
- <td>
- <!-- TODO: add some values/code to authenticate the operation. -->
- <!--form action="${link('pcuview', hostname=agg.node.hostname)}" name="internalscan${i}" method='post'>
- <input type='hidden' name='hostname' value='${agg.node.hostname}'/>
- <input type='hidden' name='type' value='InternalScan' />
- </form>
- <a onclick='javascript: document.internalscan${i}.submit();' href="javascript: void(1);">InternalScan</a-->
- </td>
- <td py:if="len(pcuquery) > 0">
- <!-- TODO: add some values/code to authenticate the operation. -->
- <!--form action="${link('pcuview', pcuid=pcu.plc_pcuid)}" name="reboot${i}" method='post'>
- <input type='hidden' name='hostname' value='${agg.node.hostname}'/>
- <input type='hidden' name='type' value='Reboot' />
- </form>
- <a onclick='javascript: document.reboot${i}.submit();' href="javascript: void(1);">Reboot</a-->
- </td>
</tr>
+ <tr>
+ <td></td>
+ <th>Kernel:</th>
+ <td colspan="3" py:content="agg.kernel"> </td>
+ </tr>
+ <tr>
+ <td></td>
+ <th>DNS Status:</th>
+ <td colspan="3"><pre py:content="agg.node.dns_status"> </pre></td>
+ </tr>
+ <tr>
+ <td></td>
+ <th>Traceroute:</th>
+ <td colspan="3"><pre py:content="agg.node.traceroute"> </pre></td>
+ </tr>
+ </span>
</tbody>
</table>
<div class="error" py:if="exceptions is not None">
<th>last_contact</th>
</span>
<span py:if="node is not None">
- <td py:content="node.node.plc_node_stats['node_id']">node_id</td>
+ <td py:content="node.node.plc_node_stats['node_id']">node_id</td>
<td nowrap="true">
<a target="_top" href="${link('pcuview', hostname=node.node.hostname)}" py:content="node.node.hostname">your.host.org</a></td>
<td>
--- /dev/null
+<!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 Node List"
+from monitor.util import diff_time
+from time import mktime
+from links import *
+
+?>
+<html py:layout="'sitemenu.kid'"
+ xmlns:py="http://purl.org/kid/ns#"
+ xmlns:mochi="http://www.mochi.org">
+
+<div py:match="item.tag == 'content'">
+
+ <script type="text/javascript">
+ function nodelist_paginator(opts) { plekit_table_paginator(opts, "nodelist"); }
+ </script>
+
+ <center>
+ <b py:content="'BOOT: %d' % len([agg for agg in query if agg.node.status == 'good'])"></b> |
+ <b py:content="'DOWN: %d' % len([agg for agg in query if agg.node.status == 'down'])"></b><br/>
+ </center>
+
+<table id="nodelist" cellpadding="0" border="0" class="plekit_table sortable-onload-2 colstyle-alt no-arrow paginationcallback-nodelist_paginator max-pages-10 paginate-25">
+ <thead>
+
+ <tr class='pagesize_area'><td class='pagesize_area' colspan='10'>
+ <form class='pagesize' action='satisfy_xhtml_validator'><fieldset>
+ <input class='pagesize_input' type='text' id="nodelist_pagesize" value='25'
+ onkeyup='plekit_pagesize_set("nodelist","nodelist_pagesize", 25);'
+ size='3' maxlength='3' />
+ <label class='pagesize_label'> items/page </label>
+ <img class='reset' src="/planetlab/icons/clear.png" alt="reset visible size"
+ onmousedown='plekit_pagesize_reset("nodelist","nodelist_pagesize", 999);' />
+ </fieldset></form></td></tr>
+
+ <tr class='search_area'><td class='search_area' colspan='10'>
+ <div class='search'><fieldset>
+ <label class='search_label'> Refine List </label>
+ <input class='search_input' type='text' id='nodelist_search'
+ onkeyup='plekit_table_filter("nodelist","nodelist_search","nodelist_search_and");'
+ size='self.search_width' maxlength='256' />
+ <label>and</label>
+ <input id='nodelist_search_and' class='search_and'
+ type='checkbox' checked='checked'
+ onchange='plekit_table_filter("nodelist","nodelist_search","nodelist_search_and");' />
+ <img class='reset' src="/planetlab/icons/clear.png" alt="reset search"
+ onmousedown='plekit_table_filter_reset("nodelist","nodelist_search","nodelist_search_and");' />
+ </fieldset></div></td></tr>
+
+ <tr>
+ <th class="sortable plekit_table">ID</th>
+ <th class="sortable plekit_table">Site</th>
+ <th class="sortable plekit_table">Hostname</th>
+ <th class="sortable plekit_table">Status</th>
+ <th class="sortable-sortLastContact plekit_table">Last Changed</th>
+ <th class="sortable plekit_table">Firewall</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr py:for="i,agg in enumerate(query)">
+ <td py:content="agg.node.plc_nodeid">node_id</td>
+ <td> <a href="${link('simpleview', loginbase=agg.loginbase)}">${agg.loginbase}</a> </td>
+ <td nowrap="true"> <a target="_top" href="${link('simpleview', hostname=agg.node.hostname)}" py:content="agg.node.hostname">your.host.org</a></td>
+ <td py:content="agg.node.status">boot</td>
+ <td id="node-${agg.node.status}" py:content="diff_time(mktime(agg.node.last_changed.timetuple()))"></td>
+ <td nowrap="true" py:content="agg.node.firewall"></td>
+ </tr>
+
+ </tbody>
+</table>
+
+</div>
+
+</html>
<tr class='search_area'><td class='search_area' colspan='10'>
<div class='search'><fieldset>
- <label class='search_label'> Search </label>
+ <label class='search_label'> Refine List</label>
<input class='search_input' type='text' id='nodelist_search'
onkeyup='plekit_table_filter("nodelist","nodelist_search","nodelist_search_and");'
size='self.search_width' maxlength='256' />
<tr class='search_area'><td class='search_area' colspan='10'>
<div class='search'><fieldset>
- <label class='search_label'> Search </label>
+ <label class='search_label'> Refine List </label>
<input class='search_input' type='text' id='nodelist_search'
onkeyup='plekit_table_filter("nodelist","nodelist_search","nodelist_search_and");'
size='self.search_width' maxlength='256' />
<tr class='search_area'><td class='search_area' colspan='5'>
<div class='search'><fieldset>
- <label class='search_label'> Search </label>
+ <label class='search_label'> Refine List</label>
<input class='search_input' type='text' id='pculist_search'
onkeyup='plekit_table_filter("pculist","pculist_search","pculist_search_and");'
size='self.search_width' maxlength='256' />
<tr py:for="i,node in enumerate(query)">
<td nowrap='true'>
<div class='oneline'>
- <a class='left' href="${link('pcuview', loginbase=node.loginbase)}">${node.loginbase}</a>
+ <a class='left' href="${link('simpleview', loginbase=node.loginbase)}">${node.loginbase}</a>
<a class='right' href="${plc_site_uri_id(node.pcu.plc_pcu_stats['site_id'])}">
<img style='display: inline' border='0' src="static/images/extlink.gif" align='right'/></a>
</div>
</td>
<td nowrap='true'>
<div class='oneline'>
- <a class='left' href="${link('pcuview', pcuid=node.pcu.plc_pcuid)}">${pcu_name(node.pcu.plc_pcu_stats)}</a>
+ <a class='left' href="${link('simpleview', pcuid=node.pcu.plc_pcuid)}">${pcu_name(node.pcu.plc_pcu_stats)}</a>
<a class='right' href="${plc_pcu_uri_id(node.pcu.plc_pcu_stats['pcu_id'])}">
<img style='display: inline' border='0' src="static/images/extlink.gif" align='right'/></a>
</div>
<td width="20%" nowrap='true' align='center' id="status-${node.status}">
<div id="links">
<a class="info" py:if="'error' in node.status"
- href="${link('pcuview', pcuid=node.pcu.plc_pcuid)}">
+ href="${link('simpleview', pcuid=node.pcu.plc_pcuid)}">
Error<span><pre>${node.pcu.reboot_trial_status}</pre></span></a>
<a py:if="'error' not in node.status"
- href="${link('pcuview', pcuid=node.pcu.plc_pcuid)}"
+ href="${link('simpleview', pcuid=node.pcu.plc_pcuid)}"
py:content="node.status">Reboot Status</a>
</div>
</td>
<th mochi:format="int"></th>
<th>History (scan)</th>
<th>Hostname</th>
- <th>DNS</th>
+ <th>Resolves?</th>
<th>last_contact (cached)</th>
<th>last_checked</th>
<th nowrap='true'>Port Status</th>
- <th>Filter</th>
+ <th>Blocked Ports?</th>
<th></th>
<th></th>
</tr>
--- /dev/null
+<!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 py:layout="'sitemenu.kid'"
+ xmlns:py="http://purl.org/kid/ns#"
+ xmlns:mochi="http://www.mochi.org">
+
+ <div py:match="item.tag == 'content'">
+ <h2>Functional, but Under Development...</h2>
+ <table>
+ <tr>
+ <td>${queryform.display(method="GET", value=data)}</td>
+ </tr>
+ </table>
+<h4>Results</h4>
+ <table py:if="fields and len(fields.keys()) > 0" id="querylist" cellpadding="0" border="0" class="plekit_table sortable-onload-0 colstyle-alt no-arrow paginationcallback-querylist_paginator max-pages-10 paginate-50" width="100%">
+ <thead>
+ <tr class='pagesize_area'><td class='pagesize_area' colspan='5'>
+ <form class='pagesize' action='satisfy_xhtml_validator'><fieldset>
+ <input class='pagesize_input' type='text' id="querylist_pagesize" value='50'
+ onkeyup='plekit_pagesize_set("querylist","querylist_pagesize", 50);'
+ size='3' maxlength='3' />
+ <label class='pagesize_label'> items/page </label>
+ <img class='reset' src="/planetlab/icons/clear.png" alt="reset visible size"
+ onmousedown='plekit_pagesize_reset("querylist","querylist_pagesize", 999);' />
+ </fieldset></form></td></tr>
+ <tr class='search_area'><td class='search_area' colspan='5'>
+ <div class='search'><fieldset>
+ <label class='search_label'> Search </label>
+ <input class='search_input' type='text' id='querylist_search'
+ onkeyup='plekit_table_filter("querylist","querylist_search","querylist_search_and");'
+ size='self.search_width' maxlength='256' />
+ <label>and</label>
+ <input id='querylist_search_and' class='search_and'
+ type='checkbox' checked='checked'
+ onchange='plekit_table_filter("querylist","querylist_search","querylist_search_and");' />
+ <img class='reset' src="/planetlab/icons/clear.png" alt="reset search"
+ onmousedown='plekit_table_filter_reset("querylist","querylist_search","querylist_search_and");' />
+ </fieldset></div></td></tr>
+ <!-- for keys show each th -->
+ <tr>
+ <span py:for="key in sorted(fields.keys())" >
+ <th class="sortable plekit_table">${key}</th>
+ </span>
+ </tr>
+ </thead>
+ <tbody>
+ <!-- for keys show value -->
+ <tr py:for="row in query" >
+ <span py:for="key in sorted(fields.keys())" >
+ <td>${row[key]}</td>
+ </span>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</html>
xmlns:mochi="http://www.mochi.org">
<div py:match="item.tag == 'content'">
+ <div py:if="len(sitequery) == 0">
+ <p>Your 'quick jump' query failed to find a matching site or hostname.</p>
+ <p>MyOps recognizes three types of expressions:
+ <ul>
+ <li>Site names, e.g. princeton, utah, nyu, etc</li>
+ <li>Host names, e.g. planetlab-1.cs.princeton.edu, pl1.university.edu, etc</li>
+ <li>Prefix a pattern with "site:" or "node:" to return all sites or
+ nodes that match a pattern. e.g. site:mlab* node:*redclara*</li>
+ </ul>
+ </p>
+ </div>
+ <div py:if="len(sitequery) != 0">
<h3 py:if="len(sitequery) > 0">Site Status</h3>
<table py:if="len(sitequery) > 0" id="sub-table" border="1" width="100%">
<thead>
</td>
<td py:content="agg.pcu.plc_pcu_stats['model']"></td>
<td py:content="len(agg.pcu.plc_pcu_stats['node_ids'])"></td>
- <td nowrap="true" width="70em"><a href="${link('detailview', loginbase=site.loginbase)}">More Details</a></td>
+ <td nowrap="true" width="70em"><a href="${link('detailview', pcuid=agg.pcu.plc_pcuid)}">More Details</a></td>
</tr>
</tbody>
</table>
<div class="oneline" id="legend" py:if="len(pcuquery) == 0">
- <em>There are no PCUs associated with this host.</em>
+ <h3>PCUs: None</h3>
</div>
<h3>Nodes</h3>
<p py:if="len(nodequery) == 0">
<span class="icon">${agg.node.hostname}</span></a>
</td>
<td py:content="diff_time(mktime(agg.node.date_checked.timetuple()))"></td>
- <td nowrap="true" width="70em"><a href="${link('detailview', loginbase=site.loginbase)}">More Details</a></td>
+ <td nowrap="true" width="70em"><a href="${link('detailview', hostname=agg.node.hostname)}">More Details</a></td>
</tr>
</tbody>
</table>
</span>
</div-->
+ </div>
</div>
</html>
<tr class='search_area'><td class='search_area' colspan='6'>
<div class='search'><fieldset>
- <label class='search_label'> Search </label>
+ <label class='search_label'> Refine List </label>
<input class='search_input' type='text' id='sitelist_search'
onkeyup='plekit_table_filter("sitelist","sitelist_search","sitelist_search_and");'
size='self.search_width' maxlength='256' />
<tr py:for="i,site in enumerate(query)">
<td nowrap="true">
<div class='oneline'>
- <a class='left' href="${link('pcuview', loginbase=site.loginbase)}">${site.loginbase}</a>
+ <a class='left' href="${link('simpleview', loginbase=site.loginbase)}">${site.loginbase}</a>
<a class='right' href="${plc_site_uri_id(site.plc_siteid)}">
<img style='display: inline' border='0' src="static/images/extlink.gif" align='right'/></a>
</div>
<table valign="top" border="1" bgcolor="white" align="center">
<tr> <td> <div id="header">${page_title}</div> </td>
<td>
- <form action="pcuview" method="GET">
+ <form action="simpleview" method="GET">
<table>
- <tr><td> Quick Search:</td>
+ <tr><td> Quick Jump:</td>
<td><input type="text" name="query"/></td>
<td><input type="submit"/></td>
+ <td><a href="query">Advanced Query</a></td>
</tr>
</table>
</form>