added actionlist_template to display action list consistently on different pages
[monitor.git] / monitor / common.py
1
2 import time
3 import struct
4 from monitor import reboot
5 from monitor import util
6 from monitor.wrapper import plc
7
8 from datetime import datetime, timedelta
9 from monitor.model import Message
10 from monitor.database.info import HistoryNodeRecord
11
12 esc = struct.pack('i', 27)
13 RED     = esc + "[1;31m"
14 GREEN   = esc + "[1;32m"
15 YELLOW  = esc + "[1;33m"
16 BLUE    = esc + "[1;34m"
17 LIGHTBLUE       = esc + "[1;36m"
18 NORMAL  = esc + "[0;39m"
19
20 def red(str):
21         return RED + str + NORMAL
22
23 def yellow(str):
24         return YELLOW + str + NORMAL
25
26 def green(str):
27         return GREEN + str + NORMAL
28
29 def lightblue(str):
30         return LIGHTBLUE + str + NORMAL
31
32 def blue(str):
33         return BLUE + str + NORMAL
34
35 def get_current_state(fbnode):
36         if 'observed_status' in fbnode:
37                 state = fbnode['observed_status']
38         else:
39                 state = "none"
40         l = state.lower()
41         if l == "debug": l = 'dbg '
42         return l
43
44 def color_pcu_state(fbnode):
45
46         if 'plcnode' in fbnode and 'pcu_ids' in fbnode['plcnode'] and len(fbnode['plcnode']['pcu_ids']) > 0 :
47                 values = reboot.get_pcu_values(fbnode['plcnode']['pcu_ids'][0])
48                 if values == None:
49                         return fbnode['pcu']
50         else:
51                 if 'pcu' not in fbnode:
52                         return 'NOPCU'
53                 else:
54                         return fbnode['pcu']
55
56         if 'reboot' in values:
57                 rb = values['reboot']
58                 if rb == 0 or rb == "0":
59                         return fbnode['pcu'] + "OK  "
60                 elif "NetDown" == rb  or "Not_Run" == rb:
61                         return fbnode['pcu'] + "DOWN"
62                 else:
63                         return fbnode['pcu'] + "BAD "
64         else:
65                 return fbnode['pcu'] + "BAD "
66
67 def color_boot_state(l):
68         if    l == "dbg": return yellow("debg")
69         elif  l == "dbg ": return yellow("debg")
70         elif  l == "failboot": return yellow("debg")
71         elif  l == "diag": return lightblue(l)
72         elif  l == "diagnose": return lightblue(l)
73         elif  l == "safeboot": return lightblue(l)
74         elif  l == "disable": return red("dsbl")
75         elif  l == "disabled": return red("dsbl")
76         elif  l == "down": return red(l)
77         elif  l == "boot": return green(l)
78         elif  l == "rins": return blue(l)
79         elif  l == "reinstall": return blue(l)
80         else:
81                 return l
82
83 def diff_time(timestamp, abstime=True):
84         import math
85         now = time.time()
86         if timestamp == None:
87                 return "unknown"
88         if type(timestamp) == type(datetime.now()):
89                 timestamp = time.mktime(timestamp.timetuple())
90         if abstime:
91                 diff = now - timestamp
92         else:
93                 diff = timestamp
94         # return the number of seconds as a difference from current time.
95         t_str = ""
96         if diff < 60: # sec in min.
97                 t = diff / 1
98                 t_str = "%s sec ago" % int(math.ceil(t))
99         elif diff < 60*60: # sec in hour
100                 t = diff / (60)
101                 t_str = "%s min ago" % int(math.ceil(t))
102         elif diff < 60*60*24: # sec in day
103                 t = diff / (60*60)
104                 t_str = "%s hrs ago" % int(math.ceil(t))
105         elif diff < 60*60*24*14: # sec in week
106                 t = diff / (60*60*24)
107                 t_str = "%s days ago" % int(math.ceil(t))
108         elif diff <= 60*60*24*30: # approx sec in month
109                 t = diff / (60*60*24*7)
110                 t_str = "%s wks ago" % int(math.ceil(t))
111         elif diff > 60*60*24*30: # approx sec in month
112                 t = diff / (60*60*24*30)
113                 t_str = "%s mnths ago" % int(t)
114         return t_str
115
116 def getvalue(fb, path):
117     indexes = path.split("/")
118     values = fb
119     for index in indexes:
120         if index in values:
121             values = values[index]
122         else:
123             return None
124     return values
125
126 def nmap_port_status(status):
127         ps = {}
128         l_nmap = status.split()
129         ports = l_nmap[4:]
130
131         continue_probe = False
132         for port in ports:
133                 results = port.split('/')
134                 ps[results[0]] = results[1]
135                 if results[1] == "open":
136                         continue_probe = True
137         return (ps, continue_probe)
138
139
140 def nodegroup_display(node, fbdata, conf=None):
141         node['current'] = get_current_state(fbdata)
142
143         s = fbdata['kernel_version'].split()
144         if len(s) >=3:
145                 node['kernel_version'] = s[2]
146         else:
147                 node['kernel_version'] = fbdata['kernel_version']
148                 
149         if '2.6' not in node['kernel_version']: node['kernel_version'] = ""
150         if conf and not conf.nocolor:
151             node['boot_state']  = color_boot_state(node['boot_state'])
152             node['current']     = color_boot_state(node['current'])
153
154         if type(fbdata['plc_node_stats']['pcu_ids']) == type([]):
155                 node['pcu'] = "PCU"
156         node['lastupdate'] = diff_time(node['last_contact'])
157
158         pf = HistoryNodeRecord.get_by(hostname=node['hostname'])
159         try:
160                 node['lc'] = diff_time(pf.last_changed)
161         except:
162                 node['lc'] = "err"
163
164         ut = fbdata['comon_stats']['uptime']
165         if ut != "null":
166                 ut = diff_time(float(fbdata['comon_stats']['uptime']), False)
167         node['uptime'] = ut
168
169         return "%(hostname)-42s %(boot_state)8s %(current)5s %(pcu)6s %(key)10.10s... %(kernel_version)35.35s %(lastupdate)12s, %(lc)s, %(uptime)s" % node
170
171 def datetime_fromstr(str):
172         if '-' in str:
173                 try:
174                         tup = time.strptime(str, "%Y-%m-%d")
175                 except:
176                         tup = time.strptime(str, "%Y-%m-%d-%H:%M")
177         elif '/' in str:
178                 tup = time.strptime(str, "%m/%d/%Y")
179         else:
180                 tup = time.strptime(str, "%m/%d/%Y")
181         ret = datetime.fromtimestamp(time.mktime(tup))
182         return ret
183
184 def get_nodeset(config):
185         """
186                 Given the config values passed in, return the set of hostnames that it
187                 evaluates to.
188         """
189         from monitor.wrapper import plccache
190         api = plc.getAuthAPI()
191         l_nodes = plccache.l_nodes
192
193         if config.nodelist:
194                 f_nodes = util.file.getListFromFile(config.nodelist)
195                 l_nodes = filter(lambda x: x['hostname'] in f_nodes, l_nodes)
196         elif config.node:
197                 f_nodes = [config.node]
198                 l_nodes = filter(lambda x: x['hostname'] in f_nodes, l_nodes)
199         elif config.nodegroup:
200                 ng = api.GetNodeGroups({'name' : config.nodegroup})
201                 l_nodes = api.GetNodes(ng[0]['node_ids'], ['hostname'])
202         elif config.site:
203                 site = api.GetSites(config.site)
204                 l_nodes = api.GetNodes(site[0]['node_ids'], ['hostname'])
205                 
206         l_nodes = [node['hostname'] for node in l_nodes]
207
208         # perform this query after the above options, so that the filter above
209         # does not break.
210         if config.nodeselect:
211                 fbquery = FindbadNodeRecord.get_all_latest()
212                 node_list = [ n.hostname for n in fbquery ]
213                 l_nodes = node_select(config.nodeselect, node_list, None)
214
215         return l_nodes
216
217 def email_exception(content=None, title=None):
218     import config
219     from monitor.model import Message
220     import traceback
221     msg=traceback.format_exc()
222     if content:
223         msg = content + "\n" + msg
224
225     full_title = "exception running monitor"
226     if title:
227         full_title = "exception running monitor %s" % title
228
229     m=Message(full_title, msg, False)
230     m.send([config.exception_email])
231     return
232
233 def changed_lessthan(last_changed, days):
234         if datetime.now() - last_changed <= timedelta(days):
235                 #print "last changed less than %s" % timedelta(days)
236                 return True
237         else:
238                 #print "last changed more than %s" % timedelta(days)
239                 return False
240
241 def changed_greaterthan(last_changed, days):
242         if datetime.now() - last_changed > timedelta(days):
243                 #print "last changed more than %s" % timedelta(days)
244                 return True
245         else:
246                 #print "last changed less than %s" % timedelta(days)
247                 return False
248
249 def found_between(recent_actions, action_type, lower, upper):
250         return found_before(recent_actions, action_type, upper) and found_within(recent_actions, action_type, lower)
251
252 def found_before(recent_actions, action_type, within):
253         for action in recent_actions:
254                 if action_type == action.action_type and \
255                                 action.date_created < (datetime.now() - timedelta(within)):
256                         return True
257         return False
258         
259 def found_within(recent_actions, action_type, within):
260         for action in recent_actions:
261                 #print "%s - %s %s > %s - %s (%s) ==> %s" % (action.loginbase, action.action_type, action.date_created, datetime.now(), timedelta(within), datetime.now()-timedelta(within), action.date_created > (datetime.now() - timedelta(within)) )
262                 if action_type == action.action_type and \
263                                 action.date_created > (datetime.now() - timedelta(within)):
264                                 #datetime.now() - action.date_created < timedelta(within):
265                         # recent action of given type.
266                         #print "%s found_within %s in recent_actions from %s" % (action_type, timedelta(within), action.date_created)
267                         return True
268
269         print "%s NOT found_within %s in recent_actions" % (action_type, timedelta(within) )
270         return False
271