示例#1
0
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
示例#2
0
def check_LAN_access():
    """Check for basic access to another reliable host on the LAN, typically the router/gateway.
    Used as an execution gate for all non-local items on each RecheckInterval.

    Requires "Gateway <IP address or hostname>" definition in the config file.

    Returns True if the "Gateway" host can be pinged, else False.
    """

    ip_or_hostname = getcfg("Gateway", False)
    if not ip_or_hostname:
        logging.error(
            f"  ERROR:  PARAMETER 'Gateway' NOT DEFINED IN CONFIG FILE - Aborting."
        )
        sys.exit(1)

    if (IP_RE.match(ip_or_hostname) is
            None) and (HOSTNAME_RE.match(ip_or_hostname) is None):
        logging.error(
            f"  ERROR:  INVALID IP ADDRESS OR HOSTNAME <{ip_or_hostname}> - Aborting."
        )
        sys.exit(1)

    pingrslt = cmd_check(["ping", "-c", "1", "-W", "1",
                          getcfg("Gateway")],
                         user_host_port="local",
                         return_type="cmdrun")
    if pingrslt[0]:
        return True
    else:
        return False
示例#3
0
    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()
示例#4
0
    def log_event (self, dict):
        """ Handle any logging for each event status type
        Passed in dict keys:
            notif_key   - Corresponds to the monitortype_key in the config file
            rslt
                RTN_PASS     - Clears any prior logged WARNING / FAIL / CRITICAL events
                RTN_WARNING  - Logged and included in summary, but no notification.
                RTN_FAIL     - Logged & notified
                RTN_CRITICAL - Logged & notified, with periodic renotification
            message     - Message text from the monitor plugin
        """

        if dict["rslt"] == RTN_PASS:
            logging.info(dict["message"])
            if dict["notif_key"] in self.events:
                del self.events[dict["notif_key"]]
                logging.warning(f"  Event {dict['notif_key']} now passing.  Removed from events log.")
            return

        if dict["rslt"] == RTN_WARNING:
            if dict["notif_key"] not in self.events:
                logging.warning(dict["message"])

        else:       # RTN_FAIL and RTN_CRITICAL cases
            if dict["rslt"] == RTN_CRITICAL:
                # if there are no prior active criticals, then set renotif time to now + renotif value
                if self.next_renotif < datetime.datetime.now()  and  not self.are_criticals():
                    self.next_renotif = datetime.datetime.now().replace(microsecond=0) + datetime.timedelta(seconds=convert_time(getcfg("CriticalReNotificationInterval"))[0])
                    if not globvars.args.once:
                        logging.info(f"Next critical renotification:  {self.next_renotif}")
            if dict["notif_key"] not in self.events  and  not globvars.args.once:
                snd_notif (subj=NOTIF_SUBJ, msg=dict["message"], log=True)
            if dict["notif_key"] not in self.events  or  globvars.args.once  or  getcfg("LoggingLevel", 30) < 30:
                logging.warning(dict["message"])

        self.events[dict["notif_key"]] = {"message": dict["message"], "criticality": dict["rslt"]}
示例#5
0
    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)
示例#6
0
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])