add pcu_name to pcufailed_notice
[monitor.git] / web / MonitorWeb / monitorweb / controllers.py
index 60bdbcc..4a74782 100644 (file)
@@ -9,8 +9,6 @@ import cherrypy
 import re
 from monitor.database.info.model import *
 #from monitor.database.zabbixapi.model import *
-#from monitor.database.dborm import zab_session as session
-#from monitor.database.dborm import zab_metadata as metadata
 from monitor_xmlrpc import MonitorXmlrpcServer
 
 from monitor import reboot
@@ -21,6 +19,67 @@ from monitor.wrapper.plccache import plcdb_hn2lb as site_hn2lb
 
 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>&#160;</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
@@ -87,6 +146,8 @@ def prep_pcu_for_display(pcu):
        except:
                agg.loginbase = "unknown"
 
+       agg.pcuhist = HistoryPCURecord.query.get(pcu.plc_pcuid)
+
        agg.ports = format_ports(pcu.port_status, pcu.plc_pcu_stats['model'])
        agg.status = format_pcu_shortstatus(pcu)
 
@@ -108,11 +169,23 @@ def prep_pcu_for_display(pcu):
 class NodeWidget(widgets.Widget):
        pass
 
-def prep_node_for_display(node, pcuhash=None):
+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
 
-       if node.plc_pcuid:
+       if node.plc_pcuid and preppcu:
                if pcuhash:
                        pcu = pcuhash[node.plc_pcuid]
                else:
@@ -145,6 +218,10 @@ def prep_node_for_display(node, pcuhash=None):
 
        if agg.loginbase:
                agg.site = HistorySiteRecord.by_loginbase(agg.loginbase)
+
+               if asofdate:
+                       agg.site = agg.site.get_as_of(asofdate)
+
                if agg.site is None:
                        # TODO: need a cleaner fix for this...
                        agg.site = HistorySiteRecord.by_loginbase("pl")
@@ -152,6 +229,8 @@ def prep_node_for_display(node, pcuhash=None):
                                agg.site = HistorySiteRecord.by_loginbase("ple")
 
        agg.history = HistoryNodeRecord.by_hostname(node.hostname)
+       if asofdate:
+               agg.history = agg.history.get_as_of(asofdate)
 
        agg.ports = format_ports(node.port_status)
 
@@ -171,33 +250,103 @@ class Root(controllers.RootController, MonitorXmlrpcServer):
                flash("Welcome To MyOps!")
                return dict(now=time.ctime())
 
-       @expose(template="monitorweb.templates.nodelist")
-       def node2(self, filter='boot'):
+       @expose(template="monitorweb.templates.nodelist", allow_json=True)
+       def node3(self, filter=None):
+               nhquery = HistoryNodeRecord.query.all()
+               query = []
+               for nh in nhquery:
+                       if filter:
+                               if nh.status == filter:
+                                       query.append(nh)
+                       else:
+                               query.append(nh)
 
-               fbquery = FindbadNodeRecord.get_all_latest()
-               fbpcus = FindbadPCURecord.get_all_latest()
-               def fbtohash(fbpculist):
-                       h = {}
-                       for p in fbpculist:
-                               h[p.plc_pcuid] = p
+               rquery=[]
+               for q in query:
+                       fb = FindbadNodeRecord.get_latest_by(hostname=q.hostname)
+                       rquery.append(fb)
 
-               pcuhash = fbtohash(fbpcus)
+               return dict(now=time.ctime(), query=rquery)
 
+       @expose(template="monitorweb.templates.nodelist", allow_json=True)
+       def node2(self, filter=None):
+               nhquery = HistoryNodeRecord.query.all()
                query = []
-               for node in fbquery:
-                       # NOTE: reformat some fields.
-                       agg = prep_node_for_display(node, pcuhash)
+               for nh in nhquery:
+                       if filter:
+                               if nh.status == filter:
+                                       query.append(nh)
+                       else:
+                               query.append(nh)
 
-                       if not agg.history:
-                               continue
+               rquery=[]
+               for q in query:
+                       fb = FindbadNodeRecord.get_latest_by(hostname=q.hostname)
+                       agg = prep_node_for_display(fb)
+                       rquery.append(agg)
 
-                       query.append(agg)
-                               
                widget = NodeWidget(template='monitorweb.templates.node_template')
-               return dict(now=time.ctime(), query=query, nodewidget=widget)
+               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()
@@ -310,14 +459,116 @@ class Root(controllers.RootController, MonitorXmlrpcServer):
                        raise RuntimeError("Unknown action given")
                return
 
+       @expose(template="monitorweb.templates.simpleview")
+       def simpleview(self, **data):
+               return self.pre_view(**data)
+
+       @expose(template="monitorweb.templates.detailview")
+       def detailview(self, **data):
+               return self.pre_view(**data)
+
+       def pre_view(self, **data):
+               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']
+                       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 'hostname' in data:
+                       hostname = data['hostname']
+
+               if 'pcuid' in data:
+                       try: pcuid = int(data['pcuid'])
+                       except: pcuid = None
+
+               if 'since' in data:
+                       try: since = int(since)
+                       except: since = 20
+
+               if pcuid:
+                       print "pcuid: %s" % pcuid
+                       pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
+                       loginbase_list += [ PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base'] ]
+
+               if hostname:
+                       if not objtype:
+                               nodes = [ FindbadNodeRecord.get_latest_by(hostname=hostname) ]
+                       else:
+                               nodes = FindbadNodeRecord.query.filter(FindbadNodeRecord.hostname.like(hostname)) 
+
+                       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 ]
+
+               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
        @expose(template="monitorweb.templates.pcuview")
        @exception_handler(nodeaction_handler,"isinstance(tg_exceptions,RuntimeError)")
        def pcuview(self, loginbase=None, pcuid=None, hostname=None, since=20, **data):
-               print "PCUVIEW------------------"
-               print "befor-len: ", len( [ i for i in session] )
                session.flush(); session.clear()
-               print "after-len: ", len( [ i for i in session] )
                sitequery=[]
                pcuquery=[]
                nodequery=[]
@@ -336,6 +587,11 @@ class Root(controllers.RootController, MonitorXmlrpcServer):
                if 'exceptions' in data:
                        exceptions = data['exceptions']
 
+               if 'query' in data:
+                       obj = data['query']
+                       if len(obj.split(".")) > 1: hostname = obj
+                       else: loginbase=obj
+
                if pcuid:
                        print "pcuid: %s" % pcuid
                        pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
@@ -379,18 +635,28 @@ class Root(controllers.RootController, MonitorXmlrpcServer):
 
                return dict(query=query, pcu_id=pcu_id)
 
+       @expose(template="monitorweb.templates.nodescanhistory")
+       def nodescanhistory(self, hostname=None, length=10):
+               try: length = int(length)
+               except: length = 21
+
+               fbnode = FindbadNodeRecord.get_by(hostname=hostname)
+               # TODO: add links for earlier history if desired.
+               l = fbnode.versions[-length:]
+               l.reverse()
+               query=[]
+               for node in l:
+                       agg = prep_node_for_display(node, pcuhash=None, preppcu=False, asofdate=node.timestamp)
+                       query.append(agg)
+
+               if 'length' in request.params: 
+                       del request.params['length']
+               return dict(query=query, hostname=hostname, params=request.params)
+
        @expose(template="monitorweb.templates.nodehistory")
        def nodehistory(self, hostname=None):
                query = []
                if hostname:
-                       #fbnode = FindbadNodeRecord.get_by(hostname=hostname)
-                       ## TODO: add links for earlier history if desired.
-                       #l = fbnode.versions[-100:]
-                       #l.reverse()
-                       #for node in l:
-                       #       prep_node_for_display(node)
-                       #       query.append(node)
-
                        fbnode = HistoryNodeRecord.get_by(hostname=hostname)
                        l = fbnode.versions[-100:]
                        l.reverse()
@@ -528,6 +794,14 @@ class Root(controllers.RootController, MonitorXmlrpcServer):
                types = filter(lambda x: 'notice' in x, dir(mailtxt))
                results = {}
 
+               print mon_metadata.bind
+               if session.bind is None:
+                       #TODO: figure out why this value gets cleared out...
+                       session.bind = mon_metadata.bind
+               result = session.execute("select distinct(action_type) from actionrecord;")
+
+               types = [r[0] for r in result]
+
                try: since = int(since)
                except: since = 7