1 import turbogears as tg
2 from turbogears import controllers, expose, flash, exception_handler, redirect
3 from turbogears import widgets
4 from cherrypy import request, response
6 # from monitorweb import model
8 # log = logging.getLogger("monitorweb.controllers")
11 from monitor.database.info.model import *
12 #from monitor.database.zabbixapi.model import *
13 from monitor_xmlrpc import MonitorXmlrpcServer
14 from controllers_local import LocalExtensions
15 from pcucontrol.reboot import pcu_name
17 from monitor import util
18 from monitor import reboot
19 from monitor import bootman
20 from monitor import scanapi
21 from monitor import config
24 from monitor.wrapper.plccache import plcdb_hn2lb as site_hn2lb
26 from monitorweb.templates.links import *
28 def session_clear_all():
32 except AttributeError: # SQLAlchemy < 0.5.1
35 class ObjectQueryFields(widgets.WidgetsList):
36 """The WidgetsList defines the fields of the form."""
41 class NodeQueryFields(widgets.WidgetsList):
42 """The WidgetsList defines the fields of the form."""
44 object = widgets.RadioButtonList(label="Query Type", options=[('nodes', 'All Nodes'),
45 ('nodehistory', 'Single Node History'),
46 #('sites', 'All Sites'),
47 #('sitehistory', 'Single Site History'),
49 nodehistory_hostname = widgets.TextField(label="Hostname Node History", attrs={'size':30})
51 hostname = widgets.CheckBox(label="Hostname")
52 firewall = widgets.CheckBox(label="Firewall?")
53 fs_status = widgets.CheckBox(label="Filesystem Status")
54 ssh_status = widgets.CheckBox(label="SSH Status")
55 ssh_error = widgets.CheckBox(label="SSH Errors")
56 dns_status = widgets.CheckBox(label="DNS Status")
57 iptables_status = widgets.CheckBox(label="IP Tables Status")
58 nm_status = widgets.CheckBox(label="NM Status")
59 princeton_comon_dir = widgets.CheckBox(label="CoMon Dir")
60 princeton_comon_running = widgets.CheckBox(label="CoMon Running")
61 princeton_comon_procs = widgets.CheckBox(label="CoMon Processes")
62 external_dns_status = widgets.CheckBox(label="Hostname Resolves?")
63 kernel_version = widgets.CheckBox(label="Kernel")
64 bootcd_version = widgets.CheckBox(label="BootCD")
65 boot_server = widgets.CheckBox(label="Boot Server")
66 install_date = widgets.CheckBox(label="Installation Date")
67 observed_status = widgets.CheckBox(label="Observed Status")
68 uptime = widgets.CheckBox(label="Uptime")
69 traceroute = widgets.CheckBox(label="Traceroute")
70 port_status = widgets.CheckBox(label="Port Status")
71 plc_pcuid = widgets.CheckBox(label="PCU ID")
72 rpms = widgets.CheckBox(label="RPM")
73 rpmvalue = widgets.TextField(label="RPM Pattern")
75 class QueryForm(widgets.TableForm):
77 <form xmlns:py="http://purl.org/kid/ns#"
85 <div py:for="field in hidden_fields"
86 py:replace="field.display(value_for(field), **params_for(field))"
88 <table border="0" cellspacing="0" cellpadding="2" py:attrs="table_attrs">
89 <tr py:for="i, field in enumerate(fields)"
90 class="${i%2 and 'odd' or 'even'}"
93 <label class="fieldlabel" for="${field.field_id}" py:content="field.label" />
96 <span py:replace="field.display(value_for(field), **params_for(field))" />
97 <span py:if="error_for(field)" class="fielderror" py:content="error_for(field)" />
98 <span py:if="field.help_text" class="fieldhelp" py:content="field.help_text" />
103 <td py:content="submit.display(submit_text)" />
109 def getNodeQueryForm():
110 return QueryForm(fields=NodeQueryFields(), action="query")
112 # make it easier group objects without invoking the elixir auto-write feature.
113 class aggregate: pass
116 def query_to_dict(query):
117 """ take a url query string and chop it up """
119 query_fields = query.split('&')
120 for f in query_fields:
121 (k,v) = urllib.splitvalue(f)
126 def format_ports(data, pcumodel=None):
131 supported_ports=reboot.model_to_object(pcumodel).supported_ports
133 # ports of a production node
134 supported_ports=[22,80,806]
136 if data and len(data.keys()) > 0 :
137 for port in supported_ports:
139 state = data[str(port)]
143 if state == "filtered":
146 retval.append( (port, state) )
149 retval = [( "Closed/Filtered", "state" )]
151 if filtered_length == len(supported_ports):
152 retval = [( "All Filtered", "state" )]
156 def format_pcu_shortstatus(pcu):
159 if pcu.reboot_trial_status == str(0) or pcu.reboot_trial_status == "Test: No error":
161 elif pcu.reboot_trial_status == "NetDown" or pcu.reboot_trial_status == "Not_Run":
162 status = pcu.reboot_trial_status
168 def prep_pcu_for_display(pcu):
173 agg.loginbase = PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base']
175 agg.loginbase = "unknown"
177 agg.pcuhist = HistoryPCURecord.query.get(pcu.plc_pcuid)
179 agg.ports = format_ports(pcu.port_status, pcu.plc_pcu_stats['model'])
180 agg.status = format_pcu_shortstatus(pcu)
181 agg.pcu_name = pcu_name(pcu.plc_pcu_stats)
183 #print pcu.entry_complete
184 agg.entry_complete_str = pcu.entry_complete
185 #pcu.entry_complete_str += "".join([ f[0] for f in pcu.entry_complete.split() ])
186 if pcu.dns_status == "NOHOSTNAME":
187 agg.dns_short_status = 'NoHost'
188 elif pcu.dns_status == "DNS-OK":
189 agg.dns_short_status = 'Ok'
190 elif pcu.dns_status == "DNS-NOENTRY":
191 agg.dns_short_status = 'NoEntry'
192 elif pcu.dns_status == "NO-DNS-OR-IP":
193 agg.dns_short_status = 'NoHostOrIP'
194 elif pcu.dns_status == "DNS-MISMATCH":
195 agg.dns_short_status = 'Mismatch'
198 class ActionListWidget(widgets.Widget):
201 class NodeWidget(widgets.Widget):
204 def prep_nodehist(node):
207 agg.loginbase = "unknown"
209 agg.loginbase = PlcSite.query.get(node.plc_siteid).plc_site_stats['login_base']
211 agg.loginbase = "exception"
216 def prep_node_for_display(node, pcuhash=None, preppcu=True, asofdate=None):
220 if node.plc_pcuid and preppcu:
222 pcu = pcuhash[node.plc_pcuid]
224 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=node.plc_pcuid)
227 agg.pcu_status = pcu.reboot_trial_status
228 agg.pcu_short_status = format_pcu_shortstatus(pcu)
229 agg.pcu = prep_pcu_for_display(pcu)
231 agg.pcu_short_status = "none"
232 agg.pcu_status = "nodata"
236 agg.pcu_status = "nopcu"
237 agg.pcu_short_status = "none"
241 if node.kernel_version:
242 agg.kernel = node.kernel_version.split()[2]
247 agg.loginbase = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
249 agg.loginbase = "unknown"
252 agg.site = HistorySiteRecord.by_loginbase(agg.loginbase)
255 agg.site = agg.site.get_as_of(asofdate)
258 # TODO: need a cleaner fix for this...
259 agg.site = HistorySiteRecord.by_loginbase("pl")
261 agg.site = HistorySiteRecord.by_loginbase("ple")
263 agg.history = HistoryNodeRecord.by_hostname(node.hostname)
265 agg.history = agg.history.get_as_of(asofdate)
267 agg.ports = format_ports(node.port_status)
270 exists = node.plc_node_stats['last_contact']
272 # TODO: this should not assign to the fb object!
273 node.plc_node_stats = {'last_contact' : None}
278 class Root(controllers.RootController, MonitorXmlrpcServer, LocalExtensions):
279 @expose(template="monitorweb.templates.welcome")
281 # log.debug("Happy TurboGears Controller Responding For Duty")
282 flash("Welcome To MyOps!")
283 return dict(now=time.ctime())
285 @expose(template="monitorweb.templates.nodelist", allow_json=True)
286 def node3(self, filter=None):
287 nhquery = HistoryNodeRecord.query.all()
291 if nh.status == filter:
298 fb = FindbadNodeRecord.get_latest_by(hostname=q.hostname)
301 return dict(now=time.ctime(), query=rquery)
303 def node_query(self, filter):
304 nhquery = HistoryNodeRecord.query.all()
308 if nh.status == filter:
315 fb = FindbadNodeRecord.get_latest_by(hostname=q.hostname)
316 agg = prep_node_for_display(fb)
320 @expose("cheetah:monitorweb.templates.nodelist_plain", as_format="plain",
321 accept_format="text/plain", content_type="text/plain")
322 @expose(template="monitorweb.templates.nodelist", allow_json=True)
323 def node2(self, filter=None):
324 rquery=self.node_query(filter)
325 widget = NodeWidget(template='monitorweb.templates.node_template')
326 return dict(now=time.ctime(), query=rquery, nodewidget=widget)
328 @expose("cheetah:monitorweb.templates.query_plain", as_format="plain",
329 accept_format="text/plain", content_type="text/plain")
330 @expose(template="monitorweb.templates.query", allow_json=True)
331 def query(self, **data):
339 if 'object' in data and data['object'] == "nodes":
340 fbquery = FindbadNodeRecord.get_all_latest()
341 elif 'object' in data and data['object'] == "nodehistory":
342 hostname = data['nodehistory_hostname']
343 data['date_checked'] = 'date_checked'
344 fbrecord = FindbadNodeRecord.get_by(hostname=hostname)
345 fbquery = fbrecord.versions[-500:]
349 # NOTE: reformat some fields.
350 if type(node) is not type(FindbadNodeRecord):
351 agg = node.__dict__.copy()
354 if agg['plc_node_stats']:
355 agg.update(agg['plc_node_stats'])
356 if agg['install_date']:
357 agg['install_date'] = time.mktime(time.strptime(agg['install_date'], "%a %b %d %H:%M:%S %Y"))
358 if agg['kernel_version']:
359 agg['kernel_version'] = agg['kernel_version'].split()[2]
360 if 'traceroute' in data and agg['traceroute']:
361 agg['traceroute'] = "<pre>" + agg['traceroute'] + "</pre>"
362 if 'rpmvalue' in data and 'rpms' in data:
364 rpm_list = agg['rpms'].split()
365 rpm_list = filter(lambda x: re.match(data['rpmvalue'], x, re.I),
367 agg['rpms'] = " ".join(rpm_list)
375 del fields['rpmvalue']
376 del fields['nodehistory_hostname']
378 return dict(now=time.ctime(), query=query, fields=fields, data=data, queryform=getNodeQueryForm())
380 @expose(template="monitorweb.templates.nodefast", allow_json=True)
381 def node(self, filter=None):
382 nhquery = HistoryNodeRecord.query.all()
386 if nh.status == filter:
387 agg = prep_nodehist(nh)
390 agg = prep_nodehist(nh)
393 return dict(now=time.ctime(), query=query)
395 @expose(template="monitorweb.templates.nodelist")
396 def nodeslow(self, filter='boot'):
397 print "NODE------------------"
398 print "befor-len: ", len( [ i for i in session] )
400 print "after-len: ", len( [ i for i in session] )
401 fbquery = FindbadNodeRecord.get_all_latest()
403 filtercount = {'down' : 0, 'boot': 0, 'debug' : 0, 'diagnose' : 0, 'disabled': 0,
404 'neverboot' : 0, 'pending' : 0, 'all' : 0, None : 0}
406 # NOTE: reformat some fields.
407 agg = prep_node_for_display(node)
412 if agg.history.status in ['down', 'offline']:
413 if node.plc_node_stats and node.plc_node_stats['last_contact'] != None:
414 filtercount['down'] += 1
416 filtercount['neverboot'] += 1
417 elif agg.history.status in ['good', 'online']:
418 filtercount['boot'] += 1
419 elif agg.history.status in ['debug', 'monitordebug']:
420 filtercount['debug'] += 1
422 if filtercount.has_key(agg.history.status):
423 filtercount[agg.history.status] += 1
427 if filter == "neverboot":
428 if not node.plc_node_stats or node.plc_node_stats['last_contact'] == None:
430 elif filter == "all":
432 elif filter == agg.history.status:
434 elif filter == 'boot':
438 widget = NodeWidget(template='monitorweb.templates.node_template')
439 return dict(now=time.ctime(), query=query, fc=filtercount, nodewidget=widget)
441 def nodeaction_handler(self, tg_exceptions=None):
442 """Handle any kind of error."""
443 print "NODEACTION_HANDLER------------------"
445 if 'pcuid' in request.params:
446 pcuid = request.params['pcuid']
448 refurl = request.headers.get("Referer",link("pcu"))
451 # TODO: do this more intelligently...
452 uri_fields = urllib.splitquery(refurl)
453 if uri_fields[1] is not None:
454 val = query_to_dict(uri_fields[1])
457 elif 'hostname' in val:
458 pcuid = FindbadNodeRecord.get_latest_by(hostname=val['hostname']).plc_pcuid
464 cherry_trail = cherrypy._cputil.get_object_trail()
465 for i in cherry_trail:
469 return self.pcuview(None, pcuid, **dict(exceptions=tg_exceptions))
471 def nodeaction(self, **data):
472 print "NODEACTION------------------"
473 for item in data.keys():
474 print "%s %s" % ( item, data[item] )
476 if 'hostname' in data:
477 hostname = data['hostname']
479 flash("No hostname given in submitted data")
482 if 'submit' in data or 'type' in data:
484 action = data['submit']
486 action = data['type']
488 flash("No submit action given in submitted data")
491 if action == "Reboot":
492 print "REBOOT: %s" % hostname
493 ret = reboot.reboot_str(str(hostname))
495 if ret: raise RuntimeError("Error using PCU: " + str(ret))
496 flash("Reboot appeared to work. Allow at most 5 minutes. Then run ExternalScan to check current status.")
498 elif action == "ExternalScan":
499 scanapi.externalprobe(str(hostname))
500 flash("External Scan Successful!")
501 elif action == "InternalScan":
502 scanapi.internalprobe(str(hostname))
503 flash("Internal Scan Successful!")
506 raise RuntimeError("Unknown action given")
509 @expose(template="monitorweb.templates.simpleview")
510 def simpleview(self, **data):
511 return self.pre_view(**data)
513 @expose(template="monitorweb.templates.simpleview")
514 def pcuview(self, **data):
515 return self.pre_view(**data)
517 @expose(template="monitorweb.templates.detailview")
518 def detailview(self, **data):
519 return self.pre_view(**data)
522 def pre_view(self, **data):
530 # if objtype is not None, then treat 'hostname' or 'loginbase' as a search pattern
545 fields = obj.split(":")
548 obj = fields[1].replace("*", "%")
551 if len(obj.split(".")) > 1 or objtype == "node":
556 if 'loginbase' in data:
557 loginbase = data['loginbase']
559 if 'hostname' in data:
560 hostname = data['hostname']
563 try: pcuid = int(data['pcuid'])
567 try: since = int(since)
571 print "pcuid: %s" % pcuid
572 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
573 loginbase_list += [ PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base'] ]
577 nodes = [ FindbadNodeRecord.get_latest_by(hostname=hostname) ]
579 nodes = FindbadNodeRecord.query.filter(FindbadNodeRecord.hostname.like(hostname))
582 lb = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
583 if lb not in loginbase_list:
584 loginbase_list += [ lb ]
588 loginbase_list = [ loginbase ]
590 loginbase_list = HistorySiteRecord.query.filter(HistorySiteRecord.loginbase.like(loginbase))
591 loginbase_list = [ l.loginbase for l in loginbase_list ]
595 for loginbase in loginbase_list:
596 actions = ActionRecord.query.filter_by(loginbase=loginbase
597 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
598 ).order_by(ActionRecord.date_created.desc())
599 actions_list += [ a for a in actions ]
600 site = HistorySiteRecord.by_loginbase(loginbase)
602 sitequery.append(site)
603 # NOTE: because a single pcu may be assigned to multiple hosts,
604 # track unique pcus by their plc_pcuid, then turn dict into list
606 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
607 # NOTE: reformat some fields.
608 agg = prep_node_for_display(node)
611 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
613 for pcuid_key in pcus:
614 pcuquery += [pcus[pcuid_key]]
618 # print type(a.node.hostname)
619 nodequery.sort(lambda a,b: cmp(a.node.hostname,b.node.hostname))
620 pcuquery.sort(lambda a,b: cmp(a.pcu_name,b.pcu_name))
622 actionlist_widget = ActionListWidget(template='monitorweb.templates.actionlist_template')
623 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions_list, actionlist_widget=actionlist_widget, since=since, exceptions=exceptions)
626 # TODO: add form validation
627 @expose(template="monitorweb.templates.pcuview")
628 @exception_handler(nodeaction_handler,"isinstance(tg_exceptions,RuntimeError)")
629 def pcuviewold(self, loginbase=None, pcuid=None, hostname=None, since=20, **data):
637 try: since = int(since)
643 if 'submit' in data.keys() or 'type' in data.keys():
644 if hostname: data['hostname'] = hostname
645 self.nodeaction(**data)
646 if 'exceptions' in data:
647 exceptions = data['exceptions']
651 if len(obj.split(".")) > 1: hostname = obj
655 print "pcuid: %s" % pcuid
656 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
657 loginbase = PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base']
660 node = FindbadNodeRecord.get_latest_by(hostname=hostname)
661 loginbase = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
664 actions = ActionRecord.query.filter_by(loginbase=loginbase
665 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
666 ).order_by(ActionRecord.date_created.desc())
667 actions = [ a for a in actions ]
668 sitequery = [HistorySiteRecord.by_loginbase(loginbase)]
670 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
671 # NOTE: reformat some fields.
672 agg = prep_node_for_display(node)
674 if agg.pcu: #.pcu.plc_pcuid: # not None
675 #pcu = FindbadPCURecord.get_latest_by(plc_pcuid=agg.plc_pcuid)
676 #prep_pcu_for_display(pcu)
677 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
679 for pcuid_key in pcus:
680 pcuquery += [pcus[pcuid_key]]
682 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions, since=since, exceptions=exceptions)
684 @expose(template="monitorweb.templates.pcuhistory")
685 def pcuhistory(self, pcu_id=None):
688 fbnode = HistoryPCURecord.get_by(plc_pcuid=pcu_id)
689 l = fbnode.versions[-1000:]
692 #prep_node_for_display(node)
695 return dict(query=query, pcu_id=pcu_id)
697 @expose(template="monitorweb.templates.nodescanhistory")
698 def nodescanhistory(self, hostname=None, length=10):
699 try: length = int(length)
702 fbnode = FindbadNodeRecord.get_by(hostname=hostname)
703 # TODO: add links for earlier history if desired.
704 l = fbnode.versions[-length:]
708 agg = prep_node_for_display(node, pcuhash=None, preppcu=False, asofdate=node.timestamp)
711 if 'length' in request.params:
712 del request.params['length']
713 return dict(query=query, hostname=hostname, params=request.params)
715 @expose(template="monitorweb.templates.nodehistory")
716 def nodehistory(self, hostname=None):
719 fbnode = HistoryNodeRecord.get_by(hostname=hostname)
720 l = fbnode.versions[-100:]
723 #prep_node_for_display(node)
726 return dict(query=query, hostname=hostname)
728 @expose(template="monitorweb.templates.sitehistory")
729 def sitehistory(self, loginbase=None):
732 fbsite = HistorySiteRecord.get_by(loginbase=loginbase)
733 # TODO: add links for earlier history if desired.
734 l = fbsite.versions[-1000:]
738 return dict(query=query, loginbase=loginbase)
741 @expose("cheetah:monitorweb.templates.pculist_plain", as_format="plain",
742 accept_format="text/plain", content_type="text/plain")
743 @expose(template="monitorweb.templates.pculist")
744 def pcu(self, filter='all'):
745 print "PCUVIEW------------------"
746 print "befor-len: ", len( [ i for i in session] )
748 print "after-len: ", len( [ i for i in session] )
749 fbquery = FindbadPCURecord.get_all_latest()
751 filtercount = {'ok' : 0, 'NetDown': 0, 'Not_Run' : 0, 'pending' : 0, 'all' : 0}
755 if node.reboot_trial_status == str(0):
756 filtercount['ok'] += 1
757 elif node.reboot_trial_status == 'NetDown' or node.reboot_trial_status == 'Not_Run':
758 filtercount[node.reboot_trial_status] += 1
760 filtercount['pending'] += 1
762 pcuagg = prep_pcu_for_display(node)
767 elif filter == "ok" and node.reboot_trial_status == str(0):
769 elif filter == node.reboot_trial_status:
771 elif filter == "pending":
772 # TODO: look in message logs...
773 if node.reboot_trial_status != str(0) and \
774 node.reboot_trial_status != 'NetDown' and \
775 node.reboot_trial_status != 'Not_Run':
779 return dict(query=query, fc=filtercount)
781 @expose(template="monitorweb.templates.sitelist")
782 def site(self, filter='all'):
783 print "SITE------------------"
784 print "befor-len: ", len( [ i for i in session] )
786 print "after-len: ", len( [ i for i in session] )
787 filtercount = {'good' : 0, 'down': 0, 'online':0, 'offline' : 0, 'new' : 0, 'pending' : 0, 'all' : 0}
788 fbquery = HistorySiteRecord.query.all()
792 filtercount['all'] += 1
793 if site.new and site.slices_used == 0 and not site.enabled:
794 filtercount['new'] += 1
795 elif not site.enabled:
796 filtercount['pending'] += 1
797 elif site.status in ['good', 'online']:
798 filtercount['good'] += 1
799 elif site.status in ['down', 'offline']:
800 filtercount['down'] += 1
805 elif filter == 'new' and site.new and site.slices_used == 0 and not site.enabled:
807 elif filter == "pending" and not site.enabled:
809 elif filter == 'good' and site.status in ['good', 'online']:
811 elif filter == 'down' and site.status in ['down', 'offline']:
814 return dict(query=query, fc=filtercount)
815 @expose(template="monitorweb.templates.sitesummary")
816 def sitesummary(self, loginbase="princeton"):
818 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
819 agg = prep_node_for_display(node)
822 return dict(nodequery=nodequery, loginbase=loginbase)
824 @expose(template="monitorweb.templates.summary")
825 def summary(self, since=7):
827 sumdata['nodes'] = {}
828 sumdata['sites'] = {}
831 def summarize(query, type):
833 if o.status not in sumdata[type]:
834 sumdata[type][o.status] = 0
835 sumdata[type][o.status] += 1
837 fbquery = HistorySiteRecord.query.all()
838 summarize(fbquery, 'sites')
839 fbquery = HistoryPCURecord.query.all()
840 summarize(fbquery, 'pcus')
841 fbquery = HistoryNodeRecord.query.all()
842 summarize(fbquery, 'nodes')
844 if 'monitordebug' in sumdata['nodes']:
845 d = sumdata['nodes']['monitordebug']
846 del sumdata['nodes']['monitordebug']
847 sumdata['nodes']['failboot'] = d
849 return dict(sumdata=sumdata, setorder=['good', 'offline', 'down', 'online'])
851 @expose(template="monitorweb.templates.actionsummary")
852 def actionsummary(self, since=7):
853 from monitor.wrapper.emailTxt import mailtxt
855 types = filter(lambda x: 'notice' in x, dir(mailtxt))
858 print mon_metadata.bind
859 if session.bind is None:
860 #TODO: figure out why this value gets cleared out...
861 session.bind = mon_metadata.bind
862 result = session.execute("select distinct(action_type) from actionrecord;")
864 types = [r[0] for r in result]
866 try: since = int(since)
870 acts = ActionRecord.query.filter(ActionRecord.action_type==t
871 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since))
872 results[t] = acts.count()
873 return dict(results=results)
875 @expose(template="monitorweb.templates.actionlist")
876 def actionlist(self, since=7, action_type=None, loginbase=None):
878 try: since = int(since)
881 acts_query = ActionRecord.query.filter(
882 ActionRecord.date_created >= datetime.now() - timedelta(since)
885 acts_query = acts_query.filter_by(loginbase=loginbase)
888 acts_query = acts_query.filter(ActionRecord.action_type==action_type)
890 acts = acts_query.order_by(ActionRecord.date_created.desc())
892 query = [ a for a in acts ]
894 return dict(actions=query, action_type=action_type, since=since)
897 def upload(self, log, **keywords):
900 logtype_list = ['bm.log', ]
902 if 'hostname' in keywords:
903 hostname = keywords['hostname']
904 if 'type' in keywords and keywords['type'] in logtype_list:
905 logtype = keywords['type']
907 if not hostname: return ""
908 if not logtype: return "unknown logtype: %s" % logtype
910 short_target_filename = bootman.bootmanager_log_name(hostname)
911 abs_target_filename = os.path.join(config.MONITOR_BOOTMANAGER_LOG, short_target_filename)
912 print "write data: %s" % abs_target_filename
913 util.file.dumpFile(abs_target_filename, log.file.read())
914 bootman.bootmanager_log_action(hostname, short_target_filename, logtype)
917 print "redirecting 3"