changes for 3.0
[monitor.git] / nodequery.py
1 #!/usr/bin/python
2
3 import plc
4 api = plc.getAuthAPI()
5
6 import sys
7 import database
8 from nodecommon import *
9 #from policy import Diagnose
10 from unified_model import Record
11 import glob
12 import os
13 from reboot import pcu_name
14 import reboot
15 import util.file
16
17 import time
18 import re
19
20 #fb = {}
21 fb = None
22 fbpcu = None
23
24 class NoKeyException(Exception): pass
25
26 def daysdown_print_nodeinfo(fbnode, hostname):
27         fbnode['hostname'] = hostname
28         fbnode['daysdown'] = Record.getStrDaysDown(fbnode)
29         fbnode['intdaysdown'] = Record.getDaysDown(fbnode)
30
31         print "%(intdaysdown)5s %(hostname)-44s | %(state)10.10s | %(daysdown)s" % fbnode
32
33 def fb_print_nodeinfo(fbnode, hostname, fields=None):
34         fbnode['hostname'] = hostname
35         fbnode['checked'] = diff_time(fbnode['checked'])
36         if fbnode['bootcd']:
37                 fbnode['bootcd'] = fbnode['bootcd'].split()[-1]
38         else:
39                 fbnode['bootcd'] = "unknown"
40         fbnode['pcu'] = color_pcu_state(fbnode)
41
42         if not fields:
43                 if 'ERROR' in fbnode['category']:
44                         fbnode['kernel'] = ""
45                 else:
46                         fbnode['kernel'] = fbnode['kernel'].split()[2]
47                 fbnode['boot_state'] = fbnode['plcnode']['boot_state']
48
49                 try:
50                         if len(fbnode['nodegroups']) > 0:
51                                 fbnode['category'] = fbnode['nodegroups'][0]
52                 except:
53                         #print "ERROR!!!!!!!!!!!!!!!!!!!!!"
54                         pass
55
56                 print "%(hostname)-45s | %(checked)11.11s | %(boot_state)5.5s| %(state)8.8s | %(ssh)5.5s | %(pcu)6.6s | %(bootcd)6.6s | %(category)8.8s | %(kernel)s" % fbnode
57         else:
58                 format = ""
59                 for f in fields:
60                         format += "%%(%s)s " % f
61                 print format % fbnode
62
63 def get(fb, path):
64     indexes = path.split("/")
65     values = fb
66     for index in indexes:
67         if index in values:
68             values = values[index]
69         else:
70             raise NoKeyException(index)
71     return values
72
73 def verifyType(constraints, data):
74         """
75                 constraints is a list of key, value pairs.
76                 # [ {... : ...}==AND , ... , ... , ] == OR
77         """
78         con_or_true = False
79         for con in constraints:
80                 #print "con: %s" % con
81                 if len(con.keys()) == 0:
82                         con_and_true = False
83                 else:
84                         con_and_true = True
85
86                 for key in con.keys():
87                         #print "looking at key: %s" % key
88                         if data is None:
89                                 con_and_true = False
90                                 break
91
92                         try:
93                                 get(data,key)
94                                 o = con[key]
95                                 if o.name() == "Match":
96                                         if get(data,key) is not None:
97                                                 value_re = re.compile(o.value)
98                                                 con_and_true = con_and_true & (value_re.search(get(data,key)) is not None)
99                                         else:
100                                                 con_and_true = False
101                                 elif o.name() == "ListMatch":
102                                         if get(data,key) is not None:
103                                                 match = False
104                                                 for listitem in get(data,key):
105                                                         value_re = re.compile(o.value)
106                                                         if value_re.search(listitem) is not None:
107                                                                 match = True
108                                                                 break
109                                                 con_and_true = con_and_true & match
110                                         else:
111                                                 con_and_true = False
112                                 elif o.name() == "Is":
113                                         con_and_true = con_and_true & (get(data,key) == o.value)
114                                 elif o.name() == "FilledIn":
115                                         con_and_true = con_and_true & (len(get(data,key)) > 0)
116                                 elif o.name() == "PortOpen":
117                                         if get(data,key) is not None:
118                                                 v = get(data,key)
119                                                 con_and_true = con_and_true & (v[str(o.value)] == "open")
120                                         else:
121                                                 con_and_true = False
122                                 else:
123                                         value_re = re.compile(o.value)
124                                         con_and_true = con_and_true & (value_re.search(get(data,key)) is not None)
125
126                         except NoKeyException, key:
127                                 print "missing key %s" % key,
128                                 pass
129                                 #print "missing key %s" % key
130                                 #con_and_true = False
131
132                 con_or_true = con_or_true | con_and_true
133
134         return con_or_true
135
136 def verify(constraints, data):
137         """
138                 constraints is a list of key, value pairs.
139                 # [ {... : ...}==AND , ... , ... , ] == OR
140         """
141         con_or_true = False
142         for con in constraints:
143                 #print "con: %s" % con
144                 if len(con.keys()) == 0:
145                         con_and_true = False
146                 else:
147                         con_and_true = True
148
149                 for key in con.keys():
150                         #print "looking at key: %s" % key
151                         if key in data: 
152                                 value_re = re.compile(con[key])
153                                 if type([]) == type(data[key]):
154                                         local_or_true = False
155                                         for val in data[key]:
156                                                 local_or_true = local_or_true | (value_re.search(val) is not None)
157                                         con_and_true = con_and_true & local_or_true
158                                 else:
159                                         con_and_true = con_and_true & (value_re.search(data[key]) is not None)
160                         elif key not in data:
161                                 print "missing key %s" % key,
162                                 pass
163                                 #print "missing key %s" % key
164                                 #con_and_true = False
165
166                 con_or_true = con_or_true | con_and_true
167
168         return con_or_true
169
170 def query_to_dict(query):
171         
172         ad = []
173
174         or_queries = query.split('||')
175         for or_query in or_queries:
176                 and_queries = or_query.split('&&')
177
178                 d = {}
179
180                 for and_query in and_queries:
181                         (key, value) = and_query.split('=')
182                         d[key] = value
183
184                 ad.append(d)
185         
186         return ad
187
188 def pcu_in(fbdata):
189         if 'plcnode' in fbdata:
190                 if 'pcu_ids' in fbdata['plcnode']:
191                         if len(fbdata['plcnode']['pcu_ids']) > 0:
192                                 return True
193         return False
194
195 def pcu_select(str_query, nodelist=None):
196         global fb
197         global fbpcu
198         pcunames = []
199         nodenames = []
200         if str_query is None: return (nodenames, pcunames)
201
202         if fb is None:
203                 fb = database.dbLoad("findbad")
204         if fbpcu is None:
205                 fbpcu = database.dbLoad("findbadpcus")
206
207         #print str_query
208         dict_query = query_to_dict(str_query)
209         #print dict_query
210
211         for node in fb['nodes'].keys():
212                 if nodelist is not None: 
213                         if node not in nodelist: continue
214         
215                 fb_nodeinfo  = fb['nodes'][node]['values']
216                 if pcu_in(fb_nodeinfo):
217                         pcuinfo = fbpcu['nodes']['id_%s' % fb_nodeinfo['plcnode']['pcu_ids'][0]]['values']
218                         if verify(dict_query, pcuinfo):
219                                 nodenames.append(node)
220                                 str = "cmdhttps/locfg.pl -s %s -f iloxml/License.xml -u %s -p '%s' | grep MESSAGE" % \
221                                                         (pcu_name(pcuinfo), pcuinfo['username'], pcuinfo['password'])
222                                 #pcunames.append(str)
223                                 pcunames.append(pcuinfo['pcu_id'])
224         return (nodenames, pcunames)
225
226 def node_select(str_query, nodelist=None, fbdb=None):
227         global fb
228
229         hostnames = []
230         if str_query is None: return hostnames
231
232         #print str_query
233         dict_query = query_to_dict(str_query)
234         #print dict_query
235
236         if fbdb is not None:
237                 fb = fbdb
238
239         for node in fb['nodes'].keys():
240                 if nodelist is not None: 
241                         if node not in nodelist: continue
242         
243                 fb_nodeinfo  = fb['nodes'][node]['values']
244
245                 if fb_nodeinfo == []:
246                         #print node, "has lost values"
247                         continue
248                         #sys.exit(1)
249                 fb_nodeinfo['pcu'] = color_pcu_state(fb_nodeinfo)
250                 fb_nodeinfo['hostname'] = node
251                 if 'plcnode' in fb_nodeinfo:
252                         fb_nodeinfo.update(fb_nodeinfo['plcnode'])
253
254                 if verify(dict_query, fb_nodeinfo):
255                         #print node #fb_nodeinfo
256                         hostnames.append(node)
257                 else:
258                         #print "NO MATCH", node
259                         pass
260         
261         return hostnames
262
263
264 def main():
265         global fb
266         global fbpcu
267
268         import parser as parsermodule
269         parser = parsermodule.getParser()
270
271         parser.set_defaults(node=None, fromtime=None, select=None, list=None, 
272                                                 pcuselect=None, nodelist=None, daysdown=None, fields=None)
273         parser.add_option("", "--daysdown", dest="daysdown", action="store_true",
274                                                 help="List the node state and days down...")
275         parser.add_option("", "--select", dest="select", metavar="key=value", 
276                                                 help="List all nodes with the given key=value pattern")
277         parser.add_option("", "--fields", dest="fields", metavar="key,list,...", 
278                                                 help="a list of keys to display for each entry.")
279         parser.add_option("", "--list", dest="list", action="store_true", 
280                                                 help="Write only the hostnames as output.")
281         parser.add_option("", "--pcuselect", dest="pcuselect", metavar="key=value", 
282                                                 help="List all nodes with the given key=value pattern")
283         parser.add_option("", "--nodelist", dest="nodelist", metavar="nodelist.txt", 
284                                                 help="A list of nodes to bring out of debug mode.")
285         parser.add_option("", "--fromtime", dest="fromtime", metavar="YYYY-MM-DD",
286                                         help="Specify a starting date from which to begin the query.")
287
288         parser = parsermodule.getParser(['defaults'], parser)
289         config = parsermodule.parse_args(parser)
290         
291         if config.fromtime:
292                 path = "archive-pdb"
293                 archive = database.SPickle(path)
294                 d = datetime_fromstr(config.fromtime)
295                 glob_str = "%s*.production.findbad.pkl" % d.strftime("%Y-%m-%d")
296                 os.chdir(path)
297                 #print glob_str
298                 file = glob.glob(glob_str)[0]
299                 #print "loading %s" % file
300                 os.chdir("..")
301                 fb = archive.load(file[:-4])
302         else:
303                 fb = database.dbLoad("findbad")
304
305         fbpcu = database.dbLoad("findbadpcus")
306         reboot.fb = fbpcu
307
308         if config.nodelist:
309                 nodelist = util.file.getListFromFile(config.nodelist)
310         else:
311                 nodelist = fb['nodes'].keys()
312
313         pculist = None
314         if config.select is not None and config.pcuselect is not None:
315                 nodelist = node_select(config.select, nodelist, fb)
316                 nodelist, pculist = pcu_select(config.pcuselect, nodelist)
317         elif config.select is not None:
318                 nodelist = node_select(config.select, nodelist, fb)
319         elif config.pcuselect is not None:
320                 nodelist, pculist = pcu_select(config.pcuselect, nodelist)
321
322         if pculist:
323                 for pcu in pculist:
324                         print pcu
325
326         for node in nodelist:
327                 config.node = node
328
329                 if node not in fb['nodes']:
330                         continue
331
332                 fb_nodeinfo  = fb['nodes'][node]['values']
333
334                 if config.list:
335                         print node
336                 else:
337                         if config.daysdown:
338                                 daysdown_print_nodeinfo(fb_nodeinfo, node)
339                         else:
340                                 if config.select:
341                                         if config.fields:
342                                                 fields = config.fields.split(",")
343                                         else:
344                                                 fields = None
345
346                                         fb_print_nodeinfo(fb_nodeinfo, node, fields)
347                                 elif not config.select and 'state' in fb_nodeinfo:
348                                         fb_print_nodeinfo(fb_nodeinfo, node)
349                                 else:
350                                         pass
351                 
352 if __name__ == "__main__":
353         main()