1 import turbogears as tg
2 from turbogears import controllers, expose, flash, exception_handler, redirect
3 from turbogears import widgets
4 from cherrypy import request, response
6 # from monitorweb import model
8 # log = logging.getLogger("monitorweb.controllers")
11 from monitor.database.info.model import *
12 #from monitor.database.zabbixapi.model import *
13 from monitor_xmlrpc import MonitorXmlrpcServer
14 from controllers_local import LocalExtensions
16 from monitor import util
17 from monitor import reboot
18 from monitor import bootman
19 from monitor import scanapi
20 from monitor import config
23 from monitor.wrapper.plccache import plcdb_hn2lb as site_hn2lb
25 from monitorweb.templates.links import *
27 def session_clear_all():
31 except AttributeError: # SQLAlchemy < 0.5.1
34 class ObjectQueryFields(widgets.WidgetsList):
35 """The WidgetsList defines the fields of the form."""
40 class NodeQueryFields(widgets.WidgetsList):
41 """The WidgetsList defines the fields of the form."""
43 object = widgets.RadioButtonList(label="Query Type", options=[('nodes', 'All Nodes'),
44 ('nodehistory', 'Single Node History'),
45 #('sites', 'All Sites'),
46 #('sitehistory', 'Single Site History'),
48 nodehistory_hostname = widgets.TextField(label="Hostname Node History", attrs={'size':30})
50 hostname = widgets.CheckBox(label="Hostname")
51 firewall = widgets.CheckBox(label="Firewall?")
52 fs_status = widgets.CheckBox(label="Filesystem Status")
53 ssh_status = widgets.CheckBox(label="SSH Status")
54 ssh_error = widgets.CheckBox(label="SSH Errors")
55 dns_status = widgets.CheckBox(label="DNS Status")
56 iptables_status = widgets.CheckBox(label="IP Tables Status")
57 nm_status = widgets.CheckBox(label="NM Status")
58 princeton_comon_dir = widgets.CheckBox(label="CoMon Dir")
59 princeton_comon_running = widgets.CheckBox(label="CoMon Running")
60 princeton_comon_procs = widgets.CheckBox(label="CoMon Processes")
61 external_dns_status = widgets.CheckBox(label="Hostname Resolves?")
62 kernel_version = widgets.CheckBox(label="Kernel")
63 bootcd_version = widgets.CheckBox(label="BootCD")
64 boot_server = widgets.CheckBox(label="Boot Server")
65 install_date = widgets.CheckBox(label="Installation Date")
66 observed_status = widgets.CheckBox(label="Observed Status")
67 uptime = widgets.CheckBox(label="Uptime")
68 traceroute = widgets.CheckBox(label="Traceroute")
69 port_status = widgets.CheckBox(label="Port Status")
70 plc_pcuid = widgets.CheckBox(label="PCU ID")
71 rpms = widgets.CheckBox(label="RPM")
72 rpmvalue = widgets.TextField(label="RPM Pattern")
74 class QueryForm(widgets.TableForm):
76 <form xmlns:py="http://purl.org/kid/ns#"
84 <div py:for="field in hidden_fields"
85 py:replace="field.display(value_for(field), **params_for(field))"
87 <table border="0" cellspacing="0" cellpadding="2" py:attrs="table_attrs">
88 <tr py:for="i, field in enumerate(fields)"
89 class="${i%2 and 'odd' or 'even'}"
92 <label class="fieldlabel" for="${field.field_id}" py:content="field.label" />
95 <span py:replace="field.display(value_for(field), **params_for(field))" />
96 <span py:if="error_for(field)" class="fielderror" py:content="error_for(field)" />
97 <span py:if="field.help_text" class="fieldhelp" py:content="field.help_text" />
102 <td py:content="submit.display(submit_text)" />
108 def getNodeQueryForm():
109 return QueryForm(fields=NodeQueryFields(), action="query")
111 # make it easier group objects without invoking the elixir auto-write feature.
112 class aggregate: pass
115 def query_to_dict(query):
116 """ take a url query string and chop it up """
118 query_fields = query.split('&')
119 for f in query_fields:
120 (k,v) = urllib.splitvalue(f)
125 def format_ports(data, pcumodel=None):
130 supported_ports=reboot.model_to_object(pcumodel).supported_ports
132 # ports of a production node
133 supported_ports=[22,80,806]
135 if data and len(data.keys()) > 0 :
136 for port in supported_ports:
138 state = data[str(port)]
142 if state == "filtered":
145 retval.append( (port, state) )
148 retval = [( "Closed/Filtered", "state" )]
150 if filtered_length == len(supported_ports):
151 retval = [( "All Filtered", "state" )]
155 def format_pcu_shortstatus(pcu):
158 if pcu.reboot_trial_status == str(0):
160 elif pcu.reboot_trial_status == "NetDown" or pcu.reboot_trial_status == "Not_Run":
161 status = pcu.reboot_trial_status
167 def prep_pcu_for_display(pcu):
172 agg.loginbase = PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base']
174 agg.loginbase = "unknown"
176 agg.pcuhist = HistoryPCURecord.query.get(pcu.plc_pcuid)
178 agg.ports = format_ports(pcu.port_status, pcu.plc_pcu_stats['model'])
179 agg.status = format_pcu_shortstatus(pcu)
181 #print pcu.entry_complete
182 agg.entry_complete_str = pcu.entry_complete
183 #pcu.entry_complete_str += "".join([ f[0] for f in pcu.entry_complete.split() ])
184 if pcu.dns_status == "NOHOSTNAME":
185 agg.dns_short_status = 'NoHost'
186 elif pcu.dns_status == "DNS-OK":
187 agg.dns_short_status = 'Ok'
188 elif pcu.dns_status == "DNS-NOENTRY":
189 agg.dns_short_status = 'NoEntry'
190 elif pcu.dns_status == "NO-DNS-OR-IP":
191 agg.dns_short_status = 'NoHostOrIP'
192 elif pcu.dns_status == "DNS-MISMATCH":
193 agg.dns_short_status = 'Mismatch'
196 class ActionListWidget(widgets.Widget):
199 class NodeWidget(widgets.Widget):
202 def prep_nodehist(node):
205 agg.loginbase = "unknown"
207 agg.loginbase = PlcSite.query.get(node.plc_siteid).plc_site_stats['login_base']
209 agg.loginbase = "exception"
214 def prep_node_for_display(node, pcuhash=None, preppcu=True, asofdate=None):
218 if node.plc_pcuid and preppcu:
220 pcu = pcuhash[node.plc_pcuid]
222 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=node.plc_pcuid)
225 agg.pcu_status = pcu.reboot_trial_status
226 agg.pcu_short_status = format_pcu_shortstatus(pcu)
227 agg.pcu = prep_pcu_for_display(pcu)
229 agg.pcu_short_status = "none"
230 agg.pcu_status = "nodata"
234 agg.pcu_status = "nopcu"
235 agg.pcu_short_status = "none"
239 if node.kernel_version:
240 agg.kernel = node.kernel_version.split()[2]
245 agg.loginbase = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
247 agg.loginbase = "unknown"
250 agg.site = HistorySiteRecord.by_loginbase(agg.loginbase)
253 agg.site = agg.site.get_as_of(asofdate)
256 # TODO: need a cleaner fix for this...
257 agg.site = HistorySiteRecord.by_loginbase("pl")
259 agg.site = HistorySiteRecord.by_loginbase("ple")
261 agg.history = HistoryNodeRecord.by_hostname(node.hostname)
263 agg.history = agg.history.get_as_of(asofdate)
265 agg.ports = format_ports(node.port_status)
268 exists = node.plc_node_stats['last_contact']
270 # TODO: this should not assign to the fb object!
271 node.plc_node_stats = {'last_contact' : None}
276 class Root(controllers.RootController, MonitorXmlrpcServer, LocalExtensions):
277 @expose(template="monitorweb.templates.welcome")
279 # log.debug("Happy TurboGears Controller Responding For Duty")
280 flash("Welcome To MyOps!")
281 return dict(now=time.ctime())
283 @expose(template="monitorweb.templates.nodelist", allow_json=True)
284 def node3(self, filter=None):
285 nhquery = HistoryNodeRecord.query.all()
289 if nh.status == filter:
296 fb = FindbadNodeRecord.get_latest_by(hostname=q.hostname)
299 return dict(now=time.ctime(), query=rquery)
301 def node_query(self, filter):
302 nhquery = HistoryNodeRecord.query.all()
306 if nh.status == filter:
313 fb = FindbadNodeRecord.get_latest_by(hostname=q.hostname)
314 agg = prep_node_for_display(fb)
318 @expose("cheetah:monitorweb.templates.nodelist_plain", as_format="plain",
319 accept_format="text/plain", content_type="text/plain")
320 @expose(template="monitorweb.templates.nodelist", allow_json=True)
321 def node2(self, filter=None):
322 rquery=self.node_query(filter)
323 widget = NodeWidget(template='monitorweb.templates.node_template')
324 return dict(now=time.ctime(), query=rquery, nodewidget=widget)
326 @expose("cheetah:monitorweb.templates.query_plain", as_format="plain",
327 accept_format="text/plain", content_type="text/plain")
328 @expose(template="monitorweb.templates.query", allow_json=True)
329 def query(self, **data):
337 if 'object' in data and data['object'] == "nodes":
338 fbquery = FindbadNodeRecord.get_all_latest()
339 elif 'object' in data and data['object'] == "nodehistory":
340 hostname = data['nodehistory_hostname']
341 data['date_checked'] = 'date_checked'
342 fbrecord = FindbadNodeRecord.get_by(hostname=hostname)
343 fbquery = fbrecord.versions[-500:]
347 # NOTE: reformat some fields.
348 if type(node) is not type(FindbadNodeRecord):
349 agg = node.__dict__.copy()
352 if agg['plc_node_stats']:
353 agg.update(agg['plc_node_stats'])
354 if agg['install_date']:
355 agg['install_date'] = time.mktime(time.strptime(agg['install_date'], "%a %b %d %H:%M:%S %Y"))
356 if agg['kernel_version']:
357 agg['kernel_version'] = agg['kernel_version'].split()[2]
358 if 'traceroute' in data and agg['traceroute']:
359 agg['traceroute'] = "<pre>" + agg['traceroute'] + "</pre>"
360 if 'rpmvalue' in data and 'rpms' in data:
362 rpm_list = agg['rpms'].split()
363 rpm_list = filter(lambda x: re.match(data['rpmvalue'], x, re.I),
365 agg['rpms'] = " ".join(rpm_list)
373 del fields['rpmvalue']
374 del fields['nodehistory_hostname']
376 return dict(now=time.ctime(), query=query, fields=fields, data=data, queryform=getNodeQueryForm())
378 @expose(template="monitorweb.templates.nodefast", allow_json=True)
379 def node(self, filter=None):
380 nhquery = HistoryNodeRecord.query.all()
384 if nh.status == filter:
385 agg = prep_nodehist(nh)
388 agg = prep_nodehist(nh)
391 return dict(now=time.ctime(), query=query)
393 @expose(template="monitorweb.templates.nodelist")
394 def nodeslow(self, filter='boot'):
395 print "NODE------------------"
396 print "befor-len: ", len( [ i for i in session] )
398 print "after-len: ", len( [ i for i in session] )
399 fbquery = FindbadNodeRecord.get_all_latest()
401 filtercount = {'down' : 0, 'boot': 0, 'debug' : 0, 'diagnose' : 0, 'disabled': 0,
402 'neverboot' : 0, 'pending' : 0, 'all' : 0, None : 0}
404 # NOTE: reformat some fields.
405 agg = prep_node_for_display(node)
410 if agg.history.status in ['down', 'offline']:
411 if node.plc_node_stats and node.plc_node_stats['last_contact'] != None:
412 filtercount['down'] += 1
414 filtercount['neverboot'] += 1
415 elif agg.history.status in ['good', 'online']:
416 filtercount['boot'] += 1
417 elif agg.history.status in ['debug', 'monitordebug']:
418 filtercount['debug'] += 1
420 if filtercount.has_key(agg.history.status):
421 filtercount[agg.history.status] += 1
425 if filter == "neverboot":
426 if not node.plc_node_stats or node.plc_node_stats['last_contact'] == None:
428 elif filter == "all":
430 elif filter == agg.history.status:
432 elif filter == 'boot':
436 widget = NodeWidget(template='monitorweb.templates.node_template')
437 return dict(now=time.ctime(), query=query, fc=filtercount, nodewidget=widget)
439 def nodeaction_handler(self, tg_exceptions=None):
440 """Handle any kind of error."""
441 print "NODEACTION_HANDLER------------------"
443 if 'pcuid' in request.params:
444 pcuid = request.params['pcuid']
446 refurl = request.headers.get("Referer",link("pcu"))
449 # TODO: do this more intelligently...
450 uri_fields = urllib.splitquery(refurl)
451 if uri_fields[1] is not None:
452 val = query_to_dict(uri_fields[1])
455 elif 'hostname' in val:
456 pcuid = FindbadNodeRecord.get_latest_by(hostname=val['hostname']).plc_pcuid
462 cherry_trail = cherrypy._cputil.get_object_trail()
463 for i in cherry_trail:
467 return self.pcuview(None, pcuid, **dict(exceptions=tg_exceptions))
469 def nodeaction(self, **data):
470 print "NODEACTION------------------"
471 for item in data.keys():
472 print "%s %s" % ( item, data[item] )
474 if 'hostname' in data:
475 hostname = data['hostname']
477 flash("No hostname given in submitted data")
480 if 'submit' in data or 'type' in data:
482 action = data['submit']
484 action = data['type']
486 flash("No submit action given in submitted data")
489 if action == "Reboot":
490 print "REBOOT: %s" % hostname
491 ret = reboot.reboot_str(str(hostname))
493 if ret: raise RuntimeError("Error using PCU: " + str(ret))
494 flash("Reboot appeared to work. Allow at most 5 minutes. Then run ExternalScan to check current status.")
496 elif action == "ExternalScan":
497 scanapi.externalprobe(str(hostname))
498 flash("External Scan Successful!")
499 elif action == "InternalScan":
500 scanapi.internalprobe(str(hostname))
501 flash("Internal Scan Successful!")
504 raise RuntimeError("Unknown action given")
507 @expose(template="monitorweb.templates.simpleview")
508 def simpleview(self, **data):
509 return self.pre_view(**data)
511 @expose(template="monitorweb.templates.simpleview")
512 def pcuview(self, **data):
513 return self.pre_view(**data)
515 @expose(template="monitorweb.templates.detailview")
516 def detailview(self, **data):
517 return self.pre_view(**data)
520 def pre_view(self, **data):
528 # if objtype is not None, then treat 'hostname' or 'loginbase' as a search pattern
543 fields = obj.split(":")
546 obj = fields[1].replace("*", "%")
549 if len(obj.split(".")) > 1 or objtype == "node":
554 if 'loginbase' in data:
555 loginbase = data['loginbase']
557 if 'hostname' in data:
558 hostname = data['hostname']
561 try: pcuid = int(data['pcuid'])
565 try: since = int(since)
569 print "pcuid: %s" % pcuid
570 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
571 loginbase_list += [ PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base'] ]
575 nodes = [ FindbadNodeRecord.get_latest_by(hostname=hostname) ]
577 nodes = FindbadNodeRecord.query.filter(FindbadNodeRecord.hostname.like(hostname))
580 lb = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
581 if lb not in loginbase_list:
582 loginbase_list += [ lb ]
586 loginbase_list = [ loginbase ]
588 loginbase_list = HistorySiteRecord.query.filter(HistorySiteRecord.loginbase.like(loginbase))
589 loginbase_list = [ l.loginbase for l in loginbase_list ]
593 for loginbase in loginbase_list:
594 actions = ActionRecord.query.filter_by(loginbase=loginbase
595 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
596 ).order_by(ActionRecord.date_created.desc())
597 actions_list += [ a for a in actions ]
598 site = HistorySiteRecord.by_loginbase(loginbase)
600 sitequery.append(site)
601 # NOTE: because a single pcu may be assigned to multiple hosts,
602 # track unique pcus by their plc_pcuid, then turn dict into list
604 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
605 # NOTE: reformat some fields.
606 agg = prep_node_for_display(node)
609 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
611 for pcuid_key in pcus:
612 pcuquery += [pcus[pcuid_key]]
614 actionlist_widget = ActionListWidget(template='monitorweb.templates.actionlist_template')
615 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions_list, actionlist_widget=actionlist_widget, since=since, exceptions=exceptions)
618 # TODO: add form validation
619 @expose(template="monitorweb.templates.pcuview")
620 @exception_handler(nodeaction_handler,"isinstance(tg_exceptions,RuntimeError)")
621 def pcuviewold(self, loginbase=None, pcuid=None, hostname=None, since=20, **data):
629 try: since = int(since)
635 if 'submit' in data.keys() or 'type' in data.keys():
636 if hostname: data['hostname'] = hostname
637 self.nodeaction(**data)
638 if 'exceptions' in data:
639 exceptions = data['exceptions']
643 if len(obj.split(".")) > 1: hostname = obj
647 print "pcuid: %s" % pcuid
648 pcu = FindbadPCURecord.get_latest_by(plc_pcuid=pcuid)
649 loginbase = PlcSite.query.get(pcu.plc_pcu_stats['site_id']).plc_site_stats['login_base']
652 node = FindbadNodeRecord.get_latest_by(hostname=hostname)
653 loginbase = PlcSite.query.get(node.plc_node_stats['site_id']).plc_site_stats['login_base']
656 actions = ActionRecord.query.filter_by(loginbase=loginbase
657 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since)
658 ).order_by(ActionRecord.date_created.desc())
659 actions = [ a for a in actions ]
660 sitequery = [HistorySiteRecord.by_loginbase(loginbase)]
662 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
663 # NOTE: reformat some fields.
664 agg = prep_node_for_display(node)
666 if agg.pcu: #.pcu.plc_pcuid: # not None
667 #pcu = FindbadPCURecord.get_latest_by(plc_pcuid=agg.plc_pcuid)
668 #prep_pcu_for_display(pcu)
669 pcus[agg.pcu.pcu.plc_pcuid] = agg.pcu
671 for pcuid_key in pcus:
672 pcuquery += [pcus[pcuid_key]]
674 return dict(sitequery=sitequery, pcuquery=pcuquery, nodequery=nodequery, actions=actions, since=since, exceptions=exceptions)
676 @expose(template="monitorweb.templates.pcuhistory")
677 def pcuhistory(self, pcu_id=None):
680 fbnode = HistoryPCURecord.get_by(plc_pcuid=pcu_id)
681 l = fbnode.versions[-1000:]
684 #prep_node_for_display(node)
687 return dict(query=query, pcu_id=pcu_id)
689 @expose(template="monitorweb.templates.nodescanhistory")
690 def nodescanhistory(self, hostname=None, length=10):
691 try: length = int(length)
694 fbnode = FindbadNodeRecord.get_by(hostname=hostname)
695 # TODO: add links for earlier history if desired.
696 l = fbnode.versions[-length:]
700 agg = prep_node_for_display(node, pcuhash=None, preppcu=False, asofdate=node.timestamp)
703 if 'length' in request.params:
704 del request.params['length']
705 return dict(query=query, hostname=hostname, params=request.params)
707 @expose(template="monitorweb.templates.nodehistory")
708 def nodehistory(self, hostname=None):
711 fbnode = HistoryNodeRecord.get_by(hostname=hostname)
712 l = fbnode.versions[-100:]
715 #prep_node_for_display(node)
718 return dict(query=query, hostname=hostname)
720 @expose(template="monitorweb.templates.sitehistory")
721 def sitehistory(self, loginbase=None):
724 fbsite = HistorySiteRecord.get_by(loginbase=loginbase)
725 # TODO: add links for earlier history if desired.
726 l = fbsite.versions[-1000:]
730 return dict(query=query, loginbase=loginbase)
733 @expose("cheetah:monitorweb.templates.pculist_plain", as_format="plain",
734 accept_format="text/plain", content_type="text/plain")
735 @expose(template="monitorweb.templates.pculist")
736 def pcu(self, filter='all'):
737 print "PCUVIEW------------------"
738 print "befor-len: ", len( [ i for i in session] )
740 print "after-len: ", len( [ i for i in session] )
741 fbquery = FindbadPCURecord.get_all_latest()
743 filtercount = {'ok' : 0, 'NetDown': 0, 'Not_Run' : 0, 'pending' : 0, 'all' : 0}
747 if node.reboot_trial_status == str(0):
748 filtercount['ok'] += 1
749 elif node.reboot_trial_status == 'NetDown' or node.reboot_trial_status == 'Not_Run':
750 filtercount[node.reboot_trial_status] += 1
752 filtercount['pending'] += 1
754 pcuagg = prep_pcu_for_display(node)
759 elif filter == "ok" and node.reboot_trial_status == str(0):
761 elif filter == node.reboot_trial_status:
763 elif filter == "pending":
764 # TODO: look in message logs...
765 if node.reboot_trial_status != str(0) and \
766 node.reboot_trial_status != 'NetDown' and \
767 node.reboot_trial_status != 'Not_Run':
771 return dict(query=query, fc=filtercount)
773 @expose(template="monitorweb.templates.sitelist")
774 def site(self, filter='all'):
775 print "SITE------------------"
776 print "befor-len: ", len( [ i for i in session] )
778 print "after-len: ", len( [ i for i in session] )
779 filtercount = {'good' : 0, 'down': 0, 'online':0, 'offline' : 0, 'new' : 0, 'pending' : 0, 'all' : 0}
780 fbquery = HistorySiteRecord.query.all()
784 filtercount['all'] += 1
785 if site.new and site.slices_used == 0 and not site.enabled:
786 filtercount['new'] += 1
787 elif not site.enabled:
788 filtercount['pending'] += 1
789 elif site.status in ['good', 'online']:
790 filtercount['good'] += 1
791 elif site.status in ['down', 'offline']:
792 filtercount['down'] += 1
797 elif filter == 'new' and site.new and site.slices_used == 0 and not site.enabled:
799 elif filter == "pending" and not site.enabled:
801 elif filter == 'good' and site.status in ['good', 'online']:
803 elif filter == 'down' and site.status in ['down', 'offline']:
806 return dict(query=query, fc=filtercount)
807 @expose(template="monitorweb.templates.sitesummary")
808 def sitesummary(self, loginbase="princeton"):
810 for node in FindbadNodeRecord.query.filter_by(loginbase=loginbase):
811 agg = prep_node_for_display(node)
814 return dict(nodequery=nodequery, loginbase=loginbase)
816 @expose(template="monitorweb.templates.summary")
817 def summary(self, since=7):
819 sumdata['nodes'] = {}
820 sumdata['sites'] = {}
823 def summarize(query, type):
825 if o.status not in sumdata[type]:
826 sumdata[type][o.status] = 0
827 sumdata[type][o.status] += 1
829 fbquery = HistorySiteRecord.query.all()
830 summarize(fbquery, 'sites')
831 fbquery = HistoryPCURecord.query.all()
832 summarize(fbquery, 'pcus')
833 fbquery = HistoryNodeRecord.query.all()
834 summarize(fbquery, 'nodes')
836 if 'monitordebug' in sumdata['nodes']:
837 d = sumdata['nodes']['monitordebug']
838 del sumdata['nodes']['monitordebug']
839 sumdata['nodes']['failboot'] = d
841 return dict(sumdata=sumdata, setorder=['good', 'offline', 'down', 'online'])
843 @expose(template="monitorweb.templates.actionsummary")
844 def actionsummary(self, since=7):
845 from monitor.wrapper.emailTxt import mailtxt
847 types = filter(lambda x: 'notice' in x, dir(mailtxt))
850 print mon_metadata.bind
851 if session.bind is None:
852 #TODO: figure out why this value gets cleared out...
853 session.bind = mon_metadata.bind
854 result = session.execute("select distinct(action_type) from actionrecord;")
856 types = [r[0] for r in result]
858 try: since = int(since)
862 acts = ActionRecord.query.filter(ActionRecord.action_type==t
863 ).filter(ActionRecord.date_created >= datetime.now() - timedelta(since))
864 results[t] = acts.count()
865 return dict(results=results)
867 @expose(template="monitorweb.templates.actionlist")
868 def actionlist(self, since=7, action_type=None, loginbase=None):
870 try: since = int(since)
873 acts_query = ActionRecord.query.filter(
874 ActionRecord.date_created >= datetime.now() - timedelta(since)
877 acts_query = acts_query.filter_by(loginbase=loginbase)
880 acts_query = acts_query.filter(ActionRecord.action_type==action_type)
882 acts = acts_query.order_by(ActionRecord.date_created.desc())
884 query = [ a for a in acts ]
886 return dict(actions=query, action_type=action_type, since=since)
889 def upload(self, log, **keywords):
892 logtype_list = ['bm.log', ]
894 if 'hostname' in keywords:
895 hostname = keywords['hostname']
896 if 'type' in keywords and keywords['type'] in logtype_list:
897 logtype = keywords['type']
899 if not hostname: return ""
900 if not logtype: return "unknown logtype: %s" % logtype
902 short_target_filename = bootman.bootmanager_log_name(hostname)
903 abs_target_filename = os.path.join(config.MONITOR_BOOTMANAGER_LOG, short_target_filename)
904 print "write data: %s" % abs_target_filename
905 util.file.dumpFile(abs_target_filename, log.file.read())
906 bootman.bootmanager_log_action(hostname, short_target_filename, logtype)
909 print "redirecting 3"