The most current version of everything.
[monitor.git] / nodequery.py
1 #!/usr/bin/python
2
3 import plc
4 import auth
5 api = plc.PLC(auth.auth, auth.plc)
6
7 import sys
8 import soltesz
9 from nodecommon import *
10 from policy import Diagnose
11 import glob
12 import os
13 from reboot import pcu_name
14
15 import time
16 import re
17
18 #fb = {}
19 fb = soltesz.dbLoad("findbad")
20 fbpcu = {}
21
22 def daysdown_print_nodeinfo(fbnode, hostname):
23         fbnode['hostname'] = hostname
24         fbnode['daysdown'] = Diagnose.getStrDaysDown(fbnode)
25         fbnode['intdaysdown'] = Diagnose.getDaysDown(fbnode)
26
27         print "%(intdaysdown)5s %(hostname)-44s | %(state)10.10s | %(daysdown)s" % fbnode
28
29 def fb_print_nodeinfo(fbnode, hostname, fields=None):
30         fbnode['hostname'] = hostname
31         fbnode['checked'] = diff_time(fbnode['checked'])
32         if fbnode['bootcd']:
33                 fbnode['bootcd'] = fbnode['bootcd'].split()[-1]
34         else:
35                 fbnode['bootcd'] = "unknown"
36         fbnode['pcu'] = color_pcu_state(fbnode)
37
38         if not fields:
39                 if 'ERROR' in fbnode['category']:
40                         fbnode['kernel'] = ""
41                 else:
42                         fbnode['kernel'] = fbnode['kernel'].split()[2]
43                 fbnode['boot_state'] = fbnode['plcnode']['boot_state']
44
45                 print "%(hostname)-39s | %(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
46         else:
47                 format = ""
48                 for f in fields:
49                         format += "%%(%s)s " % f
50                 print format % fbnode
51
52 def verify(constraints, data):
53         """
54                 constraints is a list of key, value pairs.
55                 # [ {... : ...}==AND , ... , ... , ] == OR
56         """
57         con_or_true = False
58         for con in constraints:
59                 #print "con: %s" % con
60                 if len(con.keys()) == 0:
61                         con_and_true = False
62                 else:
63                         con_and_true = True
64
65                 for key in con.keys():
66                         #print "looking at key: %s" % key
67                         if key in data: 
68                                 value_re = re.compile(con[key])
69                                 con_and_true = con_and_true & (value_re.search(data[key]) is not None)
70                         elif key not in data:
71                                 print "missing key %s" % key,
72                                 pass
73                                 #print "missing key %s" % key
74                                 #con_and_true = False
75
76                 con_or_true = con_or_true | con_and_true
77
78         return con_or_true
79
80 def query_to_dict(query):
81         
82         ad = []
83
84         or_queries = query.split('||')
85         for or_query in or_queries:
86                 and_queries = or_query.split('&&')
87
88                 d = {}
89
90                 for and_query in and_queries:
91                         (key, value) = and_query.split('=')
92                         d[key] = value
93
94                 ad.append(d)
95         
96         return ad
97
98 def _pcu_in(fbdata):
99         if 'plcnode' in fbdata:
100                 if 'pcu_ids' in fbdata['plcnode']:
101                         if len(fbdata['plcnode']['pcu_ids']) > 0:
102                                 return True
103         return False
104
105 def pcu_select(str_query, nodelist=None):
106         pcunames = []
107         nodenames = []
108         if str_query is None: return (nodenames, pcunames)
109
110         #print str_query
111         dict_query = query_to_dict(str_query)
112         #print dict_query
113
114         for node in fb['nodes'].keys():
115                 if nodelist is not None: 
116                         if node not in nodelist: continue
117         
118                 fb_nodeinfo  = fb['nodes'][node]['values']
119                 if _pcu_in(fb_nodeinfo):
120                         pcuinfo = fbpcu['nodes']['id_%s' % fb_nodeinfo['plcnode']['pcu_ids'][0]]['values']
121                         if verify(dict_query, pcuinfo):
122                                 nodenames.append(node)
123                                 str = "cmdhttps/locfg.pl -s %s -f iloxml/License.xml -u %s -p '%s' | grep MESSAGE" % \
124                                                         (pcu_name(pcuinfo), pcuinfo['username'], pcuinfo['password'])
125                                 pcunames.append(str)
126         return (nodenames, pcunames)
127
128 def node_select(str_query, nodelist=None):
129         hostnames = []
130         if str_query is None: return hostnames
131
132         #print str_query
133         dict_query = query_to_dict(str_query)
134         #print dict_query
135         global fb
136
137         for node in fb['nodes'].keys():
138                 if nodelist is not None: 
139                         if node not in nodelist: continue
140         
141                 fb_nodeinfo  = fb['nodes'][node]['values']
142
143                 if fb_nodeinfo == []:
144                         #print node, "has lost values"
145                         continue
146                         #sys.exit(1)
147                 fb_nodeinfo['pcu'] = color_pcu_state(fb_nodeinfo)
148                 fb_nodeinfo['hostname'] = node
149                 if 'plcnode' in fb_nodeinfo:
150                         fb_nodeinfo.update(fb_nodeinfo['plcnode'])
151
152                 if verify(dict_query, fb_nodeinfo):
153                         #print node #fb_nodeinfo
154                         hostnames.append(node)
155                 else:
156                         #print "NO MATCH", node
157                         pass
158         
159         return hostnames
160
161
162 def main():
163         global fb
164         global fbpcu
165
166         from config import config
167         from optparse import OptionParser
168         parser = OptionParser()
169         parser.set_defaults(node=None, fromtime=None, select=None, list=None, pcuselect=None, nodelist=None, daysdown=None, fields=None)
170         parser.add_option("", "--daysdown", dest="daysdown", action="store_true",
171                                                 help="List the node state and days down...")
172         parser.add_option("", "--select", dest="select", metavar="key=value", 
173                                                 help="List all nodes with the given key=value pattern")
174         parser.add_option("", "--fields", dest="fields", metavar="key,list,...", 
175                                                 help="a list of keys to display for each entry.")
176         parser.add_option("", "--list", dest="list", action="store_true", 
177                                                 help="Write only the hostnames as output.")
178         parser.add_option("", "--pcuselect", dest="pcuselect", metavar="key=value", 
179                                                 help="List all nodes with the given key=value pattern")
180         parser.add_option("", "--nodelist", dest="nodelist", metavar="nodelist.txt", 
181                                                 help="A list of nodes to bring out of debug mode.")
182         parser.add_option("", "--fromtime", dest="fromtime", metavar="YYYY-MM-DD",
183                                         help="Specify a starting date from which to begin the query.")
184         config = config(parser)
185         config.parse_args()
186         
187         if config.fromtime:
188                 path = "archive-pdb"
189                 archive = soltesz.SPickle(path)
190                 d = datetime_fromstr(config.fromtime)
191                 glob_str = "%s*.production.findbad.pkl" % d.strftime("%Y-%m-%d")
192                 os.chdir(path)
193                 #print glob_str
194                 file = glob.glob(glob_str)[0]
195                 #print "loading %s" % file
196                 os.chdir("..")
197                 fb = archive.load(file[:-4])
198         else:
199                 fb = soltesz.dbLoad("findbad")
200
201         fbpcu = soltesz.dbLoad("findbadpcus")
202
203         if config.nodelist:
204                 nodelist = config.getListFromFile(config.nodelist)
205         else:
206                 nodelist = fb['nodes'].keys()
207
208         pculist = None
209         if config.select is not None and config.pcuselect is not None:
210                 nodelist = node_select(config.select, nodelist)
211                 nodelist, pculist = pcu_select(config.pcuselect, nodelist)
212         elif config.select is not None:
213                 nodelist = node_select(config.select, nodelist)
214         elif config.pcuselect is not None:
215                 nodelist, pculist = pcu_select(config.pcuselect, nodelist)
216
217
218         if pculist:
219                 for pcu in pculist:
220                         print pcu
221
222         for node in nodelist:
223                 config.node = node
224
225                 if node not in fb['nodes']:
226                         continue
227
228                 fb_nodeinfo  = fb['nodes'][node]['values']
229
230                 if config.list:
231                         print node
232                 else:
233                         if config.daysdown:
234                                 daysdown_print_nodeinfo(fb_nodeinfo, node)
235                         else:
236                                 if config.select:
237                                         if config.fields:
238                                                 fields = config.fields.split(",")
239                                         else:
240                                                 fields = None
241
242                                         fb_print_nodeinfo(fb_nodeinfo, node, fields)
243                                 elif not config.select and 'state' in fb_nodeinfo:
244                                         fb_print_nodeinfo(fb_nodeinfo, node)
245                                 else:
246                                         pass
247                 
248 if __name__ == "__main__":
249         main()