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
15 from monitor import util
16 from monitor import reboot
17 from monitor import bootman
18 from monitor import scanapi
19 from monitor import config
22 from monitor.wrapper.plccache import plcdb_hn2lb as site_hn2lb
24 from monitorweb.templates.links import *
26 class ObjectQueryFields(widgets.WidgetsList):
27 """The WidgetsList defines the fields of the form."""
32 class NodeQueryFields(widgets.WidgetsList):
33 """The WidgetsList defines the fields of the form."""
35 object = widgets.RadioButtonList(label="Query Type", options=[('nodes', 'All Nodes'),
36 ('nodehistory', 'Single Node History'),
37 #('sites', 'All Sites'),
38 #('sitehistory', 'Single Site History'),
40 nodehistory_hostname = widgets.TextField(label="Hostname Node History", attrs={'size':30})
42 hostname = widgets.CheckBox(label="Hostname")
43 firewall = widgets.CheckBox(label="Firewall?")
44 fs_status = widgets.CheckBox(label="Filesystem Status")
45 ssh_status = widgets.CheckBox(label="SSH Status")
46 ssh_error = widgets.CheckBox(label="SSH Errors")
47 dns_status = widgets.CheckBox(label="DNS Status")
48 iptables_status = widgets.CheckBox(label="IP Tables Status")
49 nm_status = widgets.CheckBox(label="NM Status")
50 princeton_comon_dir = widgets.CheckBox(label="CoMon Dir")
51 princeton_comon_running = widgets.CheckBox(label="CoMon Running")
52 princeton_comon_procs = widgets.CheckBox(label="CoMon Processes")
53 external_dns_status = widgets.CheckBox(label="Hostname Resolves?")
54 kernel_version = widgets.CheckBox(label="Kernel")
55 bootcd_version = widgets.CheckBox(label="BootCD")
56 boot_server = widgets.CheckBox(label="Boot Server")
57 install_date = widgets.CheckBox(label="Installation Date")
58 observed_status = widgets.CheckBox(label="Observed Status")
59 uptime = widgets.CheckBox(label="Uptime")
60 traceroute = widgets.CheckBox(label="Traceroute")
61 port_status = widgets.CheckBox(label="Port Status")
62 rpms = widgets.CheckBox(label="RPM")
63 rpmvalue = widgets.TextField(label="RPM Pattern")
65 class QueryForm(widgets.TableForm):
67 <form xmlns:py="http://purl.org/kid/ns#"
75 <div py:for="field in hidden_fields"
76 py:replace="field.display(value_for(field), **params_for(field))"
78 <table border="0" cellspacing="0" cellpadding="2" py:attrs="table_attrs">
79 <tr py:for="i, field in enumerate(fields)"
80 class="${i%2 and 'odd' or 'even'}"
83 <label class="fieldlabel" for="${field.field_id}" py:content="field.label" />
86 <span py:replace="field.display(value_for(field), **params_for(field))" />
87 <span py:if="error_for(field)" class="fielderror" py:content="error_for(field)" />
88 <span py:if="field.help_text" class="fieldhelp" py:content="field.help_text" />
93 <td py:content="submit.display(submit_text)" />
99 def getNodeQueryForm():
100 return QueryForm(fields=NodeQueryFields(), action="query")
102 # make it easier group objects without invoking the elixir auto-write feature.
103 class aggregate: pass
106 def query_to_dict(query):
107 """ take a url query string and chop it up """
109 query_fields = query.split('&')
110 for f in query_fields:
111 (k,v) = urllib.splitvalue(f)
116 def format_ports(data, pcumodel=None):
121 supported_ports=reboot.model_to_object(pcumodel).supported_ports
123 # ports of a production node
124 supported_ports=[22,80,806]
126 if data and len(data.keys()) > 0 :
127 for port in supported_ports:
129 state = data[str(port)]
133 if state == "filtered":
136 retval.append( (port, state) )
139 retval = [( "Closed/Filtered", "state" )]
141 if filtered_length == len(supported_ports):
142 retval = [( "All Filtered", "state" )]
146 def format_pcu_shortstatus(pcu):
149 if pcu.reboot_trial_status == str(0):
151 elif pcu.reboot_trial_status == "NetDown" or pcu.reboot_trial_status == "Not_Run":
152 status = pcu.reboot_trial_status
158 def prep_pcu_for_display(pcu):
163 agg.loginbase = PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base']
165 agg.loginbase = "unknown"
167 agg.pcuhist = HistoryPCURecord.query.get(pcu.plc_pcuid)
169 agg.ports = format_ports(pcu.port_status, pcu.plc_pcu_stats['model'])
170 agg.status = format_pcu_shortstatus(pcu)
172 #print pcu.entry_complete
173 agg.entry_complete_str = pcu.entry_complete
174 #pcu.entry_complete_str += "".join([ f[0] for f in pcu.entry_complete.split() ])
175 if pcu.dns_status == "NOHOSTNAME":
176 agg.dns_short_status = 'NoHost'
177 elif pcu.dns_status == "DNS-OK":
178 agg.dns_short_status = 'Ok'
179 elif pcu.dns_status == "DNS-NOENTRY":
180 agg.dns_short_status = 'NoEntry'
181 elif pcu.dns_status == "NO-DNS-OR-IP":
182 agg.dns_short_status = 'NoHostOrIP'
183 elif pcu.dns_status == "DNS-MISMATCH":
184 agg.dns_short_status = 'Mismatch'
187 class ActionListWidget(widgets.Widget):
190 class NodeWidget(widgets.Widget):
193 def prep_nodehist(node):
196 agg.loginbase = "unknown"
198 agg.loginbase = PlcSite.query.get(node.plc_siteid).plc_site_stats['login_base']
200 agg.loginbase = "exception"
205 def prep_node_for_display(node, pcuhash=None, preppcu=True, asofdate=None):
209 if node.plc_pcuid and preppcu:
211 pcu = pcuhash[node.plc_pcuid]
213 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=node.plc_pcuid)
216 agg.pcu_status = pcu.reboot_trial_status
217 agg.pcu_short_status = format_pcu_shortstatus(pcu)
218 agg.pcu = prep_pcu_for_display(pcu)
220 agg.pcu_short_status = "none"
221 agg.pcu_status = "nodata"
225 agg.pcu_status = "nopcu"
226 agg.pcu_short_status = "none"
230 if node.kernel_version:
231 agg.kernel = node.kernel_version.split()[2]
236 agg.loginbase = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
238 agg.loginbase = "unknown"
241 agg.site = HistorySiteRecord.by_loginbase(agg.loginbase)
244 agg.site = agg.site.get_as_of(asofdate)
247 # TODO: need a cleaner fix for this...
248 agg.site = HistorySiteRecord.by_loginbase("pl")
250 agg.site = HistorySiteRecord.by_loginbase("ple")
252 agg.history = HistoryNodeRecord.by_hostname(node.hostname)
254 agg.history = agg.history.get_as_of(asofdate)
256 agg.ports = format_ports(node.port_status)
259 exists = node.plc_node_stats['last_contact']
261 # TODO: this should not assign to the fb object!
262 node.plc_node_stats = {'last_contact' : None}
267 class Root(controllers.RootController, MonitorXmlrpcServer):
268 @expose(template="monitorweb.templates.welcome")
270 # log.debug("Happy TurboGears Controller Responding For Duty")
271 flash("Welcome To MyOps!")
272 return dict(now=time.ctime())
274 @expose(template="monitorweb.templates.nodelist", allow_json=True)
275 def node3(self, filter=None):
276 nhquery = HistoryNodeRecord.query.all()
280 if nh.status == filter:
287 fb = FindbadNodeRecord.get_latest_by(hostname=q.hostname)
290 return dict(now=time.ctime(), query=rquery)
292 def node_query(self, filter):
293 nhquery = HistoryNodeRecord.query.all()
297 if nh.status == filter:
304 fb = FindbadNodeRecord.get_latest_by(hostname=q.hostname)
305 agg = prep_node_for_display(fb)
309 @expose("cheetah:monitorweb.templates.nodelist_plain", as_format="plain",
310 accept_format="text/plain", content_type="text/plain")
311 @expose(template="monitorweb.templates.nodelist", allow_json=True)
312 def node2(self, filter=None):
313 rquery=self.node_query(filter)
314 widget = NodeWidget(template='monitorweb.templates.node_template')
315 return dict(now=time.ctime(), query=rquery, nodewidget=widget)
317 @expose("cheetah:monitorweb.templates.query_plain", as_format="plain",
318 accept_format="text/plain", content_type="text/plain")
319 @expose(template="monitorweb.templates.query", allow_json=True)
320 def query(self, **data):
328 if 'object' in data and data['object'] == "nodes":
329 fbquery = FindbadNodeRecord.get_all_latest()
330 elif 'object' in data and data['object'] == "nodehistory":
331 hostname = data['nodehistory_hostname']
332 data['date_checked'] = 'date_checked'
333 fbrecord = FindbadNodeRecord.get_by(hostname=hostname)
334 fbquery = fbrecord.versions[-500:]
338 # NOTE: reformat some fields.
339 if type(node) is not type(FindbadNodeRecord):
340 agg = node.__dict__.copy()
343 agg.update(agg['plc_node_stats'])
344 if agg['install_date']:
345 agg['install_date'] = time.mktime(time.strptime(agg['install_date'], "%a %b %d %H:%M:%S %Y"))
346 if agg['kernel_version']:
347 agg['kernel_version'] = agg['kernel_version'].split()[2]
348 if 'traceroute' in data and agg['traceroute']:
349 agg['traceroute'] = "<pre>" + agg['traceroute'] + "</pre>"
350 if 'rpmvalue' in data and 'rpms' in data:
352 rpm_list = agg['rpms'].split()
353 rpm_list = filter(lambda x: data['rpmvalue'] in x, rpm_list)
354 agg['rpms'] = " ".join(rpm_list)
362 del fields['rpmvalue']
363 del fields['nodehistory_hostname']
365 return dict(now=time.ctime(), query=query, fields=fields, data=data, queryform=getNodeQueryForm())
367 @expose(template="monitorweb.templates.nodefast", allow_json=True)
368 def node(self, filter=None):
369 nhquery = HistoryNodeRecord.query.all()
373 if nh.status == filter:
374 agg = prep_nodehist(nh)
377 agg = prep_nodehist(nh)
380 return dict(now=time.ctime(), query=query)
382 @expose(template="monitorweb.templates.nodelist")
383 def nodeslow(self, filter='boot'):
384 print "NODE------------------"
385 print "befor-len: ", len( [ i for i in session] )
386 session.flush(); session.clear()
387 print "after-len: ", len( [ i for i in session] )
388 fbquery = FindbadNodeRecord.get_all_latest()
390 filtercount = {'down' : 0, 'boot': 0, 'debug' : 0, 'diagnose' : 0, 'disabled': 0,
391 'neverboot' : 0, 'pending' : 0, 'all' : 0, None : 0}
393 # NOTE: reformat some fields.
394 agg = prep_node_for_display(node)
399 if agg.history.status in ['down', 'offline']:
400 if node.plc_node_stats and node.plc_node_stats['last_contact'] != None:
401 filtercount['down'] += 1
403 filtercount['neverboot'] += 1
404 elif agg.history.status in ['good', 'online']:
405 filtercount['boot'] += 1
406 elif agg.history.status in ['debug', 'monitordebug']:
407 filtercount['debug'] += 1
409 if filtercount.has_key(agg.history.status):
410 filtercount[agg.history.status] += 1
414 if filter == "neverboot":
415 if not node.plc_node_stats or node.plc_node_stats['last_contact'] == None:
417 elif filter == "all":
419 elif filter == agg.history.status:
421 elif filter == 'boot':
425 widget = NodeWidget(template='monitorweb.templates.node_template')
426 return dict(now=time.ctime(), query=query, fc=filtercount, nodewidget=widget)
428 def nodeaction_handler(self, tg_exceptions=None):
429 """Handle any kind of error."""
430 print "NODEACTION_HANDLER------------------"
432 if 'pcuid' in request.params:
433 pcuid = request.params['pcuid']
435 refurl = request.headers.get("Referer",link("pcu"))
438 # TODO: do this more intelligently...
439 uri_fields = urllib.splitquery(refurl)
440 if uri_fields[1] is not None:
441 val = query_to_dict(uri_fields[1])
444 elif 'hostname' in val:
445 pcuid = FindbadNodeRecord.get_latest_by(hostname=val['hostname']).plc_pcuid
451 cherry_trail = cherrypy._cputil.get_object_trail()
452 for i in cherry_trail:
456 return self.pcuview(None, pcuid, **dict(exceptions=tg_exceptions))
458 def nodeaction(self, **data):
459 print "NODEACTION------------------"
460 for item in data.keys():
461 print "%s %s" % ( item, data[item] )
463 if 'hostname' in data:
464 hostname = data['hostname']
466 flash("No hostname given in submitted data")
469 if 'submit' in data or 'type' in data:
471 action = data['submit']
473 action = data['type']
475 flash("No submit action given in submitted data")
478 if action == "Reboot":
479 print "REBOOT: %s" % hostname
480 ret = reboot.reboot_str(str(hostname))
482 if ret: raise RuntimeError("Error using PCU: " + str(ret))
483 flash("Reboot appeared to work. Allow at most 5 minutes. Then run ExternalScan to check current status.")
485 elif action == "ExternalScan":
486 scanapi.externalprobe(str(hostname))
487 flash("External Scan Successful!")
488 elif action == "InternalScan":
489 scanapi.internalprobe(str(hostname))
490 flash("Internal Scan Successful!")
493 raise RuntimeError("Unknown action given")
496 @expose(template="monitorweb.templates.simpleview")
497 def simpleview(self, **data):
498 return self.pre_view(**data)
500 @expose(template="monitorweb.templates.simpleview")
501 def pcuview(self, **data):
502 return self.pre_view(**data)
504 @expose(template="monitorweb.templates.detailview")
505 def detailview(self, **data):
506 return self.pre_view(**data)
509 def pre_view(self, **data):
510 session.flush(); session.clear()
517 # if objtype is not None, then treat 'hostname' or 'loginbase' as a search pattern
532 fields = obj.split(":")
535 obj = fields[1].replace("*", "%")
538 if len(obj.split(".")) > 1 or objtype == "node":
543 if 'loginbase' in data:
544 loginbase = data['loginbase']
546 if 'hostname' in data:
547 hostname = data['hostname']
550 try: pcuid = int(data['pcuid'])
554 try: since = int(since)
558 print "pcuid: %s" % pcuid
559 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
560 loginbase_list += [ PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base'] ]
564 nodes = [ FindbadNodeRecord.get_latest_by(hostname=hostname) ]
566 nodes = FindbadNodeRecord.query.filter(FindbadNodeRecord.hostname.like(hostname))
569 lb = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
570 if lb not in loginbase_list:
571 loginbase_list += [ lb ]
575 loginbase_list = [ loginbase ]
577 loginbase_list = HistorySiteRecord.query.filter(HistorySiteRecord.loginbase.like(loginbase))
578 loginbase_list = [ l.loginbase for l in loginbase_list ]
582 for loginbase in loginbase_list:
583 actions = ActionRecord.query.filter_by(loginbase=loginbase
584 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
585 ).order_by(ActionRecord.date_created.desc())
586 actions_list += [ a for a in actions ]
587 site = HistorySiteRecord.by_loginbase(loginbase)
589 sitequery.append(site)
590 # NOTE: because a single pcu may be assigned to multiple hosts,
591 # track unique pcus by their plc_pcuid, then turn dict into list
593 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
594 # NOTE: reformat some fields.
595 agg = prep_node_for_display(node)
598 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
600 for pcuid_key in pcus:
601 pcuquery += [pcus[pcuid_key]]
603 actionlist_widget = ActionListWidget(template='monitorweb.templates.actionlist_template')
604 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions_list, actionlist_widget=actionlist_widget, since=since, exceptions=exceptions)
607 # TODO: add form validation
608 @expose(template="monitorweb.templates.pcuview")
609 @exception_handler(nodeaction_handler,"isinstance(tg_exceptions,RuntimeError)")
610 def pcuviewold(self, loginbase=None, pcuid=None, hostname=None, since=20, **data):
611 session.flush(); session.clear()
618 try: since = int(since)
624 if 'submit' in data.keys() or 'type' in data.keys():
625 if hostname: data['hostname'] = hostname
626 self.nodeaction(**data)
627 if 'exceptions' in data:
628 exceptions = data['exceptions']
632 if len(obj.split(".")) > 1: hostname = obj
636 print "pcuid: %s" % pcuid
637 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
638 loginbase = PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base']
641 node = FindbadNodeRecord.get_latest_by(hostname=hostname)
642 loginbase = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
645 actions = ActionRecord.query.filter_by(loginbase=loginbase
646 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
647 ).order_by(ActionRecord.date_created.desc())
648 actions = [ a for a in actions ]
649 sitequery = [HistorySiteRecord.by_loginbase(loginbase)]
651 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
652 # NOTE: reformat some fields.
653 agg = prep_node_for_display(node)
655 if agg.pcu: #.pcu.plc_pcuid: # not None
656 #pcu = FindbadPCURecord.get_latest_by(plc_pcuid=agg.plc_pcuid)
657 #prep_pcu_for_display(pcu)
658 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
660 for pcuid_key in pcus:
661 pcuquery += [pcus[pcuid_key]]
663 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions, since=since, exceptions=exceptions)
665 @expose(template="monitorweb.templates.pcuhistory")
666 def pcuhistory(self, pcu_id=None):
669 fbnode = HistoryPCURecord.get_by(plc_pcuid=pcu_id)
670 l = fbnode.versions[-100:]
673 #prep_node_for_display(node)
676 return dict(query=query, pcu_id=pcu_id)
678 @expose(template="monitorweb.templates.nodescanhistory")
679 def nodescanhistory(self, hostname=None, length=10):
680 try: length = int(length)
683 fbnode = FindbadNodeRecord.get_by(hostname=hostname)
684 # TODO: add links for earlier history if desired.
685 l = fbnode.versions[-length:]
689 agg = prep_node_for_display(node, pcuhash=None, preppcu=False, asofdate=node.timestamp)
692 if 'length' in request.params:
693 del request.params['length']
694 return dict(query=query, hostname=hostname, params=request.params)
696 @expose(template="monitorweb.templates.nodehistory")
697 def nodehistory(self, hostname=None):
700 fbnode = HistoryNodeRecord.get_by(hostname=hostname)
701 l = fbnode.versions[-100:]
704 #prep_node_for_display(node)
707 return dict(query=query, hostname=hostname)
709 @expose(template="monitorweb.templates.sitehistory")
710 def sitehistory(self, loginbase=None):
713 fbsite = HistorySiteRecord.get_by(loginbase=loginbase)
714 # TODO: add links for earlier history if desired.
715 l = fbsite.versions[-100:]
719 return dict(query=query, loginbase=loginbase)
722 @expose(template="monitorweb.templates.pculist")
723 def pcu(self, filter='all'):
724 print "PCUVIEW------------------"
725 print "befor-len: ", len( [ i for i in session] )
726 session.flush(); session.clear()
727 print "after-len: ", len( [ i for i in session] )
728 fbquery = FindbadPCURecord.get_all_latest()
730 filtercount = {'ok' : 0, 'NetDown': 0, 'Not_Run' : 0, 'pending' : 0, 'all' : 0}
734 if node.reboot_trial_status == str(0):
735 filtercount['ok'] += 1
736 elif node.reboot_trial_status == 'NetDown' or node.reboot_trial_status == 'Not_Run':
737 filtercount[node.reboot_trial_status] += 1
739 filtercount['pending'] += 1
741 pcuagg = prep_pcu_for_display(node)
746 elif filter == "ok" and node.reboot_trial_status == str(0):
748 elif filter == node.reboot_trial_status:
750 elif filter == "pending":
751 # TODO: look in message logs...
752 if node.reboot_trial_status != str(0) and \
753 node.reboot_trial_status != 'NetDown' and \
754 node.reboot_trial_status != 'Not_Run':
758 return dict(query=query, fc=filtercount)
760 @expose(template="monitorweb.templates.sitelist")
761 def site(self, filter='all'):
762 print "SITE------------------"
763 print "befor-len: ", len( [ i for i in session] )
764 session.flush(); session.clear()
765 print "after-len: ", len( [ i for i in session] )
766 filtercount = {'good' : 0, 'down': 0, 'online':0, 'offline' : 0, 'new' : 0, 'pending' : 0, 'all' : 0}
767 fbquery = HistorySiteRecord.query.all()
771 filtercount['all'] += 1
772 if site.new and site.slices_used == 0 and not site.enabled:
773 filtercount['new'] += 1
774 elif not site.enabled:
775 filtercount['pending'] += 1
776 elif site.status in ['good', 'online']:
777 filtercount['good'] += 1
778 elif site.status in ['down', 'offline']:
779 filtercount['down'] += 1
784 elif filter == 'new' and site.new and site.slices_used == 0 and not site.enabled:
786 elif filter == "pending" and not site.enabled:
788 elif filter == 'good' and site.status in ['good', 'online']:
790 elif filter == 'down' and site.status in ['down', 'offline']:
793 return dict(query=query, fc=filtercount)
794 @expose(template="monitorweb.templates.sitesummary")
795 def sitesummary(self, loginbase="princeton"):
797 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
798 agg = prep_node_for_display(node)
801 return dict(nodequery=nodequery, loginbase=loginbase)
803 @expose(template="monitorweb.templates.summary")
804 def summary(self, since=7):
806 sumdata['nodes'] = {}
807 sumdata['sites'] = {}
810 def summarize(query, type):
812 if o.status not in sumdata[type]:
813 sumdata[type][o.status] = 0
814 sumdata[type][o.status] += 1
816 fbquery = HistorySiteRecord.query.all()
817 summarize(fbquery, 'sites')
818 fbquery = HistoryPCURecord.query.all()
819 summarize(fbquery, 'pcus')
820 fbquery = HistoryNodeRecord.query.all()
821 summarize(fbquery, 'nodes')
823 if 'monitordebug' in sumdata['nodes']:
824 d = sumdata['nodes']['monitordebug']
825 del sumdata['nodes']['monitordebug']
826 sumdata['nodes']['failboot'] = d
828 return dict(sumdata=sumdata, setorder=['good', 'offline', 'down', 'online'])
830 @expose(template="monitorweb.templates.actionsummary")
831 def actionsummary(self, since=7):
832 from monitor.wrapper.emailTxt import mailtxt
834 types = filter(lambda x: 'notice' in x, dir(mailtxt))
837 print mon_metadata.bind
838 if session.bind is None:
839 #TODO: figure out why this value gets cleared out...
840 session.bind = mon_metadata.bind
841 result = session.execute("select distinct(action_type) from actionrecord;")
843 types = [r[0] for r in result]
845 try: since = int(since)
849 acts = ActionRecord.query.filter(ActionRecord.action_type==t
850 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since))
851 results[t] = acts.count()
852 return dict(results=results)
854 @expose(template="monitorweb.templates.actionlist")
855 def actionlist(self, since=7, action_type=None, loginbase=None):
857 try: since = int(since)
860 acts_query = ActionRecord.query.filter(
861 ActionRecord.date_created >= datetime.now() - timedelta(since)
864 acts_query = acts_query.filter_by(loginbase=loginbase)
867 acts_query = acts_query.filter(ActionRecord.action_type==action_type)
869 acts = acts_query.order_by(ActionRecord.date_created.desc())
871 query = [ a for a in acts ]
873 return dict(actions=query, action_type=action_type, since=since)
876 def upload(self, log, **keywords):
879 logtype_list = ['bm.log', ]
881 if 'hostname' in keywords:
882 hostname = keywords['hostname']
883 if 'type' in keywords and keywords['type'] in logtype_list:
884 logtype = keywords['type']
886 if not hostname: return ""
887 if not logtype: return "unknown logtype: %s" % logtype
889 short_target_filename = bootman.bootmanager_log_name(hostname)
890 abs_target_filename = os.path.join(config.MONITOR_BOOTMANAGER_LOG, short_target_filename)
891 print "write data: %s" % abs_target_filename
892 util.file.dumpFile(abs_target_filename, log.file.read())
893 bootman.bootmanager_log_action(hostname, short_target_filename, logtype)
896 print "redirecting 3"