3131import json
3232import struct
3333import logging
34+ import platform
3435
3536from collections import namedtuple
3637
5051 from urllib2 import urlopen
5152
5253USERSPACE_JSON = 'http://patches04.kernelcare.com/userspace.json'
54+ KCARE_PLUS_JSON = 'https://patches04.kernelcare.com/userspace-patches.json'
5355LOGLEVEL = os .environ .get ('LOGLEVEL' , 'ERROR' ).upper ()
5456logging .basicConfig (level = LOGLEVEL , format = '%(message)s' )
5557
5658
59+ DIST , _ , _ = platform .linux_distribution ()
60+ DATA = json .load (urlopen (USERSPACE_JSON ))
61+ KCPLUS_DATA = json .load (urlopen (KCARE_PLUS_JSON ))
62+
63+
5764class NotAnELFException (Exception ):
5865 pass
5966
@@ -116,10 +123,14 @@ def get_build_id(fileobj):
116123
117124
118125def iter_maps (pid ):
119- with open ('/proc/{:d}/maps' .format (pid ), 'r' ) as mapfd :
120- for line in mapfd :
121- data = (line .split () + [None , None ])[:7 ]
122- yield Map (* data )
126+ try :
127+ with open ('/proc/{:d}/maps' .format (pid ), 'r' ) as mapfd :
128+ for line in mapfd :
129+ data = (line .split () + [None , None ])[:7 ]
130+ yield Map (* data )
131+ except IOError as err :
132+ # Most cases of IOErrors is a lack of maps due to process exit
133+ logging .debug ("Iter via `%d` map error: %s" , pid , err )
123134
124135
125136def get_vmas (pid , inode ):
@@ -224,8 +235,8 @@ def iter_proc_lib():
224235
225236 try :
226237 cache [inode ] = get_build_id (fileobj )
227- except NotAnELFException as err :
228- logging .debug ("Cat't read buildID from {0}: {1}" .format (pathname , err ))
238+ except ( NotAnELFException , BuildIDParsingException ) as err :
239+ logging .info ("Cat't read buildID from {0}: {1}" .format (pathname , err ))
229240 cache [inode ] = None
230241 except Exception as err :
231242 logging .error ("Cat't read buildID from {0}: {1}" .format (pathname , err ))
@@ -240,29 +251,33 @@ def is_kcplus_handled(build_id):
240251 return True
241252
242253
254+ def is_up_to_date (libname , build_id ):
255+ subset = DATA .get (DIST , {}).get (libname , {})
256+ if not subset :
257+ logging .warning ('No data for %s/%s.' , DIST , libname )
258+ return not subset or build_id in subset
259+
260+
243261def main ():
244- data = json .load (urlopen (USERSPACE_JSON ))
245262 failed = False
246263 for pid , libname , build_id in iter_proc_lib ():
247264 comm = get_comm (pid )
248265 logging .info ("For %s[%s] `%s` was found with buid id = %s" ,
249266 comm , pid , libname , build_id )
250- if libname in data and build_id and build_id not in data [ libname ] :
267+ if build_id and not is_up_to_date ( libname , build_id ) :
251268 failed = True
252269 logging .error (
253270 "[%s] Process %s[%d] linked to the `%s` that is not up to date." ,
254271 "*" if is_kcplus_handled (build_id ) else " " ,
255- comm ,
256- pid ,
257- libname
258- )
272+ comm , pid , libname )
259273
260274 if not failed :
261275 print ("Everything is OK." )
262276 else :
263- print ("\n You may want to update libraries above and restart corresponding processes.\n \n "
264- "KernelCare+ allows to resolve such issues with no process downtime. "
265- "To find out more, please, visit https://lp.kernelcare.com/kernelcare-early-access?" )
277+ print ("\n You may want to update libraries above and restart "
278+ "corresponding processes.\n \n KernelCare+ allows to resolve "
279+ "such issues with no process downtime. To find out more, please,"
280+ " visit https://lp.kernelcare.com/kernelcare-early-access?" )
266281
267282
268283if __name__ == '__main__' :
0 commit comments