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['kernel_version']:
345 agg['kernel_version'] = agg['kernel_version'].split()[2]
346 if 'traceroute' in data and agg['traceroute']:
347 agg['traceroute'] = "<pre>" + agg['traceroute'] + "</pre>"
348 if 'rpmvalue' in data and 'rpms' in data:
350 rpm_list = agg['rpms'].split()
351 rpm_list = filter(lambda x: data['rpmvalue'] in x, rpm_list)
352 agg['rpms'] = " ".join(rpm_list)
360 del fields['rpmvalue']
361 del fields['nodehistory_hostname']
363 return dict(now=time.ctime(), query=query, fields=fields, data=data, queryform=getNodeQueryForm())
365 @expose(template="monitorweb.templates.nodefast", allow_json=True)
366 def node(self, filter=None):
367 nhquery = HistoryNodeRecord.query.all()
371 if nh.status == filter:
372 agg = prep_nodehist(nh)
375 agg = prep_nodehist(nh)
378 return dict(now=time.ctime(), query=query)
380 @expose(template="monitorweb.templates.nodelist")
381 def nodeslow(self, filter='boot'):
382 print "NODE------------------"
383 print "befor-len: ", len( [ i for i in session] )
384 session.flush(); session.clear()
385 print "after-len: ", len( [ i for i in session] )
386 fbquery = FindbadNodeRecord.get_all_latest()
388 filtercount = {'down' : 0, 'boot': 0, 'debug' : 0, 'diagnose' : 0, 'disabled': 0,
389 'neverboot' : 0, 'pending' : 0, 'all' : 0, None : 0}
391 # NOTE: reformat some fields.
392 agg = prep_node_for_display(node)
397 if agg.history.status in ['down', 'offline']:
398 if node.plc_node_stats and node.plc_node_stats['last_contact'] != None:
399 filtercount['down'] += 1
401 filtercount['neverboot'] += 1
402 elif agg.history.status in ['good', 'online']:
403 filtercount['boot'] += 1
404 elif agg.history.status in ['debug', 'monitordebug']:
405 filtercount['debug'] += 1
407 if filtercount.has_key(agg.history.status):
408 filtercount[agg.history.status] += 1
412 if filter == "neverboot":
413 if not node.plc_node_stats or node.plc_node_stats['last_contact'] == None:
415 elif filter == "all":
417 elif filter == agg.history.status:
419 elif filter == 'boot':
423 widget = NodeWidget(template='monitorweb.templates.node_template')
424 return dict(now=time.ctime(), query=query, fc=filtercount, nodewidget=widget)
426 def nodeaction_handler(self, tg_exceptions=None):
427 """Handle any kind of error."""
428 print "NODEACTION_HANDLER------------------"
430 if 'pcuid' in request.params:
431 pcuid = request.params['pcuid']
433 refurl = request.headers.get("Referer",link("pcu"))
436 # TODO: do this more intelligently...
437 uri_fields = urllib.splitquery(refurl)
438 if uri_fields[1] is not None:
439 val = query_to_dict(uri_fields[1])
442 elif 'hostname' in val:
443 pcuid = FindbadNodeRecord.get_latest_by(hostname=val['hostname']).plc_pcuid
449 cherry_trail = cherrypy._cputil.get_object_trail()
450 for i in cherry_trail:
454 return self.pcuview(None, pcuid, **dict(exceptions=tg_exceptions))
456 def nodeaction(self, **data):
457 print "NODEACTION------------------"
458 for item in data.keys():
459 print "%s %s" % ( item, data[item] )
461 if 'hostname' in data:
462 hostname = data['hostname']
464 flash("No hostname given in submitted data")
467 if 'submit' in data or 'type' in data:
469 action = data['submit']
471 action = data['type']
473 flash("No submit action given in submitted data")
476 if action == "Reboot":
477 print "REBOOT: %s" % hostname
478 ret = reboot.reboot_str(str(hostname))
480 if ret: raise RuntimeError("Error using PCU: " + str(ret))
481 flash("Reboot appeared to work. Allow at most 5 minutes. Then run ExternalScan to check current status.")
483 elif action == "ExternalScan":
484 scanapi.externalprobe(str(hostname))
485 flash("External Scan Successful!")
486 elif action == "InternalScan":
487 scanapi.internalprobe(str(hostname))
488 flash("Internal Scan Successful!")
491 raise RuntimeError("Unknown action given")
494 @expose(template="monitorweb.templates.simpleview")
495 def simpleview(self, **data):
496 return self.pre_view(**data)
498 @expose(template="monitorweb.templates.simpleview")
499 def pcuview(self, **data):
500 return self.pre_view(**data)
502 @expose(template="monitorweb.templates.detailview")
503 def detailview(self, **data):
504 return self.pre_view(**data)
507 def pre_view(self, **data):
508 session.flush(); session.clear()
515 # if objtype is not None, then treat 'hostname' or 'loginbase' as a search pattern
530 fields = obj.split(":")
533 obj = fields[1].replace("*", "%")
536 if len(obj.split(".")) > 1 or objtype == "node":
541 if 'loginbase' in data:
542 loginbase = data['loginbase']
544 if 'hostname' in data:
545 hostname = data['hostname']
548 try: pcuid = int(data['pcuid'])
552 try: since = int(since)
556 print "pcuid: %s" % pcuid
557 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
558 loginbase_list += [ PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base'] ]
562 nodes = [ FindbadNodeRecord.get_latest_by(hostname=hostname) ]
564 nodes = FindbadNodeRecord.query.filter(FindbadNodeRecord.hostname.like(hostname))
567 lb = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
568 if lb not in loginbase_list:
569 loginbase_list += [ lb ]
573 loginbase_list = [ loginbase ]
575 loginbase_list = HistorySiteRecord.query.filter(HistorySiteRecord.loginbase.like(loginbase))
576 loginbase_list = [ l.loginbase for l in loginbase_list ]
580 for loginbase in loginbase_list:
581 actions = ActionRecord.query.filter_by(loginbase=loginbase
582 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
583 ).order_by(ActionRecord.date_created.desc())
584 actions_list += [ a for a in actions ]
585 site = HistorySiteRecord.by_loginbase(loginbase)
587 sitequery.append(site)
588 # NOTE: because a single pcu may be assigned to multiple hosts,
589 # track unique pcus by their plc_pcuid, then turn dict into list
591 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
592 # NOTE: reformat some fields.
593 agg = prep_node_for_display(node)
596 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
598 for pcuid_key in pcus:
599 pcuquery += [pcus[pcuid_key]]
601 actionlist_widget = ActionListWidget(template='monitorweb.templates.actionlist_template')
602 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions_list, actionlist_widget=actionlist_widget, since=since, exceptions=exceptions)
605 # TODO: add form validation
606 @expose(template="monitorweb.templates.pcuview")
607 @exception_handler(nodeaction_handler,"isinstance(tg_exceptions,RuntimeError)")
608 def pcuviewold(self, loginbase=None, pcuid=None, hostname=None, since=20, **data):
609 session.flush(); session.clear()
616 try: since = int(since)
622 if 'submit' in data.keys() or 'type' in data.keys():
623 if hostname: data['hostname'] = hostname
624 self.nodeaction(**data)
625 if 'exceptions' in data:
626 exceptions = data['exceptions']
630 if len(obj.split(".")) > 1: hostname = obj
634 print "pcuid: %s" % pcuid
635 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
636 loginbase = PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base']
639 node = FindbadNodeRecord.get_latest_by(hostname=hostname)
640 loginbase = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
643 actions = ActionRecord.query.filter_by(loginbase=loginbase
644 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
645 ).order_by(ActionRecord.date_created.desc())
646 actions = [ a for a in actions ]
647 sitequery = [HistorySiteRecord.by_loginbase(loginbase)]
649 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
650 # NOTE: reformat some fields.
651 agg = prep_node_for_display(node)
653 if agg.pcu: #.pcu.plc_pcuid: # not None
654 #pcu = FindbadPCURecord.get_latest_by(plc_pcuid=agg.plc_pcuid)
655 #prep_pcu_for_display(pcu)
656 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
658 for pcuid_key in pcus:
659 pcuquery += [pcus[pcuid_key]]
661 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions, since=since, exceptions=exceptions)
663 @expose(template="monitorweb.templates.pcuhistory")
664 def pcuhistory(self, pcu_id=None):
667 fbnode = HistoryPCURecord.get_by(plc_pcuid=pcu_id)
668 l = fbnode.versions[-100:]
671 #prep_node_for_display(node)
674 return dict(query=query, pcu_id=pcu_id)
676 @expose(template="monitorweb.templates.nodescanhistory")
677 def nodescanhistory(self, hostname=None, length=10):
678 try: length = int(length)
681 fbnode = FindbadNodeRecord.get_by(hostname=hostname)
682 # TODO: add links for earlier history if desired.
683 l = fbnode.versions[-length:]
687 agg = prep_node_for_display(node, pcuhash=None, preppcu=False, asofdate=node.timestamp)
690 if 'length' in request.params:
691 del request.params['length']
692 return dict(query=query, hostname=hostname, params=request.params)
694 @expose(template="monitorweb.templates.nodehistory")
695 def nodehistory(self, hostname=None):
698 fbnode = HistoryNodeRecord.get_by(hostname=hostname)
699 l = fbnode.versions[-100:]
702 #prep_node_for_display(node)
705 return dict(query=query, hostname=hostname)
707 @expose(template="monitorweb.templates.sitehistory")
708 def sitehistory(self, loginbase=None):
711 fbsite = HistorySiteRecord.get_by(loginbase=loginbase)
712 # TODO: add links for earlier history if desired.
713 l = fbsite.versions[-100:]
717 return dict(query=query, loginbase=loginbase)
720 @expose(template="monitorweb.templates.pculist")
721 def pcu(self, filter='all'):
722 print "PCUVIEW------------------"
723 print "befor-len: ", len( [ i for i in session] )
724 session.flush(); session.clear()
725 print "after-len: ", len( [ i for i in session] )
726 fbquery = FindbadPCURecord.get_all_latest()
728 filtercount = {'ok' : 0, 'NetDown': 0, 'Not_Run' : 0, 'pending' : 0, 'all' : 0}
732 if node.reboot_trial_status == str(0):
733 filtercount['ok'] += 1
734 elif node.reboot_trial_status == 'NetDown' or node.reboot_trial_status == 'Not_Run':
735 filtercount[node.reboot_trial_status] += 1
737 filtercount['pending'] += 1
739 pcuagg = prep_pcu_for_display(node)
744 elif filter == "ok" and node.reboot_trial_status == str(0):
746 elif filter == node.reboot_trial_status:
748 elif filter == "pending":
749 # TODO: look in message logs...
750 if node.reboot_trial_status != str(0) and \
751 node.reboot_trial_status != 'NetDown' and \
752 node.reboot_trial_status != 'Not_Run':
756 return dict(query=query, fc=filtercount)
758 @expose(template="monitorweb.templates.sitelist")
759 def site(self, filter='all'):
760 print "SITE------------------"
761 print "befor-len: ", len( [ i for i in session] )
762 session.flush(); session.clear()
763 print "after-len: ", len( [ i for i in session] )
764 filtercount = {'good' : 0, 'down': 0, 'online':0, 'offline' : 0, 'new' : 0, 'pending' : 0, 'all' : 0}
765 fbquery = HistorySiteRecord.query.all()
769 filtercount['all'] += 1
770 if site.new and site.slices_used == 0 and not site.enabled:
771 filtercount['new'] += 1
772 elif not site.enabled:
773 filtercount['pending'] += 1
774 elif site.status in ['good', 'online']:
775 filtercount['good'] += 1
776 elif site.status in ['down', 'offline']:
777 filtercount['down'] += 1
782 elif filter == 'new' and site.new and site.slices_used == 0 and not site.enabled:
784 elif filter == "pending" and not site.enabled:
786 elif filter == 'good' and site.status in ['good', 'online']:
788 elif filter == 'down' and site.status in ['down', 'offline']:
791 return dict(query=query, fc=filtercount)
792 @expose(template="monitorweb.templates.sitesummary")
793 def sitesummary(self, loginbase="princeton"):
795 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
796 agg = prep_node_for_display(node)
799 return dict(nodequery=nodequery, loginbase=loginbase)
801 @expose(template="monitorweb.templates.summary")
802 def summary(self, since=7):
804 sumdata['nodes'] = {}
805 sumdata['sites'] = {}
808 def summarize(query, type):
810 if o.status not in sumdata[type]:
811 sumdata[type][o.status] = 0
812 sumdata[type][o.status] += 1
814 fbquery = HistorySiteRecord.query.all()
815 summarize(fbquery, 'sites')
816 fbquery = HistoryPCURecord.query.all()
817 summarize(fbquery, 'pcus')
818 fbquery = HistoryNodeRecord.query.all()
819 summarize(fbquery, 'nodes')
821 if 'monitordebug' in sumdata['nodes']:
822 d = sumdata['nodes']['monitordebug']
823 del sumdata['nodes']['monitordebug']
824 sumdata['nodes']['failboot'] = d
826 return dict(sumdata=sumdata, setorder=['good', 'offline', 'down', 'online'])
828 @expose(template="monitorweb.templates.actionsummary")
829 def actionsummary(self, since=7):
830 from monitor.wrapper.emailTxt import mailtxt
832 types = filter(lambda x: 'notice' in x, dir(mailtxt))
835 print mon_metadata.bind
836 if session.bind is None:
837 #TODO: figure out why this value gets cleared out...
838 session.bind = mon_metadata.bind
839 result = session.execute("select distinct(action_type) from actionrecord;")
841 types = [r[0] for r in result]
843 try: since = int(since)
847 acts = ActionRecord.query.filter(ActionRecord.action_type==t
848 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since))
849 results[t] = acts.count()
850 return dict(results=results)
852 @expose(template="monitorweb.templates.actionlist")
853 def actionlist(self, since=7, action_type=None, loginbase=None):
855 try: since = int(since)
858 acts_query = ActionRecord.query.filter(
859 ActionRecord.date_created >= datetime.now() - timedelta(since)
862 acts_query = acts_query.filter_by(loginbase=loginbase)
865 acts_query = acts_query.filter(ActionRecord.action_type==action_type)
867 acts = acts_query.order_by(ActionRecord.date_created.desc())
869 query = [ a for a in acts ]
871 return dict(actions=query, action_type=action_type, since=since)
874 def upload(self, log, **keywords):
877 logtype_list = ['bm.log', ]
879 if 'hostname' in keywords:
880 hostname = keywords['hostname']
881 if 'type' in keywords and keywords['type'] in logtype_list:
882 logtype = keywords['type']
884 if not hostname: return ""
885 if not logtype: return "unknown logtype: %s" % logtype
887 short_target_filename = bootman.bootmanager_log_name(hostname)
888 abs_target_filename = os.path.join(config.MONITOR_BOOTMANAGER_LOG, short_target_filename)
889 print "write data: %s" % abs_target_filename
890 util.file.dumpFile(abs_target_filename, log.file.read())
891 bootman.bootmanager_log_action(hostname, short_target_filename, logtype)
894 print "redirecting 3"