def screen_return_codes(msg_on_hit, return_code_target, o, e, rc, command): """ Provides a central mechanism to screen return codes from executing smart commands. This is required as some non zero return codes would otherwise trigger a generic exception clause in our general purpose run_command. If the target return code is seen then email root with the message provided, otherwise raise a generic exception with the command information. N.B. May be done better by acting as a SMART run_command wrapper (Future). :param msg_on_hit: message used to email root :param return_code_target: return code to screen for :param o: the output from the command when it was run :param e: the error from the command when it was run :param rc: the return code from running the command :param command: the command that produced the previous o, e, and rc params. """ # if our return code is our target then log with our message and email root # with the same. if rc == return_code_target: logger.error(msg_on_hit) email_root('S.M.A.R.T error', msg_on_hit) # In all other non zero (error) instances we raise an exception as normal. elif rc != 0: e_msg = ('non-zero code(%d) returned by command: %s output: ' '%s error: %s' % (rc, command, o, e)) logger.error(e_msg) raise CommandException(('%s' % command), o, e, rc)
def screen_return_codes(msg_on_hit, return_code_target, o, e, rc, command): """Provides a central mechanism to screen return codes from executing smart commands. This is required as some non zero return codes would otherwise trigger a generic exception clause in our general purpose run_command. If the target return code is seen then email root with the message provided, otherwise raise a generic exception with the command information. N.B. May be done better by acting as a SMART run_command wrapper (Future). :param msg_on_hit: message used to email root :param return_code_target: return code to screen for :param o: the output from the command when it was run :param e: the error from the command when it was run :param rc: the return code from running the command :param command: the command that produced the previous o, e, and rc params. """ # if our return code is our target then log with our message and email root # with the same. if rc == return_code_target: logger.error(msg_on_hit) email_root('S.M.A.R.T error', msg_on_hit) # In all other non zero (error) instances we raise an exception as normal. elif rc != 0: e_msg = ('non-zero code(%d) returned by command: %s output: ' '%s error: %s' % (rc, command, o, e)) logger.error(e_msg) raise CommandException(('%s' % command), o, e, rc)
def generate_otp(username): #Generate a random 6 chars text and sent to root mail new_otp = ''.join(random.choice(string.letters + string.digits) for _ in range(6)) otp_subject = 'Received password reset request for uid 0 user' otp_message = 'System has received a password reset request for user %s\n\n OTP string value is: %s' % (username, new_otp) email_root(otp_subject, otp_message) return new_otp
def error_logs(device): o, e, rc = run_command( [SMART, '-l', 'error', '/dev/%s' % device], throw=False) # As we mute exceptions when calling the above command we should at least # examine what we have as return code (rc); 64 has been seen when the error # log contains errors but otherwise executes successfully so we catch this. if rc == 64: e_msg = 'Drive /dev/%s has logged S.M.A.R.T errors. Please view ' \ 'the Error logs tab for this device.' % device logger.error(e_msg) email_root('S.M.A.R.T error', e_msg) # In all other instances that are an error (non zero) we raise exception # as normal. elif rc != 0: e_msg = ('non-zero code(%d) returned by command: %s -l error output: ' '%s error: %s' % (rc, SMART, o, e)) logger.error(e_msg) raise CommandException(('%s -l error /dev/%s' % (SMART, device)), o, e, rc) ecode_map = { 'ABRT': 'Command ABoRTed', 'AMNF': 'Address Mark Not Found', 'CCTO': 'Command Completion Timed Out', 'EOM': 'End Of Media', 'ICRC': 'Interface Cyclic Redundancy Code (CRC) error', 'IDNF': 'IDentity Not Found', 'ILI': '(packet command-set specific)', 'MC': 'Media Changed', 'MCR': 'Media Change Request', 'NM': 'No Media', 'obs': 'obsolete', 'TK0NF': 'TracK 0 Not Found', 'UNC': 'UNCorrectable Error in Data', 'WP': 'Media is Write Protected', } summary = {} log_l = [] for i in range(len(o)): if (re.match('=== START OF READ SMART DATA SECTION ===', o[i]) is not None): err_num = None lifetime_hours = None state = None etype = None details = None for j in range(i + 1, len(o)): log_l.append(o[j]) if (re.match('Error ', o[j]) is not None): fields = o[j].split() err_num = fields[1] if ('lifetime:' in fields): lifetime_hours = int(fields[fields.index('lifetime:') + 1]) if (re.match( 'When the command that caused the error occurred, the device was', o[j].strip()) is not None): state = o[j].strip().split('the device was ')[1] if (re.search('Error: ', o[j]) is not None): e_substr = o[j].split('Error: ')[1] e_fields = e_substr.split() etype = e_fields[0] if (etype in ecode_map): etype = ecode_map[etype] details = ' '.join( e_fields[1:]) if (len(e_fields) > 1) else None summary[err_num] = list( [lifetime_hours, state, etype, details]) err_num = lifetime_hours = state = etype = details = None print('summary_d %s' % summary) return (summary, log_l)
def error_logs(device): o, e, rc = run_command([SMART, "-l", "error", "/dev/%s" % device], throw=False) # As we mute exceptions when calling the above command we should at least # examine what we have as return code (rc); 64 has been seen when the error # log contains errors but otherwise executes successfully so we catch this. if rc == 64: e_msg = "Drive /dev/%s has logged S.M.A.R.T errors. Please view " "the Error logs tab for this device." % device logger.error(e_msg) email_root("S.M.A.R.T error", e_msg) # In all other instances that are an error (non zero) we raise exception # as normal. elif rc != 0: e_msg = "non-zero code(%d) returned by command: %s -l error output: " "%s error: %s" % (rc, SMART, o, e) logger.error(e_msg) raise CommandException(("%s -l error /dev/%s" % (SMART, device)), o, e, rc) ecode_map = { "ABRT": "Command ABoRTed", "AMNF": "Address Mark Not Found", "CCTO": "Command Completion Timed Out", "EOM": "End Of Media", "ICRC": "Interface Cyclic Redundancy Code (CRC) error", "IDNF": "IDentity Not Found", "ILI": "(packet command-set specific)", "MC": "Media Changed", "MCR": "Media Change Request", "NM": "No Media", "obs": "obsolete", "TK0NF": "TracK 0 Not Found", "UNC": "UNCorrectable Error in Data", "WP": "Media is Write Protected", } summary = {} log_l = [] for i in range(len(o)): if re.match("=== START OF READ SMART DATA SECTION ===", o[i]) is not None: err_num = None lifetime_hours = None state = None etype = None details = None for j in range(i + 1, len(o)): log_l.append(o[j]) if re.match("Error ", o[j]) is not None: fields = o[j].split() err_num = fields[1] if "lifetime:" in fields: lifetime_hours = int(fields[fields.index("lifetime:") + 1]) if ( re.match("When the command that caused the error occurred, the device was", o[j].strip()) is not None ): state = o[j].strip().split("the device was ")[1] if re.search("Error: ", o[j]) is not None: e_substr = o[j].split("Error: ")[1] e_fields = e_substr.split() etype = e_fields[0] if etype in ecode_map: etype = ecode_map[etype] details = " ".join(e_fields[1:]) if (len(e_fields) > 1) else None summary[err_num] = list([lifetime_hours, state, etype, details]) err_num = lifetime_hours = state = etype = details = None print("summary_d %s" % summary) return (summary, log_l)
def error_logs(device, test_mode=TESTMODE): """ Retrieves a parsed list of SMART errors from the output of smartctl -l error May be empty if no errors, also returns a raw output of the error log itself :param device: disk device name :param test_mode: Not True causes cat from file rather than smartctl command :return: summary: dictionary of lists containing details of error. Index is error number. :return: log_l: A list containing each line in turn of the error log. """ if not test_mode: o, e, rc = run_command([SMART, '-l', 'error', '/dev/%s' % device], throw=False) else: o, e, rc = run_command([CAT, '/root/smartdumps/smart-l-error.out'], throw=False) # As we mute exceptions when calling the above command we should at least # examine what we have as return code (rc); 64 has been seen when the error # log contains errors but otherwise executes successfully so we catch this. if rc == 64: e_msg = 'Drive /dev/%s has logged S.M.A.R.T errors. Please view ' \ 'the Error logs tab for this device.' % device logger.error(e_msg) email_root('S.M.A.R.T error', e_msg) # In all other instances that are an error (non zero) we raise exception # as normal. elif rc != 0: e_msg = ('non-zero code(%d) returned by command: %s -l error output: ' '%s error: %s' % (rc, SMART, o, e)) logger.error(e_msg) raise CommandException(('%s -l error /dev/%s' % (SMART, device)), o, e, rc) ecode_map = { 'ABRT' : 'Command ABoRTed', 'AMNF' : 'Address Mark Not Found', 'CCTO' : 'Command Completion Timed Out', 'EOM' : 'End Of Media', 'ICRC' : 'Interface Cyclic Redundancy Code (CRC) error', 'IDNF' : 'IDentity Not Found', 'ILI' : '(packet command-set specific)', 'MC' : 'Media Changed', 'MCR' : 'Media Change Request', 'NM' : 'No Media', 'obs' : 'obsolete', 'TK0NF' : 'TracK 0 Not Found', 'UNC' : 'UNCorrectable Error in Data', 'WP' : 'Media is Write Protected', } summary = {} log_l = [] for i in range(len(o)): if (re.match('=== START OF READ SMART DATA SECTION ===', o[i]) is not None): err_num = None lifetime_hours = None state = None etype = None details = None for j in range(i + 1, len(o)): log_l.append(o[j]) if (re.match('Error ', o[j]) is not None): fields = o[j].split() err_num = fields[1] if ('lifetime:' in fields): lifetime_hours = int(fields[fields.index('lifetime:')+1]) if (re.match('When the command that caused the error occurred, the device was', o[j].strip()) is not None): state = o[j].strip().split('the device was ')[1] if (re.search('Error: ', o[j]) is not None): e_substr = o[j].split('Error: ')[1] e_fields = e_substr.split() etype = e_fields[0] if (etype in ecode_map): etype = ecode_map[etype] details = ' '.join(e_fields[1:]) if (len(e_fields) > 1) else None summary[err_num] = list([lifetime_hours, state, etype, details]) err_num = lifetime_hours = state = etype = details = None print ('summary_d %s' % summary) return (summary, log_l)