updates to various files needed to enable this.
nodes_total = Field(Int,default=0)
nodes_up = Field(Int,default=0)
+ slices_total = Field(Int,default=0)
slices_used = Field(Int,default=0)
+ # all nodes offline and never-contact.
+ new = Field(Boolean,default=False)
+
+ enabled = Field(Boolean,default=False)
+
status = Field(String,default="unknown")
@classmethod
__all__=["writepid","removepid","daemonize"]
+
+import time
+import math
+
+def diff_time(timestamp, abstime=True):
+ now = time.time()
+ if timestamp == None:
+ return "unknown"
+ if abstime:
+ diff = now - timestamp
+ else:
+ diff = timestamp
+ # return the number of seconds as a difference from current time.
+ t_str = ""
+ if diff < 60: # sec in min.
+ t = diff / 1
+ t_str = "%s sec ago" % int(math.ceil(t))
+ elif diff < 60*60: # sec in hour
+ t = diff / (60)
+ t_str = "%s min ago" % int(math.ceil(t))
+ elif diff < 60*60*24: # sec in day
+ t = diff / (60*60)
+ t_str = "%s hrs ago" % int(math.ceil(t))
+ elif diff < 60*60*24*14: # sec in week
+ t = diff / (60*60*24)
+ t_str = "%s days ago" % int(math.ceil(t))
+ elif diff <= 60*60*24*30: # approx sec in month
+ t = diff / (60*60*24*7)
+ t_str = "%s wks ago" % int(math.ceil(t))
+ elif diff > 60*60*24*30: # approx sec in month
+ t = diff / (60*60*24*30)
+ t_str = "%s mnths ago" % int(t)
+ return t_str
api = plc.getCachedAuthAPI()
l_sites = api.GetSites({'peer_id':None},
['login_base', 'site_id', 'abbreviated_name', 'latitude',
- 'longitude', 'max_slices', 'slice_ids', 'node_ids' ])
+ 'longitude', 'max_slices', 'slice_ids', 'node_ids', 'enabled' ])
l_nodes = api.GetNodes({'peer_id':None},
['hostname', 'node_id', 'ports', 'site_id', 'version', 'last_updated',
'date_created', 'last_contact', 'pcu_ids', 'nodenetwork_ids'])
from pcucontrol import reboot
from monitor import parser as parsermodule
from monitor import config
-from monitor.database import HistorySiteRecord, FindbadNodeRecord
+from monitor.database.info.model import HistorySiteRecord, FindbadNodeRecord, session
from monitor.wrapper import plc, plccache
from monitor.const import MINUP
checkAndRecordState(l_sites, l_plcsites)
+def getnewsite(nodelist):
+ new = True
+ for node in nodelist:
+ try:
+ noderec = FindbadNodeRecord.query.filter(FindbadNodeRecord.hostname==node['hostname']).order_by(FindbadNodeRecord.date_checked.desc()).first()
+ if noderec is not None and \
+ noderec.plc_node_stats['last_contact'] != None:
+ new = False
+ except:
+ import traceback
+ print traceback.print_exc()
+ return new
+
def getnodesup(nodelist):
up = 0
for node in nodelist:
pf = HistorySiteRecord.findby_or_create(loginbase=sitename)
pf.last_checked = datetime.now()
+ pf.slices_total = d_site['max_slices']
pf.slices_used = len(d_site['slice_ids'])
pf.nodes_total = len(lb2hn[sitename])
pf.nodes_up = getnodesup(lb2hn[sitename])
+ pf.new = getnewsite(lb2hn[sitename])
+ pf.enabled = d_site['enabled']
if pf.nodes_up >= MINUP:
if pf.status != "good": pf.last_changed = datetime.now()
count += 1
print "%d %15s slices(%2s) nodes(%2s) up(%2s) %s" % (count, sitename, pf.slices_used,
pf.nodes_total, pf.nodes_up, pf.status)
+ pf.flush()
+
print HistorySiteRecord.query.count()
+ session.flush()
return True
autoreload.package="monitorweb"
-server.socket_host="127.0.0.1"
+server.socket_host="monitor.planet-lab.org"
server.socket_port=8080
-server.webpath="/monitor/"
-base_url_filter.on = False
-base_url_filter.base_url = "http://127.0.0.1:8080/monitor"
-base_url_filter.use_x_forwarded_host = True
+#server.webpath="/monitor/"
+#base_url_filter.on = False
+#base_url_filter.base_url = "http://127.0.0.1:8080/monitor"
+#base_url_filter.use_x_forwarded_host = True
# Auto-Reload after code modification
# autoreload.on = True
node.pcu_status = pcu.reboot_trial_status
else:
node.pcu_status = "nodata"
+ node.pcu_short_status = format_pcu_shortstatus(pcu)
+
else:
node.pcu_status = "nopcu"
+ node.pcu_short_status = "none"
if node.kernel_version:
node.kernel = node.kernel_version.split()[2]
else:
node.kernel = ""
+
# NOTE: count filters
if node.observed_status != 'DOWN':
filtercount[node.observed_status] += 1
else:
filtercount['pending'] += 1
- print reboot.pcu_name(node.plc_pcu_stats)
node.ports = format_ports(node)
node.status = format_pcu_shortstatus(node)
return dict(query=query, fc=filtercount)
- @expose(template="monitorweb.templates.pculist")
+ @expose(template="monitorweb.templates.sitelist")
def site(self, filter='all'):
- filtercount = {'ok' : 0, 'NetDown': 0, 'Not_Run' : 0, 'pending' : 0, 'all' : 0}
- return dict(query=[], fc=filtercount)
+ filtercount = {'good' : 0, 'down': 0, 'new' : 0, 'pending' : 0, 'all' : 0}
+ fbquery = HistorySiteRecord.query.all()
+ query = []
+ for site in fbquery:
+ # count filter
+ filtercount['all'] += 1
+ if site.new and site.slices_used == 0 and not site.enabled:
+ filtercount['new'] += 1
+ elif not site.enabled:
+ filtercount['pending'] += 1
+ else:
+ filtercount[site.status] += 1
+
+ # apply filter
+ if filter == "all":
+ query.append(site)
+ elif filter == 'new' and site.new and site.slices_used == 0 and not site.enabled:
+ query.append(site)
+ elif filter == "pending" and not site.enabled:
+ query.append(site)
+ elif filter == site.status:
+ query.append(site)
+
+ return dict(query=query, fc=filtercount)
@expose(template="monitorweb.templates.pculist")
def action(self, filter='all'):
options_defaults['autosetup'] = False
+from monitor.database.info.model import *
# your data model
padding: 0;\r
}\r
\r
-td, th {padding:2px;border:none;}\r
+td, th {padding:1px;border:none;}\r
tr th {text-align:left;background-color:#f0f0f0;color:#333;}\r
tr.odd td {background-color:#edf3fe;}\r
tr.even td {background-color:#fff;}\r
\r
#header {\r
- height: 80px;\r
- width: 777px;\r
- background: blue URL('../images/header_inner.png') no-repeat;\r
+ height: 40px;\r
+ width: 780px;\r
+ /*background: blue URL('../images/header_inner.png') no-repeat;*/\r
border-left: 1px solid #aaa;\r
border-right: 1px solid #aaa;\r
margin: 0 auto 0 auto;\r
+ text-align: center;\r
+ font-size: 180%;\r
}\r
\r
a.link, a, a.active {\r
#status-Not_Run { background-color: lightgrey; }\r
#status-ok { background-color: darkseagreen; }\r
#status-0 { background-color: darkseagreen; }\r
-#status-error { background-color: indianred; width="200px"; }\r
+#status-error { background-color: indianred; }\r
+#status-none { background-color: white; }\r
+\r
+#site-good { background-color : darkseagreen; }\r
+#site-down { background-color: indianred; }\r
+\r
+/*#nps-table { background-color: lightgrey; }*/\r
+/*#sub-table { background-color: lightgrey; }*/\r
+/* td, th {padding:2px;border:none;} */\r
+/* tr th {text-align:left;background-color:#f0f0f0;color:#333;} */\r
\r
#main_content {\r
color: black;\r
padding: 10px;\r
font-size: 80%;\r
text-align: center;\r
- width: 757px;\r
+ width: 765px;\r
margin: 0 auto 1em auto;\r
}\r
\r
<!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'] = "Monitor Node View"
+from monitor.util import diff_time
+from time import mktime
?>
<html py:layout="'sitemenu.kid'"
xmlns:py="http://purl.org/kid/ns#">
<tbody>
<tr>
<td colspan="5">
- <table border="1">
+ <table id="sub-table" border="1" width="100%">
<thead>
<tr>
<th>Hostname</th>
<th>ping</th>
- <th>ssh</th>
+ <!--th>ssh</th-->
<th>pcu</th>
<th>status</th>
<th>kernel</th>
<tr py:for="i,node in enumerate(query)" class="${i%2 and 'odd' or 'even'}" >
<td nowrap="true" py:content="node.hostname"></td>
<td py:content="node.ping_status"></td>
- <td py:content="node.ssh_status"></td>
- <td py:content="node.pcu_status"></td>
+ <!--td py:content="node.ssh_status"></td-->
+ <td id="status-${node.pcu_short_status}" py:content="node.pcu_short_status"></td>
<td py:content="node.observed_status"></td>
<td nowrap="true" py:content="node.kernel"></td>
- <td py:content="node.plc_node_stats['last_contact']"></td>
+ <td py:content="diff_time(node.plc_node_stats['last_contact'])"></td>
</tr>
</tbody>
</table>
xmlns:py="http://purl.org/kid/ns#">
<div py:match="item.tag == 'content'">
- <table width="100%">
+ <table id="sub-table" width="100%">
<thead>
<tr>
<th><a href="${tg.url('pcu', filter='ok')}">Ok(${fc['ok']})</a></th>
<tbody>
<tr>
<td colspan="5">
- <table border="1">
+ <table border="1" width="100%">
<thead>
<tr>
<th>Site</th>
<span py:for="port,state in node.ports"
id="port${state}" py:content="'%s, ' % port">80</span>
</td>
- <td id="status-${node.status}" py:content="node.reboot_trial_status"></td>
+ <td width="40" id="status-${node.status}" py:content="node.reboot_trial_status"></td>
<td py:content="node.plc_pcu_stats['model']"></td>
<td py:content="len(node.plc_pcu_stats['node_ids'])"></td>
</tr>
</head>
<body>
- <h1>Monitor : ${page_title}</h1>
- <table valign="top" border="1" bgcolor="white" align="center" width="800">
+ <div id="header">Monitor : ${page_title}</div>
+ <table valign="top" border="1" bgcolor="white" align="center" width="60em">
<tr>
<td>
- <table>
+ <table id="nps-table" width="100%">
<thead>
<tr>
<th><a href="${tg.url('node')}">Nodes</a></th>
</tr>
</table>
- <div class="footer">Copywrite XYZ</div>
+ <div id="footer">Copywrite © 2007-2008 The Trustees of Princeton University</div>
</body>
</html>
--- /dev/null
+[global]
+# This is where all of your settings go for your development environment
+# Settings that are the same for both development and production
+# (such as template engine, encodings, etc.) all go in
+# monitorweb/config/app.cfg
+
+# DATABASE
+
+# driver://username:password@host:port/database
+
+# pick the form for your database
+# sqlalchemy.dburi="postgres://username@hostname/databasename"
+# sqlalchemy.dburi="mysql://username:password@hostname:port/databasename"
+# sqlalchemy.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite"
+
+# If you have sqlite, here's a simple default to get you started
+# in development
+sqlalchemy.dburi="sqlite:///devdata.sqlite"
+
+
+# SERVER
+
+# Some server parameters that you may want to tweak
+# server.socket_port=8080
+
+# Enable the debug output at the end on pages.
+# log_debug_info_filter.on = False
+
+server.environment="development"
+autoreload.package="monitorweb"
+
+
+server.socket_host="127.0.0.1"
+server.socket_port=8080
+server.webpath="/monitor/"
+base_url_filter.on = False
+base_url_filter.base_url = "http://127.0.0.1:8080/monitor"
+base_url_filter.use_x_forwarded_host = True
+
+# Auto-Reload after code modification
+# autoreload.on = True
+
+# Set to True if you'd like to abort execution if a controller gets an
+# unexpected parameter. False by default
+tg.strict_parameters = True
+
+# LOGGING
+# Logging configuration generally follows the style of the standard
+# Python logging module configuration. Note that when specifying
+# log format messages, you need to use *() for formatting variables.
+# Deployment independent log configuration is in monitorweb/config/log.cfg
+[logging]
+
+[[loggers]]
+[[[monitorweb]]]
+level='DEBUG'
+qualname='monitorweb'
+handlers=['debug_out']
+
+[[[allinfo]]]
+level='INFO'
+handlers=['debug_out']
+
+[[[access]]]
+level='INFO'
+qualname='turbogears.access'
+handlers=['access_out']
+propagate=0
+
+
+[[[database]]]
+# Set to INFO to make SQLAlchemy display SQL commands
+level='ERROR'
+qualname='sqlalchemy.engine'
+handlers=['debug_out']
+propagate=0