add pcu_name to pcufailed_notice
[monitor.git] / web / MonitorWeb / monitorweb / controllers.py
1 import turbogears as tg
2 from turbogears import controllers, expose, flash, exception_handler
3 from turbogears import widgets
4 from cherrypy import request, response
5 import cherrypy
6 # from monitorweb import model
7 # import logging
8 # log = logging.getLogger("monitorweb.controllers")
9 import re
10 from monitor.database.info.model import *
11 #from monitor.database.zabbixapi.model import *
12 from monitor_xmlrpc import MonitorXmlrpcServer
13
14 from monitor import reboot
15 from monitor import scanapi
16 import time
17
18 from monitor.wrapper.plccache import plcdb_hn2lb as site_hn2lb
19
20 from monitorweb.templates.links import *
21
22 class ObjectQueryFields(widgets.WidgetsList):
23         """The WidgetsList defines the fields of the form."""
24         pass
25
26
27
28 class NodeQueryFields(widgets.WidgetsList):
29         """The WidgetsList defines the fields of the form."""
30
31         object = widgets.RadioButtonList(label="Query Type", options=[('nodes', 'All Nodes'), 
32                                                                                                                           ('nodehistory', 'Single Node History'),
33                                                                                                                           #('sites', 'All Sites'),
34                                                                                                                           #('sitehistory', 'Single Site History'),
35                                                                                                                           ], default="nodes")
36         nodehistory_hostname = widgets.TextField(label="Hostname Node History", attrs={'size':30})
37
38         hostname = widgets.CheckBox(label="Hostname")
39         firewall = widgets.CheckBox(label="Firewall?")
40         dns_status = widgets.CheckBox(label="DNS Status")
41         external_dns_status = widgets.CheckBox(label="Hostname Resolves?")
42         kernel_version = widgets.CheckBox(label="Kernel")
43         observed_status = widgets.CheckBox(label="Observed Status")
44         port_status = widgets.CheckBox(label="Port Status")
45         rpms = widgets.CheckBox(label="RPM")
46         rpmvalue = widgets.TextField(label="RPM Pattern")
47
48 class QueryForm(widgets.TableForm):
49     template = """
50     <form xmlns:py="http://purl.org/kid/ns#"
51         name="${name}"
52         action="${action}"
53         method="${method}"
54         class="tableform"
55         py:attrs="form_attrs"
56     >
57         <div py:for="field in hidden_fields"
58             py:replace="field.display(value_for(field), **params_for(field))"
59         />
60         <table border="0" cellspacing="0" cellpadding="2" py:attrs="table_attrs">
61             <tr py:for="i, field in enumerate(fields)"
62                 class="${i%2 and 'odd' or 'even'}"
63             >
64                 <th>
65                     <label class="fieldlabel" for="${field.field_id}" py:content="field.label" />
66                 </th>
67                 <td>
68                     <span py:replace="field.display(value_for(field), **params_for(field))" />
69                     <span py:if="error_for(field)" class="fielderror" py:content="error_for(field)" />
70                     <span py:if="field.help_text" class="fieldhelp" py:content="field.help_text" />
71                 </td>
72             </tr>
73             <tr>
74                 <td>&#160;</td>
75                 <td py:content="submit.display(submit_text)" />
76             </tr>
77         </table>
78     </form>
79         """
80
81 def getNodeQueryForm():
82         return QueryForm(fields=NodeQueryFields(), action="query")
83
84 # make it easier group objects without invoking the elixir auto-write feature.
85 class aggregate: pass
86
87
88 def query_to_dict(query):
89         """ take a url query string and chop it up """
90         val = {}
91         query_fields = query.split('&')
92         for f in query_fields:
93                 (k,v) = urllib.splitvalue(f)
94                 val[k] = v
95
96         return val
97
98 def format_ports(data, pcumodel=None):
99         retval = []
100         filtered_length=0
101
102         if pcumodel:
103                 supported_ports=reboot.model_to_object(pcumodel).supported_ports
104         else:
105                 # ports of a production node
106                 supported_ports=[22,80,806]
107
108         if data and len(data.keys()) > 0 :
109                 for port in supported_ports:
110                         try:
111                                 state = data[str(port)]
112                         except:
113                                 state = "unknown"
114
115                         if state == "filtered":
116                                 filtered_length += 1
117                                 
118                         retval.append( (port, state) )
119
120         if retval == []: 
121                 retval = [( "Closed/Filtered", "state" )]
122
123         if filtered_length == len(supported_ports):
124                 retval = [( "All Filtered", "state" )]
125
126         return retval
127
128 def format_pcu_shortstatus(pcu):
129         status = "error"
130         if pcu:
131                 if pcu.reboot_trial_status == str(0):
132                         status = "Ok"
133                 elif pcu.reboot_trial_status == "NetDown" or pcu.reboot_trial_status == "Not_Run":
134                         status = pcu.reboot_trial_status
135                 else:
136                         status = "error"
137
138         return status
139
140 def prep_pcu_for_display(pcu):
141         agg = aggregate()
142         agg.pcu = pcu 
143                 
144         try:
145                 agg.loginbase = PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base']
146         except:
147                 agg.loginbase = "unknown"
148
149         agg.pcuhist = HistoryPCURecord.query.get(pcu.plc_pcuid)
150
151         agg.ports = format_ports(pcu.port_status, pcu.plc_pcu_stats['model'])
152         agg.status = format_pcu_shortstatus(pcu)
153
154         #print pcu.entry_complete
155         agg.entry_complete_str = pcu.entry_complete
156         #pcu.entry_complete_str += "".join([ f[0] for f in pcu.entry_complete.split() ])
157         if pcu.dns_status == "NOHOSTNAME":
158                 agg.dns_short_status = 'NoHost'
159         elif pcu.dns_status == "DNS-OK":
160                 agg.dns_short_status = 'Ok'
161         elif pcu.dns_status == "DNS-NOENTRY":
162                 agg.dns_short_status = 'NoEntry'
163         elif pcu.dns_status == "NO-DNS-OR-IP":
164                 agg.dns_short_status = 'NoHostOrIP'
165         elif pcu.dns_status == "DNS-MISMATCH":
166                 agg.dns_short_status = 'Mismatch'
167         return agg
168
169 class NodeWidget(widgets.Widget):
170         pass
171
172 def prep_nodehist(node):
173         agg = aggregate()
174         agg.node = node
175         agg.loginbase = "unknown"
176         try:
177                 agg.loginbase = PlcSite.query.get(node.plc_siteid).plc_site_stats['login_base']
178         except:
179                 agg.loginbase = "exception"
180                 
181
182         return agg
183
184 def prep_node_for_display(node, pcuhash=None, preppcu=True, asofdate=None):
185         agg = aggregate()
186         agg.node = node
187
188         if node.plc_pcuid and preppcu:
189                 if pcuhash:
190                         pcu = pcuhash[node.plc_pcuid]
191                 else:
192                         pcu = FindbadPCURecord.get_latest_by(plc_pcuid=node.plc_pcuid)
193
194                 if pcu:
195                         agg.pcu_status = pcu.reboot_trial_status
196                         agg.pcu_short_status = format_pcu_shortstatus(pcu)
197                         agg.pcu = prep_pcu_for_display(pcu)
198                 else:
199                         agg.pcu_short_status = "none"
200                         agg.pcu_status = "nodata"
201                         agg.pcu = None
202
203         else:
204                 agg.pcu_status = "nopcu"
205                 agg.pcu_short_status = "none"
206                 agg.pcu = None
207
208
209         if node.kernel_version:
210                 agg.kernel = node.kernel_version.split()[2]
211         else:
212                 agg.kernel = ""
213
214         try:
215                 agg.loginbase = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
216         except:
217                 agg.loginbase = "unknown"
218
219         if agg.loginbase:
220                 agg.site = HistorySiteRecord.by_loginbase(agg.loginbase)
221
222                 if asofdate:
223                         agg.site = agg.site.get_as_of(asofdate)
224
225                 if agg.site is None:
226                         # TODO: need a cleaner fix for this...
227                         agg.site = HistorySiteRecord.by_loginbase("pl")
228                         if not agg.site:
229                                 agg.site = HistorySiteRecord.by_loginbase("ple")
230
231         agg.history = HistoryNodeRecord.by_hostname(node.hostname)
232         if asofdate:
233                 agg.history = agg.history.get_as_of(asofdate)
234
235         agg.ports = format_ports(node.port_status)
236
237         try:
238                 exists = node.plc_node_stats['last_contact']
239         except:
240                 # TODO: this should not assign to the fb object!
241                 node.plc_node_stats = {'last_contact' : None}
242         
243         return agg
244
245
246 class Root(controllers.RootController, MonitorXmlrpcServer):
247         @expose(template="monitorweb.templates.welcome")
248         def index(self):
249                 # log.debug("Happy TurboGears Controller Responding For Duty")
250                 flash("Welcome To MyOps!")
251                 return dict(now=time.ctime())
252
253         @expose(template="monitorweb.templates.nodelist", allow_json=True)
254         def node3(self, filter=None):
255                 nhquery = HistoryNodeRecord.query.all()
256                 query = []
257                 for nh in nhquery:
258                         if filter:
259                                 if nh.status == filter:
260                                         query.append(nh)
261                         else:
262                                 query.append(nh)
263
264                 rquery=[]
265                 for q in query:
266                         fb = FindbadNodeRecord.get_latest_by(hostname=q.hostname)
267                         rquery.append(fb)
268
269                 return dict(now=time.ctime(), query=rquery)
270
271         @expose(template="monitorweb.templates.nodelist", allow_json=True)
272         def node2(self, filter=None):
273                 nhquery = HistoryNodeRecord.query.all()
274                 query = []
275                 for nh in nhquery:
276                         if filter:
277                                 if nh.status == filter:
278                                         query.append(nh)
279                         else:
280                                 query.append(nh)
281
282                 rquery=[]
283                 for q in query:
284                         fb = FindbadNodeRecord.get_latest_by(hostname=q.hostname)
285                         agg = prep_node_for_display(fb)
286                         rquery.append(agg)
287
288                 widget = NodeWidget(template='monitorweb.templates.node_template')
289                 return dict(now=time.ctime(), query=rquery, nodewidget=widget)
290
291         @expose(template="monitorweb.templates.query", allow_json=True)
292         def query(self, **data):
293                 query = []
294
295                 for k in data:
296                         print k, data[k]
297
298                 fbquery = None
299                 
300                 if 'object' in data and data['object'] == "nodes":
301                         fbquery = FindbadNodeRecord.get_all_latest()
302                 elif 'object' in data and data['object'] == "nodehistory": 
303                         hostname = data['nodehistory_hostname']
304                         data['date_checked'] = 'date_checked'
305                         fbrecord = FindbadNodeRecord.get_by(hostname=hostname)
306                         fbquery = fbrecord.versions[-500:]
307
308                 if fbquery:
309                         for node in fbquery:
310                                 # NOTE: reformat some fields.
311                                 if type(node) is not type(FindbadNodeRecord):
312                                         agg = node.__dict__.copy()
313                                 else:
314                                         agg = node.to_dict()
315                                 agg.update(agg['plc_node_stats'])
316                                 if 'rpmvalue' in data and 'rpms' in data:
317                                         if agg['rpms']:
318                                                 rpm_list = agg['rpms'].split()
319                                                 rpm_list = filter(lambda x: data['rpmvalue'] in x, rpm_list)
320                                                 agg['rpms'] = " ".join(rpm_list)
321
322                                 query.append(agg)
323
324                 fields=data.copy()
325
326                 try: 
327                         del fields['object']
328                         del fields['rpmvalue']
329                         del fields['nodehistory_hostname']
330                 except: pass
331                 return dict(now=time.ctime(), query=query, fields=fields, data=data, queryform=getNodeQueryForm())
332
333         @expose(template="monitorweb.templates.nodefast", allow_json=True)
334         def node(self, filter=None):
335                 nhquery = HistoryNodeRecord.query.all()
336                 query = []
337                 for nh in nhquery:
338                         if filter:
339                                 if nh.status == filter:
340                                         agg = prep_nodehist(nh)
341                                         query.append(agg)
342                         else:
343                                 agg = prep_nodehist(nh)
344                                 query.append(agg)
345
346                 return dict(now=time.ctime(), query=query)
347
348         @expose(template="monitorweb.templates.nodelist")
349         def nodeslow(self, filter='boot'):
350                 print "NODE------------------"
351                 print "befor-len: ", len( [ i for i in session] )
352                 session.flush(); session.clear()
353                 print "after-len: ", len( [ i for i in session] )
354                 fbquery = FindbadNodeRecord.get_all_latest()
355                 query = []
356                 filtercount = {'down' : 0, 'boot': 0, 'debug' : 0, 'diagnose' : 0, 'disabled': 0, 
357                                                 'neverboot' : 0, 'pending' : 0, 'all' : 0, None : 0}
358                 for node in fbquery:
359                         # NOTE: reformat some fields.
360                         agg = prep_node_for_display(node)
361
362                         if not agg.history:
363                                 continue
364
365                         if agg.history.status in ['down', 'offline']:
366                                 if node.plc_node_stats and node.plc_node_stats['last_contact'] != None:
367                                         filtercount['down'] += 1
368                                 else:
369                                         filtercount['neverboot'] += 1
370                         elif agg.history.status in ['good', 'online']:
371                                 filtercount['boot'] += 1
372                         elif agg.history.status in ['debug', 'monitordebug']:
373                                 filtercount['debug'] += 1
374                         else:
375                                 if filtercount.has_key(agg.history.status):
376                                         filtercount[agg.history.status] += 1
377                                 
378
379                         # NOTE: apply filter
380                         if filter == "neverboot":
381                                 if not node.plc_node_stats or node.plc_node_stats['last_contact'] == None:
382                                         query.append(agg)
383                         elif filter == "all":
384                                 query.append(agg)
385                         elif filter == agg.history.status:
386                                 query.append(agg)
387                         elif filter == 'boot':
388                                 query.append(agg)
389
390                                 
391                 widget = NodeWidget(template='monitorweb.templates.node_template')
392                 return dict(now=time.ctime(), query=query, fc=filtercount, nodewidget=widget)
393         
394         def nodeaction_handler(self, tg_exceptions=None):
395                 """Handle any kind of error."""
396                 print "NODEACTION_HANDLER------------------"
397
398                 if 'pcuid' in request.params:
399                         pcuid = request.params['pcuid']
400                 else:
401                         refurl = request.headers.get("Referer",link("pcu"))
402                         print refurl
403
404                         # TODO: do this more intelligently...
405                         uri_fields = urllib.splitquery(refurl)
406                         if uri_fields[1] is not None:
407                                 val = query_to_dict(uri_fields[1])
408                                 if 'pcuid' in val:
409                                         pcuid = val['pcuid']
410                                 elif 'hostname' in val:
411                                         pcuid = FindbadNodeRecord.get_latest_by(hostname=val['hostname']).plc_pcuid
412                                 else:
413                                         pcuid=None
414                         else:
415                                 pcuid=None
416
417                 cherry_trail = cherrypy._cputil.get_object_trail()
418                 for i in cherry_trail:
419                         print "trail: ", i
420
421                 print pcuid
422                 return self.pcuview(None, pcuid, **dict(exceptions=tg_exceptions))
423
424         def nodeaction(self, **data):
425                 print "NODEACTION------------------"
426                 for item in data.keys():
427                         print "%s %s" % ( item, data[item] )
428
429                 if 'hostname' in data:
430                         hostname = data['hostname']
431                 else:
432                         flash("No hostname given in submitted data")
433                         return
434
435                 if 'submit' in data or 'type' in data:
436                         try:
437                                 action = data['submit']
438                         except:
439                                 action = data['type']
440                 else:
441                         flash("No submit action given in submitted data")
442                         return
443
444                 if action == "Reboot":
445                         print "REBOOT: %s" % hostname
446                         ret = reboot.reboot_str(str(hostname))
447                         print ret
448                         if ret: raise RuntimeError("Error using PCU: " + str(ret))
449                         flash("Reboot appeared to work.  Allow at most 5 minutes.  Then run ExternalScan to check current status.")
450
451                 elif action == "ExternalScan":
452                         scanapi.externalprobe(str(hostname))
453                         flash("External Scan Successful!")
454                 elif action == "InternalScan":
455                         scanapi.internalprobe(str(hostname))
456                         flash("Internal Scan Successful!")
457                 else:
458                         # unknown action
459                         raise RuntimeError("Unknown action given")
460                 return
461
462         @expose(template="monitorweb.templates.simpleview")
463         def simpleview(self, **data):
464                 return self.pre_view(**data)
465
466         @expose(template="monitorweb.templates.detailview")
467         def detailview(self, **data):
468                 return self.pre_view(**data)
469
470         def pre_view(self, **data):
471                 session.flush(); session.clear()
472
473                 loginbase=None
474                 loginbase_list=[]
475                 hostname=None
476                 pcuid=None
477                 since=20
478                 # if objtype is not None, then treat 'hostname' or 'loginbase' as a search pattern
479                 objtype=None
480
481                 exceptions = None
482                 sitequery=[]
483                 nodequery=[]
484                 pcuquery=[]
485                 actions=[]
486                 actions_list=[]
487
488                 for key in data:
489                         print key, data[key]
490
491                 if 'query' in data:
492                         obj = data['query']
493                         fields = obj.split(":")
494                         if len(fields) > 1:
495                                 objtype = fields[0]
496                                 obj = fields[1].replace("*", "%")
497                                 print "obj: %s"% obj
498
499                         if len(obj.split(".")) > 1 or objtype == "node": 
500                                 hostname = obj
501                         else: 
502                                 loginbase = obj
503
504                 if 'loginbase' in data:
505                         loginbase = data['loginbase']
506
507                 if 'hostname' in data:
508                         hostname = data['hostname']
509
510                 if 'pcuid' in data:
511                         try: pcuid = int(data['pcuid'])
512                         except: pcuid = None
513
514                 if 'since' in data:
515                         try: since = int(since)
516                         except: since = 20
517
518                 if pcuid:
519                         print "pcuid: %s" % pcuid
520                         pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
521                         loginbase_list += [ PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base'] ]
522
523                 if hostname:
524                         if not objtype:
525                                 nodes = [ FindbadNodeRecord.get_latest_by(hostname=hostname) ]
526                         else:
527                                 nodes = FindbadNodeRecord.query.filter(FindbadNodeRecord.hostname.like(hostname)) 
528
529                         for node in nodes:
530                                 lb = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
531                                 if lb not in loginbase_list:
532                                         loginbase_list += [ lb ]
533
534                 if loginbase:
535                         if not objtype:
536                                 loginbase_list = [ loginbase ]
537                         else:
538                                 loginbase_list = HistorySiteRecord.query.filter(HistorySiteRecord.loginbase.like(loginbase)) 
539                                 loginbase_list = [ l.loginbase for l in loginbase_list ]
540                         
541
542                 if loginbase_list:
543                         for loginbase in loginbase_list:
544                                 actions = ActionRecord.query.filter_by(loginbase=loginbase
545                                                                 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
546                                                                 ).order_by(ActionRecord.date_created.desc())
547                                 actions_list += [ a for a in actions ]
548                                 site = HistorySiteRecord.by_loginbase(loginbase)
549                                 if site:
550                                         sitequery.append(site)
551                                 # NOTE: because a single pcu may be assigned to multiple hosts,
552                                 # track unique pcus by their plc_pcuid, then turn dict into list
553                                 pcus = {}
554                                 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
555                                                 # NOTE: reformat some fields.
556                                                 agg = prep_node_for_display(node)
557                                                 nodequery += [agg]
558                                                 if agg.pcu: 
559                                                         pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
560
561                                 for pcuid_key in pcus:
562                                         pcuquery += [pcus[pcuid_key]]
563
564                 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions_list, since=since, exceptions=exceptions)
565
566
567         # TODO: add form validation
568         @expose(template="monitorweb.templates.pcuview")
569         @exception_handler(nodeaction_handler,"isinstance(tg_exceptions,RuntimeError)")
570         def pcuview(self, loginbase=None, pcuid=None, hostname=None, since=20, **data):
571                 session.flush(); session.clear()
572                 sitequery=[]
573                 pcuquery=[]
574                 nodequery=[]
575                 actions=[]
576                 exceptions = None
577
578                 try: since = int(since)
579                 except: since = 7
580
581                 for key in data:
582                         print key, data[key]
583
584                 if 'submit' in data.keys() or 'type' in data.keys():
585                         if hostname: data['hostname'] = hostname
586                         self.nodeaction(**data)
587                 if 'exceptions' in data:
588                         exceptions = data['exceptions']
589
590                 if 'query' in data:
591                         obj = data['query']
592                         if len(obj.split(".")) > 1: hostname = obj
593                         else: loginbase=obj
594
595                 if pcuid:
596                         print "pcuid: %s" % pcuid
597                         pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
598                         loginbase = PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base']
599
600                 if hostname:
601                         node = FindbadNodeRecord.get_latest_by(hostname=hostname)
602                         loginbase = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
603
604                 if loginbase:
605                         actions = ActionRecord.query.filter_by(loginbase=loginbase
606                                                         ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
607                                                         ).order_by(ActionRecord.date_created.desc())
608                         actions = [ a for a in actions ]
609                         sitequery = [HistorySiteRecord.by_loginbase(loginbase)]
610                         pcus = {}
611                         for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
612                                         # NOTE: reformat some fields.
613                                         agg = prep_node_for_display(node)
614                                         nodequery += [agg]
615                                         if agg.pcu: #.pcu.plc_pcuid:    # not None
616                                                 #pcu = FindbadPCURecord.get_latest_by(plc_pcuid=agg.plc_pcuid)
617                                                 #prep_pcu_for_display(pcu)
618                                                 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
619
620                         for pcuid_key in pcus:
621                                 pcuquery += [pcus[pcuid_key]]
622
623                 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions, since=since, exceptions=exceptions)
624
625         @expose(template="monitorweb.templates.pcuhistory")
626         def pcuhistory(self, pcu_id=None):
627                 query = []
628                 if pcu_id:
629                         fbnode = HistoryPCURecord.get_by(plc_pcuid=pcu_id)
630                         l = fbnode.versions[-100:]
631                         l.reverse()
632                         for pcu in l:
633                                 #prep_node_for_display(node)
634                                 query.append(pcu)
635
636                 return dict(query=query, pcu_id=pcu_id)
637
638         @expose(template="monitorweb.templates.nodescanhistory")
639         def nodescanhistory(self, hostname=None, length=10):
640                 try: length = int(length)
641                 except: length = 21
642
643                 fbnode = FindbadNodeRecord.get_by(hostname=hostname)
644                 # TODO: add links for earlier history if desired.
645                 l = fbnode.versions[-length:]
646                 l.reverse()
647                 query=[]
648                 for node in l:
649                         agg = prep_node_for_display(node, pcuhash=None, preppcu=False, asofdate=node.timestamp)
650                         query.append(agg)
651
652                 if 'length' in request.params: 
653                         del request.params['length']
654                 return dict(query=query, hostname=hostname, params=request.params)
655
656         @expose(template="monitorweb.templates.nodehistory")
657         def nodehistory(self, hostname=None):
658                 query = []
659                 if hostname:
660                         fbnode = HistoryNodeRecord.get_by(hostname=hostname)
661                         l = fbnode.versions[-100:]
662                         l.reverse()
663                         for node in l:
664                                 #prep_node_for_display(node)
665                                 query.append(node)
666
667                 return dict(query=query, hostname=hostname)
668
669         @expose(template="monitorweb.templates.sitehistory")
670         def sitehistory(self, loginbase=None):
671                 query = []
672                 if loginbase:
673                         fbsite = HistorySiteRecord.get_by(loginbase=loginbase)
674                         # TODO: add links for earlier history if desired.
675                         l = fbsite.versions[-100:]
676                         l.reverse()
677                         for site in l:
678                                 query.append(site)
679                 return dict(query=query, loginbase=loginbase)
680
681
682         @expose(template="monitorweb.templates.pculist")
683         def pcu(self, filter='all'):
684                 print "PCUVIEW------------------"
685                 print "befor-len: ", len( [ i for i in session] )
686                 session.flush(); session.clear()
687                 print "after-len: ", len( [ i for i in session] )
688                 fbquery = FindbadPCURecord.get_all_latest()
689                 query = []
690                 filtercount = {'ok' : 0, 'NetDown': 0, 'Not_Run' : 0, 'pending' : 0, 'all' : 0}
691                 for node in fbquery:
692
693                         # NOTE: count filter
694                         if node.reboot_trial_status == str(0):
695                                 filtercount['ok'] += 1
696                         elif node.reboot_trial_status == 'NetDown' or node.reboot_trial_status == 'Not_Run':
697                                 filtercount[node.reboot_trial_status] += 1
698                         else:
699                                 filtercount['pending'] += 1
700
701                         pcuagg = prep_pcu_for_display(node)
702
703                         # NOTE: apply filter
704                         if filter == "all":
705                                 query.append(pcuagg)
706                         elif filter == "ok" and node.reboot_trial_status == str(0):
707                                 query.append(pcuagg)
708                         elif filter == node.reboot_trial_status:
709                                 query.append(pcuagg)
710                         elif filter == "pending":
711                                 # TODO: look in message logs...
712                                 if node.reboot_trial_status != str(0) and \
713                                         node.reboot_trial_status != 'NetDown' and \
714                                         node.reboot_trial_status != 'Not_Run':
715
716                                         query.append(pcuagg)
717                                 
718                 return dict(query=query, fc=filtercount)
719
720         @expose(template="monitorweb.templates.sitelist")
721         def site(self, filter='all'):
722                 print "SITE------------------"
723                 print "befor-len: ", len( [ i for i in session] )
724                 session.flush(); session.clear()
725                 print "after-len: ", len( [ i for i in session] )
726                 filtercount = {'good' : 0, 'down': 0, 'online':0, 'offline' : 0, 'new' : 0, 'pending' : 0, 'all' : 0}
727                 fbquery = HistorySiteRecord.query.all()
728                 query = []
729                 for site in fbquery:
730                         # count filter
731                         filtercount['all'] += 1
732                         if site.new and site.slices_used == 0 and not site.enabled:
733                                 filtercount['new'] += 1
734                         elif not site.enabled:
735                                 filtercount['pending'] += 1
736                         elif site.status in ['good', 'online']:
737                                 filtercount['good'] += 1
738                         elif site.status in ['down', 'offline']:
739                                 filtercount['down'] += 1
740
741                         # apply filter
742                         if filter == "all":
743                                 query.append(site)
744                         elif filter == 'new' and site.new and site.slices_used == 0 and not site.enabled:
745                                 query.append(site)
746                         elif filter == "pending" and not site.enabled:
747                                 query.append(site)
748                         elif filter == 'good' and site.status in ['good', 'online']:
749                                 query.append(site)
750                         elif filter == 'down' and site.status in ['down', 'offline']:
751                                 query.append(site)
752                                 
753                 return dict(query=query, fc=filtercount)
754         @expose(template="monitorweb.templates.sitesummary")
755         def sitesummary(self, loginbase="princeton"):
756                 nodequery = []
757                 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
758                         agg = prep_node_for_display(node)
759                         nodequery += [agg]
760                 
761                 return dict(nodequery=nodequery, loginbase=loginbase)
762
763         @expose(template="monitorweb.templates.summary")
764         def summary(self, since=7):
765                 sumdata = {}
766                 sumdata['nodes'] = {}
767                 sumdata['sites'] = {}
768                 sumdata['pcus'] = {}
769
770                 def summarize(query, type):
771                         for o in query:
772                                 if o.status not in sumdata[type]:
773                                         sumdata[type][o.status] = 0
774                                 sumdata[type][o.status] += 1
775
776                 fbquery = HistorySiteRecord.query.all()
777                 summarize(fbquery, 'sites')
778                 fbquery = HistoryPCURecord.query.all()
779                 summarize(fbquery, 'pcus')
780                 fbquery = HistoryNodeRecord.query.all()
781                 summarize(fbquery, 'nodes')
782
783                 if 'monitordebug' in sumdata['nodes']:
784                         d = sumdata['nodes']['monitordebug']
785                         del sumdata['nodes']['monitordebug']
786                         sumdata['nodes']['failboot'] = d
787                 
788                 return dict(sumdata=sumdata, setorder=['good', 'offline', 'down', 'online']) 
789
790         @expose(template="monitorweb.templates.actionsummary")
791         def actionsummary(self, since=7):
792                 from monitor.wrapper.emailTxt import mailtxt
793
794                 types = filter(lambda x: 'notice' in x, dir(mailtxt))
795                 results = {}
796
797                 print mon_metadata.bind
798                 if session.bind is None:
799                         #TODO: figure out why this value gets cleared out...
800                         session.bind = mon_metadata.bind
801                 result = session.execute("select distinct(action_type) from actionrecord;")
802
803                 types = [r[0] for r in result]
804
805                 try: since = int(since)
806                 except: since = 7
807
808                 for  t in types:
809                         acts = ActionRecord.query.filter(ActionRecord.action_type==t
810                                         ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since))
811                         results[t] = acts.count()
812                 return dict(results=results)
813
814         @expose(template="monitorweb.templates.actionlist")
815         def actionlist(self, action_type='down_notice', since=7, loginbase=None):
816
817                 try: since = int(since)
818                 except: since = 7
819
820                 if loginbase:
821                         acts = ActionRecord.query.filter_by(loginbase=loginbase
822                                 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
823                                 ).order_by(ActionRecord.date_created.desc())
824                 else:
825                         acts = ActionRecord.query.filter(ActionRecord.action_type==action_type
826                                 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
827                                 ).order_by(ActionRecord.date_created.desc())
828                 query = [ a for a in acts ]
829                 
830                 return dict(actions=query, action_type=action_type, since=since)