def next_summary_timestring(): """Calculate timestring of next summary. SummaryDays 0 1 2 3 4 5 6 # Days of week. 0 = Sunday SummaryTime 9:45 # 24 hour clock NOTE: May be off by 1 hour over a DTS changes. """ try: target_hour = int(getcfg("SummaryTime", "").split(":")[0]) target_minute = int(getcfg("SummaryTime", "").split(":")[1]) today_day_num = datetime.datetime.today().isoweekday( ) # Sunday = 0, Saturday = 6 now = datetime.datetime.now().replace(second=0, microsecond=0) next_summary = now + datetime.timedelta(days=30) for daynum in getcfg("SummaryDays").split(): offset_num_days = int(daynum) - today_day_num if offset_num_days < 0: offset_num_days += 7 plus_day = now + datetime.timedelta(days=offset_num_days) with_time = plus_day.replace(hour=target_hour, minute=target_minute) if with_time < datetime.datetime.now(): with_time = with_time + datetime.timedelta(days=7) if with_time < next_summary: next_summary = with_time logging.debug(f"Next summary: {next_summary}") return next_summary except Exception as e: _msg = f"SummaryDays <{getcfg('SummaryDays','')}> or SummaryTime <{getcfg('SummaryTime','')}> settings could not be parsed\n {e}" logging.error(f"ERROR: {_msg}") raise ValueError(_msg) from None
def summary(self): logging.debug (f"Entering: {HANDLER_NAME}.summary") if (self.next_summary < datetime.datetime.now()) or globvars.args.once: sum = "" if len(self.events) == 0: sum += " No current events. All is well." else: for event in self.events: sum += f"{self.events[event]['message']}\n" if globvars.args.once: logging.debug(f"lanmonitor status summary\n{sum}") return snd_email(subj="lanmonitor status summary", body=sum, to=getcfg("EmailTo"), log=True) if getcfg("LogSummary", False): logging.warning(f"Summary:\n{sum}") self.next_summary = next_summary_timestring()
def renotif(self): """ Periodically send a consolidated notification with all current critical events if renotif time passed then if there are active criticals then send consolidated renotif message else set renotif time = now, which allows next critical to be notified immediately """ logging.debug (f"Entering: {HANDLER_NAME}.renotif") if (self.next_renotif < datetime.datetime.now()): logging.debug (f"self.next_renotif: {self.next_renotif}") logging.debug (f"datetime.datetime.now(): {datetime.datetime.now()}") if self.are_criticals(): criticals = "" for event in self.events: if self.events[event]["criticality"] == RTN_CRITICAL: criticals += f" {self.events[event]['message']}\n" snd_notif (subj=NOTIF_SUBJ, msg=criticals, log=True) self.next_renotif = datetime.datetime.now().replace(microsecond=0) + datetime.timedelta(seconds=convert_time(getcfg("CriticalReNotificationInterval"))[0]) logging.info(f"Next critical renotification: {self.next_renotif}") else: self.next_renotif = datetime.datetime.now().replace(microsecond=0)
def each_loop(self): """ Called every service loop (10 seconds) """ logging.debug (f"Entering: {HANDLER_NAME}.each_loop")
def cmd_check(cmd, user_host_port, return_type=None, check_line_text=None, expected_text=None, not_text=None): """ Runs the cmd and operates on the response based on return_type. return_types: check_string Returns True if expected_text occurs in response of the cmd, plus the full full subprocess run structure check_line_text If provided, only the first line containing this text is checked expected_text Text that must be found not_text Text that must NOT be found cmdrun Returns True if the cmd return code was 0, plus the full full subprocess run structure """ if user_host_port != "local": u_h, _, port = split_user_host_port(user_host_port) cmd = ["ssh", u_h, "-p" + port, "-o", "ConnectTimeout=1", "-T"] + cmd for nTry in range(getcfg('nRetries')): try: logging.debug( f"cmd_check subprocess command try {nTry+1}: <{cmd}>") # runtry = subprocess.run(cmd, capture_output=True, text=True) # Py 3.7+ runtry = subprocess.run( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) #Py3.6 requires old-style params except Exception as e: logging.error( f"ERROR: subprocess.run of cmd <{cmd}> failed.\n {e}") return False, None if return_type == "check_string": if check_line_text is None: text_to_check = runtry.stdout else: text_to_check = "" for line in runtry.stdout.split("\n"): if check_line_text in line: text_to_check = line break if expected_text in text_to_check: if not_text is not None: if not_text not in text_to_check: return True, runtry else: return True, runtry else: if nTry == getcfg('nRetries') - 1: return False, runtry elif return_type == "cmdrun": if runtry.returncode == 0: return True, runtry elif nTry == getcfg('nRetries') - 1: return False, runtry else: _msg = f"Invalid return_type <{return_type}> passed to cmd_check" logging.error(f"ERROR: {_msg}") raise ValueError(_msg) time.sleep(convert_time(getcfg('RetryInterval'))[0])