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 if agg['plc_node_stats']:
344 agg.update(agg['plc_node_stats'])
345 if agg['install_date']:
346 agg['install_date'] = time.mktime(time.strptime(agg['install_date'], "%a %b %d %H:%M:%S %Y"))
347 if agg['kernel_version']:
348 agg['kernel_version'] = agg['kernel_version'].split()[2]
349 if 'traceroute' in data and agg['traceroute']:
350 agg['traceroute'] = "<pre>" + agg['traceroute'] + "</pre>"
351 if 'rpmvalue' in data and 'rpms' in data:
353 rpm_list = agg['rpms'].split()
354 rpm_list = filter(lambda x: re.match(data['rpmvalue'], x, re.I),
356 agg['rpms'] = " ".join(rpm_list)
364 del fields['rpmvalue']
365 del fields['nodehistory_hostname']
367 return dict(now=time.ctime(), query=query, fields=fields, data=data, queryform=getNodeQueryForm())
369 @expose(template="monitorweb.templates.nodefast", allow_json=True)
370 def node(self, filter=None):
371 nhquery = HistoryNodeRecord.query.all()
375 if nh.status == filter:
376 agg = prep_nodehist(nh)
379 agg = prep_nodehist(nh)
382 return dict(now=time.ctime(), query=query)
384 @expose(template="monitorweb.templates.nodelist")
385 def nodeslow(self, filter='boot'):
386 print "NODE------------------"
387 print "befor-len: ", len( [ i for i in session] )
388 session.flush(); session.clear()
389 print "after-len: ", len( [ i for i in session] )
390 fbquery = FindbadNodeRecord.get_all_latest()
392 filtercount = {'down' : 0, 'boot': 0, 'debug' : 0, 'diagnose' : 0, 'disabled': 0,
393 'neverboot' : 0, 'pending' : 0, 'all' : 0, None : 0}
395 # NOTE: reformat some fields.
396 agg = prep_node_for_display(node)
401 if agg.history.status in ['down', 'offline']:
402 if node.plc_node_stats and node.plc_node_stats['last_contact'] != None:
403 filtercount['down'] += 1
405 filtercount['neverboot'] += 1
406 elif agg.history.status in ['good', 'online']:
407 filtercount['boot'] += 1
408 elif agg.history.status in ['debug', 'monitordebug']:
409 filtercount['debug'] += 1
411 if filtercount.has_key(agg.history.status):
412 filtercount[agg.history.status] += 1
416 if filter == "neverboot":
417 if not node.plc_node_stats or node.plc_node_stats['last_contact'] == None:
419 elif filter == "all":
421 elif filter == agg.history.status:
423 elif filter == 'boot':
427 widget = NodeWidget(template='monitorweb.templates.node_template')
428 return dict(now=time.ctime(), query=query, fc=filtercount, nodewidget=widget)
430 def nodeaction_handler(self, tg_exceptions=None):
431 """Handle any kind of error."""
432 print "NODEACTION_HANDLER------------------"
434 if 'pcuid' in request.params:
435 pcuid = request.params['pcuid']
437 refurl = request.headers.get("Referer",link("pcu"))
440 # TODO: do this more intelligently...
441 uri_fields = urllib.splitquery(refurl)
442 if uri_fields[1] is not None:
443 val = query_to_dict(uri_fields[1])
446 elif 'hostname' in val:
447 pcuid = FindbadNodeRecord.get_latest_by(hostname=val['hostname']).plc_pcuid
453 cherry_trail = cherrypy._cputil.get_object_trail()
454 for i in cherry_trail:
458 return self.pcuview(None, pcuid, **dict(exceptions=tg_exceptions))
460 def nodeaction(self, **data):
461 print "NODEACTION------------------"
462 for item in data.keys():
463 print "%s %s" % ( item, data[item] )
465 if 'hostname' in data:
466 hostname = data['hostname']
468 flash("No hostname given in submitted data")
471 if 'submit' in data or 'type' in data:
473 action = data['submit']
475 action = data['type']
477 flash("No submit action given in submitted data")
480 if action == "Reboot":
481 print "REBOOT: %s" % hostname
482 ret = reboot.reboot_str(str(hostname))
484 if ret: raise RuntimeError("Error using PCU: " + str(ret))
485 flash("Reboot appeared to work. Allow at most 5 minutes. Then run ExternalScan to check current status.")
487 elif action == "ExternalScan":
488 scanapi.externalprobe(str(hostname))
489 flash("External Scan Successful!")
490 elif action == "InternalScan":
491 scanapi.internalprobe(str(hostname))
492 flash("Internal Scan Successful!")
495 raise RuntimeError("Unknown action given")
498 @expose(template="monitorweb.templates.simpleview")
499 def simpleview(self, **data):
500 return self.pre_view(**data)
502 @expose(template="monitorweb.templates.simpleview")
503 def pcuview(self, **data):
504 return self.pre_view(**data)
506 @expose(template="monitorweb.templates.detailview")
507 def detailview(self, **data):
508 return self.pre_view(**data)
511 def pre_view(self, **data):
512 session.flush(); session.clear()
519 # if objtype is not None, then treat 'hostname' or 'loginbase' as a search pattern
534 fields = obj.split(":")
537 obj = fields[1].replace("*", "%")
540 if len(obj.split(".")) > 1 or objtype == "node":
545 if 'loginbase' in data:
546 loginbase = data['loginbase']
548 if 'hostname' in data:
549 hostname = data['hostname']
552 try: pcuid = int(data['pcuid'])
556 try: since = int(since)
560 print "pcuid: %s" % pcuid
561 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
562 loginbase_list += [ PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base'] ]
566 nodes = [ FindbadNodeRecord.get_latest_by(hostname=hostname) ]
568 nodes = FindbadNodeRecord.query.filter(FindbadNodeRecord.hostname.like(hostname))
571 lb = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
572 if lb not in loginbase_list:
573 loginbase_list += [ lb ]
577 loginbase_list = [ loginbase ]
579 loginbase_list = HistorySiteRecord.query.filter(HistorySiteRecord.loginbase.like(loginbase))
580 loginbase_list = [ l.loginbase for l in loginbase_list ]
584 for loginbase in loginbase_list:
585 actions = ActionRecord.query.filter_by(loginbase=loginbase
586 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
587 ).order_by(ActionRecord.date_created.desc())
588 actions_list += [ a for a in actions ]
589 site = HistorySiteRecord.by_loginbase(loginbase)
591 sitequery.append(site)
592 # NOTE: because a single pcu may be assigned to multiple hosts,
593 # track unique pcus by their plc_pcuid, then turn dict into list
595 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
596 # NOTE: reformat some fields.
597 agg = prep_node_for_display(node)
600 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
602 for pcuid_key in pcus:
603 pcuquery += [pcus[pcuid_key]]
605 actionlist_widget = ActionListWidget(template='monitorweb.templates.actionlist_template')
606 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions_list, actionlist_widget=actionlist_widget, since=since, exceptions=exceptions)
609 # TODO: add form validation
610 @expose(template="monitorweb.templates.pcuview")
611 @exception_handler(nodeaction_handler,"isinstance(tg_exceptions,RuntimeError)")
612 def pcuviewold(self, loginbase=None, pcuid=None, hostname=None, since=20, **data):
613 session.flush(); session.clear()
620 try: since = int(since)
626 if 'submit' in data.keys() or 'type' in data.keys():
627 if hostname: data['hostname'] = hostname
628 self.nodeaction(**data)
629 if 'exceptions' in data:
630 exceptions = data['exceptions']
634 if len(obj.split(".")) > 1: hostname = obj
638 print "pcuid: %s" % pcuid
639 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
640 loginbase = PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base']
643 node = FindbadNodeRecord.get_latest_by(hostname=hostname)
644 loginbase = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
647 actions = ActionRecord.query.filter_by(loginbase=loginbase
648 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
649 ).order_by(ActionRecord.date_created.desc())
650 actions = [ a for a in actions ]
651 sitequery = [HistorySiteRecord.by_loginbase(loginbase)]
653 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
654 # NOTE: reformat some fields.
655 agg = prep_node_for_display(node)
657 if agg.pcu: #.pcu.plc_pcuid: # not None
658 #pcu = FindbadPCURecord.get_latest_by(plc_pcuid=agg.plc_pcuid)
659 #prep_pcu_for_display(pcu)
660 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
662 for pcuid_key in pcus:
663 pcuquery += [pcus[pcuid_key]]
665 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions, since=since, exceptions=exceptions)
667 @expose(template="monitorweb.templates.pcuhistory")
668 def pcuhistory(self, pcu_id=None):
671 fbnode = HistoryPCURecord.get_by(plc_pcuid=pcu_id)
672 l = fbnode.versions[-100:]
675 #prep_node_for_display(node)
678 return dict(query=query, pcu_id=pcu_id)
680 @expose(template="monitorweb.templates.nodescanhistory")
681 def nodescanhistory(self, hostname=None, length=10):
682 try: length = int(length)
685 fbnode = FindbadNodeRecord.get_by(hostname=hostname)
686 # TODO: add links for earlier history if desired.
687 l = fbnode.versions[-length:]
691 agg = prep_node_for_display(node, pcuhash=None, preppcu=False, asofdate=node.timestamp)
694 if 'length' in request.params:
695 del request.params['length']
696 return dict(query=query, hostname=hostname, params=request.params)
698 @expose(template="monitorweb.templates.nodehistory")
699 def nodehistory(self, hostname=None):
702 fbnode = HistoryNodeRecord.get_by(hostname=hostname)
703 l = fbnode.versions[-100:]
706 #prep_node_for_display(node)
709 return dict(query=query, hostname=hostname)
711 @expose(template="monitorweb.templates.sitehistory")
712 def sitehistory(self, loginbase=None):
715 fbsite = HistorySiteRecord.get_by(loginbase=loginbase)
716 # TODO: add links for earlier history if desired.
717 l = fbsite.versions[-100:]
721 return dict(query=query, loginbase=loginbase)
724 @expose(template="monitorweb.templates.pculist")
725 def pcu(self, filter='all'):
726 print "PCUVIEW------------------"
727 print "befor-len: ", len( [ i for i in session] )
728 session.flush(); session.clear()
729 print "after-len: ", len( [ i for i in session] )
730 fbquery = FindbadPCURecord.get_all_latest()
732 filtercount = {'ok' : 0, 'NetDown': 0, 'Not_Run' : 0, 'pending' : 0, 'all' : 0}
736 if node.reboot_trial_status == str(0):
737 filtercount['ok'] += 1
738 elif node.reboot_trial_status == 'NetDown' or node.reboot_trial_status == 'Not_Run':
739 filtercount[node.reboot_trial_status] += 1
741 filtercount['pending'] += 1
743 pcuagg = prep_pcu_for_display(node)
748 elif filter == "ok" and node.reboot_trial_status == str(0):
750 elif filter == node.reboot_trial_status:
752 elif filter == "pending":
753 # TODO: look in message logs...
754 if node.reboot_trial_status != str(0) and \
755 node.reboot_trial_status != 'NetDown' and \
756 node.reboot_trial_status != 'Not_Run':
760 return dict(query=query, fc=filtercount)
762 @expose(template="monitorweb.templates.sitelist")
763 def site(self, filter='all'):
764 print "SITE------------------"
765 print "befor-len: ", len( [ i for i in session] )
766 session.flush(); session.clear()
767 print "after-len: ", len( [ i for i in session] )
768 filtercount = {'good' : 0, 'down': 0, 'online':0, 'offline' : 0, 'new' : 0, 'pending' : 0, 'all' : 0}
769 fbquery = HistorySiteRecord.query.all()
773 filtercount['all'] += 1
774 if site.new and site.slices_used == 0 and not site.enabled:
775 filtercount['new'] += 1
776 elif not site.enabled:
777 filtercount['pending'] += 1
778 elif site.status in ['good', 'online']:
779 filtercount['good'] += 1
780 elif site.status in ['down', 'offline']:
781 filtercount['down'] += 1
786 elif filter == 'new' and site.new and site.slices_used == 0 and not site.enabled:
788 elif filter == "pending" and not site.enabled:
790 elif filter == 'good' and site.status in ['good', 'online']:
792 elif filter == 'down' and site.status in ['down', 'offline']:
795 return dict(query=query, fc=filtercount)
796 @expose(template="monitorweb.templates.sitesummary")
797 def sitesummary(self, loginbase="princeton"):
799 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
800 agg = prep_node_for_display(node)
803 return dict(nodequery=nodequery, loginbase=loginbase)
805 @expose(template="monitorweb.templates.summary")
806 def summary(self, since=7):
808 sumdata['nodes'] = {}
809 sumdata['sites'] = {}
812 def summarize(query, type):
814 if o.status not in sumdata[type]:
815 sumdata[type][o.status] = 0
816 sumdata[type][o.status] += 1
818 fbquery = HistorySiteRecord.query.all()
819 summarize(fbquery, 'sites')
820 fbquery = HistoryPCURecord.query.all()
821 summarize(fbquery, 'pcus')
822 fbquery = HistoryNodeRecord.query.all()
823 summarize(fbquery, 'nodes')
825 if 'monitordebug' in sumdata['nodes']:
826 d = sumdata['nodes']['monitordebug']
827 del sumdata['nodes']['monitordebug']
828 sumdata['nodes']['failboot'] = d
830 return dict(sumdata=sumdata, setorder=['good', 'offline', 'down', 'online'])
832 @expose(template="monitorweb.templates.actionsummary")
833 def actionsummary(self, since=7):
834 from monitor.wrapper.emailTxt import mailtxt
836 types = filter(lambda x: 'notice' in x, dir(mailtxt))
839 print mon_metadata.bind
840 if session.bind is None:
841 #TODO: figure out why this value gets cleared out...
842 session.bind = mon_metadata.bind
843 result = session.execute("select distinct(action_type) from actionrecord;")
845 types = [r[0] for r in result]
847 try: since = int(since)
851 acts = ActionRecord.query.filter(ActionRecord.action_type==t
852 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since))
853 results[t] = acts.count()
854 return dict(results=results)
856 @expose(template="monitorweb.templates.actionlist")
857 def actionlist(self, since=7, action_type=None, loginbase=None):
859 try: since = int(since)
862 acts_query = ActionRecord.query.filter(
863 ActionRecord.date_created >= datetime.now() - timedelta(since)
866 acts_query = acts_query.filter_by(loginbase=loginbase)
869 acts_query = acts_query.filter(ActionRecord.action_type==action_type)
871 acts = acts_query.order_by(ActionRecord.date_created.desc())
873 query = [ a for a in acts ]
875 return dict(actions=query, action_type=action_type, since=since)
878 def upload(self, log, **keywords):
881 logtype_list = ['bm.log', ]
883 if 'hostname' in keywords:
884 hostname = keywords['hostname']
885 if 'type' in keywords and keywords['type'] in logtype_list:
886 logtype = keywords['type']
888 if not hostname: return ""
889 if not logtype: return "unknown logtype: %s" % logtype
891 short_target_filename = bootman.bootmanager_log_name(hostname)
892 abs_target_filename = os.path.join(config.MONITOR_BOOTMANAGER_LOG, short_target_filename)
893 print "write data: %s" % abs_target_filename
894 util.file.dumpFile(abs_target_filename, log.file.read())
895 bootman.bootmanager_log_action(hostname, short_target_filename, logtype)
898 print "redirecting 3"