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
16 from monitor import util
17 from monitor import reboot
18 from monitor import bootman
19 from monitor import scanapi
20 from monitor import config
23 from monitor.wrapper.plccache import plcdb_hn2lb as site_hn2lb
25 from monitorweb.templates.links import *
27 class ObjectQueryFields(widgets.WidgetsList):
28 """The WidgetsList defines the fields of the form."""
33 class NodeQueryFields(widgets.WidgetsList):
34 """The WidgetsList defines the fields of the form."""
36 object = widgets.RadioButtonList(label="Query Type", options=[('nodes', 'All Nodes'),
37 ('nodehistory', 'Single Node History'),
38 #('sites', 'All Sites'),
39 #('sitehistory', 'Single Site History'),
41 nodehistory_hostname = widgets.TextField(label="Hostname Node History", attrs={'size':30})
43 hostname = widgets.CheckBox(label="Hostname")
44 firewall = widgets.CheckBox(label="Firewall?")
45 fs_status = widgets.CheckBox(label="Filesystem Status")
46 ssh_status = widgets.CheckBox(label="SSH Status")
47 ssh_error = widgets.CheckBox(label="SSH Errors")
48 dns_status = widgets.CheckBox(label="DNS Status")
49 iptables_status = widgets.CheckBox(label="IP Tables Status")
50 nm_status = widgets.CheckBox(label="NM Status")
51 princeton_comon_dir = widgets.CheckBox(label="CoMon Dir")
52 princeton_comon_running = widgets.CheckBox(label="CoMon Running")
53 princeton_comon_procs = widgets.CheckBox(label="CoMon Processes")
54 external_dns_status = widgets.CheckBox(label="Hostname Resolves?")
55 kernel_version = widgets.CheckBox(label="Kernel")
56 bootcd_version = widgets.CheckBox(label="BootCD")
57 boot_server = widgets.CheckBox(label="Boot Server")
58 install_date = widgets.CheckBox(label="Installation Date")
59 observed_status = widgets.CheckBox(label="Observed Status")
60 uptime = widgets.CheckBox(label="Uptime")
61 traceroute = widgets.CheckBox(label="Traceroute")
62 port_status = widgets.CheckBox(label="Port Status")
63 plc_pcuid = widgets.CheckBox(label="PCU ID")
64 rpms = widgets.CheckBox(label="RPM")
65 rpmvalue = widgets.TextField(label="RPM Pattern")
67 class QueryForm(widgets.TableForm):
69 <form xmlns:py="http://purl.org/kid/ns#"
77 <div py:for="field in hidden_fields"
78 py:replace="field.display(value_for(field), **params_for(field))"
80 <table border="0" cellspacing="0" cellpadding="2" py:attrs="table_attrs">
81 <tr py:for="i, field in enumerate(fields)"
82 class="${i%2 and 'odd' or 'even'}"
85 <label class="fieldlabel" for="${field.field_id}" py:content="field.label" />
88 <span py:replace="field.display(value_for(field), **params_for(field))" />
89 <span py:if="error_for(field)" class="fielderror" py:content="error_for(field)" />
90 <span py:if="field.help_text" class="fieldhelp" py:content="field.help_text" />
95 <td py:content="submit.display(submit_text)" />
101 def getNodeQueryForm():
102 return QueryForm(fields=NodeQueryFields(), action="query")
104 # make it easier group objects without invoking the elixir auto-write feature.
105 class aggregate: pass
108 def query_to_dict(query):
109 """ take a url query string and chop it up """
111 query_fields = query.split('&')
112 for f in query_fields:
113 (k,v) = urllib.splitvalue(f)
118 def format_ports(data, pcumodel=None):
123 supported_ports=reboot.model_to_object(pcumodel).supported_ports
125 # ports of a production node
126 supported_ports=[22,80,806]
128 if data and len(data.keys()) > 0 :
129 for port in supported_ports:
131 state = data[str(port)]
135 if state == "filtered":
138 retval.append( (port, state) )
141 retval = [( "Closed/Filtered", "state" )]
143 if filtered_length == len(supported_ports):
144 retval = [( "All Filtered", "state" )]
148 def format_pcu_shortstatus(pcu):
151 if pcu.reboot_trial_status == str(0):
153 elif pcu.reboot_trial_status == "NetDown" or pcu.reboot_trial_status == "Not_Run":
154 status = pcu.reboot_trial_status
160 def prep_pcu_for_display(pcu):
165 agg.loginbase = PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base']
167 agg.loginbase = "unknown"
169 agg.pcuhist = HistoryPCURecord.query.get(pcu.plc_pcuid)
171 agg.ports = format_ports(pcu.port_status, pcu.plc_pcu_stats['model'])
172 agg.status = format_pcu_shortstatus(pcu)
174 #print pcu.entry_complete
175 agg.entry_complete_str = pcu.entry_complete
176 #pcu.entry_complete_str += "".join([ f[0] for f in pcu.entry_complete.split() ])
177 if pcu.dns_status == "NOHOSTNAME":
178 agg.dns_short_status = 'NoHost'
179 elif pcu.dns_status == "DNS-OK":
180 agg.dns_short_status = 'Ok'
181 elif pcu.dns_status == "DNS-NOENTRY":
182 agg.dns_short_status = 'NoEntry'
183 elif pcu.dns_status == "NO-DNS-OR-IP":
184 agg.dns_short_status = 'NoHostOrIP'
185 elif pcu.dns_status == "DNS-MISMATCH":
186 agg.dns_short_status = 'Mismatch'
189 class ActionListWidget(widgets.Widget):
192 class NodeWidget(widgets.Widget):
195 def prep_nodehist(node):
198 agg.loginbase = "unknown"
200 agg.loginbase = PlcSite.query.get(node.plc_siteid).plc_site_stats['login_base']
202 agg.loginbase = "exception"
207 def prep_node_for_display(node, pcuhash=None, preppcu=True, asofdate=None):
211 if node.plc_pcuid and preppcu:
213 pcu = pcuhash[node.plc_pcuid]
215 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=node.plc_pcuid)
218 agg.pcu_status = pcu.reboot_trial_status
219 agg.pcu_short_status = format_pcu_shortstatus(pcu)
220 agg.pcu = prep_pcu_for_display(pcu)
222 agg.pcu_short_status = "none"
223 agg.pcu_status = "nodata"
227 agg.pcu_status = "nopcu"
228 agg.pcu_short_status = "none"
232 if node.kernel_version:
233 agg.kernel = node.kernel_version.split()[2]
238 agg.loginbase = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
240 agg.loginbase = "unknown"
243 agg.site = HistorySiteRecord.by_loginbase(agg.loginbase)
246 agg.site = agg.site.get_as_of(asofdate)
249 # TODO: need a cleaner fix for this...
250 agg.site = HistorySiteRecord.by_loginbase("pl")
252 agg.site = HistorySiteRecord.by_loginbase("ple")
254 agg.history = HistoryNodeRecord.by_hostname(node.hostname)
256 agg.history = agg.history.get_as_of(asofdate)
258 agg.ports = format_ports(node.port_status)
261 exists = node.plc_node_stats['last_contact']
263 # TODO: this should not assign to the fb object!
264 node.plc_node_stats = {'last_contact' : None}
269 class Root(controllers.RootController, MonitorXmlrpcServer, LocalExtensions):
270 @expose(template="monitorweb.templates.welcome")
272 # log.debug("Happy TurboGears Controller Responding For Duty")
273 flash("Welcome To MyOps!")
274 return dict(now=time.ctime())
276 @expose(template="monitorweb.templates.nodelist", allow_json=True)
277 def node3(self, filter=None):
278 nhquery = HistoryNodeRecord.query.all()
282 if nh.status == filter:
289 fb = FindbadNodeRecord.get_latest_by(hostname=q.hostname)
292 return dict(now=time.ctime(), query=rquery)
294 def node_query(self, filter):
295 nhquery = HistoryNodeRecord.query.all()
299 if nh.status == filter:
306 fb = FindbadNodeRecord.get_latest_by(hostname=q.hostname)
307 agg = prep_node_for_display(fb)
311 @expose("cheetah:monitorweb.templates.nodelist_plain", as_format="plain",
312 accept_format="text/plain", content_type="text/plain")
313 @expose(template="monitorweb.templates.nodelist", allow_json=True)
314 def node2(self, filter=None):
315 rquery=self.node_query(filter)
316 widget = NodeWidget(template='monitorweb.templates.node_template')
317 return dict(now=time.ctime(), query=rquery, nodewidget=widget)
319 @expose("cheetah:monitorweb.templates.query_plain", as_format="plain",
320 accept_format="text/plain", content_type="text/plain")
321 @expose(template="monitorweb.templates.query", allow_json=True)
322 def query(self, **data):
330 if 'object' in data and data['object'] == "nodes":
331 fbquery = FindbadNodeRecord.get_all_latest()
332 elif 'object' in data and data['object'] == "nodehistory":
333 hostname = data['nodehistory_hostname']
334 data['date_checked'] = 'date_checked'
335 fbrecord = FindbadNodeRecord.get_by(hostname=hostname)
336 fbquery = fbrecord.versions[-500:]
340 # NOTE: reformat some fields.
341 if type(node) is not type(FindbadNodeRecord):
342 agg = node.__dict__.copy()
345 if agg['plc_node_stats']:
346 agg.update(agg['plc_node_stats'])
347 if agg['install_date']:
348 agg['install_date'] = time.mktime(time.strptime(agg['install_date'], "%a %b %d %H:%M:%S %Y"))
349 if agg['kernel_version']:
350 agg['kernel_version'] = agg['kernel_version'].split()[2]
351 if 'traceroute' in data and agg['traceroute']:
352 agg['traceroute'] = "<pre>" + agg['traceroute'] + "</pre>"
353 if 'rpmvalue' in data and 'rpms' in data:
355 rpm_list = agg['rpms'].split()
356 rpm_list = filter(lambda x: re.match(data['rpmvalue'], x, re.I),
358 agg['rpms'] = " ".join(rpm_list)
366 del fields['rpmvalue']
367 del fields['nodehistory_hostname']
369 return dict(now=time.ctime(), query=query, fields=fields, data=data, queryform=getNodeQueryForm())
371 @expose(template="monitorweb.templates.nodefast", allow_json=True)
372 def node(self, filter=None):
373 nhquery = HistoryNodeRecord.query.all()
377 if nh.status == filter:
378 agg = prep_nodehist(nh)
381 agg = prep_nodehist(nh)
384 return dict(now=time.ctime(), query=query)
386 @expose(template="monitorweb.templates.nodelist")
387 def nodeslow(self, filter='boot'):
388 print "NODE------------------"
389 print "befor-len: ", len( [ i for i in session] )
390 session.flush(); session.clear()
391 print "after-len: ", len( [ i for i in session] )
392 fbquery = FindbadNodeRecord.get_all_latest()
394 filtercount = {'down' : 0, 'boot': 0, 'debug' : 0, 'diagnose' : 0, 'disabled': 0,
395 'neverboot' : 0, 'pending' : 0, 'all' : 0, None : 0}
397 # NOTE: reformat some fields.
398 agg = prep_node_for_display(node)
403 if agg.history.status in ['down', 'offline']:
404 if node.plc_node_stats and node.plc_node_stats['last_contact'] != None:
405 filtercount['down'] += 1
407 filtercount['neverboot'] += 1
408 elif agg.history.status in ['good', 'online']:
409 filtercount['boot'] += 1
410 elif agg.history.status in ['debug', 'monitordebug']:
411 filtercount['debug'] += 1
413 if filtercount.has_key(agg.history.status):
414 filtercount[agg.history.status] += 1
418 if filter == "neverboot":
419 if not node.plc_node_stats or node.plc_node_stats['last_contact'] == None:
421 elif filter == "all":
423 elif filter == agg.history.status:
425 elif filter == 'boot':
429 widget = NodeWidget(template='monitorweb.templates.node_template')
430 return dict(now=time.ctime(), query=query, fc=filtercount, nodewidget=widget)
432 def nodeaction_handler(self, tg_exceptions=None):
433 """Handle any kind of error."""
434 print "NODEACTION_HANDLER------------------"
436 if 'pcuid' in request.params:
437 pcuid = request.params['pcuid']
439 refurl = request.headers.get("Referer",link("pcu"))
442 # TODO: do this more intelligently...
443 uri_fields = urllib.splitquery(refurl)
444 if uri_fields[1] is not None:
445 val = query_to_dict(uri_fields[1])
448 elif 'hostname' in val:
449 pcuid = FindbadNodeRecord.get_latest_by(hostname=val['hostname']).plc_pcuid
455 cherry_trail = cherrypy._cputil.get_object_trail()
456 for i in cherry_trail:
460 return self.pcuview(None, pcuid, **dict(exceptions=tg_exceptions))
462 def nodeaction(self, **data):
463 print "NODEACTION------------------"
464 for item in data.keys():
465 print "%s %s" % ( item, data[item] )
467 if 'hostname' in data:
468 hostname = data['hostname']
470 flash("No hostname given in submitted data")
473 if 'submit' in data or 'type' in data:
475 action = data['submit']
477 action = data['type']
479 flash("No submit action given in submitted data")
482 if action == "Reboot":
483 print "REBOOT: %s" % hostname
484 ret = reboot.reboot_str(str(hostname))
486 if ret: raise RuntimeError("Error using PCU: " + str(ret))
487 flash("Reboot appeared to work. Allow at most 5 minutes. Then run ExternalScan to check current status.")
489 elif action == "ExternalScan":
490 scanapi.externalprobe(str(hostname))
491 flash("External Scan Successful!")
492 elif action == "InternalScan":
493 scanapi.internalprobe(str(hostname))
494 flash("Internal Scan Successful!")
497 raise RuntimeError("Unknown action given")
500 @expose(template="monitorweb.templates.simpleview")
501 def simpleview(self, **data):
502 return self.pre_view(**data)
504 @expose(template="monitorweb.templates.simpleview")
505 def pcuview(self, **data):
506 return self.pre_view(**data)
508 @expose(template="monitorweb.templates.detailview")
509 def detailview(self, **data):
510 return self.pre_view(**data)
513 def pre_view(self, **data):
514 session.flush(); session.clear()
521 # if objtype is not None, then treat 'hostname' or 'loginbase' as a search pattern
536 fields = obj.split(":")
539 obj = fields[1].replace("*", "%")
542 if len(obj.split(".")) > 1 or objtype == "node":
547 if 'loginbase' in data:
548 loginbase = data['loginbase']
550 if 'hostname' in data:
551 hostname = data['hostname']
554 try: pcuid = int(data['pcuid'])
558 try: since = int(since)
562 print "pcuid: %s" % pcuid
563 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
564 loginbase_list += [ PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base'] ]
568 nodes = [ FindbadNodeRecord.get_latest_by(hostname=hostname) ]
570 nodes = FindbadNodeRecord.query.filter(FindbadNodeRecord.hostname.like(hostname))
573 lb = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
574 if lb not in loginbase_list:
575 loginbase_list += [ lb ]
579 loginbase_list = [ loginbase ]
581 loginbase_list = HistorySiteRecord.query.filter(HistorySiteRecord.loginbase.like(loginbase))
582 loginbase_list = [ l.loginbase for l in loginbase_list ]
586 for loginbase in loginbase_list:
587 actions = ActionRecord.query.filter_by(loginbase=loginbase
588 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
589 ).order_by(ActionRecord.date_created.desc())
590 actions_list += [ a for a in actions ]
591 site = HistorySiteRecord.by_loginbase(loginbase)
593 sitequery.append(site)
594 # NOTE: because a single pcu may be assigned to multiple hosts,
595 # track unique pcus by their plc_pcuid, then turn dict into list
597 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
598 # NOTE: reformat some fields.
599 agg = prep_node_for_display(node)
602 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
604 for pcuid_key in pcus:
605 pcuquery += [pcus[pcuid_key]]
607 actionlist_widget = ActionListWidget(template='monitorweb.templates.actionlist_template')
608 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions_list, actionlist_widget=actionlist_widget, since=since, exceptions=exceptions)
611 # TODO: add form validation
612 @expose(template="monitorweb.templates.pcuview")
613 @exception_handler(nodeaction_handler,"isinstance(tg_exceptions,RuntimeError)")
614 def pcuviewold(self, loginbase=None, pcuid=None, hostname=None, since=20, **data):
615 session.flush(); session.clear()
622 try: since = int(since)
628 if 'submit' in data.keys() or 'type' in data.keys():
629 if hostname: data['hostname'] = hostname
630 self.nodeaction(**data)
631 if 'exceptions' in data:
632 exceptions = data['exceptions']
636 if len(obj.split(".")) > 1: hostname = obj
640 print "pcuid: %s" % pcuid
641 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
642 loginbase = PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base']
645 node = FindbadNodeRecord.get_latest_by(hostname=hostname)
646 loginbase = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
649 actions = ActionRecord.query.filter_by(loginbase=loginbase
650 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
651 ).order_by(ActionRecord.date_created.desc())
652 actions = [ a for a in actions ]
653 sitequery = [HistorySiteRecord.by_loginbase(loginbase)]
655 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
656 # NOTE: reformat some fields.
657 agg = prep_node_for_display(node)
659 if agg.pcu: #.pcu.plc_pcuid: # not None
660 #pcu = FindbadPCURecord.get_latest_by(plc_pcuid=agg.plc_pcuid)
661 #prep_pcu_for_display(pcu)
662 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
664 for pcuid_key in pcus:
665 pcuquery += [pcus[pcuid_key]]
667 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions, since=since, exceptions=exceptions)
669 @expose(template="monitorweb.templates.pcuhistory")
670 def pcuhistory(self, pcu_id=None):
673 fbnode = HistoryPCURecord.get_by(plc_pcuid=pcu_id)
674 l = fbnode.versions[-1000:]
677 #prep_node_for_display(node)
680 return dict(query=query, pcu_id=pcu_id)
682 @expose(template="monitorweb.templates.nodescanhistory")
683 def nodescanhistory(self, hostname=None, length=10):
684 try: length = int(length)
687 fbnode = FindbadNodeRecord.get_by(hostname=hostname)
688 # TODO: add links for earlier history if desired.
689 l = fbnode.versions[-length:]
693 agg = prep_node_for_display(node, pcuhash=None, preppcu=False, asofdate=node.timestamp)
696 if 'length' in request.params:
697 del request.params['length']
698 return dict(query=query, hostname=hostname, params=request.params)
700 @expose(template="monitorweb.templates.nodehistory")
701 def nodehistory(self, hostname=None):
704 fbnode = HistoryNodeRecord.get_by(hostname=hostname)
705 l = fbnode.versions[-100:]
708 #prep_node_for_display(node)
711 return dict(query=query, hostname=hostname)
713 @expose(template="monitorweb.templates.sitehistory")
714 def sitehistory(self, loginbase=None):
717 fbsite = HistorySiteRecord.get_by(loginbase=loginbase)
718 # TODO: add links for earlier history if desired.
719 l = fbsite.versions[-1000:]
723 return dict(query=query, loginbase=loginbase)
726 @expose("cheetah:monitorweb.templates.pculist_plain", as_format="plain",
727 accept_format="text/plain", content_type="text/plain")
728 @expose(template="monitorweb.templates.pculist")
729 def pcu(self, filter='all'):
730 print "PCUVIEW------------------"
731 print "befor-len: ", len( [ i for i in session] )
732 session.flush(); session.clear()
733 print "after-len: ", len( [ i for i in session] )
734 fbquery = FindbadPCURecord.get_all_latest()
736 filtercount = {'ok' : 0, 'NetDown': 0, 'Not_Run' : 0, 'pending' : 0, 'all' : 0}
740 if node.reboot_trial_status == str(0):
741 filtercount['ok'] += 1
742 elif node.reboot_trial_status == 'NetDown' or node.reboot_trial_status == 'Not_Run':
743 filtercount[node.reboot_trial_status] += 1
745 filtercount['pending'] += 1
747 pcuagg = prep_pcu_for_display(node)
752 elif filter == "ok" and node.reboot_trial_status == str(0):
754 elif filter == node.reboot_trial_status:
756 elif filter == "pending":
757 # TODO: look in message logs...
758 if node.reboot_trial_status != str(0) and \
759 node.reboot_trial_status != 'NetDown' and \
760 node.reboot_trial_status != 'Not_Run':
764 return dict(query=query, fc=filtercount)
766 @expose(template="monitorweb.templates.sitelist")
767 def site(self, filter='all'):
768 print "SITE------------------"
769 print "befor-len: ", len( [ i for i in session] )
770 session.flush(); session.clear()
771 print "after-len: ", len( [ i for i in session] )
772 filtercount = {'good' : 0, 'down': 0, 'online':0, 'offline' : 0, 'new' : 0, 'pending' : 0, 'all' : 0}
773 fbquery = HistorySiteRecord.query.all()
777 filtercount['all'] += 1
778 if site.new and site.slices_used == 0 and not site.enabled:
779 filtercount['new'] += 1
780 elif not site.enabled:
781 filtercount['pending'] += 1
782 elif site.status in ['good', 'online']:
783 filtercount['good'] += 1
784 elif site.status in ['down', 'offline']:
785 filtercount['down'] += 1
790 elif filter == 'new' and site.new and site.slices_used == 0 and not site.enabled:
792 elif filter == "pending" and not site.enabled:
794 elif filter == 'good' and site.status in ['good', 'online']:
796 elif filter == 'down' and site.status in ['down', 'offline']:
799 return dict(query=query, fc=filtercount)
800 @expose(template="monitorweb.templates.sitesummary")
801 def sitesummary(self, loginbase="princeton"):
803 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
804 agg = prep_node_for_display(node)
807 return dict(nodequery=nodequery, loginbase=loginbase)
809 @expose(template="monitorweb.templates.summary")
810 def summary(self, since=7):
812 sumdata['nodes'] = {}
813 sumdata['sites'] = {}
816 def summarize(query, type):
818 if o.status not in sumdata[type]:
819 sumdata[type][o.status] = 0
820 sumdata[type][o.status] += 1
822 fbquery = HistorySiteRecord.query.all()
823 summarize(fbquery, 'sites')
824 fbquery = HistoryPCURecord.query.all()
825 summarize(fbquery, 'pcus')
826 fbquery = HistoryNodeRecord.query.all()
827 summarize(fbquery, 'nodes')
829 if 'monitordebug' in sumdata['nodes']:
830 d = sumdata['nodes']['monitordebug']
831 del sumdata['nodes']['monitordebug']
832 sumdata['nodes']['failboot'] = d
834 return dict(sumdata=sumdata, setorder=['good', 'offline', 'down', 'online'])
836 @expose(template="monitorweb.templates.actionsummary")
837 def actionsummary(self, since=7):
838 from monitor.wrapper.emailTxt import mailtxt
840 types = filter(lambda x: 'notice' in x, dir(mailtxt))
843 print mon_metadata.bind
844 if session.bind is None:
845 #TODO: figure out why this value gets cleared out...
846 session.bind = mon_metadata.bind
847 result = session.execute("select distinct(action_type) from actionrecord;")
849 types = [r[0] for r in result]
851 try: since = int(since)
855 acts = ActionRecord.query.filter(ActionRecord.action_type==t
856 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since))
857 results[t] = acts.count()
858 return dict(results=results)
860 @expose(template="monitorweb.templates.actionlist")
861 def actionlist(self, since=7, action_type=None, loginbase=None):
863 try: since = int(since)
866 acts_query = ActionRecord.query.filter(
867 ActionRecord.date_created >= datetime.now() - timedelta(since)
870 acts_query = acts_query.filter_by(loginbase=loginbase)
873 acts_query = acts_query.filter(ActionRecord.action_type==action_type)
875 acts = acts_query.order_by(ActionRecord.date_created.desc())
877 query = [ a for a in acts ]
879 return dict(actions=query, action_type=action_type, since=since)
882 def upload(self, log, **keywords):
885 logtype_list = ['bm.log', ]
887 if 'hostname' in keywords:
888 hostname = keywords['hostname']
889 if 'type' in keywords and keywords['type'] in logtype_list:
890 logtype = keywords['type']
892 if not hostname: return ""
893 if not logtype: return "unknown logtype: %s" % logtype
895 short_target_filename = bootman.bootmanager_log_name(hostname)
896 abs_target_filename = os.path.join(config.MONITOR_BOOTMANAGER_LOG, short_target_filename)
897 print "write data: %s" % abs_target_filename
898 util.file.dumpFile(abs_target_filename, log.file.read())
899 bootman.bootmanager_log_action(hostname, short_target_filename, logtype)
902 print "redirecting 3"