def _create_service(self, data): """create GenericService from json data""" result = self._update_object(GenericService(), data) result.name = data['display_name'] service_states = {0: 'OK', 1: 'WARNING', 2: 'CRITICAL', 3: 'UNKNOWN'} result.status = service_states[data['state']] return result
def _insert_service_to_hosts(self, service: GenericService): service_host = service.get_host_name() if service_host not in self.new_hosts: self.new_hosts[service_host] = GenericHost() self.new_hosts[service_host].name = service_host self.new_hosts[service_host].services[service.name] = service
def _insert_service_to_hosts(self, service: GenericService): """ We want to create hosts for faulty services as GenericService requires that logic. """ service_host = service.get_host_name() if service_host not in self.new_hosts: self.new_hosts[service_host] = GenericHost() self.new_hosts[service_host].name = service_host self.new_hosts[service_host].site = service.site self.new_hosts[service_host].services[service.name] = service
def _create_service(self, data): """create GenericService from json data""" result = self._update_object(GenericService(), data) result.name = data['custom_variables']['_SERVICE_NAME'] result.svid = data['display_name'] result.custom_variables = data['custom_variables'] # result.name = data['display_name'] service_states = {0: 'OK', 1: 'WARNING', 2: 'CRITICAL', 3: 'UNKNOWN'} service_state_list = [0, 1, 2, 3] if data['state'] in service_state_list: result.status = service_states[data['state']] else: result.status = 'OTHER' return result
def _get_status(self): """ Get status from Zabbix Server """ # ========================================= # problems # ========================================= problems = [] try: #Are we logged in? if self.zlapi is None: self.zlapi = ZabbixLightApi(server_name=self.name, monitor_url=self.monitor_url, validate_certs=self.validate_certs) #zabbix could get an upgrade between checks, we need to check version each time self.zbx_version = self.zlapi.do_request("apiinfo.version", {}, no_auth=True) #check are we still logged in, if not, relogin if not self.zlapi.logged_in(): self.zlapi.login(self.username, self.password) #Get all current problems (trigger based), no need to check acknowledged problems if they are filtered out (load reduce) if conf.filter_acknowledged_hosts_services: problems = self.zlapi.do_request("problem.get", { 'recent': False, 'acknowledged': False }) else: problems = self.zlapi.do_request("problem.get", {'recent': False}) for problem in problems: #get trigger which rose current problem trigger = self.zlapi.do_request( "trigger.get", { 'triggerids': problem['objectid'], 'monitored': True, 'active': True, 'skipDependent': True, 'selectHosts': [ 'hostid', 'name', 'maintenance_status', 'available', 'error', 'errors_from', 'ipmi_available', 'ipmi_error', 'ipmi_errors_from', 'jmx_available', 'jmx_error', 'jmx_errors_from', 'snmp_available', 'snmp_error', 'snmp_errors_from' ], 'selectItems': ['key_', 'lastclock'] }) #problems on disabled/maintenance/deleted hosts don't have triggers #have to do that because of how zabbix housekeeping service work #API reports past problems for hosts that no longer exist if not trigger: continue service_id = problem['eventid'] host_id = trigger[0]['hosts'][0]['hostid'] #new host to report, we only need to do that at first problem for that host if host_id not in self.new_hosts: self.new_hosts[host_id] = GenericHost() self.new_hosts[host_id].name = trigger[0]['hosts'][0][ 'name'] #host has active maintenance period if trigger[0]['hosts'][0]['maintenance_status'] == "1": self.new_hosts[host_id].scheduled_downtime = True #old api shows host interfaces status in host object if parse_version( self.zbx_version) < parse_version("5.4.0"): #host not available via agent if trigger[0]['hosts'][0].get('available', '0') == "2": self.new_hosts[host_id].status = "DOWN" self.new_hosts[ host_id].status_information = trigger[0][ 'hosts'][0]['error'] self.new_hosts[ host_id].duration = HumanReadableDurationFromTimestamp( trigger[0]['hosts'][0]['errors_from']) #host not available via ipmi if trigger[0]['hosts'][0].get('ipmi_available', '0') == "2": self.new_hosts[host_id].status = "DOWN" self.new_hosts[ host_id].status_information = trigger[0][ 'hosts'][0]['ipmi_error'] self.new_hosts[ host_id].duration = HumanReadableDurationFromTimestamp( trigger[0]['hosts'][0]['ipmi_errors_from']) #host not available via jmx if trigger[0]['hosts'][0].get('jmx_available', '0') == "2": self.new_hosts[host_id].status = "DOWN" self.new_hosts[ host_id].status_information = trigger[0][ 'hosts'][0]['jmx_error'] self.new_hosts[ host_id].duration = HumanReadableDurationFromTimestamp( trigger[0]['hosts'][0]['jmx_errors_from']) #host not available via snmp if trigger[0]['hosts'][0].get('snmp_available', '0') == "2": self.new_hosts[host_id].status = "DOWN" self.new_hosts[ host_id].status_information = trigger[0][ 'hosts'][0]['snmp_error'] self.new_hosts[ host_id].duration = HumanReadableDurationFromTimestamp( trigger[0]['hosts'][0]['snmp_errors_from']) #new api shows host interfaces status in hostinterfaces object else: #get all host interfaces hostinterfaces = self.zlapi.do_request( "hostinterface.get", {"hostids": host_id}) #check them all and mark host as DOWN on first not available interface for hostinterface in hostinterfaces: if hostinterface.get('available', '0') == "2": self.new_hosts[host_id].status = "DOWN" self.new_hosts[ host_id].status_information = hostinterface[ 'error'] self.new_hosts[ host_id].duration = HumanReadableDurationFromTimestamp( hostinterface['errors_from']) #we stop checking rest of interfaces break #service to report self.new_hosts[host_id].services[service_id] = GenericService() self.new_hosts[host_id].services[service_id].host = trigger[0][ 'hosts'][0]['name'] self.new_hosts[host_id].services[ service_id].status = self.statemap.get( problem['severity'], problem['severity']) self.new_hosts[host_id].services[ service_id].duration = HumanReadableDurationFromTimestamp( problem['clock']) self.new_hosts[host_id].services[service_id].name = trigger[0][ 'items'][0]['key_'] self.new_hosts[host_id].services[ service_id].last_check = time.strftime( "%d/%m/%Y %H:%M:%S", time.localtime(int( trigger[0]['items'][0]['lastclock']))) #we add opdata to status information just like in zabbix GUI if problem["opdata"] != "": self.new_hosts[host_id].services[ service_id].status_information = problem[ 'name'] + " (" + problem["opdata"] + ")" else: self.new_hosts[host_id].services[ service_id].status_information = problem['name'] #service is acknowledged if problem['acknowledged'] == "1": self.new_hosts[host_id].services[ service_id].acknowledged = True except ZabbixLightApiException: # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) return Result()
def _get_status(self): """ Get status from Icinga Server - only JSON """ # define CGI URLs for hosts and services if self.cgiurl_hosts == self.cgiurl_services == self.cgiurl_monitoring_health == None: # services (unknown, warning or critical?) self.cgiurl_services = {'hard': self.monitor_cgi_url + '/monitoring/list/services?service_state>0&service_state<=3&service_state_type=1&addColumns=service_last_check,service_is_reachable&format=json', \ 'soft': self.monitor_cgi_url + '/monitoring/list/services?service_state>0&service_state<=3&service_state_type=0&addColumns=service_last_check,service_is_reachable&format=json'} # hosts (up or down or unreachable) self.cgiurl_hosts = {'hard': self.monitor_cgi_url + '/monitoring/list/hosts?host_state>0&host_state<=2&host_state_type=1&addColumns=host_last_check&format=json', \ 'soft': self.monitor_cgi_url + '/monitoring/list/hosts?host_state>0&host_state<=2&host_state_type=0&addColumns=host_last_check&format=json'} # monitoring health self.cgiurl_monitoring_health = self.monitor_cgi_url + '/monitoring/health/info?format=json' # new_hosts dictionary self.new_hosts = dict() # hosts - mostly the down ones # now using JSON output from Icinga try: for status_type in 'hard', 'soft': # first attempt result = self.FetchURL(self.cgiurl_hosts[status_type], giveback='raw') # authentication errors get a status code 200 too back because its # HTML works fine :-( if result.status_code < 400 and\ result.result.startswith('<'): # in case of auth error reset HTTP session and try again self.reset_HTTP() result = self.FetchURL(self.cgiurl_hosts[status_type], giveback='raw') # if it does not work again tell GUI there is a problem if result.status_code < 400 and\ result.result.startswith('<'): self.refresh_authentication = True return Result(result=result.result, error='Authentication error', status_code=result.status_code) # purify JSON result of unnecessary control sequence \n jsonraw, error, status_code = copy.deepcopy(result.result.replace('\n', '')),\ copy.deepcopy(result.error),\ result.status_code if error != '' or status_code >= 400: return Result(result=jsonraw, error=error, status_code=status_code) # check if any error occured self.check_for_error(jsonraw, error, status_code) # Check if the backend is running # If it isn't running the last values stored in the database are returned/shown # Unfortunately we need to make a extra request for this and only, if monitoring health is possible if self.cgiurl_monitoring_health: try: result = self.FetchURL(self.cgiurl_monitoring_health, giveback='raw') monitoring_health = json.loads(result.result)[0] if (monitoring_health['is_currently_running'] == '0'): return Result(result=monitoring_health, error='Icinga2 backend not running') except json.decoder.JSONDecodeError: # https://github.com/HenriWahl/Nagstamon/issues/619 # Icinga2 monitoring health status query does not seem to work (on older version?) self.cgiurl_monitoring_health = None hosts = json.loads(jsonraw) for host in hosts: # make dict of tuples for better reading h = dict(host.items()) # host if self.use_display_name_host == False: # according to http://sourceforge.net/p/nagstamon/bugs/83/ it might # better be host_name instead of host_display_name # legacy Icinga adjustments if 'host_name' in h: host_name = h['host_name'] elif 'host' in h: host_name = h['host'] else: # https://github.com/HenriWahl/Nagstamon/issues/46 on the other hand has # problems with that so here we go with extra display_name option host_name = h['host_display_name'] # host objects contain service objects if not host_name in self.new_hosts: self.new_hosts[host_name] = GenericHost() self.new_hosts[host_name].name = host_name self.new_hosts[host_name].server = self.name self.new_hosts[host_name].status = self.STATES_MAPPING[ 'hosts'][int(h['host_state'])] self.new_hosts[ host_name].last_check = datetime.datetime.fromtimestamp( int(h['host_last_check'])) self.new_hosts[host_name].attempt = h['host_attempt'] self.new_hosts[ host_name].status_information = BeautifulSoup( h['host_output'].replace('\n', ' ').strip(), 'html.parser').text self.new_hosts[host_name].passiveonly = not (int( h['host_active_checks_enabled'])) self.new_hosts[ host_name].notifications_disabled = not (int( h['host_notifications_enabled'])) self.new_hosts[host_name].flapping = bool( int(h['host_is_flapping'])) self.new_hosts[host_name].acknowledged = bool( int(h['host_acknowledged'])) self.new_hosts[host_name].scheduled_downtime = bool( int(h['host_in_downtime'])) self.new_hosts[host_name].status_type = status_type # extra Icinga properties to solve https://github.com/HenriWahl/Nagstamon/issues/192 # acknowledge needs host_description and no display name self.new_hosts[host_name].real_name = h['host_name'] # Icinga only updates the attempts for soft states. When hard state is reached, a flag is set and # attemt is set to 1/x. if (status_type == 'hard'): try: maxAttempts = h['host_attempt'].split('/')[1] self.new_hosts[ host_name].attempt = "{0}/{0}".format( maxAttempts) except Exception: self.new_hosts[host_name].attempt = "HARD" # extra duration needed for calculation if h['host_last_state_change'] is not None: last_change = h['host_last_state_change'] if h[ 'host_last_state_change'] is not None else 0 duration = datetime.datetime.now( ) - datetime.datetime.fromtimestamp( int(last_change)) self.new_hosts[host_name].duration = strfdelta( duration, '{days}d {hours}h {minutes}m {seconds}s') else: self.new_hosts[host_name].duration = 'n/a' del h, host_name except: import traceback traceback.print_exc(file=sys.stdout) # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # services try: for status_type in 'hard', 'soft': result = self.FetchURL(self.cgiurl_services[status_type], giveback='raw') # purify JSON result of unnecessary control sequence \n jsonraw, error, status_code = copy.deepcopy(result.result.replace('\n', '')),\ copy.deepcopy(result.error),\ result.status_code if error != '' or status_code >= 400: return Result(result=jsonraw, error=error, status_code=status_code) # check if any error occured self.check_for_error(jsonraw, error, status_code) services = copy.deepcopy(json.loads(jsonraw)) for service in services: # make dict of tuples for better reading s = dict(service.items()) if self.use_display_name_host == False: # according to http://sourceforge.net/p/nagstamon/bugs/83/ it might # better be host_name instead of host_display_name # legacy Icinga adjustments if 'host_name' in s: host_name = s['host_name'] elif 'host' in s: host_name = s['host'] else: # https://github.com/HenriWahl/Nagstamon/issues/46 on the other hand has # problems with that so here we go with extra display_name option host_name = s['host_display_name'] # host objects contain service objects if not host_name in self.new_hosts: self.new_hosts[host_name] = GenericHost() self.new_hosts[host_name].name = host_name self.new_hosts[host_name].status = 'UP' # extra Icinga properties to solve https://github.com/HenriWahl/Nagstamon/issues/192 # acknowledge needs host_description and no display name self.new_hosts[host_name].real_name = s['host_name'] service_name = s['service_display_name'] # if a service does not exist create its object if not service_name in self.new_hosts[host_name].services: self.new_hosts[host_name].services[ service_name] = GenericService() self.new_hosts[host_name].services[ service_name].host = host_name self.new_hosts[host_name].services[ service_name].name = service_name self.new_hosts[host_name].services[ service_name].server = self.name self.new_hosts[host_name].services[ service_name].status = self.STATES_MAPPING[ 'services'][int(s['service_state'])] self.new_hosts[host_name].services[ service_name].last_check = datetime.datetime.fromtimestamp( int(s['service_last_check'])) self.new_hosts[host_name].services[ service_name].attempt = s['service_attempt'] self.new_hosts[host_name].services[ service_name].status_information = BeautifulSoup( s['service_output'].replace('\n', ' ').strip(), 'html.parser').text self.new_hosts[host_name].services[ service_name].passiveonly = not (int( s['service_active_checks_enabled'])) self.new_hosts[host_name].services[ service_name].notifications_disabled = not (int( s['service_notifications_enabled'])) self.new_hosts[host_name].services[ service_name].flapping = bool( int(s['service_is_flapping'])) self.new_hosts[host_name].services[ service_name].acknowledged = bool( int(s['service_acknowledged'])) self.new_hosts[host_name].services[ service_name].scheduled_downtime = bool( int(s['service_in_downtime'])) self.new_hosts[host_name].services[ service_name].status_type = status_type self.new_hosts[host_name].services[ service_name].unreachable = s[ 'service_is_reachable'] == '0' if self.new_hosts[host_name].services[ service_name].unreachable: self.new_hosts[host_name].services[ service_name].status_information += " (SERVICE UNREACHABLE)" # extra Icinga properties to solve https://github.com/HenriWahl/Nagstamon/issues/192 # acknowledge needs service_description and no display name self.new_hosts[host_name].services[ service_name].real_name = s['service_description'] # Icinga only updates the attempts for soft states. When hard state is reached, a flag is set and # attemt is set to 1/x. if (status_type == 'hard'): try: maxAttempts = s['service_attempt'].split( '/')[1] self.new_hosts[host_name].services[ service_name].attempt = "{0}/{0}".format( maxAttempts) except Exception: self.new_hosts[host_name].services[ service_name].attempt = "HARD" # extra duration needed for calculation if s['service_last_state_change'] is not None: last_change = s['service_last_state_change'] if s[ 'service_last_state_change'] is not None else 0 duration = datetime.datetime.now( ) - datetime.datetime.fromtimestamp( int(last_change)) self.new_hosts[host_name].services[ service_name].duration = strfdelta( duration, '{days}d {hours}h {minutes}m {seconds}s') else: self.new_hosts[host_name].services[ service_name].duration = 'n/a' del s, host_name, service_name except: import traceback traceback.print_exc(file=sys.stdout) # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # some cleanup del jsonraw, error, hosts, services # dummy return in case all is OK return Result()
def _get_status(self): """ Get status from Nagios Server """ ret = Result() # create Nagios items dictionary with to lists for services and hosts # every list will contain a dictionary for every failed service/host # this dictionary is only temporarily nagitems = {"services": [], "hosts": []} # Create URLs for the configured filters if self.zapi is None: self._login() try: hosts = [] try: hosts = self.zapi.host.get({ "output": [ "host", "ip", "status", "available", "error", "errors_from" ], "filter": {} }) except: # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) for host in hosts: n = { 'host': host['host'], 'status': self.statemap.get(host['available'], host['available']), 'last_check': 'n/a', 'duration': HumanReadableDurationFromTimestamp(host['errors_from']), 'status_information': host['error'], 'attempt': '1/1', 'site': '', 'address': host['host'], } # add dictionary full of information about this host item to nagitems nagitems["hosts"].append(n) # after collection data in nagitems create objects from its informations # host objects contain service objects if n["host"] not in self.new_hosts: new_host = n["host"] self.new_hosts[new_host] = GenericHost() self.new_hosts[new_host].name = n["host"] self.new_hosts[new_host].status = n["status"] self.new_hosts[new_host].last_check = n["last_check"] self.new_hosts[new_host].duration = n["duration"] self.new_hosts[new_host].attempt = n["attempt"] self.new_hosts[new_host].status_information = n[ "status_information"] self.new_hosts[new_host].site = n["site"] self.new_hosts[new_host].address = n["address"] except ZabbixError: self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # services services = [] groupids = [] zabbix_triggers = [] try: api_version = self.zapi.api_version() except ZabbixAPIException: # FIXME Is there a cleaner way to handle this? I just borrowed # this code from 80 lines ahead. -- AGV # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) print(sys.exc_info()) return Result(result=result, error=error) try: response = [] try: #service = self.zapi.trigger.get({"select_items":"extend","monitored":1,"only_true":1,"min_severity":3,"output":"extend","filter":{}}) triggers_list = [] if self.monitor_cgi_url: group_list = self.monitor_cgi_url.split(',') #hostgroup_ids = [x['groupid'] for x in self.zapi.hostgroup.get( # {'output': 'extend', # 'with_monitored_items': True, # 'filter': {"name": group_list}}) if int(x['internal']) == 0] # only without filter there is anything shown at all hostgroup_ids = [ x['groupid'] for x in self.zapi.hostgroup.get( { 'output': 'extend', 'with_monitored_items': True }) if int(x['internal']) == 0 ] zabbix_triggers = self.zapi.trigger.get({ 'sortfield': 'lastchange', 'withLastEventUnacknowledged': True, 'groupids': hostgroup_ids, "monitored": True, "filter": { 'value': 1 } }) else: zabbix_triggers = self.zapi.trigger.get({ 'sortfield': 'lastchange', 'withLastEventUnacknowledged': True, "monitored": True, "filter": { 'value': 1 } }) triggers_list = [] for trigger in zabbix_triggers: triggers_list.append(trigger.get('triggerid')) this_trigger = self.zapi.trigger.get({ 'triggerids': triggers_list, 'expandDescription': True, 'output': 'extend', 'select_items': 'extend', 'expandData': True }) if type(this_trigger) is dict: for triggerid in list(this_trigger.keys()): services.append(this_trigger[triggerid]) elif type(this_trigger) is list: for trigger in this_trigger: services.append(trigger) except ZabbixAPIException: # FIXME Is there a cleaner way to handle this? I just borrowed # this code from 80 lines ahead. -- AGV # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) print(sys.exc_info()) return Result(result=result, error=error) except ZabbixError as e: #print "------------------------------------" #print "%s" % e.result.error if e.terminate: return e.result else: service = e.result.content ret = e.result for service in services: if api_version > '1.8': state = '%s' % service['description'] else: state = '%s=%s' % (service['items'][0]['key_'], service['items'][0]['lastvalue']) n = { 'host': service['host'], 'service': service['description'], 'status': self.statemap.get(service['priority'], service['priority']), # 1/1 attempt looks at least like there has been any attempt 'attempt': '1/1', 'duration': HumanReadableDurationFromTimestamp(service['lastchange']), 'status_information': state, 'passiveonly': 'no', 'last_check': 'n/a', 'notifications': 'yes', 'flapping': 'no', 'site': '', 'command': 'zabbix', 'triggerid': service['triggerid'], } nagitems["services"].append(n) # after collection data in nagitems create objects of its informations # host objects contain service objects if n["host"] not in self.new_hosts: self.new_hosts[n["host"]] = GenericHost() self.new_hosts[n["host"]].name = n["host"] self.new_hosts[n["host"]].status = "UP" self.new_hosts[n["host"]].site = n["site"] self.new_hosts[n["host"]].address = n["host"] # if a service does not exist create its object if n["service"] not in self.new_hosts[n["host"]].services: # workaround for non-existing (or not found) host status flag if n["service"] == "Host is down %s" % (n["host"]): self.new_hosts[n["host"]].status = "DOWN" # also take duration from "service" aka trigger self.new_hosts[n["host"]].duration = n["duration"] else: new_service = n["service"] self.new_hosts[n["host"]].services[ new_service] = GenericService() self.new_hosts[ n["host"]].services[new_service].host = n["host"] # next dirty workaround to get Zabbix events to look Nagios-esque if (" on " or " is ") in n["service"]: for separator in [" on ", " is "]: n["service"] = n["service"].split(separator)[0] self.new_hosts[n["host"]].services[ new_service].name = n["service"] self.new_hosts[n["host"]].services[ new_service].status = n["status"] self.new_hosts[n["host"]].services[ new_service].last_check = n["last_check"] self.new_hosts[n["host"]].services[ new_service].duration = n["duration"] self.new_hosts[n["host"]].services[ new_service].attempt = n["attempt"] self.new_hosts[n["host"]].services[ new_service].status_information = n[ "status_information"] #self.new_hosts[n["host"]].services[new_service].passiveonly = n["passiveonly"] self.new_hosts[n["host"]].services[ new_service].passiveonly = False #self.new_hosts[n["host"]].services[new_service].flapping = n["flapping"] self.new_hosts[ n["host"]].services[new_service].flapping = False self.new_hosts[ n["host"]].services[new_service].site = n["site"] self.new_hosts[n["host"]].services[ new_service].address = n["host"] self.new_hosts[n["host"]].services[ new_service].command = n["command"] self.new_hosts[n["host"]].services[ new_service].triggerid = n["triggerid"] except (ZabbixError, ZabbixAPIException): # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) print(sys.exc_info()) return Result(result=result, error=error) return ret
def _get_status(self): """ Get status from Icinga Server and translate it into Nagstamon magic generic array """ # new_hosts dictionary self.new_hosts = dict() # hosts - the down ones try: # We ask icinga for hosts which are not doing well hosts = self._get_host_events() for host in hosts: host_name = host['attrs']['name'] if host_name not in self.new_hosts: self.new_hosts[host_name] = GenericHost() self.new_hosts[host_name].name = host_name self.new_hosts[host_name].site = self.name try: self.new_hosts[ host_name].status = self.HOST_SEVERITY_CODE_TEXT_MAP.get( host['attrs']['state']) except KeyError: self.new_hosts[host_name].status = 'UNKNOWN' if int( host['attrs']['state_type'] ) > 0: # if state is not SOFT, icinga does not report attempts properly self.new_hosts[host_name].attempt = "{}/{}".format( int(host['attrs']['max_check_attempts']), int(host['attrs']['max_check_attempts'])) else: self.new_hosts[host_name].attempt = "{}/{}".format( int(host['attrs']['check_attempt']), int(host['attrs']['max_check_attempts'])) self.new_hosts[host_name].last_check = arrow.get( host['attrs']['last_check']).humanize() self.new_hosts[host_name].duration = arrow.get( host['attrs']['previous_state_change']).humanize() self.new_hosts[host_name].status_information = host[ 'attrs']['last_check_result']['output'] self.new_hosts[host_name].passiveonly = not ( host['attrs']['enable_active_checks']) self.new_hosts[host_name].notifications_disabled = not ( host['attrs']['enable_notifications']) self.new_hosts[host_name].flapping = host['attrs'][ 'flapping'] self.new_hosts[host_name].acknowledged = host['attrs'][ 'acknowledgement'] self.new_hosts[host_name].status_type = { 0: "soft", 1: "hard" }[host['attrs']['state_type']] del host_name del hosts except Exception as e: # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) log.exception(e) return Result(result=result, error=error) # services try: services = self._get_service_events() for service in services: new_service = GenericService() new_service.host = service['attrs']['host_name'] new_service.name = service['attrs']['name'] try: new_service.status = self.SERVICE_SEVERITY_CODE_TEXT_MAP.get( service['attrs']['state']) except KeyError: new_service.status = 'UNKNOWN' if int( service['attrs']['state_type'] ) > 0: # if state is not SOFT, icinga does not report attempts properly new_service.attempt = "{}/{}".format( int(service['attrs']['max_check_attempts']), int(service['attrs']['max_check_attempts'])) else: new_service.attempt = "{}/{}".format( int(service['attrs']['check_attempt']), int(service['attrs']['max_check_attempts'])) new_service.last_check = arrow.get( service['attrs']['last_check']).humanize() new_service.duration = arrow.get( service['attrs']['previous_state_change']).humanize() new_service.status_information = service['attrs'][ 'last_check_result']['output'] new_service.passiveonly = not ( service['attrs']['enable_active_checks']) new_service.notifications_disabled = not ( service['attrs']['enable_notifications']) new_service.flapping = service['attrs']['flapping'] new_service.acknowledged = service['attrs']['acknowledgement'] new_service.status_type = { 0: "soft", 1: "hard" }[service['attrs']['state_type']] self._insert_service_to_hosts(new_service) del services except Exception as e: log.exception(e) # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # dummy return in case all is OK return Result()
def _get_status(self): """ Get status from op5 Monitor Server """ # create Nagios items dictionary with to lists for services and hosts # every list will contain a dictionary for every failed service/host # this dictionary is only temporarily nagitems = {"hosts": [], "services": []} # new_hosts dictionary self.new_hosts = dict() # Fetch api listview with filters try: # Fetch Host info api_default_host_query = '[hosts] %s ' % self.host_filter api_default_host_query += '&columns=%s' % (','.join( self.api_host_col)) api_default_host_query += '&format=json' api_default_host_query = api_default_host_query.replace(" ", "%20") result = self.FetchURL(self.monitor_url + self.api_count + api_default_host_query, giveback="raw") data, error, status_code = json.loads(result.result),\ result.error,\ result.status_code # check if any error occured errors_occured = self.check_for_error(data, error, status_code) # if there are errors return them if errors_occured != False: return (errors_occured) if data['count']: count = data['count'] api_default_host_query = '[hosts] %s ' % self.host_filter api_default_host_query += '&columns=%s' % (','.join( self.api_host_col)) api_default_host_query += '&format=json' api_default_host_query = api_default_host_query.replace( " ", "%20") result = self.FetchURL(self.monitor_url + self.api_query + api_default_host_query + '&limit=' + str(count), giveback="raw") data = json.loads(result.result) n = dict() for api in data: n['host'] = api['name'] n["acknowledged"] = api['acknowledged'] n["flapping"] = api['is_flapping'] n["notifications_disabled"] = 0 if api[ 'notifications_enabled'] else 1 n["passiveonly"] = 0 if api['active_checks_enabled'] else 1 n["scheduled_downtime"] = 1 if api[ 'scheduled_downtime_depth'] else 0 n['attempt'] = "%s/%s" % (str(api['current_attempt']), str(api['max_check_attempts'])) n['duration'] = human_duration(api['last_state_change']) n['last_check'] = datetime.fromtimestamp( int(api['last_check'])).strftime('%Y-%m-%d %H:%M:%S') n['status'] = self.STATUS_HOST_MAPPING[str(api['state'])] n['status_information'] = api['plugin_output'] n['status_type'] = api['state'] if not n['host'] in self.new_hosts: self.new_hosts[n['host']] = GenericHost() self.new_hosts[n['host']].name = n['host'] self.new_hosts[ n['host']].acknowledged = n["acknowledged"] self.new_hosts[n['host']].attempt = n['attempt'] self.new_hosts[n['host']].duration = n['duration'] self.new_hosts[n['host']].flapping = n["flapping"] self.new_hosts[n['host']].last_check = n['last_check'] self.new_hosts[n['host']].notifications_disabled = n[ "notifications_disabled"] self.new_hosts[ n['host']].passiveonly = n["passiveonly"] self.new_hosts[n['host']].scheduled_downtime = n[ "scheduled_downtime"] self.new_hosts[n['host']].status = n['status'] self.new_hosts[n['host']].status_information = n[ 'status_information'].replace("\n", " ").strip() self.new_hosts[ n['host']].status_type = n['status_type'] nagitems['hosts'].append(n) del n # Fetch services info api_default_svc_query = '[services] %s ' % self.service_filter api_default_svc_query += '&columns=%s' % (','.join( self.api_svc_col)) api_default_svc_query += '&format=json' api_default_svc_query = api_default_svc_query.replace(" ", "%20") result = self.FetchURL(self.monitor_url + self.api_count + api_default_svc_query, giveback="raw") data, error, status_code = json.loads(result.result),\ result.error,\ result.status_code # check if any error occured errors_occured = self.check_for_error(data, error, status_code) # if there are errors return them if errors_occured != False: return (errors_occured) if data['count']: count = data['count'] api_default_svc_query = '[services] %s ' % self.service_filter api_default_svc_query += '&columns=%s' % (','.join( self.api_svc_col)) api_default_svc_query += '&format=json' api_default_svc_query = api_default_svc_query.replace( " ", "%20") result = self.FetchURL(self.monitor_url + self.api_query + api_default_svc_query + '&limit=' + str(count), giveback="raw") data = json.loads(result.result) for api in data: n = dict() n['host'] = api['host']['name'] n['status'] = self.STATUS_HOST_MAPPING[str( api['host']['state'])] n["passiveonly"] = 0 if api['host'][ 'active_checks_enabled'] else 1 if not n['host'] in self.new_hosts: self.new_hosts[n['host']] = GenericHost() self.new_hosts[n['host']].name = n['host'] self.new_hosts[n['host']].status = n['status'] self.new_hosts[ n['host']].passiveonly = n["passiveonly"] n['service'] = api['description'] n["acknowledged"] = api['acknowledged'] n["flapping"] = api['is_flapping'] n["notifications_disabled"] = 0 if api[ 'notifications_enabled'] else 1 n["passiveonly"] = 0 if api['active_checks_enabled'] else 1 n["scheduled_downtime"] = 1 if api[ 'scheduled_downtime_depth'] or api['host'][ 'scheduled_downtime_depth'] else 0 n['attempt'] = "%s/%s" % (str(api['current_attempt']), str(api['max_check_attempts'])) n['duration'] = human_duration(api['last_state_change']) n['last_check'] = datetime.fromtimestamp( int(api['last_check'])).strftime('%Y-%m-%d %H:%M:%S') n['status_information'] = api['plugin_output'] if not n['host'] in self.new_hosts: self.new_hosts[n['host']] = GenericHost() self.new_hosts[n['host']].name = n['host'] self.new_hosts[n['host']].status = n['status'] if not n['service'] in self.new_hosts[n['host']].services: n['status'] = self.STATUS_SVC_MAPPING[str( api['state'])] self.new_hosts[n['host']].services[ n['service']] = GenericService() self.new_hosts[n['host']].services[ n['service']].acknowledged = n['acknowledged'] self.new_hosts[n['host']].services[ n['service']].attempt = n['attempt'] self.new_hosts[n['host']].services[ n['service']].duration = n['duration'] self.new_hosts[n['host']].services[ n['service']].flapping = n['flapping'] self.new_hosts[n['host']].services[ n['service']].host = n['host'] self.new_hosts[n['host']].services[ n['service']].last_check = n['last_check'] self.new_hosts[n['host']].services[ n['service']].name = n['service'] self.new_hosts[n['host']].services[ n['service']].notifications_disabled = n[ "notifications_disabled"] self.new_hosts[n['host']].services[ n['service']].passiveonly = n['passiveonly'] self.new_hosts[n['host']].services[ n['service']].scheduled_downtime = n['duration'] self.new_hosts[n['host']].services[ n['service']].scheduled_downtime = n[ 'scheduled_downtime'] self.new_hosts[n['host']].services[ n['service']].status = n['status'] self.new_hosts[n['host']].services[ n['service']].status_information = n[ 'status_information'].replace("\n", " ").strip() nagitems['services'].append(n) return Result() except: self.isChecking = False # store status_code for returning result to tell GUI to reauthenticate status_code = result.status_code result, error = self.Error(sys.exc_info()) return Result(result=result, error=error, status_code=status_code) return Result()
def _get_status(self): """ Get status from SNAG-View 3 Server - only JSON """ # define CGI URLs for hosts and services if self.cgiurl_hosts == None: # hosts (up, down, unreachable or pending) self.cgiurl_hosts = self.monitor_cgi_url + '/rest/private/nagios/host' if self.cgiurl_services == None: # services (warning, critical, unknown or pending) self.cgiurl_services = self.monitor_cgi_url + \ '/rest/private/nagios/service_status/browser' self.new_hosts = dict() # hosts try: form_data = dict() form_data['acknowledged'] = 1 form_data['downtime'] = 1 form_data['inactiveHosts'] = 0 form_data['disabledNotification'] = 1 form_data['limit_start'] = 0 # Get all hosts form_data['limit_length'] = 99999 result = self.FetchURL(self.cgiurl_hosts, giveback='raw', cgi_data=form_data) # authentication errors get a status code 200 too if result.status_code < 400 and \ result.result.startswith('<'): # in case of auth error reset HTTP session and try again self.reset_HTTP() result = self.FetchURL(self.cgiurl_hosts, giveback='raw', cgi_data=form_data) if result.status_code < 400 and \ result.result.startswith('<'): self.refresh_authentication = True return Result(result=result.result, error='Authentication error', status_code=result.status_code) # purify JSON result jsonraw = copy.deepcopy(result.result.replace('\n', '')) error = copy.deepcopy(result.error) status_code = result.status_code if error != '' or status_code >= 400: return Result(result=jsonraw, error=error, status_code=status_code) self.check_for_error(jsonraw, error, status_code) hosts = json.loads(jsonraw) for host in hosts['data']: h = dict(host) # Skip if Host is 'Pending' if int(h['sv_host__nagios_status__current_state']) == 4: continue # Skip if Host has notifications disabled if int(h['sv_host__nagios_status__notifications_enabled'] ) == 0: continue # host host_name = h['sv_host__nagios__host_name'] # If a host does not exist, create its object if host_name not in self.new_hosts: self.new_hosts[host_name] = GenericHost() self.new_hosts[host_name].name = host_name self.new_hosts[host_name].svid = h[ 'sv_host__svobjects____SVID'] self.new_hosts[host_name].server = self.name self.new_hosts[host_name].status = self.STATES_MAPPING[ 'hosts'][int( h['sv_host__nagios_status__current_state'])] self.new_hosts[ host_name].last_check = datetime.datetime.fromtimestamp( int(h['sv_host__nagios_status__last_check'])) self.new_hosts[host_name].attempt = h[ 'sv_host__nagios__max_check_attempts'] self.new_hosts[host_name].status_information = h[ 'sv_host__nagios_status__plugin_output'] self.new_hosts[host_name].passiveonly = not (int( h['sv_host__nagios_status__checks_enabled'])) self.new_hosts[host_name].notifications_disabled = not ( int(h['sv_host__nagios_status__notifications_enabled']) ) self.new_hosts[host_name].flapping = int( h['sv_host__nagios_status__is_flapping']) self.new_hosts[host_name].acknowledged = int(h[ 'sv_host__nagios_status__problem_has_been_acknowledged'] ) self.new_hosts[host_name].scheduled_downtime = int( h['sv_host__nagios_status__scheduled_downtime_depth']) self.new_hosts[host_name].status_type = 'soft' if int( h['sv_host__nagios_status__state_type'] ) == 0 else 'hard' # extra duration needed for calculation duration = datetime.datetime.now( ) - datetime.datetime.fromtimestamp( int(h['sv_host__nagios_status__last_state_change'])) self.new_hosts[host_name].duration = strfdelta( duration, '{days}d {hours}h {minutes}m {seconds}s') del h, host_name except: import traceback traceback.print_exc(file=sys.stdout) # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # services try: form_data = dict() form_data['acknowledged'] = 1 form_data['downtime'] = 1 form_data['inactiveHosts'] = 0 form_data['disabledNotification'] = 1 form_data['softstate'] = 1 form_data['limit_start'] = 0 # Get all services form_data['limit_length'] = 99999 result = self.FetchURL(self.cgiurl_services, giveback='raw', cgi_data=form_data) # purify JSON result jsonraw = copy.deepcopy(result.result.replace('\n', '')) error = copy.deepcopy(result.error) status_code = result.status_code if error != '' or status_code >= 400: return Result(result=jsonraw, error=error, status_code=status_code) self.check_for_error(jsonraw, error, status_code) services = json.loads(jsonraw) for service in services['data']: s = dict(service) # Skip if Host or Service is 'Pending' if int(s['sv_service_status__nagios_status__current_state'] ) == 4 or int( s['sv_host__nagios_status__current_state']) == 4: continue # Skip if Host or Service has notifications disabled if int(s[ 'sv_service_status__nagios_status__notifications_enabled'] ) == 0 or int( s['sv_host__nagios_status__notifications_enabled'] ) == 0: continue # host and service host_name = s['sv_host__nagios__host_name'] service_name = s[ 'sv_service_status__svobjects__rendered_label'] # If a service does not exist, create its object if service_name not in self.new_hosts[host_name].services: self.new_hosts[host_name].services[ service_name] = GenericService() self.new_hosts[host_name].services[ service_name].host = host_name self.new_hosts[host_name].services[service_name].svid = s[ 'sv_service_status__svobjects____SVID'] self.new_hosts[host_name].services[ service_name].name = service_name self.new_hosts[host_name].services[ service_name].server = self.name self.new_hosts[host_name].services[ service_name].status = self.STATES_MAPPING['services'][ int(s[ 'sv_service_status__nagios_status__current_state'] )] self.new_hosts[host_name].services[ service_name].last_check = datetime.datetime.fromtimestamp( int(s[ 'sv_service_status__nagios_status__last_check'] )) self.new_hosts[host_name].services[ service_name].attempt = s[ 'sv_service_status__nagios__max_check_attempts'] self.new_hosts[host_name].services[ service_name].status_information = BeautifulSoup( s['sv_service_status__nagios_status__plugin_output'] .replace('\n', ' ').strip(), 'html.parser').text self.new_hosts[host_name].services[ service_name].passiveonly = not (int(s[ 'sv_service_status__nagios_status__checks_enabled'] )) self.new_hosts[host_name].services[ service_name].notifications_disabled = not (int(s[ 'sv_service_status__nagios_status__notifications_enabled'] )) self.new_hosts[host_name].services[ service_name].flapping = int( s['sv_service_status__nagios_status__is_flapping']) self.new_hosts[host_name].services[ service_name].acknowledged = int(s[ 'sv_service_status__nagios_status__problem_has_been_acknowledged'] ) self.new_hosts[host_name].services[ service_name].scheduled_downtime = int(s[ 'sv_service_status__nagios_status__scheduled_downtime_depth'] ) self.new_hosts[host_name].services[ service_name].status_type = 'soft' if int( s['sv_service_status__nagios_status__state_type'] ) == 0 else 'hard' # acknowledge needs service_description and no display name self.new_hosts[host_name].services[ service_name].real_name = s[ 'sv_service_status__nagios__service_description'] # extra duration needed for calculation duration = datetime.datetime.now( ) - datetime.datetime.fromtimestamp( int(s[ 'sv_service_status__nagios_status__last_state_change'] )) self.new_hosts[host_name].services[ service_name].duration = strfdelta( duration, '{days}d {hours}h {minutes}m {seconds}s') del s, host_name, service_name except: import traceback traceback.print_exc(file=sys.stdout) # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) del jsonraw, error, hosts # dummy return in case all is OK return Result()
def _get_status(self): """ Get status from Zabbix Server """ # Login to ZabbixAPI self._login() # ========================================= # problems # ========================================= problems = [] try: #Get all current problems (trigger based) problems = self.zapi.problem.get({'recent': False}) for problem in problems: #get trigger which rose current problem trigger = self.zapi.trigger.get({'triggerids': problem['objectid'], 'monitored': True, 'active': True, 'skipDependent': True, 'selectHosts': ['hostid', 'name', 'maintenance_status', 'available', 'error', 'errors_from', 'ipmi_available', 'ipmi_error', 'ipmi_errors_from', 'jmx_available', 'jmx_error', 'jmx_errors_from', 'snmp_available', 'snmp_error', 'snmp_errors_from'], 'selectItems': ['key_', 'lastclock']}) #problems on disabled/maintenance/deleted hosts don't have triggers #have to do that because of how zabbix housekeeping service work #API reports past problems for hosts that no longer exist if not trigger: continue service_id = problem['eventid'] host_id = trigger[0]['hosts'][0]['hostid'] #new host to report, we only need to do that at first problem for that host if host_id not in self.new_hosts: self.new_hosts[host_id] = GenericHost() self.new_hosts[host_id].name = trigger[0]['hosts'][0]['name'] #host has active maintenance period if trigger[0]['hosts'][0]['maintenance_status'] == "1": self.new_hosts[host_id].scheduled_downtime = True #host not available via agent if trigger[0]['hosts'][0]['available'] == "2": self.new_hosts[host_id].status = "DOWN" self.new_hosts[host_id].status_information = trigger[0]['hosts'][0]['error'] self.new_hosts[host_id].duration = HumanReadableDurationFromTimestamp(trigger[0]['hosts'][0]['errors_from']) #host not available via ipmi if trigger[0]['hosts'][0]['ipmi_available'] == "2": self.new_hosts[host_id].status = "DOWN" self.new_hosts[host_id].status_information = trigger[0]['hosts'][0]['ipmi_error'] self.new_hosts[host_id].duration = HumanReadableDurationFromTimestamp(trigger[0]['hosts'][0]['ipmi_errors_from']) #host not available via jmx if trigger[0]['hosts'][0]['jmx_available'] == "2": self.new_hosts[host_id].status = "DOWN" self.new_hosts[host_id].status_information = trigger[0]['hosts'][0]['jmx_error'] self.new_hosts[host_id].duration = HumanReadableDurationFromTimestamp(trigger[0]['hosts'][0]['jmx_errors_from']) #host not available via snmp if trigger[0]['hosts'][0]['snmp_available'] == "2": self.new_hosts[host_id].status = "DOWN" self.new_hosts[host_id].status_information = trigger[0]['hosts'][0]['snmp_error'] self.new_hosts[host_id].duration = HumanReadableDurationFromTimestamp(trigger[0]['hosts'][0]['snmp_errors_from']) #service to report self.new_hosts[host_id].services[service_id] = GenericService() self.new_hosts[host_id].services[service_id].host = trigger[0]['hosts'][0]['name'] self.new_hosts[host_id].services[service_id].status = self.statemap.get(problem['severity'], problem['severity']) self.new_hosts[host_id].services[service_id].duration = HumanReadableDurationFromTimestamp(problem['clock']) self.new_hosts[host_id].services[service_id].name = trigger[0]['items'][0]['key_'] self.new_hosts[host_id].services[service_id].last_check = time.strftime("%d/%m/%Y %H:%M:%S", time.localtime(int(trigger[0]['items'][0]['lastclock']))) #we add opdata to status information just like in zabbix GUI if problem["opdata"] != "": self.new_hosts[host_id].services[service_id].status_information = problem['name'] + " (" + problem["opdata"] + ")" else: self.new_hosts[host_id].services[service_id].status_information = problem['name'] #service is acknowledged if problem['acknowledged'] == "1": self.new_hosts[host_id].services[service_id].acknowledged = True except (ZabbixAPIException): # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) print(sys.exc_info()) return Result(result=result, error=error) return Result()
def _get_status(self): """ Get status from Thruk Server """ # new_hosts dictionary self.new_hosts = dict() # hosts - mostly the down ones # unfortunately the hosts status page has a different structure so # hosts must be analyzed separately try: # JSON experiments result = self.FetchURL(self.cgiurl_hosts, giveback='raw') jsonraw, error, status_code = copy.deepcopy(result.result),\ copy.deepcopy(result.error),\ result.status_code # check if any error occured errors_occured = self.check_for_error(jsonraw, error, status_code) # if there are errors return them if errors_occured != False: return(errors_occured) # in case basic auth did not work try form login cookie based login if jsonraw.startswith("<"): self.refresh_authentication = True return Result(result=None, error="Login failed") # in case JSON is not empty evaluate it elif not jsonraw == "[]": hosts = json.loads(jsonraw) for h in hosts: if h["name"] not in self.new_hosts: self.new_hosts[h["name"]] = GenericHost() self.new_hosts[h["name"]].name = h["name"] self.new_hosts[h["name"]].server = self.name self.new_hosts[h["name"]].status = self.STATES_MAPPING["hosts"][h["state"]] self.new_hosts[h["name"]].last_check = datetime.datetime.fromtimestamp(int(h["last_check"])).isoformat(" ") self.new_hosts[h["name"]].duration = HumanReadableDurationFromTimestamp(h["last_state_change"]) self.new_hosts[h["name"]].attempt = "%s/%s" % (h["current_attempt"], h["max_check_attempts"]) self.new_hosts[h["name"]].status_information = h["plugin_output"].replace("\n", " ").strip() self.new_hosts[h["name"]].passiveonly = not(bool(int(h["active_checks_enabled"]))) self.new_hosts[h["name"]].notifications_disabled = not(bool(int(h["notifications_enabled"]))) self.new_hosts[h["name"]].flapping = bool(int(h["is_flapping"])) self.new_hosts[h["name"]].acknowledged = bool(int(h["acknowledged"])) self.new_hosts[h["name"]].scheduled_downtime = bool(int(h["scheduled_downtime_depth"])) self.new_hosts[h["name"]].status_type = {0: "soft", 1: "hard"}[h["state_type"]] del h except: import traceback traceback.print_exc(file=sys.stdout) # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # services try: # JSON experiments result = self.FetchURL(self.cgiurl_services, giveback="raw") jsonraw, error, status_code = copy.deepcopy(result.result),\ copy.deepcopy(result.error),\ result.status_code # check if any error occured errors_occured = self.check_for_error(jsonraw, error, status_code) # if there are errors return them if errors_occured != False: return(errors_occured) # in case basic auth did not work try form login cookie based login if jsonraw.startswith("<"): self.refresh_authentication = True return Result(result=None, error="Login failed") # in case JSON is not empty evaluate it elif not jsonraw == "[]": services = json.loads(jsonraw) for s in services: # host objects contain service objects if s["host_name"] not in self.new_hosts: self.new_hosts[s["host_name"]] = GenericHost() self.new_hosts[s["host_name"]].name = s["host_name"] self.new_hosts[s["host_name"]].server = self.name self.new_hosts[s["host_name"]].status = "UP" # if a service does not exist create its object if s["description"] not in self.new_hosts[s["host_name"]].services: # ##new_service = s["description"] self.new_hosts[s["host_name"]].services[s["description"]] = GenericService() self.new_hosts[s["host_name"]].services[s["description"]].host = s["host_name"] self.new_hosts[s["host_name"]].services[s["description"]].name = s["description"] self.new_hosts[s["host_name"]].services[s["description"]].server = self.name self.new_hosts[s["host_name"]].services[s["description"]].status = self.STATES_MAPPING["services"][s["state"]] self.new_hosts[s["host_name"]].services[s["description"]].last_check = datetime.datetime.fromtimestamp(int(s["last_check"])).isoformat(" ") self.new_hosts[s["host_name"]].services[s["description"]].duration = HumanReadableDurationFromTimestamp(s["last_state_change"]) self.new_hosts[s["host_name"]].services[s["description"]].attempt = "%s/%s" % (s["current_attempt"], s["max_check_attempts"]) self.new_hosts[s["host_name"]].services[s["description"]].status_information = s["plugin_output"].replace("\n", " ").strip() self.new_hosts[s["host_name"]].services[s["description"]].passiveonly = not(bool(int(s["active_checks_enabled"]))) self.new_hosts[s["host_name"]].services[s["description"]].notifications_disabled = not(bool(int(s["notifications_enabled"]))) self.new_hosts[s["host_name"]].services[s["description"]].flapping = not(bool(int(s["notifications_enabled"]))) self.new_hosts[s["host_name"]].services[s["description"]].acknowledged = bool(int(s["acknowledged"])) self.new_hosts[s["host_name"]].services[s["description"]].scheduled_downtime = bool(int(s["scheduled_downtime_depth"])) self.new_hosts[s["host_name"]].services[s["description"]].status_type = {0: "soft", 1: "hard"}[s["state_type"]] del s except: import traceback traceback.print_exc(file=sys.stdout) # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # dummy return in case all is OK return Result()
def _get_status(self): """ Get status from monitos4 Server - only JSON """ # define CGI URLs for hosts and services if self.cgiurl_hosts == None: # hosts (up, down, unreachable or pending) # https://locmos41xsupport/rest/private/nagios/host if self.use_autologin == True: self.cgiurl_hosts = self.monitor_cgi_url + '/rest/private/nagios/host' + '?authtoken=' + self.autologin_key else: self.cgiurl_hosts = self.monitor_cgi_url + '/rest/private/nagios/host' if conf.debug_mode == True: self.Debug(server=self.get_name(), debug='cgiurl_hosts is: ' + self.cgiurl_hosts) if self.cgiurl_services == None: # services (warning, critical, unknown or pending) # https://locmos41xsupport/rest/private/nagios/service_status/browser if self.use_autologin == True: self.cgiurl_services = self.monitor_cgi_url + \ '/rest/private/nagios/service_status/browser' + '?authtoken=' + self.autologin_key else: self.cgiurl_services = self.monitor_cgi_url + \ '/rest/private/nagios/service_status/browser' if conf.debug_mode == True: self.Debug(server=self.get_name(), debug='cgiurl_services is: ' + self.cgiurl_services) self.new_hosts = dict() if conf.debug_mode == True: self.Debug(server=self.get_name(), debug='monitos4 Authtoken is: ' + self.autologin_key) # hostlist try: form_data = dict() form_data['acknowledged'] = 1 form_data['downtime'] = 1 form_data['inactiveHosts'] = 0 form_data['disabledNotification'] = 1 form_data['limit_start'] = 0 # Get all hosts form_data['limit_length'] = 99999 # 2018_11_18, studo, fetch only hostproblems #form_data['filter[0][data][type]'] = 'list' #form_data['filter[0][data][value]'] = '1,2,4' #form_data['filter[0][field]'] = 'sv_host__nagios_status__current_state' #if self.use_autologin == True: # form_data['authtoken'] = self.autologin_key result = self.FetchURL( self.cgiurl_hosts, giveback='raw', cgi_data=form_data) # authentication errors get a status code 200 too if result.status_code < 400 and \ result.result.startswith('<'): # in case of auth error reset HTTP session and try again self.reset_HTTP() result = self.FetchURL( self.cgiurl_hosts, giveback='raw', cgi_data=form_data) if result.status_code < 400 and \ result.result.startswith('<'): self.refresh_authentication = True return Result(result=result.result, error='Authentication error', status_code=result.status_code) # purify JSON result jsonraw = copy.deepcopy(result.result.replace('\n', '')) error = copy.deepcopy(result.error) status_code = result.status_code if error != '' or status_code >= 400: return Result(result=jsonraw, error=error, status_code=status_code) self.check_for_error(jsonraw, error, status_code) hosts = json.loads(jsonraw) for host in hosts['data']: h = dict(host) # Skip if Host is 'Pending' # 2018_04_10 try: if type(h['sv_host__nagios_status__current_state']) is int and int(h['sv_host__nagios_status__current_state']) == 4: continue except: pass # hostlist host_name = h['sv_host__nagios__host_name'] current_host_state = h['sv_host__nagios_status__current_state'] #2018_11_18: debugging if conf.debug_mode: self.Debug(server=self.get_name(), debug=time.strftime('%a %H:%M:%S') + ' host ' + host_name + ' has current_state ' + str(current_host_state)) # If a host does not exist, create its object if host_name not in self.new_hosts: self.new_hosts[host_name] = GenericHost() self.new_hosts[host_name].name = host_name self.new_hosts[host_name].svid = h['sv_host__svobjects____SVID'] self.new_hosts[host_name].server = self.name try: self.new_hosts[host_name].status = self.STATES_MAPPING['hosts'][int(h['sv_host__nagios_status__current_state'])] except: pass try: self.new_hosts[host_name].last_check = datetime.datetime.fromtimestamp( int(h['sv_host__nagios_status__last_check'])) except: pass self.new_hosts[host_name].attempt = h['sv_host__nagios__max_check_attempts'] self.new_hosts[host_name].status_information = h['sv_host__nagios_status__plugin_output'] if type(h['sv_host__nagios_status__checks_enabled']) is int: self.new_hosts[host_name].passiveonly = not (int(h['sv_host__nagios_status__checks_enabled'])) if type(h['sv_host__nagios_status__is_flapping']) is int: if int(h['sv_host__nagios_status__is_flapping']) != 0: self.new_hosts[host_name].flapping = True # 2017_11_06 if type(h['sv_host__nagios_status__problem_has_been_acknowledged']) is int: if int(h['sv_host__nagios_status__problem_has_been_acknowledged']) != 0: self.new_hosts[host_name].acknowledged = True # 2017_11_06 try: if int(h['sv_host__nagios_status__scheduled_downtime_depth']) != 0: self.new_hosts[host_name].scheduled_downtime = True except: self.new_hosts[host_name].scheduled_downtime = False # 2017_11_06 Skip if Host has notifications disabled try: if int(h['sv_host__nagios_status__notifications_enabled']) == 0: self.new_hosts[host_name].notifications_disabled = True except: self.new_hosts[host_name].notifications_disabled = False try: self.new_hosts[host_name].status_type = 'soft' if int(h['sv_host__nagios_status__state_type']) == 0 else 'hard' except: self.new_hosts[host_name].status_type = 'hard' # extra duration needed for calculation duration = datetime.datetime.now() - datetime.datetime.fromtimestamp(int(h['sv_host__nagios_status__last_state_change'])) self.new_hosts[host_name].duration = strfdelta( duration, '{days}d {hours}h {minutes}m {seconds}s') del h, host_name except: import traceback traceback.print_exc(file=sys.stdout) # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # servicelist # 2018_03_27 # https://locmos41xsupport/rest/private/nagios/service_status/browser #filter[0][data][type] list #filter[0][data][value] 0,1,2,4 #filter[0][field] sv_host__nagios_status__current_state #filter[1][data][type] list #filter[1][data][value] 1,2,3,4 #filter[1][field] sv_service_status__nagios_status__current_state try: form_data = dict() form_data['acknowledged'] = 1 form_data['downtime'] = 1 form_data['inactiveHosts'] = 0 form_data['disabledNotification'] = 1 form_data['softstate'] = 1 form_data['limit_start'] = 0 # Get all services form_data['limit_length'] = 99999 # 2018_11_18, studo, fetch only serviceproblems form_data['filter[0][data][type]'] = 'list' form_data['filter[0][data][value]'] = '0,1,2,4' form_data['filter[0][field]'] = 'sv_host__nagios_status__current_state' form_data['filter[1][data][type]'] = 'list' form_data['filter[1][data][value]'] = '1,2,3,4' form_data['filter[1][field]'] = 'sv_service_status__nagios_status__current_state' #if self.use_autologin == True: # form_data['authtoken'] = self.autologin_key result = self.FetchURL(self.cgiurl_services, giveback='raw', cgi_data=form_data) # purify JSON result jsonraw = copy.deepcopy(result.result.replace('\n', '')) error = copy.deepcopy(result.error) status_code = result.status_code if error != '' or status_code >= 400: return Result(result=jsonraw, error=error, status_code=status_code) self.check_for_error(jsonraw, error, status_code) services = json.loads(jsonraw) for service in services['data']: s = dict(service) # Skip if Host or Service is 'Pending' if int(s['sv_service_status__nagios_status__current_state']) == 4 or int( s['sv_host__nagios_status__current_state']) == 4: continue # host and service # 2017_11_09, this is a hack host_name = s['sv_host__nagios__host_name'] service_name = s['sv_service_status__nagios__service_description'] # service_name = s['sv_service_status__svobjects__rendered_label'] display_name = s['sv_service_status__nagios__service_description'] current_service_state = s['sv_service_status__nagios_status__current_state'] #2018_11_18: debugging if conf.debug_mode: self.Debug(server=self.get_name(), debug=time.strftime('%a %H:%M:%S') + ' Service ' + host_name + '!' + service_name + ' has current_state: ' + str(current_service_state) ) # If a service does not exist, create its object if service_name not in self.new_hosts[host_name].services: self.new_hosts[host_name].services[service_name] = GenericService( ) self.new_hosts[host_name].services[service_name].host = host_name self.new_hosts[host_name].services[service_name].svid = s['sv_service_status__svobjects____SVID'] self.new_hosts[host_name].services[service_name].name = display_name # self.new_hosts[host_name].services[service_name].name = service_name self.new_hosts[host_name].services[service_name].server = self.name self.new_hosts[host_name].services[service_name].status = self.STATES_MAPPING['services'][int( s['sv_service_status__nagios_status__current_state'])] self.new_hosts[host_name].services[service_name].last_check = datetime.datetime.fromtimestamp( int(s['sv_service_status__nagios_status__last_check'])) self.new_hosts[host_name].services[service_name].attempt = s[ 'sv_service_status__nagios__max_check_attempts'] self.new_hosts[host_name].services[service_name].status_information = BeautifulSoup( s['sv_service_status__nagios_status__plugin_output'].replace( '\n', ' ').strip(), 'html.parser').text self.new_hosts[host_name].services[service_name].passiveonly = not ( int(s['sv_service_status__nagios_status__checks_enabled'])) if int(s['sv_service_status__nagios_status__is_flapping']) != 0: self.new_hosts[host_name].services[service_name].flapping = True # 2017_11_05 if int(s['sv_service_status__nagios_status__problem_has_been_acknowledged']) != 0: self.new_hosts[host_name].services[service_name].acknowledged = True # 2017_11_06 if int(s['sv_service_status__nagios_status__scheduled_downtime_depth']) != 0: self.new_hosts[host_name].services[service_name].scheduled_downtime = True # 2017_11_06 Skip if Host or Service has notifications disabled if int(s['sv_service_status__nagios_status__notifications_enabled']) == 0 or int(s['sv_host__nagios_status__notifications_enabled']) == 0: self.new_hosts[host_name].services[service_name].notifications_disabled = True self.new_hosts[host_name].services[service_name].status_type = 'soft' if int( s['sv_service_status__nagios_status__state_type']) == 0 else 'hard' # acknowledge needs service_description and no display name self.new_hosts[host_name].services[service_name].real_name = s[ 'sv_service_status__nagios__service_description'] # extra duration needed for calculation duration = datetime.datetime.now( ) - datetime.datetime.fromtimestamp( int(s['sv_service_status__nagios_status__last_state_change'])) self.new_hosts[host_name].services[service_name].duration = strfdelta( duration, '{days}d {hours}h {minutes}m {seconds}s') del s, host_name, service_name except: import traceback traceback.print_exc(file=sys.stdout) # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) del jsonraw, error, hosts # dummy return in case all is OK return Result()
def _get_status(self): """ Get status from Icinga Server - only JSON """ # define CGI URLs for hosts and services if self.cgiurl_hosts == self.cgiurl_services == None: # services (unknown, warning or critical?) self.cgiurl_services = {'hard': self.monitor_cgi_url + '/monitoring/list/services?service_state>0&service_state<=3&service_state_type=1&addColumns=service_last_check&format=json', \ 'soft': self.monitor_cgi_url + '/monitoring/list/services?service_state>0&service_state<=3&service_state_type=0&addColumns=service_last_check&format=json'} # hosts (up or down or unreachable) self.cgiurl_hosts = {'hard': self.monitor_cgi_url + '/monitoring/list/hosts?host_state>0&host_state<=2&host_state_type=1&addColumns=host_last_check&format=json', \ 'soft': self.monitor_cgi_url + '/monitoring/list/hosts?host_state>0&host_state<=2&host_state_type=0&addColumns=host_last_check&format=json'} # new_hosts dictionary self.new_hosts = dict() # hosts - mostly the down ones # now using JSON output from Icinga try: for status_type in 'hard', 'soft': # first attempt result = self.FetchURL(self.cgiurl_hosts[status_type], giveback='raw') # authentication errors get a status code 200 too back because its # HTML works fine :-( if result.status_code < 400 and\ result.result.startswith('<'): # in case of auth error reset HTTP session and try again self.reset_HTTP() result = self.FetchURL(self.cgiurl_hosts[status_type], giveback='raw') # if it does not work again tell GUI there is a problem if result.status_code < 400 and\ result.result.startswith('<'): self.refresh_authentication = True return Result(result=result.result, error='Authentication error', status_code=result.status_code) # purify JSON result of unnecessary control sequence \n jsonraw, error, status_code = copy.deepcopy(result.result.replace('\n', '')),\ copy.deepcopy(result.error),\ result.status_code if error != '' or status_code >= 400: return Result(result=jsonraw, error=error, status_code=status_code) # check if any error occured self.check_for_error(jsonraw, error, status_code) hosts = json.loads(jsonraw) for host in hosts: # make dict of tuples for better reading h = dict(host.items()) # host if self.use_display_name_host == False: # according to http://sourceforge.net/p/nagstamon/bugs/83/ it might # better be host_name instead of host_display_name # legacy Icinga adjustments if 'host_name' in h: host_name = h['host_name'] elif 'host' in h: host_name = h['host'] else: # https://github.com/HenriWahl/Nagstamon/issues/46 on the other hand has # problems with that so here we go with extra display_name option host_name = h['host_display_name'] # host objects contain service objects if not host_name in self.new_hosts: self.new_hosts[host_name] = GenericHost() self.new_hosts[host_name].name = host_name self.new_hosts[host_name].server = self.name self.new_hosts[host_name].status = self.STATES_MAPPING[ 'hosts'][int(h['host_state'])] self.new_hosts[ host_name].last_check = datetime.datetime.fromtimestamp( int(h['host_last_check'])) self.new_hosts[host_name].attempt = h['host_attempt'] self.new_hosts[ host_name].status_information = BeautifulSoup( h['host_output'].replace('\n', ' ').strip(), 'html.parser').text self.new_hosts[host_name].passiveonly = not (int( h['host_active_checks_enabled'])) self.new_hosts[ host_name].notifications_disabled = not (int( h['host_notifications_enabled'])) self.new_hosts[host_name].flapping = bool( int(h['host_is_flapping'])) self.new_hosts[host_name].acknowledged = bool( int(h['host_acknowledged'])) self.new_hosts[host_name].scheduled_downtime = bool( int(h['host_in_downtime'])) self.new_hosts[host_name].status_type = status_type # extra Icinga properties to solve https://github.com/HenriWahl/Nagstamon/issues/192 # acknowledge needs host_description and no display name self.new_hosts[host_name].real_name = h['host_name'] # extra duration needed for calculation duration = datetime.datetime.now( ) - datetime.datetime.fromtimestamp( int(h['host_last_state_change'])) self.new_hosts[host_name].duration = strfdelta( duration, '{days}d {hours}h {minutes}m {seconds}s') del h, host_name except: import traceback traceback.print_exc(file=sys.stdout) # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # services try: for status_type in 'hard', 'soft': result = self.FetchURL(self.cgiurl_services[status_type], giveback='raw') # purify JSON result of unnecessary control sequence \n jsonraw, error, status_code = copy.deepcopy(result.result.replace('\n', '')),\ copy.deepcopy(result.error),\ result.status_code if error != '' or status_code >= 400: return Result(result=jsonraw, error=error, status_code=status_code) # check if any error occured self.check_for_error(jsonraw, error, status_code) services = copy.deepcopy(json.loads(jsonraw)) for service in services: # make dict of tuples for better reading s = dict(service.items()) if self.use_display_name_host == False: # according to http://sourceforge.net/p/nagstamon/bugs/83/ it might # better be host_name instead of host_display_name # legacy Icinga adjustments if 'host_name' in s: host_name = s['host_name'] elif 'host' in s: host_name = s['host'] else: # https://github.com/HenriWahl/Nagstamon/issues/46 on the other hand has # problems with that so here we go with extra display_name option host_name = s['host_display_name'] # host objects contain service objects if not host_name in self.new_hosts: self.new_hosts[host_name] = GenericHost() self.new_hosts[host_name].name = host_name self.new_hosts[host_name].status = 'UP' # extra Icinga properties to solve https://github.com/HenriWahl/Nagstamon/issues/192 # acknowledge needs host_description and no display name self.new_hosts[host_name].real_name = s['host_name'] #if self.use_display_name_host == False: # # legacy Icinga adjustments # if 'service_description' in s: service_name = s['service_description'] # elif 'description' in s: service_name = s['description'] # elif 'service' in s: service_name = s['service'] #else: # service_name = s['service_display_name'] # regarding to https://github.com/HenriWahl/Nagstamon/issues/400 Icinga2 needs no legacy adjustments service_name = s['service_display_name'] # if a service does not exist create its object if not service_name in self.new_hosts[host_name].services: self.new_hosts[host_name].services[ service_name] = GenericService() self.new_hosts[host_name].services[ service_name].host = host_name self.new_hosts[host_name].services[ service_name].name = service_name self.new_hosts[host_name].services[ service_name].server = self.name self.new_hosts[host_name].services[ service_name].status = self.STATES_MAPPING[ 'services'][int(s['service_state'])] self.new_hosts[host_name].services[ service_name].last_check = datetime.datetime.fromtimestamp( int(s['service_last_check'])) self.new_hosts[host_name].services[ service_name].attempt = s['service_attempt'] self.new_hosts[host_name].services[ service_name].status_information = BeautifulSoup( s['service_output'].replace('\n', ' ').strip(), 'html.parser').text self.new_hosts[host_name].services[ service_name].passiveonly = not (int( s['service_active_checks_enabled'])) self.new_hosts[host_name].services[ service_name].notifications_disabled = not (int( s['service_notifications_enabled'])) self.new_hosts[host_name].services[ service_name].flapping = bool( int(s['service_is_flapping'])) self.new_hosts[host_name].services[ service_name].acknowledged = bool( int(s['service_acknowledged'])) self.new_hosts[host_name].services[ service_name].scheduled_downtime = bool( int(s['service_in_downtime'])) self.new_hosts[host_name].services[ service_name].status_type = status_type # extra Icinga properties to solve https://github.com/HenriWahl/Nagstamon/issues/192 # acknowledge needs service_description and no display name self.new_hosts[host_name].services[ service_name].real_name = s['service_description'] # extra duration needed for calculation duration = datetime.datetime.now( ) - datetime.datetime.fromtimestamp( int(s['service_last_state_change'])) self.new_hosts[host_name].services[ service_name].duration = strfdelta( duration, '{days}d {hours}h {minutes}m {seconds}s') del s, host_name, service_name except: import traceback traceback.print_exc(file=sys.stdout) # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # some cleanup del jsonraw, error, hosts, services # dummy return in case all is OK return Result()
def _get_status_JSON(self): """ Get status from Icinga Server - the JSON way """ # new_hosts dictionary self.new_hosts = dict() # hosts - mostly the down ones # now using JSON output from Icinga try: for status_type in 'hard', 'soft': result = self.FetchURL(self.cgiurl_hosts[status_type], giveback='raw') # purify JSON result of unnecessary control sequence \n jsonraw, error, status_code = copy.deepcopy(result.result.replace('\n', '')),\ copy.deepcopy(result.error),\ result.status_code # check if any error occured errors_occured = self.check_for_error(jsonraw, error, status_code) # if there are errors return them if errors_occured != False: return (errors_occured) jsondict = json.loads(jsonraw) hosts = copy.deepcopy(jsondict['status']['host_status']) for host in hosts: # make dict of tuples for better reading h = dict(host.items()) # host if self.use_display_name_host == False: # according to http://sourceforge.net/p/nagstamon/bugs/83/ it might # better be host_name instead of host_display_name # legacy Icinga adjustments if 'host_name' in h: host_name = h['host_name'] elif 'host' in h: host_name = h['host'] else: # https://github.com/HenriWahl/Nagstamon/issues/46 on the other hand has # problems with that so here we go with extra display_name option host_name = h['host_display_name'] # host objects contain service objects if not host_name in self.new_hosts: self.new_hosts[host_name] = GenericHost() self.new_hosts[host_name].name = host_name self.new_hosts[host_name].server = self.name self.new_hosts[host_name].status = h['status'] self.new_hosts[host_name].last_check = h['last_check'] self.new_hosts[host_name].duration = h['duration'] self.new_hosts[host_name].attempt = h['attempts'] self.new_hosts[host_name].status_information = h[ 'status_information'].replace('\n', ' ').strip() self.new_hosts[host_name].passiveonly = not ( h['active_checks_enabled']) self.new_hosts[ host_name].notifications_disabled = not ( h['notifications_enabled']) self.new_hosts[host_name].flapping = h['is_flapping'] self.new_hosts[host_name].acknowledged = h[ 'has_been_acknowledged'] self.new_hosts[host_name].scheduled_downtime = h[ 'in_scheduled_downtime'] self.new_hosts[host_name].status_type = status_type # extra Icinga properties to solve https://github.com/HenriWahl/Nagstamon/issues/192 # acknowledge needs host_description and no display name self.new_hosts[host_name].real_name = h['host_name'] del h, host_name except: # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # services try: for status_type in 'hard', 'soft': result = self.FetchURL(self.cgiurl_services[status_type], giveback='raw') # purify JSON result of unnecessary control sequence \n jsonraw, error, status_code = copy.deepcopy(result.result.replace('\n', '')),\ copy.deepcopy(result.error),\ result.status_code # check if any error occured errors_occured = self.check_for_error(jsonraw, error, status_code) # if there are errors return them if errors_occured != False: return (errors_occured) jsondict = json.loads(jsonraw) services = copy.deepcopy(jsondict['status']['service_status']) for service in services: # make dict of tuples for better reading s = dict(service.items()) if self.use_display_name_host == False: # according to http://sourceforge.net/p/nagstamon/bugs/83/ it might # better be host_name instead of host_display_name # legacy Icinga adjustments if 'host_name' in s: host_name = s['host_name'] elif 'host' in s: host_name = s['host'] else: # https://github.com/HenriWahl/Nagstamon/issues/46 on the other hand has # problems with that so here we go with extra display_name option host_name = s['host_display_name'] # host objects contain service objects if not host_name in self.new_hosts: self.new_hosts[host_name] = GenericHost() self.new_hosts[host_name].name = host_name self.new_hosts[host_name].status = 'UP' # extra Icinga properties to solve https://github.com/HenriWahl/Nagstamon/issues/192 # acknowledge needs host_description and no display name self.new_hosts[host_name].real_name = s['host_name'] if self.use_display_name_host == False: # legacy Icinga adjustments if 'service_description' in s: service_name = s['service_description'] elif 'description' in s: service_name = s['description'] elif 'service' in s: service_name = s['service'] else: service_name = s['service_display_name'] # if a service does not exist create its object if not service_name in self.new_hosts[host_name].services: self.new_hosts[host_name].services[ service_name] = GenericService() self.new_hosts[host_name].services[ service_name].host = host_name self.new_hosts[host_name].services[ service_name].name = service_name self.new_hosts[host_name].services[ service_name].server = self.name self.new_hosts[host_name].services[ service_name].status = s['status'] self.new_hosts[host_name].services[ service_name].last_check = s['last_check'] self.new_hosts[host_name].services[ service_name].duration = s['duration'] self.new_hosts[host_name].services[ service_name].attempt = s['attempts'] self.new_hosts[host_name].services[ service_name].status_information = s[ 'status_information'].replace('\n', ' ').strip() self.new_hosts[host_name].services[ service_name].passiveonly = not ( s['active_checks_enabled']) self.new_hosts[host_name].services[ service_name].notifications_disabled = not ( s['notifications_enabled']) self.new_hosts[host_name].services[ service_name].flapping = s['is_flapping'] self.new_hosts[host_name].services[ service_name].acknowledged = s[ 'has_been_acknowledged'] self.new_hosts[host_name].services[ service_name].scheduled_downtime = s[ 'in_scheduled_downtime'] self.new_hosts[host_name].services[ service_name].status_type = status_type # extra Icinga properties to solve https://github.com/HenriWahl/Nagstamon/issues/192 # acknowledge needs service_description and no display name self.new_hosts[host_name].services[ service_name].real_name = s['service_description'] del s, host_name, service_name except: # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # some cleanup del jsonraw, jsondict, error, hosts, services # dummy return in case all is OK return Result()
def _get_status_HTML(self): """ Get status from Nagios Server - the oldschool CGI HTML way """ # create Nagios items dictionary with to lists for services and hosts # every list will contain a dictionary for every failed service/host # this dictionary is only temporarily # ##global icons nagitems = {'services': [], 'hosts': []} # new_hosts dictionary self.new_hosts = dict() # hosts - mostly the down ones # unfortunately the hosts status page has a different structure so # hosts must be analyzed separately try: for status_type in 'hard', 'soft': result = self.FetchURL(self.cgiurl_hosts[status_type]) htobj, error, status_code = result.result,\ result.error,\ result.status_code # check if any error occured errors_occured = self.check_for_error(htobj, error, status_code) # if there are errors return them if errors_occured != False: return (errors_occured) # put a copy of a part of htobj into table to be able to delete htobj table = htobj('table', {'class': 'status'})[0] # do some cleanup del result, error # access table rows # some Icinga versions have a <tbody> tag in cgi output HTML which # omits the <tr> tags being found if len(table('tbody')) == 0: trs = table('tr', recursive=False) else: tbody = table('tbody')[0] trs = tbody('tr', recursive=False) # kick out table heads trs.pop(0) for tr in trs: try: # ignore empty <tr> rows if len(tr('td', recursive=False)) > 1: n = {} # get tds in one tr tds = tr('td', recursive=False) # host try: n['host'] = str( tds[0].table.tr.td.table.tr.td.a.string) except: n['host'] = str(nagitems[len(nagitems) - 1]['host']) # status n['status'] = str(tds[1].string) # last_check n['last_check'] = str(tds[2].string) # duration n['duration'] = str(tds[3].string) # division between Nagios and Icinga in real life... where # Nagios has only 5 columns there are 7 in Icinga 1.3... # ... and 6 in Icinga 1.2 :-) if len(tds) < 7: # the old Nagios table # status_information if len(tds[4](text=not_empty)) == 0: n['status_information'] = '' else: n['status_information'] = str( tds[4].string) # attempts are not shown in case of hosts so it defaults to 'N/A' n['attempt'] = 'N/A' else: # attempts are shown for hosts # to fix http://sourceforge.net/tracker/?func=detail&atid=1101370&aid=3280961&group_id=236865 .attempt needs # to be stripped n['attempt'] = str(tds[4].string).strip() # status_information if len(tds[5](text=not_empty)) == 0: n['status_information'] = '' else: n['status_information'] = str( tds[5].string) # status flags n['passiveonly'] = False n['notifications_disabled'] = False n['flapping'] = False n['acknowledged'] = False n['scheduled_downtime'] = False # map status icons to status flags icons = tds[0].findAll('img') for i in icons: icon = i['src'].split('/')[-1] if icon in self.STATUS_MAPPING: n[self.STATUS_MAPPING[icon]] = True # cleaning del icons # add dictionary full of information about this host item to nagitems nagitems['hosts'].append(n) # after collection data in nagitems create objects from its informations # host objects contain service objects if not 'host' in self.new_hosts: new_host = n['host'] self.new_hosts[new_host] = GenericHost() self.new_hosts[new_host].name = n['host'] self.new_hosts[new_host].server = self.name self.new_hosts[new_host].status = n['status'] self.new_hosts[new_host].last_check = n[ 'last_check'] self.new_hosts[new_host].duration = n[ 'duration'] self.new_hosts[new_host].attempt = n['attempt'] self.new_hosts[ new_host].status_information = n[ 'status_information'].replace( '\n', ' ').strip() self.new_hosts[new_host].passiveonly = n[ 'passiveonly'] self.new_hosts[ new_host].notifications_disabled = n[ 'notifications_disabled'] self.new_hosts[new_host].flapping = n[ 'flapping'] self.new_hosts[new_host].acknowledged = n[ 'acknowledged'] self.new_hosts[ new_host].scheduled_downtime = n[ 'scheduled_downtime'] self.new_hosts[ new_host].status_type = status_type # extra Icinga properties to solve https://github.com/HenriWahl/Nagstamon/issues/192 # acknowledge needs host_name and no display name self.new_hosts[new_host].real_name = n['host'] # some cleanup del tds, n except: self.Error(sys.exc_info()) # do some cleanup htobj.decompose() del htobj, trs, table except: # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # services try: for status_type in 'hard', 'soft': result = self.FetchURL(self.cgiurl_services[status_type]) htobj, error, status_code = result.result,\ result.error,\ result.status_code # check if any error occured errors_occured = self.check_for_error(htobj, error, status_code) # if there are errors return them if errors_occured != False: return (errors_occured) table = htobj('table', {'class': 'status'})[0] # some Icinga versions have a <tbody> tag in cgi output HTML which # omits the <tr> tags being found if len(table('tbody')) == 0: trs = table('tr', recursive=False) else: tbody = table('tbody')[0] trs = tbody('tr', recursive=False) # do some cleanup del result, error # kick out table heads trs.pop(0) for tr in trs: try: # ignore empty <tr> rows - there are a lot of them - a Nagios bug? tds = tr('td', recursive=False) if len(tds) > 1: n = {} # host # the resulting table of Nagios status.cgi table omits the # hostname of a failing service if there are more than one # so if the hostname is empty the nagios status item should get # its hostname from the previuos item - one reason to keep 'nagitems' try: n['host'] = str(tds[0](text=not_empty)[0]) except: n['host'] = str(nagitems['services'][ len(nagitems['services']) - 1]['host']) # service n['service'] = str(tds[1](text=not_empty)[0]) # status n['status'] = str(tds[2](text=not_empty)[0]) # last_check n['last_check'] = str(tds[3](text=not_empty)[0]) # duration n['duration'] = str(tds[4](text=not_empty)[0]) # attempt # to fix http://sourceforge.net/tracker/?func=detail&atid=1101370&aid=3280961&group_id=236865 .attempt needs # to be stripped n['attempt'] = str( tds[5](text=not_empty)[0]).strip() # status_information if len(tds[6](text=not_empty)) == 0: n['status_information'] = '' else: n['status_information'] = str( tds[6](text=not_empty)[0]) # status flags n['passiveonly'] = False n['notifications_disabled'] = False n['flapping'] = False n['acknowledged'] = False n['scheduled_downtime'] = False # map status icons to status flags icons = tds[1].findAll('img') for i in icons: icon = i['src'].split('/')[-1] if icon in self.STATUS_MAPPING: n[self.STATUS_MAPPING[icon]] = True # cleaning del icons # add dictionary full of information about this service item to nagitems - only if service nagitems['services'].append(n) # after collection data in nagitems create objects of its informations # host objects contain service objects if not n['host'] in self.new_hosts: self.new_hosts[n['host']] = GenericHost() self.new_hosts[n['host']].name = n['host'] self.new_hosts[n['host']].status = 'UP' # extra Icinga properties to solve https://github.com/HenriWahl/Nagstamon/issues/192 # acknowledge needs host_description and no display name self.new_hosts[n['host']].real_name = n['host'] # trying to fix https://sourceforge.net/tracker/index.php?func=detail&aid=3299790&group_id=236865&atid=1101370 # if host is not down but in downtime or any other flag this should be evaluated too # map status icons to status flags icons = tds[0].findAll('img') for i in icons: icon = i['src'].split('/')[-1] if icon in self.STATUS_MAPPING: self.new_hosts[n['host']].__dict__[ self.STATUS_MAPPING[icon]] = True # cleaning del icons # if a service does not exist create its object if not n['service'] in self.new_hosts[ n['host']].services: new_service = n['service'] self.new_hosts[n['host']].services[ new_service] = GenericService() self.new_hosts[n['host']].services[ new_service].host = n['host'] self.new_hosts[n['host']].services[ new_service].server = self.name self.new_hosts[n['host']].services[ new_service].name = n['service'] self.new_hosts[n['host']].services[ new_service].status = n['status'] self.new_hosts[n['host']].services[ new_service].last_check = n['last_check'] self.new_hosts[n['host']].services[ new_service].duration = n['duration'] self.new_hosts[n['host']].services[ new_service].attempt = n['attempt'] self.new_hosts[n['host']].services[ new_service].status_information = n[ 'status_information'].replace( '\n', ' ').strip() self.new_hosts[n['host']].services[ new_service].passiveonly = n['passiveonly'] self.new_hosts[n['host']].services[ new_service].notifications_disabled = n[ 'notifications_disabled'] self.new_hosts[n['host']].services[ new_service].flapping = n['flapping'] self.new_hosts[n['host']].services[ new_service].acknowledged = n[ 'acknowledged'] self.new_hosts[n['host']].services[ new_service].scheduled_downtime = n[ 'scheduled_downtime'] # extra Icinga properties to solve https://github.com/HenriWahl/Nagstamon/issues/192 # acknowledge needs service_description and no display name self.new_hosts[n['host']].services[ new_service].real_name = n[ 'service_description'] # some cleanup del tds, n except: self.Error(sys.exc_info()) # do some cleanup htobj.decompose() del htobj, trs, table except: # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # some cleanup del nagitems # dummy return in case all is OK return Result()
def _get_status(self): nagitems = {"services":[], "hosts":[]} self.new_hosts = dict() try: hosts = self._get_all_events() if 'events' in hosts: hosts = hosts['events'] for host in hosts: n = dict() n['evid'] = host['evid'] n['host'] = host['device']['text'] n['service'] = host['eventClass']['text'] n['status'] = self.SEVERITY_MAP.get(host['severity']) n['last_check'] = host['lastTime'] duration = self._calc_duration(host['firstTime'], host['lastTime']) if (duration == None): continue #Zenoss needs a length to cause an error n['duration'] = duration n["status_information"] = host['message'] n["attempt"] = str(host['count'])+"/1" # needs a / with a number on either side to work n["passiveonly"] = False n["notifications_disabled"] = False n["flapping"] = False n["acknowledged"] = (host['eventState'] == 'Acknowledged') n["scheduled_downtime"] = False nagitems["hosts"].append(n) new_host = n["host"] if not new_host in self.new_hosts: self.new_hosts[new_host] = GenericHost() self.new_hosts[new_host].name = new_host if not new_host in self.new_hosts[new_host].services: new_service = new_host self.new_hosts[new_host].services[new_service] = GenericService() self.new_hosts[new_host].services[new_service].host = new_host self.new_hosts[new_host].services[new_service].evid = n['evid'] self.new_hosts[new_host].services[new_service].name = n["service"] self.new_hosts[new_host].services[new_service].server = self.name self.new_hosts[new_host].services[new_service].status = n["status"] self.new_hosts[new_host].services[new_service].last_check = n["last_check"] self.new_hosts[new_host].services[new_service].duration = n["duration"] self.new_hosts[new_host].services[new_service].status_information= n["status_information"].encode("utf-8") self.new_hosts[new_host].services[new_service].attempt = n["attempt"] self.new_hosts[new_host].services[new_service].passiveonly = n["passiveonly"] self.new_hosts[new_host].services[new_service].notifications_disabled = n["notifications_disabled"] self.new_hosts[new_host].services[new_service].flapping = n["flapping"] self.new_hosts[new_host].services[new_service].acknowledged = n["acknowledged"] self.new_hosts[new_host].services[new_service].scheduled_downtime = n["scheduled_downtime"] del n except: self.isChecking = False result, error = self.Error(sys.exc_info()) print(traceback.format_exc()) return Result(result=result, error=error) del nagitems return Result(error="")
def _get_status(self): """ Get status from monitos 4 Server - only JSON """ # define CGI URLs for hosts and services if self.use_autologin is True: if self.cgiurl_hosts is None: # hosts (up, down, unreachable) self.cgiurl_hosts = self.monitor_cgi_url + '/api/host?include=status,configuration&limit=100&filter[states]=0,1,2&filter[onlysyncenabled]' + '&authtoken=' + self.autologin_key if self.cgiurl_services is None: # services (warning, critical, unknown) self.cgiurl_services = self.monitor_cgi_url + \ '/api/serviceinstance?include=status,configuration&limit=100&filter[states]=1,2,3&filter[onlysyncenabled]' + '&authtoken=' + self.autologin_key else: if self.cgiurl_hosts is None: # hosts (up, down, unreachable) self.cgiurl_hosts = self.monitor_cgi_url + '/api/host?include=status,configuration&limit=100&filter[states]=0,1,2&filter[onlysyncenabled]' if self.cgiurl_services is None: # services (warning, critical, unknown) self.cgiurl_services = self.monitor_cgi_url + '/api/serviceinstance?include=status,configuration&limit=100&filter[states]=1,2,3&filter[onlysyncenabled]' self.new_hosts = dict() # hosts try: form_data = dict() page = 1 # loop trough all api pages while True: cgiurl_hosts_page = self.cgiurl_hosts + '&page=' + str(page) result = self.FetchURL(cgiurl_hosts_page, giveback='raw', cgi_data=None) # authentication errors get a status code 200 too if result.status_code < 400 and \ result.result.startswith('<'): # in case of auth error reset HTTP session and try again self.reset_HTTP() result = self.FetchURL(cgiurl_hosts_page, giveback='raw', cgi_data=None) if result.status_code < 400 and \ result.result.startswith('<'): self.refresh_authentication = True return Result(result=result.result, error='Authentication error', status_code=result.status_code) # purify JSON result jsonraw = copy.deepcopy(result.result.replace('\n', '')) error = copy.deepcopy(result.error) status_code = result.status_code if error != '' or status_code >= 400: return Result(result=jsonraw, error=error, status_code=status_code) self.check_for_error(jsonraw, error, status_code) hosts = json.loads(jsonraw) if not hosts['data']: break page += 1 for host in hosts['data']: h = dict(host) # Skip if host is disabled if h['syncEnabled'] is not None: if not int(h['syncEnabled']): continue # host host_name = h['name'] if conf.debug_mode: self.Debug(server=self.get_name(), debug=time.strftime('%a %H:%M:%S') + ' host_name is: ' + host_name) # If a host does not exist, create its object if host_name not in self.new_hosts: self.new_hosts[host_name] = GenericHost() self.new_hosts[host_name].name = host_name self.new_hosts[host_name].uuid = h['uuid'] self.new_hosts[host_name].server = 'monitos' try: self.new_hosts[ host_name].status = self.STATES_MAPPING[ 'hosts'][int(h['status']['currentState'])] except: pass try: self.new_hosts[ host_name].last_check = datetime.datetime.fromtimestamp( int(h['status']['lastCheck'])) except: pass self.new_hosts[host_name].attempt = h['configuration'][ 'maxCheckAttempts'] try: self.new_hosts[ host_name].status_information = BeautifulSoup( h['status']['output'].replace('\n', ' ').strip(), 'html.parser').text except: self.new_hosts[host_name].services[ service_name].status_information = 'Cant parse output' self.new_hosts[host_name].passiveonly = not (int( h['status']['checksEnabled'])) try: self.new_hosts[ host_name].notifications_disabled = not (int( s['status']['notificationsEnabled'])) except: self.new_hosts[ host_name].notifications_disabled = False try: self.new_hosts[host_name].flapping = (int( h['status']['isFlapping'])) except: self.new_hosts[host_name].flapping = False if h['status']['acknowleged'] is None: self.new_hosts[host_name].acknowledged = False else: if h['status']['acknowleged'] != 0: self.new_hosts[host_name].acknowledged = True try: if int(h['status']['scheduledDowntimeDepth']) != 0: self.new_hosts[ host_name].scheduled_downtime = True except: self.new_hosts[ host_name].scheduled_downtime = False try: self.new_hosts[ host_name].status_type = 'soft' if int( h['status']['stateType']) == 0 else 'hard' except: self.new_hosts[host_name].status_type = 'hard' # extra duration needed for calculation if h['status']['lastStateChange'] is None: self.Debug( server=self.get_name(), debug=time.strftime('%a %H:%M:%S') + 'Host has wrong lastStateChange - host_name is: ' + host_name) else: duration = datetime.datetime.now( ) - datetime.datetime.fromtimestamp( int(h['status']['lastStateChange'])) self.new_hosts[host_name].duration = strfdelta( duration, '{days}d {hours}h {minutes}m {seconds}s') del h, host_name del hosts except: import traceback traceback.print_exc(file=sys.stdout) # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # services try: form_data = dict() page = 1 # loop trough all api pages while True: cgiurl_services_page = self.cgiurl_services + '&page=' + str( page) result = self.FetchURL(cgiurl_services_page, giveback='raw', cgi_data=None) # purify JSON result jsonraw = copy.deepcopy(result.result.replace('\n', '')) error = copy.deepcopy(result.error) status_code = result.status_code if error != '' or status_code >= 400: return Result(result=jsonraw, error=error, status_code=status_code) self.check_for_error(jsonraw, error, status_code) services = json.loads(jsonraw) if not services['data']: break page += 1 for service in services['data']: s = dict(service) # Skip if host is disabled if s['syncEnabled'] is not None: if not int(s['syncEnabled']): continue # host and service host_name = s['configuration']['hostName'] service_name = s['configuration']['serviceDescription'] if conf.debug_mode: self.Debug(server=self.get_name(), debug=time.strftime('%a %H:%M:%S') + ' host_name is: ' + host_name + ' service_name is: ' + service_name) # If host not in problem list, create it if host_name not in self.new_hosts: self.new_hosts[host_name] = GenericHost() self.new_hosts[host_name].name = host_name self.new_hosts[host_name].uuid = s['configuration'][ 'host']['uuid'] self.new_hosts[host_name].status = self.STATES_MAPPING[ 'services'][0] # If a service does not exist, create its object if service_name not in self.new_hosts[host_name].services: self.new_hosts[host_name].services[ service_name] = GenericService() self.new_hosts[host_name].services[ service_name].host = s['configuration']['hostName'] self.new_hosts[host_name].services[ service_name].uuid = s['uuid'] self.new_hosts[host_name].services[ service_name].name = service_name self.new_hosts[host_name].services[ service_name].server = 'monitos' try: self.new_hosts[host_name].services[ service_name].status = self.STATES_MAPPING[ 'services'][int( s['status']['currentState'])] except: pass try: self.new_hosts[host_name].services[ service_name].last_check = datetime.datetime.fromtimestamp( int(s['status']['lastCheck'])) except: pass self.new_hosts[host_name].services[ service_name].attempt = s['configuration'][ 'maxCheckAttempts'] try: self.new_hosts[host_name].services[ service_name].status_information = BeautifulSoup( s['status']['output'].replace('\n', ' ').strip(), 'html.parser').text except: self.new_hosts[host_name].services[ service_name].status_information = 'Cant parse output' self.new_hosts[host_name].services[ service_name].passiveonly = not (int( s['status']['checksEnabled'])) try: self.new_hosts[host_name].services[ service_name].notifications_disabled = not ( int(s['status']['notificationsEnabled'])) except: self.new_hosts[host_name].services[ service_name].notifications_disabled = False try: self.new_hosts[host_name].services[ service_name].flapping = (int( s['status']['isFlapping'])) except: self.new_hosts[host_name].services[ service_name].flapping = False if s['status']['acknowleged'] is None: self.new_hosts[host_name].services[ service_name].acknowledged = False else: if s['status']['acknowleged'] != 0: self.new_hosts[host_name].services[ service_name].acknowledged = True try: if int(s['status']['scheduledDowntimeDepth']) != 0: self.new_hosts[host_name].services[ service_name].scheduled_downtime = True except: self.new_hosts[host_name].services[ service_name].scheduled_downtime = False try: self.new_hosts[host_name].services[ service_name].status_type = 'soft' if int( s['status']['stateType']) == 0 else 'hard' except: self.new_hosts[host_name].services[ service_name].status_type = 'hard' # extra duration needed for calculation if s['status']['lastStateChange'] is None: self.Debug( server=self.get_name(), debug=time.strftime('%a %H:%M:%S') + 'Service has wrong lastStateChange - host_name is ' + host_name + ' service_name is: ' + service_name) else: duration = datetime.datetime.now( ) - datetime.datetime.fromtimestamp( int(s['status']['lastStateChange'])) self.new_hosts[host_name].services[ service_name].duration = strfdelta( duration, '{days}d {hours}h {minutes}m {seconds}s') del s, host_name, service_name del services except: import traceback traceback.print_exc(file=sys.stdout) # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) del jsonraw, error, hosts # dummy return in case all is OK return Result()
def _get_status(self): """ Get status from Zabbix Server """ ret = Result() # create Nagios items dictionary with to lists for services and hosts # every list will contain a dictionary for every failed service/host # this dictionary is only temporarily nagitems = {"services": [], "hosts": []} # Create URLs for the configured filters if self.zapi is None: self._login() try: # ========================================= # Hosts Zabbix API data # ========================================= hosts = [] try: hosts = self.zapi.host.get({"output": ["hostid", "host", "name", "status", \ "available", "error", "errors_from", \ "snmp_available", "snmp_error", "snmp_errors_from", \ "ipmi_available", "ipmi_error", "ipmi_errors_from", \ "jmx_available", "jmx_error", "jmx_errors_from", \ "maintenance_status", "maintenance_from"], "selectInterfaces": ["ip"], "filter": {}}) except (ZabbixError, ZabbixAPIException, APITimeout, Already_Exists): # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # get All Hosts. # 1. Store data in cache (to be used by events) # 2. We store as faulty two kinds of hosts incidences: # - Disabled hosts # - Hosts with issues trying to connect to agent/service # - In maintenance # status = 1 -> Disabled # available ZBX: 0 -> No agents 1 -> available 2-> Agent access error # ipmi_available IPMI: 0 -> No agents 1 -> available 2-> Agent access error # maintenance_status = 1 In maintenance for host in hosts: n = { 'host': host['host'], 'name': host['name'], 'server': self.name, 'status': 'UP', # Host is OK by default 'last_check': 'n/a', 'duration': '', 'attempt': 'N/A', 'status_information': '', # status flags 'passiveonly': False, 'notifications_disabled': False, 'flapping': False, 'acknowledged': False, 'scheduled_downtime': False, # Zabbix backend data 'hostid': host['hostid'], 'site': '', 'address': host['interfaces'][0]['ip'], } if host['maintenance_status'] == '1': n['scheduled_downtime'] = True if host['status'] == '1': # filter services and hosts by "filter_hosts_services_disabled_notifications" n['notifications_disabled'] = True # Filter only hosts by filter "Host & services with disabled checks" n['passiveonly'] = True # attempt to fix https://github.com/HenriWahl/Nagstamon/issues/535 # if host['available'] == '0' and host['snmp_available'] == '0' and host['ipmi_available'] == '0' and host['jmx_available'] == '0': # n['status'] = 'UNREACHABLE' # n['status_information'] = 'Host agents in unknown state' # n['duration'] = 'Unknown' if host['ipmi_available'] == '2': n['status'] = 'DOWN' n['status_information'] = host['ipmi_error'] n['duration'] = HumanReadableDurationFromTimestamp(host['ipmi_errors_from']) if host['snmp_available'] == '2': n['status'] = 'DOWN' n['status_information'] = host['snmp_error'] n['duration'] = HumanReadableDurationFromTimestamp(host['snmp_errors_from']) if host['jmx_available'] == '2': n['status'] = 'DOWN' n['status_information'] = host['jmx_error'] n['duration'] = HumanReadableDurationFromTimestamp(host['jmx_errors_from']) if host['available'] == '2': n['status'] = 'DOWN' n['status_information'] = host['error'] n['duration'] = HumanReadableDurationFromTimestamp(host['errors_from']) # Zabbix shows OK hosts too - kick 'em! if not n['status'] == 'UP': # add dictionary full of information about this host item to nagitems nagitems["hosts"].append(n) # after collection data in nagitems create objects from its informations # host objects contain service objects #key_host = n["host"] key_host = n["name"] if len(n['name']) != 0 else n["host"]; #key_host = n["hostid"] if key_host not in self.new_hosts: self.new_hosts[key_host] = GenericHost() self.new_hosts[key_host].hostid = n["hostid"] self.new_hosts[key_host].host = n["host"] self.new_hosts[key_host].name = n["name"] self.new_hosts[key_host].status = n["status"] self.new_hosts[key_host].last_check = n["last_check"] self.new_hosts[key_host].duration = n["duration"] self.new_hosts[key_host].attempt = n["attempt"] self.new_hosts[key_host].status_information = n["status_information"] self.new_hosts[key_host].site = n["site"] self.new_hosts[key_host].address = n["address"] self.new_hosts[key_host].notifications_disabled = n["notifications_disabled"] self.new_hosts[key_host].scheduled_downtime = n["scheduled_downtime"] self.new_hosts[key_host].passiveonly = n["passiveonly"] self.new_hosts[key_host].acknowledged = n["acknowledged"] self.new_hosts[key_host].flapping = n["flapping"] except ZabbixError: self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # ========================================= # services # ========================================= services = [] try: api_version = self.zapi.api_version() except ZabbixAPIException: # FIXME Is there a cleaner way to handle this? I just borrowed # this code from 80 lines ahead. -- AGV # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) print(sys.exc_info()) return Result(result=result, error=error) try: try: # Get a list of all issues (AKA tripped triggers) # Zabbix 3+ returns array of objects triggers = self.zapi.trigger.get({'only_true': True, 'skipDependent': True, 'monitored': True, 'active': True, 'output': 'extend', 'expandDescription': True, 'selectHosts': ['hostid','host','name'], 'selectItems': ['itemid','name','key_','lastvalue','state','lastclock'], # thats for zabbix api 2.0+ 'filter': {'value': 1}, }) # Do another query to find out which issues are Unacknowledged # Zabbix 3+ returns array of objects unack_triggers = self.zapi.trigger.get({'only_true': True, 'skipDependent': True, 'monitored': True, 'active': True, 'output': ['triggerid'], 'expandDescription': True, 'selectHosts': ['hostid'], 'withLastEventUnacknowledged': True, }) unack_trigger_ids = [u['triggerid'] for u in unack_triggers] for t in triggers: t['acknowledged'] = False if t['triggerid'] in unack_trigger_ids else True # get Application name for the trigger this_item = self.zapi.item.get( {'itemids': [t['items'][0]['itemid']], 'output': ['itemid', 'hostid', 'name', 'lastvalue'], 'selectApplications': 'extend'} ) t['application'] = self.getLastApp(this_item) try: t['lastvalue'] = this_item[0]['lastvalue'] except IndexError as e: self.Debug(server=self.get_name(), debug="ItemID '%s' has no values" % t['items'][0]['itemid'], head='WARNING') services.append(t) except ZabbixAPIException: # FIXME Is there a cleaner way to handle this? I just borrowed # this code from 80 lines ahead. -- AGV # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) print(sys.exc_info()) return Result(result=result, error=error) except ZabbixError as e: if e.terminate: return e.result else: service = e.result.content ret = e.result for service in services: # Zabbix probably shows OK services too - kick 'em! # UPDATE Zabbix api 3.0 doesn't but I didn't tried with older # so I left it status = self.statemap.get(service['priority'], service['priority']) # self.Debug(server=self.get_name(), debug="SERVICE (" + service['application'] + ") STATUS: **" + status + "** PRIORITY: #" + service['priority']) # self.Debug(server=self.get_name(), debug="-----======== SERVICE " + str(service)) if not status == 'OK': if not service['description'].endswith('...'): state = service['description'] else: state = service['items'][0]['lastvalue'] # A trigger can be triggered by multiple items # Get last checking date of any of the items involved lastcheck = 0 for item in service['items']: if int(item['lastclock']) > lastcheck: lastcheck = int(item['lastclock']) if self.use_description_name_service and \ len(service['comments']) != 0: srvc = self.nagiosify_service(service['comments']) else: srvc = service['application'] n = { 'host': '', 'hostname': '', 'service': service['triggerid'], 'server': self.name, 'status': status, # Putting service in attempt column allow to see it in GUI 'attempt': srvc, 'duration': HumanReadableDurationFromTimestamp(service['lastchange']), 'status_information': state, 'last_check': time.strftime("%d/%m/%Y %H:%M:%S", time.localtime(lastcheck)), 'site': '', 'command': 'zabbix', # status flags 'passiveonly': False, 'notifications_disabled': False, 'flapping': False, 'acknowledged' : service['acknowledged'], 'scheduled_downtime': False, # Zabbix data 'triggerid': service['triggerid'], } n['hostid'] = service['hosts'][0]['hostid'] n['host'] = service['hosts'][0]['host'] n['hostname'] = service['hosts'][0]['name'] key = n["hostname"] if len(n['hostname']) != 0 else n["host"]; #key = n["hostid"]; if self.new_hosts[key].scheduled_downtime == True: n['scheduled_downtime'] = True nagitems["services"].append(n) # after collection data in nagitems create objects of its informations # host objects contain service objects # if not created previously, host should be created with proper data if key not in self.new_hosts: # This should never happen, because we've stored all hosts in new_hosts array print("================================") print("Host " + key + "Not found in host cache") if conf.debug_mode is True: self.Debug(server=self.get_name(), debug="Host not found [" + key + "]") # if a service does not exist create its object new_service = n["triggerid"] if new_service not in self.new_hosts[key].services: self.new_hosts[key].services[new_service] = GenericService() self.new_hosts[key].services[new_service].host = n["hostname"] if len(n['hostname']) != 0 else n["host"] self.new_hosts[key].services[new_service].name = n["service"] self.new_hosts[key].services[new_service].status = n["status"] self.new_hosts[key].services[new_service].last_check = n["last_check"] self.new_hosts[key].services[new_service].duration = n["duration"] self.new_hosts[key].services[new_service].attempt = n["attempt"] self.new_hosts[key].services[new_service].status_information = n["status_information"] self.new_hosts[key].services[new_service].passiveonly = n["passiveonly"] self.new_hosts[key].services[new_service].notifications_disabled = n["notifications_disabled"] self.new_hosts[key].services[new_service].flapping = n["flapping"] self.new_hosts[key].services[new_service].acknowledged = n["acknowledged"] self.new_hosts[key].services[new_service].scheduled_downtime = n["scheduled_downtime"] self.new_hosts[key].services[new_service].site = n["site"] self.new_hosts[key].services[new_service].address = self.new_hosts[key].address self.new_hosts[key].services[new_service].command = n["command"] self.new_hosts[key].services[new_service].hostid = n["hostid"] self.new_hosts[key].services[new_service].triggerid = n["triggerid"] if conf.debug_mode is True: self.Debug(server=self.get_name(), debug="Adding new service[" + new_service + "] **" + n['service'] + "**") except (ZabbixError, ZabbixAPIException): # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) print(sys.exc_info()) return Result(result=result, error=error) return ret
def _get_status(self): """ Get status from Zabbix Server """ ret = Result() # create Nagios items dictionary with to lists for services and hosts # every list will contain a dictionary for every failed service/host # this dictionary is only temporarily nagitems = {"services": [], "hosts": []} # Create URLs for the configured filters if self.zapi is None: self._login() try: hosts = [] try: hosts = self.zapi.host.get({ "output": [ "host", "ip", "status", "available", "error", "errors_from" ], "filter": {} }) except (ZabbixError, ZabbixAPIException): # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) for host in hosts: # if host is disabled on server safely ignore it if host['available'] != '0': n = { 'host': host['host'], 'status': self.statemap.get(host['status'], host['status']), 'last_check': 'n/a', 'duration': HumanReadableDurationFromTimestamp( host['errors_from']), 'status_information': host['error'], 'attempt': '1/1', 'site': '', 'address': host['host'], } # Zabbix shows OK hosts too - kick 'em! if not n['status'] == 'OK': # add dictionary full of information about this host item to nagitems nagitems["hosts"].append(n) # after collection data in nagitems create objects from its informations # host objects contain service objects if n["host"] not in self.new_hosts: new_host = n["host"] self.new_hosts[new_host] = GenericHost() self.new_hosts[new_host].name = n["host"] self.new_hosts[new_host].status = n["status"] self.new_hosts[new_host].last_check = n[ "last_check"] self.new_hosts[new_host].duration = n["duration"] self.new_hosts[new_host].attempt = n["attempt"] self.new_hosts[new_host].status_information = n[ "status_information"] self.new_hosts[new_host].site = n["site"] self.new_hosts[new_host].address = n["address"] except ZabbixError: self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # services services = [] # groupids = [] # never used - probably old code zabbix_triggers = [] try: api_version = self.zapi.api_version() except ZabbixAPIException: # FIXME Is there a cleaner way to handle this? I just borrowed # this code from 80 lines ahead. -- AGV # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) print(sys.exc_info()) return Result(result=result, error=error) try: # response = [] # never used - probably old code try: triggers_list = [] hostgroup_ids = [ x['groupid'] for x in self.zapi.hostgroup.get( { 'output': 'extend', 'with_monitored_items': True }) if int(x['internal']) == 0 ] zabbix_triggers = self.zapi.trigger.get({ 'sortfield': 'lastchange', 'withLastEventUnacknowledged': True, 'groupids': hostgroup_ids, "monitored": True, "filter": { 'value': 1 } }) triggers_list = [] for trigger in zabbix_triggers: triggers_list.append(trigger.get('triggerid')) this_trigger = self.zapi.trigger.get({ 'triggerids': triggers_list, 'expandDescription': True, 'output': 'extend', 'select_items': 'extend', # thats for zabbix api 1.8 'selectItems': 'extend', # thats for zabbix api 2.0+ 'expandData': True }) if type(this_trigger) is dict: for triggerid in list(this_trigger.keys()): services.append(this_trigger[triggerid]) this_item = self.zapi.item.get({ 'itemids': [this_trigger[triggerid]['items'][0]['itemid']], 'selectApplications': 'extend' }) last_app = len(this_item[0]['applications']) - 1 this_trigger[triggerid]['application'] = this_item[0][ 'applications'][last_app]['name'] elif type(this_trigger) is list: for trigger in this_trigger: services.append(trigger) this_item = self.zapi.item.get({ 'itemids': trigger['items'][0]['itemid'], 'selectApplications': 'extend' }) # last_app = 0 # use it to get the first application name last_app = len( this_item[0]['applications'] ) - 1 # use it to get the last application name trigger['application'] = this_item[0]['applications'][ last_app]['name'] except ZabbixAPIException: # FIXME Is there a cleaner way to handle this? I just borrowed # this code from 80 lines ahead. -- AGV # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) print(sys.exc_info()) return Result(result=result, error=error) except ZabbixError as e: if e.terminate: return e.result else: service = e.result.content ret = e.result for service in services: # Zabbix probably shows OK services too - kick 'em! # UPDATE Zabbix api 3.0 doesn't but I didn't tried with older # so I left it status = self.statemap.get(service['priority'], service['priority']) if not status == 'OK': if not service['description'].endswith('...'): state = service['description'] else: state = service['items'][0]['lastvalue'] lastcheck = 0 for item in service['items']: if int(item['lastclock']) > lastcheck: lastcheck = int(item['lastclock']) if len(service['comments']) == 0: srvc = service['application'] else: srvc = self.nagiosify_service(service['comments']) n = { 'service': srvc, 'status': status, # 1/1 attempt looks at least like there has been any attempt 'attempt': '1/1', 'duration': HumanReadableDurationFromTimestamp( service['lastchange']), 'status_information': state, 'passiveonly': 'no', 'last_check': time.strftime("%d/%m/%Y %H:%M:%S", time.localtime(lastcheck)), 'notifications': 'yes', 'flapping': 'no', 'site': '', 'command': 'zabbix', 'triggerid': service['triggerid'], } if api_version >= '3.0': n['host'] = self.zapi.host.get({ "output": ["host"], "filter": {}, "triggerids": service['triggerid'] })[0]['host'] else: n['host'] = service['host'] nagitems["services"].append(n) # after collection data in nagitems create objects of its informations # host objects contain service objects if n["host"] not in self.new_hosts: self.new_hosts[n["host"]] = GenericHost() self.new_hosts[n["host"]].name = n["host"] self.new_hosts[n["host"]].status = "UP" self.new_hosts[n["host"]].site = n["site"] self.new_hosts[n["host"]].address = n["host"] # if a service does not exist create its object if n["service"] not in self.new_hosts[n["host"]].services: # workaround for non-existing (or not found) host status flag if n["service"] == "Host is down %s" % (n["host"]): self.new_hosts[n["host"]].status = "DOWN" # also take duration from "service" aka trigger self.new_hosts[n["host"]].duration = n["duration"] else: new_service = n["service"] self.new_hosts[n["host"]].services[ new_service] = GenericService() self.new_hosts[n["host"]].services[ new_service].host = n["host"] self.new_hosts[n["host"]].services[ new_service].name = n["service"] self.new_hosts[n["host"]].services[ new_service].status = n["status"] self.new_hosts[n["host"]].services[ new_service].last_check = n["last_check"] self.new_hosts[n["host"]].services[ new_service].duration = n["duration"] self.new_hosts[n["host"]].services[ new_service].attempt = n["attempt"] self.new_hosts[n["host"]].services[ new_service].status_information = n[ "status_information"] self.new_hosts[n["host"]].services[ new_service].passiveonly = False self.new_hosts[n["host"]].services[ new_service].flapping = False self.new_hosts[n["host"]].services[ new_service].site = n["site"] self.new_hosts[n["host"]].services[ new_service].address = n["host"] self.new_hosts[n["host"]].services[ new_service].command = n["command"] self.new_hosts[n["host"]].services[ new_service].triggerid = n["triggerid"] except (ZabbixError, ZabbixAPIException): # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) print(sys.exc_info()) return Result(result=result, error=error) return ret
def _get_status(self): self.new_hosts = dict() try: events = self._get_all_events() for event in events: event_check = event['check'] event_client = event['client'] new_service = GenericService() new_service.event_id = event['id'] new_service.host = event_client['name'] new_service.name = event_check['name'] # Uchiwa needs the 'dc' for re_check; Sensu does not if 'dc' in event: new_service.site = event['dc'] else: new_service.site = None new_service.status = None try: new_service.status = self.SEVERITY_CODE_TEXT_MAP.get( event_check['status']) except KeyError: new_service.status = 'UNKNOWN' last_check_time = datetime.utcfromtimestamp( int(event['timestamp'])) new_service.last_check = self._aslocaltimestr(last_check_time) new_service.duration = HumanReadableDurationFromTimestamp( int(event['last_state_change'])) new_service.status_information = event_check['output'] # needs a / with a number on either side to work new_service.attempt = str(event['occurrences']) + '/1' new_service.passiveonly = False new_service.notifications_disabled = event['silenced'] new_service.flapping = False new_service.acknowledged = event['silenced'] new_service.scheduled_downtime = False self._insert_service_to_hosts(new_service) except: self.isChecking = False result, error = self.Error(sys.exc_info()) print(traceback.format_exc()) return Result(result=result, error=error) return Result(error="")
def _get_status(self): """ Get status from Checkmk Server """ ret = Result() # Create URLs for the configured filters url_params = '' if self.force_authuser: url_params += "&force_authuser=1" url_params += '&is_host_acknowledged=-1&is_service_acknowledged=-1' url_params += '&is_host_notifications_enabled=-1&is_service_notifications_enabled=-1' url_params += '&is_host_active_checks_enabled=-1&is_service_active_checks_enabled=-1' url_params += '&host_scheduled_downtime_depth=-1&is_in_downtime=-1' try: response = [] try: response = self._get_url(self.urls['api_hosts'] + url_params) except MultisiteError as e: if e.terminate: return e.result if response == '': return Result(result='', error='Login failed', status_code=401) for row in response[1:]: host= dict(list(zip(copy.deepcopy(response[0]), copy.deepcopy(row)))) n = { 'host': host['host'], 'status': self.statemap.get(host['host_state'], host['host_state']), 'last_check': host['host_check_age'], 'duration': host['host_state_age'], 'status_information': html.unescape(host['host_plugin_output'].replace('\n', ' ')), 'attempt': host['host_attempt'], 'site': host['sitename_plain'], 'address': host['host_address'] } # host objects contain service objects if n['host'] not in self.new_hosts: new_host = n['host'] self.new_hosts[new_host] = GenericHost() self.new_hosts[new_host].name = n['host'] self.new_hosts[new_host].server = self.name self.new_hosts[new_host].status = n['status'] self.new_hosts[new_host].last_check = n['last_check'] self.new_hosts[new_host].duration = n['duration'] self.new_hosts[new_host].attempt = n['attempt'] self.new_hosts[new_host].status_information= html.unescape(n['status_information'].replace('\n', ' ')) self.new_hosts[new_host].site = n['site'] self.new_hosts[new_host].address = n['address'] # transisition to Checkmk 1.1.10p2 if 'host_in_downtime' in host: if host['host_in_downtime'] == 'yes': self.new_hosts[new_host].scheduled_downtime = True if 'host_acknowledged' in host: if host['host_acknowledged'] == 'yes': self.new_hosts[new_host].acknowledged = True if 'host_notifications_enabled' in host: if host['host_notifications_enabled'] == 'no': self.new_hosts[new_host].notifications_disabled = True # hard/soft state for later filter evaluation real_attempt, max_attempt = self.new_hosts[new_host].attempt.split('/') if real_attempt != max_attempt: self.new_hosts[new_host].status_type = 'soft' else: self.new_hosts[new_host].status_type = 'hard' del response except: import traceback traceback.print_exc(file=sys.stdout) self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=result, error=error) # Add filters to the url which should only be applied to the service request if conf.filter_services_on_unreachable_hosts == True: # thanks to https://github.com/HenriWahl/Nagstamon/issues/510 url_params += '&hst0=On&hst1=On' # services try: response = [] try: response = self._get_url(self.urls['api_services'] + url_params) except MultisiteError as e: if e.terminate: return e.result else: response = copy.deepcopy(e.result.content) ret = copy.deepcopy(e.result) for row in response[1:]: service = dict(list(zip(copy.deepcopy(response[0]), copy.deepcopy(row)))) n = { 'host': service['host'], 'service': service['service_description'], 'status': self.statemap.get(service['service_state'], service['service_state']), 'last_check': service['svc_check_age'], 'duration': service['svc_state_age'], 'attempt': service['svc_attempt'], 'status_information': html.unescape(service['svc_plugin_output'].replace('\n', ' ')), # Checkmk passive services can be re-scheduled by using the Checkmk service 'passiveonly': service['svc_is_active'] == 'no' and not service['svc_check_command'].startswith('check_mk'), 'flapping': service['svc_flapping'] == 'yes', 'site': service['sitename_plain'], 'address': service['host_address'], 'command': service['svc_check_command'], } # host objects contain service objects if n['host'] not in self.new_hosts: self.new_hosts[n['host']] = GenericHost() self.new_hosts[n['host']].name = n['host'] self.new_hosts[n['host']].status = 'UP' self.new_hosts[n['host']].site = n['site'] self.new_hosts[n['host']].address = n['address'] # if a service does not exist create its object if n['service'] not in self.new_hosts[n['host']].services: new_service = n['service'] self.new_hosts[n['host']].services[new_service] = GenericService() self.new_hosts[n['host']].services[new_service].host = n['host'] self.new_hosts[n['host']].services[new_service].server = self.name self.new_hosts[n['host']].services[new_service].name = n['service'] self.new_hosts[n['host']].services[new_service].status = n['status'] self.new_hosts[n['host']].services[new_service].last_check = n['last_check'] self.new_hosts[n['host']].services[new_service].duration = n['duration'] self.new_hosts[n['host']].services[new_service].attempt = n['attempt'] self.new_hosts[n['host']].services[new_service].status_information = n['status_information'].strip() self.new_hosts[n['host']].services[new_service].passiveonly = n['passiveonly'] self.new_hosts[n['host']].services[new_service].flapping = n['flapping'] self.new_hosts[n['host']].services[new_service].site = n['site'] self.new_hosts[n['host']].services[new_service].address = n['address'] self.new_hosts[n['host']].services[new_service].command = n['command'] # transistion to Checkmk 1.1.10p2 if 'svc_in_downtime' in service: if service['svc_in_downtime'] == 'yes': self.new_hosts[n['host']].services[new_service].scheduled_downtime = True if 'svc_acknowledged' in service: if service['svc_acknowledged'] == 'yes': self.new_hosts[n['host']].services[new_service].acknowledged = True if 'svc_flapping' in service: if service['svc_flapping'] == 'yes': self.new_hosts[n['host']].services[new_service].flapping = True if 'svc_notifications_enabled' in service: if service['svc_notifications_enabled'] == 'no': self.new_hosts[n['host']].services[new_service].notifications_disabled = True # hard/soft state for later filter evaluation real_attempt, max_attempt = self.new_hosts[n['host']].services[new_service].attempt.split('/') if real_attempt != max_attempt: self.new_hosts[n['host']].services[new_service].status_type = 'soft' else: self.new_hosts[n['host']].services[new_service].status_type = 'hard' del response except: import traceback traceback.print_exc(file=sys.stdout) # set checking flag back to False self.isChecking = False result, error = self.Error(sys.exc_info()) return Result(result=copy.deepcopy(result), error=copy.deepcopy(error)) del url_params return ret
def _parse_event_to_service(self, event): service = GenericService() namespace_host = event['entity']['metadata'][ 'namespace'] + NAMESPACE_SEPARATOR + event['entity']['metadata'][ 'name'] service.hostid = namespace_host service.host = namespace_host service.name = event['check']['metadata']['name'] service.status = SensuGoAPI.parse_check_status( event['check']['status']) service.last_check = datetime.fromtimestamp(int( event['timestamp'])).strftime('%Y-%m-%d %H:%M:%S') service.duration = self._duration_since(event['check']['last_ok']) service.status_information = event['check']['output'] service.acknowledged = event['check']['is_silenced'] service.notifications_disabled = event['check']['is_silenced'] service.attempt = str(event['check']['occurrences']) + '/1' service.passiveonly = event['check']['publish'] service.flapping = False service.scheduled_downtime = False return service