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: re.match(data['rpmvalue'], x, re.I),
355 agg['rpms'] = " ".join(rpm_list)
363 del fields['rpmvalue']
364 del fields['nodehistory_hostname']
366 return dict(now=time.ctime(), query=query, fields=fields, data=data, queryform=getNodeQueryForm())
368 @expose(template="monitorweb.templates.nodefast", allow_json=True)
369 def node(self, filter=None):
370 nhquery = HistoryNodeRecord.query.all()
374 if nh.status == filter:
375 agg = prep_nodehist(nh)
378 agg = prep_nodehist(nh)
381 return dict(now=time.ctime(), query=query)
383 @expose(template="monitorweb.templates.nodelist")
384 def nodeslow(self, filter='boot'):
385 print "NODE------------------"
386 print "befor-len: ", len( [ i for i in session] )
387 session.flush(); session.clear()
388 print "after-len: ", len( [ i for i in session] )
389 fbquery = FindbadNodeRecord.get_all_latest()
391 filtercount = {'down' : 0, 'boot': 0, 'debug' : 0, 'diagnose' : 0, 'disabled': 0,
392 'neverboot' : 0, 'pending' : 0, 'all' : 0, None : 0}
394 # NOTE: reformat some fields.
395 agg = prep_node_for_display(node)
400 if agg.history.status in ['down', 'offline']:
401 if node.plc_node_stats and node.plc_node_stats['last_contact'] != None:
402 filtercount['down'] += 1
404 filtercount['neverboot'] += 1
405 elif agg.history.status in ['good', 'online']:
406 filtercount['boot'] += 1
407 elif agg.history.status in ['debug', 'monitordebug']:
408 filtercount['debug'] += 1
410 if filtercount.has_key(agg.history.status):
411 filtercount[agg.history.status] += 1
415 if filter == "neverboot":
416 if not node.plc_node_stats or node.plc_node_stats['last_contact'] == None:
418 elif filter == "all":
420 elif filter == agg.history.status:
422 elif filter == 'boot':
426 widget = NodeWidget(template='monitorweb.templates.node_template')
427 return dict(now=time.ctime(), query=query, fc=filtercount, nodewidget=widget)
429 def nodeaction_handler(self, tg_exceptions=None):
430 """Handle any kind of error."""
431 print "NODEACTION_HANDLER------------------"
433 if 'pcuid' in request.params:
434 pcuid = request.params['pcuid']
436 refurl = request.headers.get("Referer",link("pcu"))
439 # TODO: do this more intelligently...
440 uri_fields = urllib.splitquery(refurl)
441 if uri_fields[1] is not None:
442 val = query_to_dict(uri_fields[1])
445 elif 'hostname' in val:
446 pcuid = FindbadNodeRecord.get_latest_by(hostname=val['hostname']).plc_pcuid
452 cherry_trail = cherrypy._cputil.get_object_trail()
453 for i in cherry_trail:
457 return self.pcuview(None, pcuid, **dict(exceptions=tg_exceptions))
459 def nodeaction(self, **data):
460 print "NODEACTION------------------"
461 for item in data.keys():
462 print "%s %s" % ( item, data[item] )
464 if 'hostname' in data:
465 hostname = data['hostname']
467 flash("No hostname given in submitted data")
470 if 'submit' in data or 'type' in data:
472 action = data['submit']
474 action = data['type']
476 flash("No submit action given in submitted data")
479 if action == "Reboot":
480 print "REBOOT: %s" % hostname
481 ret = reboot.reboot_str(str(hostname))
483 if ret: raise RuntimeError("Error using PCU: " + str(ret))
484 flash("Reboot appeared to work. Allow at most 5 minutes. Then run ExternalScan to check current status.")
486 elif action == "ExternalScan":
487 scanapi.externalprobe(str(hostname))
488 flash("External Scan Successful!")
489 elif action == "InternalScan":
490 scanapi.internalprobe(str(hostname))
491 flash("Internal Scan Successful!")
494 raise RuntimeError("Unknown action given")
497 @expose(template="monitorweb.templates.simpleview")
498 def simpleview(self, **data):
499 return self.pre_view(**data)
501 @expose(template="monitorweb.templates.simpleview")
502 def pcuview(self, **data):
503 return self.pre_view(**data)
505 @expose(template="monitorweb.templates.detailview")
506 def detailview(self, **data):
507 return self.pre_view(**data)
510 def pre_view(self, **data):
511 session.flush(); session.clear()
518 # if objtype is not None, then treat 'hostname' or 'loginbase' as a search pattern
533 fields = obj.split(":")
536 obj = fields[1].replace("*", "%")
539 if len(obj.split(".")) > 1 or objtype == "node":
544 if 'loginbase' in data:
545 loginbase = data['loginbase']
547 if 'hostname' in data:
548 hostname = data['hostname']
551 try: pcuid = int(data['pcuid'])
555 try: since = int(since)
559 print "pcuid: %s" % pcuid
560 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
561 loginbase_list += [ PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base'] ]
565 nodes = [ FindbadNodeRecord.get_latest_by(hostname=hostname) ]
567 nodes = FindbadNodeRecord.query.filter(FindbadNodeRecord.hostname.like(hostname))
570 lb = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
571 if lb not in loginbase_list:
572 loginbase_list += [ lb ]
576 loginbase_list = [ loginbase ]
578 loginbase_list = HistorySiteRecord.query.filter(HistorySiteRecord.loginbase.like(loginbase))
579 loginbase_list = [ l.loginbase for l in loginbase_list ]
583 for loginbase in loginbase_list:
584 actions = ActionRecord.query.filter_by(loginbase=loginbase
585 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
586 ).order_by(ActionRecord.date_created.desc())
587 actions_list += [ a for a in actions ]
588 site = HistorySiteRecord.by_loginbase(loginbase)
590 sitequery.append(site)
591 # NOTE: because a single pcu may be assigned to multiple hosts,
592 # track unique pcus by their plc_pcuid, then turn dict into list
594 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
595 # NOTE: reformat some fields.
596 agg = prep_node_for_display(node)
599 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
601 for pcuid_key in pcus:
602 pcuquery += [pcus[pcuid_key]]
604 actionlist_widget = ActionListWidget(template='monitorweb.templates.actionlist_template')
605 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions_list, actionlist_widget=actionlist_widget, since=since, exceptions=exceptions)
608 # TODO: add form validation
609 @expose(template="monitorweb.templates.pcuview")
610 @exception_handler(nodeaction_handler,"isinstance(tg_exceptions,RuntimeError)")
611 def pcuviewold(self, loginbase=None, pcuid=None, hostname=None, since=20, **data):
612 session.flush(); session.clear()
619 try: since = int(since)
625 if 'submit' in data.keys() or 'type' in data.keys():
626 if hostname: data['hostname'] = hostname
627 self.nodeaction(**data)
628 if 'exceptions' in data:
629 exceptions = data['exceptions']
633 if len(obj.split(".")) > 1: hostname = obj
637 print "pcuid: %s" % pcuid
638 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
639 loginbase = PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base']
642 node = FindbadNodeRecord.get_latest_by(hostname=hostname)
643 loginbase = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
646 actions = ActionRecord.query.filter_by(loginbase=loginbase
647 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
648 ).order_by(ActionRecord.date_created.desc())
649 actions = [ a for a in actions ]
650 sitequery = [HistorySiteRecord.by_loginbase(loginbase)]
652 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
653 # NOTE: reformat some fields.
654 agg = prep_node_for_display(node)
656 if agg.pcu: #.pcu.plc_pcuid: # not None
657 #pcu = FindbadPCURecord.get_latest_by(plc_pcuid=agg.plc_pcuid)
658 #prep_pcu_for_display(pcu)
659 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
661 for pcuid_key in pcus:
662 pcuquery += [pcus[pcuid_key]]
664 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions, since=since, exceptions=exceptions)
666 @expose(template="monitorweb.templates.pcuhistory")
667 def pcuhistory(self, pcu_id=None):
670 fbnode = HistoryPCURecord.get_by(plc_pcuid=pcu_id)
671 l = fbnode.versions[-100:]
674 #prep_node_for_display(node)
677 return dict(query=query, pcu_id=pcu_id)
679 @expose(template="monitorweb.templates.nodescanhistory")
680 def nodescanhistory(self, hostname=None, length=10):
681 try: length = int(length)
684 fbnode = FindbadNodeRecord.get_by(hostname=hostname)
685 # TODO: add links for earlier history if desired.
686 l = fbnode.versions[-length:]
690 agg = prep_node_for_display(node, pcuhash=None, preppcu=False, asofdate=node.timestamp)
693 if 'length' in request.params:
694 del request.params['length']
695 return dict(query=query, hostname=hostname, params=request.params)
697 @expose(template="monitorweb.templates.nodehistory")
698 def nodehistory(self, hostname=None):
701 fbnode = HistoryNodeRecord.get_by(hostname=hostname)
702 l = fbnode.versions[-100:]
705 #prep_node_for_display(node)
708 return dict(query=query, hostname=hostname)
710 @expose(template="monitorweb.templates.sitehistory")
711 def sitehistory(self, loginbase=None):
714 fbsite = HistorySiteRecord.get_by(loginbase=loginbase)
715 # TODO: add links for earlier history if desired.
716 l = fbsite.versions[-100:]
720 return dict(query=query, loginbase=loginbase)
723 @expose(template="monitorweb.templates.pculist")
724 def pcu(self, filter='all'):
725 print "PCUVIEW------------------"
726 print "befor-len: ", len( [ i for i in session] )
727 session.flush(); session.clear()
728 print "after-len: ", len( [ i for i in session] )
729 fbquery = FindbadPCURecord.get_all_latest()
731 filtercount = {'ok' : 0, 'NetDown': 0, 'Not_Run' : 0, 'pending' : 0, 'all' : 0}
735 if node.reboot_trial_status == str(0):
736 filtercount['ok'] += 1
737 elif node.reboot_trial_status == 'NetDown' or node.reboot_trial_status == 'Not_Run':
738 filtercount[node.reboot_trial_status] += 1
740 filtercount['pending'] += 1
742 pcuagg = prep_pcu_for_display(node)
747 elif filter == "ok" and node.reboot_trial_status == str(0):
749 elif filter == node.reboot_trial_status:
751 elif filter == "pending":
752 # TODO: look in message logs...
753 if node.reboot_trial_status != str(0) and \
754 node.reboot_trial_status != 'NetDown' and \
755 node.reboot_trial_status != 'Not_Run':
759 return dict(query=query, fc=filtercount)
761 @expose(template="monitorweb.templates.sitelist")
762 def site(self, filter='all'):
763 print "SITE------------------"
764 print "befor-len: ", len( [ i for i in session] )
765 session.flush(); session.clear()
766 print "after-len: ", len( [ i for i in session] )
767 filtercount = {'good' : 0, 'down': 0, 'online':0, 'offline' : 0, 'new' : 0, 'pending' : 0, 'all' : 0}
768 fbquery = HistorySiteRecord.query.all()
772 filtercount['all'] += 1
773 if site.new and site.slices_used == 0 and not site.enabled:
774 filtercount['new'] += 1
775 elif not site.enabled:
776 filtercount['pending'] += 1
777 elif site.status in ['good', 'online']:
778 filtercount['good'] += 1
779 elif site.status in ['down', 'offline']:
780 filtercount['down'] += 1
785 elif filter == 'new' and site.new and site.slices_used == 0 and not site.enabled:
787 elif filter == "pending" and not site.enabled:
789 elif filter == 'good' and site.status in ['good', 'online']:
791 elif filter == 'down' and site.status in ['down', 'offline']:
794 return dict(query=query, fc=filtercount)
795 @expose(template="monitorweb.templates.sitesummary")
796 def sitesummary(self, loginbase="princeton"):
798 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
799 agg = prep_node_for_display(node)
802 return dict(nodequery=nodequery, loginbase=loginbase)
804 @expose(template="monitorweb.templates.summary")
805 def summary(self, since=7):
807 sumdata['nodes'] = {}
808 sumdata['sites'] = {}
811 def summarize(query, type):
813 if o.status not in sumdata[type]:
814 sumdata[type][o.status] = 0
815 sumdata[type][o.status] += 1
817 fbquery = HistorySiteRecord.query.all()
818 summarize(fbquery, 'sites')
819 fbquery = HistoryPCURecord.query.all()
820 summarize(fbquery, 'pcus')
821 fbquery = HistoryNodeRecord.query.all()
822 summarize(fbquery, 'nodes')
824 if 'monitordebug' in sumdata['nodes']:
825 d = sumdata['nodes']['monitordebug']
826 del sumdata['nodes']['monitordebug']
827 sumdata['nodes']['failboot'] = d
829 return dict(sumdata=sumdata, setorder=['good', 'offline', 'down', 'online'])
831 @expose(template="monitorweb.templates.actionsummary")
832 def actionsummary(self, since=7):
833 from monitor.wrapper.emailTxt import mailtxt
835 types = filter(lambda x: 'notice' in x, dir(mailtxt))
838 print mon_metadata.bind
839 if session.bind is None:
840 #TODO: figure out why this value gets cleared out...
841 session.bind = mon_metadata.bind
842 result = session.execute("select distinct(action_type) from actionrecord;")
844 types = [r[0] for r in result]
846 try: since = int(since)
850 acts = ActionRecord.query.filter(ActionRecord.action_type==t
851 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since))
852 results[t] = acts.count()
853 return dict(results=results)
855 @expose(template="monitorweb.templates.actionlist")
856 def actionlist(self, since=7, action_type=None, loginbase=None):
858 try: since = int(since)
861 acts_query = ActionRecord.query.filter(
862 ActionRecord.date_created >= datetime.now() - timedelta(since)
865 acts_query = acts_query.filter_by(loginbase=loginbase)
868 acts_query = acts_query.filter(ActionRecord.action_type==action_type)
870 acts = acts_query.order_by(ActionRecord.date_created.desc())
872 query = [ a for a in acts ]
874 return dict(actions=query, action_type=action_type, since=since)
877 def upload(self, log, **keywords):
880 logtype_list = ['bm.log', ]
882 if 'hostname' in keywords:
883 hostname = keywords['hostname']
884 if 'type' in keywords and keywords['type'] in logtype_list:
885 logtype = keywords['type']
887 if not hostname: return ""
888 if not logtype: return "unknown logtype: %s" % logtype
890 short_target_filename = bootman.bootmanager_log_name(hostname)
891 abs_target_filename = os.path.join(config.MONITOR_BOOTMANAGER_LOG, short_target_filename)
892 print "write data: %s" % abs_target_filename
893 util.file.dumpFile(abs_target_filename, log.file.read())
894 bootman.bootmanager_log_action(hostname, short_target_filename, logtype)
897 print "redirecting 3"