Exemple #1
0
 def _login(self):
     try:
         self.zapi = ZabbixAPI(server=self.monitor_url, path="", log_level=0)
         self.zapi.login(self.username, self.password)
     except ZabbixAPIException:
         result, error = self.Error(sys.exc_info())
         return Result(result=result, error=error)
Exemple #2
0
 def _login(self):
     try:
         # create ZabbixAPI if not yet created
         if self.zapi is None:
             self.zapi = ZabbixAPI(server=self.monitor_url, path="", log_level=self.log_level, validate_certs=self.validate_certs)
         # login if not yet logged in, or if login was refused previously
         if not self.zapi.logged_in():
             self.zapi.login(self.username, self.password)
     except ZabbixAPIException:
         result, error = self.Error(sys.exc_info())
         return Result(result=result, error=error)
Exemple #3
0
 def _login(self):
     try:
         self.zapi = ZabbixAPI(server=self.monitor_url, path="", log_level=0)
         self.zapi.login(self.username, self.password)
     except ZabbixAPIException:
         result, error = self.Error(sys.exc_info())
         return Result(result=result, error=error)
Exemple #4
0
class ZabbixServer(GenericServer):
    """
       special treatment for Zabbix, taken from Check_MK Multisite JSON API
    """
    TYPE = 'Zabbix'
    zapi = None

    def __init__(self, **kwds):
        GenericServer.__init__(self, **kwds)

        # Prepare all urls needed by nagstamon -
        self.urls = {}
        # self.statemap = {}
        self.statemap = {
            'UNREACH': 'UNREACHABLE',
            'CRIT': 'CRITICAL',
            'WARN': 'WARNING',
            'UNKN': 'UNKNOWN',
            'PEND': 'PENDING',
            '0': 'OK',
            '1': 'UNKNOWN',
            '2': 'WARNING',
            '5': 'CRITICAL',
            '3': 'WARNING',
            '4': 'CRITICAL'
        }

        # Entries for monitor default actions in context menu
        self.MENU_ACTIONS = ["Recheck", "Acknowledge", "Downtime"]
        self.username = conf.servers[self.get_name()].username
        self.password = conf.servers[self.get_name()].password

    def _login(self):
        try:
            self.zapi = ZabbixAPI(server=self.monitor_url,
                                  path="",
                                  log_level=0)
            self.zapi.login(self.username, self.password)
        except ZabbixAPIException:
            result, error = self.Error(sys.exc_info())
            return Result(result=result, error=error)

    """
    def init_HTTP(self):

        # not necessary to be initialized wit hevery HTTP request
        self.statemap = {
            'UNREACH': 'UNREACHABLE',
            'CRIT': 'CRITICAL',
            'WARN': 'WARNING',
            'UNKN': 'UNKNOWN',
            'PEND': 'PENDING',
            '0': 'OK',
            '1': 'UNKNOWN',
            '2': 'WARNING',
            '5': 'CRITICAL',
            '3': 'WARNING',
            '4': 'CRITICAL'}
        GenericServer.init_HTTP(self)
    """

    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 _open_browser(self, url):
        webbrowser_open(url)

        if conf.debug_mode is True:
            self.Debug(server=self.get_name(), debug="Open web page " + url)

    def open_services(self):
        self._open_browser(self.urls['human_services'])

    def open_hosts(self):
        self._open_browser(self.urls['human_hosts'])

    def open_monitor(self, host, service=""):
        """
            open monitor from treeview context menu
        """

        if service == "":
            url = self.urls['human_host'] + urllib.parse.urlencode({
                'x':
                'site=' + self.hosts[host].site + '&host=' + host
            }).replace('x=', '%26')
        else:
            url = self.urls['human_service'] + urllib.parse.urlencode({
                'x':
                'site=' + self.hosts[host].site + '&host=' + host +
                '&service=' + service
            }).replace('x=', '%26')

        if conf.debug_mode is True:
            self.Debug(server=self.get_name(),
                       host=host,
                       service=service,
                       debug="Open host/service monitor web page " + url)
        webbrowser_open(url)

    # def GetHost(self, host):
    # """
    # find out ip or hostname of given host to access hosts/devices which do not appear in DNS but
    # have their ip saved in Nagios
    # """

    # # the fasted method is taking hostname as used in monitor
    # if conf.connect_by_host is True:
    # return Result(result=host)

    # ip = ""

    # try:
    # if host in self.hosts:
    # ip = self.hosts[host].address
    # if conf.debug_mode is True:
    # self.Debug(server=self.get_name(), host=host, debug="IP of %s:" % host + " " + ip)

    # if conf.connect_by_dns is True:
    # try:
    # address = socket.gethostbyaddr(ip)[0]
    # except socket.herror:
    # address = ip
    # else:
    # address = ip
    # except ZabbixError:
    # result, error = self.Error(sys.exc_info())
    # return Result(result=result, error=error)

    # return Result(result=address)

    def _set_recheck(self, host, service):
        pass

    def get_start_end(self, host):
        return time.strftime("%Y-%m-%d %H:%M"), time.strftime(
            "%Y-%m-%d %H:%M", time.localtime(time.time() + 7200))

    def _action(self, site, host, service, specific_params):
        params = {
            'site': self.hosts[host].site,
            'host': host,
        }
        params.update(specific_params)

        if self.zapi is None:
            self._login()
        events = []
        for e in self.zapi.event.get({
                'triggerids': params['triggerids'],
                # from zabbix 2.2 should be used "objectids" that instead of "triggerids"
                'objectids': params['triggerids'],
                'hide_unknown': True,
                'sortfield': 'clock',
                'sortorder': 'DESC'
        }):
            # stop at first event in "OK" status
            if e['value'] == '0':
                break
            events.append(e['eventid'])
        self.zapi.event.acknowledge({
            'eventids': events,
            'message': params['message']
        })

    def _set_downtime(self, host, service, author, comment, fixed, start_time,
                      end_time, hours, minutes):
        pass

    def _set_acknowledge(self,
                         host,
                         service,
                         author,
                         comment,
                         sticky,
                         notify,
                         persistent,
                         all_services=[]):
        triggerid = self.hosts[host].services[service].triggerid
        p = {
            'message': '%s: %s' % (author, comment),
            'triggerids': [triggerid],
        }
        self._action(self.hosts[host].site, host, service, p)

        # acknowledge all services on a host when told to do so
        for s in all_services:
            self._action(self.hosts[host].site, host, s, p)

    def nagiosify_service(self, service):
        """
            next dirty workaround to get Zabbix events to look Nagios-esque
        """
        if (" on " or " is ") in service:
            for separator in [" on ", " is "]:
                service = service.split(separator)[0]
        return (service)
class ZabbixServer(GenericServer):

    """
       special treatment for Zabbix, taken from Check_MK Multisite JSON API
    """
    TYPE = 'Zabbix'
    zapi = None
    if conf.debug_mode is True:
        log_level = logging.DEBUG
    else:
        log_level = logging.WARNING
    log.setLevel(log_level)

    def __init__(self, **kwds):
        GenericServer.__init__(self, **kwds)

        # Prepare all urls needed by nagstamon -
        self.urls = {}
        # self.statemap = {}
        self.statemap = {
            'UNREACH': 'UNREACHABLE',
            'CRIT': 'CRITICAL',
            'WARN': 'WARNING',
            'UNKN': 'UNKNOWN',
            'PEND': 'PENDING',
            '0': 'OK',
            '1': 'INFORMATION',
            '2': 'WARNING',
            '3': 'AVERAGE',
            '4': 'HIGH',
            '5': 'DISASTER'}

        # Entries for monitor default actions in context menu
        self.MENU_ACTIONS = ["Acknowledge", "Downtime"]
        # URLs for browser shortlinks/buttons on popup window
        self.BROWSER_URLS = {'monitor': '$MONITOR$',
                             'hosts': '$MONITOR-CGI$/hosts.php?ddreset=1',
                             'services': '$MONITOR-CGI$/zabbix.php?action=problem.view&fullscreen=0&page=1&filter_show=3&filter_set=1',
                             'history':  '$MONITOR-CGI$/zabbix.php?action=problem.view&fullscreen=0&page=1&filter_show=2&filter_set=1'}

        self.username = conf.servers[self.get_name()].username
        self.password = conf.servers[self.get_name()].password
        self.ignore_cert = conf.servers[self.get_name()].ignore_cert
        self.use_description_name_service = conf.servers[self.get_name()].use_description_name_service
        if self.ignore_cert is True:
            self.validate_certs = False
        else:
            self.validate_certs = True

    def _login(self):
        try:
            self.zapi = ZabbixAPI(server=self.monitor_url, path="", log_level=self.log_level,
                                  validate_certs=self.validate_certs)
            self.zapi.login(self.username, self.password)
        except ZabbixAPIException:
            result, error = self.Error(sys.exc_info())
            return Result(result=result, error=error)

    def getLastApp(self, this_item):
        if len(this_item) > 0:
            last_app = len(this_item[0]['applications']) - 1  # use it to get the last application name
            if last_app > -1:
                return "%s" % this_item[0]['applications'][last_app]['name']
            else:
                return "NO APP"
        else:
            return "Web scenario"

    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 _open_browser(self, url):
        webbrowser_open(url)

        if conf.debug_mode is True:
            self.Debug(server=self.get_name(), debug="Open web page " + url)

    def open_services(self):
        self._open_browser(self.urls['human_services'])

    def open_hosts(self):
        self._open_browser(self.urls['human_hosts'])

    def open_monitor(self, host, service=""):
        """
            open monitor from treeview context menu
        """

        if service == "":
            url = self.urls['human_host'] + urllib.parse.urlencode(
                {'x': 'site=' + self.hosts[host].site + '&host=' + host}).replace('x=', '%26')
        else:
            url = self.urls['human_service'] + urllib.parse.urlencode(
                {'x': 'site=' + self.hosts[host].site + '&host=' + host + '&service=' + service}).replace('x=', '%26')

        if conf.debug_mode is True:
            self.Debug(server=self.get_name(), host=host, service=service,
                       debug="Open host/service monitor web page " + url)
        webbrowser_open(url)

    # Disable set_recheck (nosense in Zabbix)
    def set_recheck(self, info_dict):
        pass

    def _set_acknowledge(self, host, service, author, comment, sticky, notify, persistent, all_services=[]):
        if conf.debug_mode is True:
            self.Debug(server=self.get_name(), debug="Set Acknowledge Host: " + host + " Service: " + service + " Sticky: " + str(sticky) + " persistent:" + str(persistent) +  " All services: " + str(all_services))

        # Service column is storing current trigger id
        triggerids = []
        triggerids.append(service)
        
        # acknowledge all problems (column services) on a host when told to do so
        for s in all_services:
            triggerids.append(s)

        if self.zapi is None:
            self._login()

        for triggerid in triggerids:
            events = []
            for e in self.zapi.event.get({'triggerids': [triggerid],
                                          # from zabbix 2.2 should be used "objectids" instead of "triggerids"
                                          'objectids': [triggerid],
#                                          'acknowledged': False,
                                          'sortfield': 'clock',
                                          'sortorder': 'DESC'}):
                # Get only current event status, but retrieving first row ordered by clock DESC
                
                # If event status is not "OK" (Still is an active problem), mark event to acknowledge/close
                if e['value'] != '0':
                    events.append(e['eventid'])
                # Only take care of newest event, discard all next
                break
                
            # If events pending of acknowledge, execute ack
            if len(events) > 0:
                # If sticky is set then close only current event
                close = 1 if (triggerid == service and sticky is True) else 0
                if conf.debug_mode is True:
                    self.Debug(server=self.get_name(), debug="Events to acknowledge: " + str(events) + " Close: " + str(close))
                self.zapi.event.acknowledge({'eventids': events, 'message': '%s: %s' % (author, comment), 'action': close})
 
    def _set_downtime(self, hostname, service, author, comment, fixed, start_time, end_time, hours, minutes):

        hostids = [ self.hosts[hostname].hostid ]
        
        date  = datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M")
        stime = time.mktime(date.timetuple())

        date  = datetime.datetime.strptime(end_time, "%Y-%m-%d %H:%M")
        etime = time.mktime(date.timetuple())
        
        if conf.debug_mode is True:
            self.Debug(server=self.get_name(), debug="Downtime for " + hostname + "[" + str(hostids[0]) + "] stime:" + str(stime) + " etime:" + str(etime))
            
        self.zapi.maintenance.create({'hostids': hostids, 'name': comment, 'description': author, 'active_since': stime, 'active_till': etime, 'maintenance_type' : 0, "timeperiods": [
            { "timeperiod_type": 0, "start_date": stime, "period": etime - stime }
        ]})

    def get_start_end(self, host):
        return time.strftime("%Y-%m-%d %H:%M"), time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time() + 7200))

    def GetHost(self, host):
        """
            find out ip or hostname of given host to access hosts/devices which do not appear in DNS but
            have their ip saved in Nagios
        """

        # the fasted method is taking hostname as used in monitor
        if conf.connect_by_host is True:
            return Result(result=host)

        ip = ""
        address = host;

        try:
            if host in self.hosts:
                ip = self.hosts[host].address
            if conf.debug_mode is True:
                self.Debug(server=self.get_name(), host=host, debug="IP of %s:" % host + " " + ip)

            if conf.connect_by_dns is True:
                try:
                    address = socket.gethostbyaddr(ip)[0]
                except socket.herror:
                    address = ip
            else:
                address = ip
        except ZabbixError:
            result, error = self.Error(sys.exc_info())
            return Result(result=result, error=error)

        return Result(result=address)

    def nagiosify_service(self, service):
        """
            next dirty workaround to get Zabbix events to look Nagios-esque
        """
        if (" on " or " is ") in service:
            for separator in [" on ", " is "]:
                service = service.split(separator)[0]
        return(service)
Exemple #6
0
class ZabbixServer(GenericServer):
    """
       special treatment for Zabbix, taken from Check_MK Multisite JSON API
    """
    TYPE = 'Zabbix'
    zapi = None

    # A Monitor CGI URL is not necessary so hide it in settings
    # autologin is used only by Centreon
    DISABLED_CONTROLS = ["label_monitor_cgi_url",
                         "input_entry_monitor_cgi_url",
                         "input_checkbutton_use_autologin",
                         "label_autologin_key",
                         "input_entry_autologin_key",
                         "input_checkbutton_use_display_name_host",
                         "input_checkbutton_use_display_name_service"]


    def __init__(self, **kwds):
        GenericServer.__init__(self, **kwds)

        # Prepare all urls needed by nagstamon - 
        self.urls = {}
        self.statemap = {}

        # Entries for monitor default actions in context menu
        self.MENU_ACTIONS = ["Recheck", "Acknowledge", "Downtime"]
        self.username = self.conf.servers[self.get_name()].username
        self.password = self.conf.servers[self.get_name()].password


    def _login(self):
        try:
            self.zapi = ZabbixAPI(server=self.monitor_url, path="", log_level=0)
            self.zapi.login(self.username, self.password)
        except ZabbixAPIException:
            result, error = self.Error(sys.exc_info())
            return Result(result=result, error=error)


    def init_HTTP(self):

        self.statemap = {
            'UNREACH': 'UNREACHABLE',
            'CRIT': 'CRITICAL',
            'WARN': 'WARNING',
            'UNKN': 'UNKNOWN',
            'PEND': 'PENDING',
            '0': 'OK',
            '1': 'UNKNOWN',
            '2': 'WARNING',
            '5': 'CRITICAL',
            '3': 'WARNING',
            '4': 'CRITICAL'}
        GenericServer.init_HTTP(self)


    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:
                # johncan
                # self.Debug(str(host))
                duration = int(time.time()) - int(host['errors_from'])
                n = {
                    'host': host['host'],
                    'status': self.statemap.get(host['available'], host['available']),
                    'last_check': 'n/a',
                    'duration': Actions.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"]
                    # transisition to Check_MK 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

        except ZabbixError:
            self.isChecking = False
            result, error = self.Error(sys.exc_info())
            return Result(result=result, error=error)

        # services
        services = []
        groupids = []
        zabbix_triggers = []
        api_version = self.zapi.api_version()
        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(',')
                    # johncan
                    #self.Debug(str(group_list))
                    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]
                    # johncan
                    # self.Debug(str(hostgroup_ids))
                    # johncan
                    # hostgroup_ids = [7]
                    zabbix_triggers = self.zapi.trigger.get(
                        {'sortfield': 'lastchange', 'withUnacknowledgedEvents': True, 'groupids': hostgroup_ids,
                         "monitored": True, "filter": {'value': 1}})
                else:
                    zabbix_triggers = self.zapi.trigger.get(
                        {'sortfield': 'lastchange', 'withUnacknowledgedEvents': 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}
                )
                # johncan
                self.Debug(str(this_trigger))
                if type(this_trigger) is dict:
                    for triggerid in this_trigger.keys():
                        services.append(this_trigger[triggerid])
                elif type(this_trigger) is list:
                    for trigger in this_trigger:
                        services.append(trigger)

            except ZabbixError, 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:
                # johncan
                # self.Debug(str(service))
                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 have been any attempt
                    'attempt': '1/1',
                    'duration': Actions.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:
                    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 = 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["host"]
                    self.new_hosts[n["host"]].services[new_service].command = n["command"]
                    self.new_hosts[n["host"]].services[new_service].triggerid = n["triggerid"]

                    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_is_active' in service:
                        if service['svc_is_active'] == 'no':
                            self.new_hosts[n["host"]].services[new_service].passiveonly = True
                    if 'svc_flapping' in service:
                        if service['svc_flapping'] == 'yes':
                            self.new_hosts[n["host"]].services[new_service].flapping = True
        except ZabbixError:
            # 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)
Exemple #7
0
class ZabbixServer(GenericServer):
    """
       special treatment for Zabbix, taken from Check_MK Multisite JSON API
    """

    TYPE = "Zabbix"
    zapi = None

    # A Monitor CGI URL is not necessary so hide it in settings
    # autologin is used only by Centreon
    DISABLED_CONTROLS = [
        "label_monitor_cgi_url",
        "input_entry_monitor_cgi_url",
        "input_checkbutton_use_autologin",
        "label_autologin_key",
        "input_entry_autologin_key",
        "input_checkbutton_use_display_name_host",
        "input_checkbutton_use_display_name_service",
    ]

    def __init__(self, **kwds):
        GenericServer.__init__(self, **kwds)

        # Prepare all urls needed by nagstamon -
        self.urls = {}
        self.statemap = {}

        # Entries for monitor default actions in context menu
        self.MENU_ACTIONS = ["Recheck", "Acknowledge", "Downtime"]
        self.username = self.conf.servers[self.get_name()].username
        self.password = self.conf.servers[self.get_name()].password

    def _login(self):
        try:
            self.zapi = ZabbixAPI(server=self.monitor_url, path="", log_level=0)
            self.zapi.login(self.username, self.password)
        except ZabbixAPIException:
            result, error = self.Error(sys.exc_info())
            return Result(result=result, error=error)

    def init_HTTP(self):
        # Fix eventually missing tailing "/" in url
        self.statemap = {
            "UNREACH": "UNREACHABLE",
            "CRIT": "CRITICAL",
            "WARN": "WARNING",
            "UNKN": "UNKNOWN",
            "PEND": "PENDING",
            "0": "OK",
            "1": "UNKNOWN",
            "2": "WARNING",
            "5": "CRITICAL",
            "3": "WARNING",
            "4": "CRITICAL",
        }
        GenericServer.init_HTTP(self)

    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:
                # johncan
                # self.Debug(str(host))
                duration = int(time.time()) - int(host["errors_from"])
                n = {
                    "host": host["host"],
                    "status": self.statemap.get(host["available"], host["available"]),
                    "last_check": int(time.time()),
                    "duration": duration,
                    "status_information": host["error"],
                    "attempt": "0/0",
                    "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"]
                    # transisition to Check_MK 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

        except ZabbixError:
            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 str(self.conf.filter_services_on_unreachable_hosts) == "True":
        #    url_params += '&hst2=0'

        # services
        services = []
        groupids = []
        zabbix_triggers = []
        api_version = self.zapi.api_version()
        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(",")
                    # johncan
                    # self.Debug(str(group_list))
                    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
                    ]
                    # johncan
                    # self.Debug(str(hostgroup_ids))
                    # johncan
                    # hostgroup_ids = [7]
                    zabbix_triggers = self.zapi.trigger.get(
                        {
                            "sortfield": "lastchange",
                            "withUnacknowledgedEvents": True,
                            "groupids": hostgroup_ids,
                            "monitored": True,
                            "filter": {"value": 1},
                        }
                    )
                else:
                    zabbix_triggers = self.zapi.trigger.get(
                        {
                            "sortfield": "lastchange",
                            "withUnacknowledgedEvents": 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,
                    }
                )
                # johncan
                # self.Debug(str(this_trigger))
                if type(this_trigger) is dict:
                    for triggerid in this_trigger.keys():
                        services.append(this_trigger[triggerid])
                elif type(this_trigger) is list:
                    for trigger in this_trigger:
                        services.append(trigger)

            except ZabbixError, 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:
                # johncan
                # self.Debug(str(service))
                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"]),
                    "attempt": "0/0",
                    "duration": 60,
                    "status_information": state,
                    "passiveonly": "no",
                    "last_check": datetime.datetime.fromtimestamp(int(service["lastchange"])),
                    "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:
                    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 = 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["host"]
                    self.new_hosts[n["host"]].services[new_service].command = n["command"]
                    self.new_hosts[n["host"]].services[new_service].triggerid = n["triggerid"]

                    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_is_active" in service:
                        if service["svc_is_active"] == "no":
                            self.new_hosts[n["host"]].services[new_service].passiveonly = True
                    if "svc_flapping" in service:
                        if service["svc_flapping"] == "yes":
                            self.new_hosts[n["host"]].services[new_service].flapping = True
        except ZabbixError:
            # 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)
class ZabbixProblemBasedServer(GenericServer):

    TYPE = 'ZabbixProblemBased'
    zapi = None

    if conf.debug_mode is True:
        log_level = logging.DEBUG
    else:
        log_level = logging.WARNING

    def __init__(self, **kwds):
        GenericServer.__init__(self, **kwds)

        self.statemap = {
            '0': 'OK',
            '1': 'INFORMATION',
            '2': 'WARNING',
            '3': 'AVERAGE',
            '4': 'HIGH',
            '5': 'DISASTER'}

        # Entries for monitor default actions in context menu
        self.MENU_ACTIONS = []
        # URLs for browser shortlinks/buttons on popup window
        self.BROWSER_URLS = {'monitor': '$MONITOR$',
                             'hosts': '$MONITOR-CGI$/hosts.php?ddreset=1',
                             'services': '$MONITOR-CGI$/zabbix.php?action=problem.view&fullscreen=0&page=1&filter_show=3&filter_set=1',
                             'history':  '$MONITOR-CGI$/zabbix.php?action=problem.view&fullscreen=0&page=1&filter_show=2&filter_set=1'}

        self.username = conf.servers[self.get_name()].username
        self.password = conf.servers[self.get_name()].password
        self.ignore_cert = conf.servers[self.get_name()].ignore_cert
        self.validate_certs = not self.ignore_cert


    def _login(self):
        try:
            # create ZabbixAPI if not yet created
            if self.zapi is None:
                self.zapi = ZabbixAPI(server=self.monitor_url, path="", log_level=self.log_level, validate_certs=self.validate_certs)
            # login if not yet logged in, or if login was refused previously
            if not self.zapi.logged_in():
                self.zapi.login(self.username, self.password)
        except ZabbixAPIException:
            result, error = self.Error(sys.exc_info())
            return Result(result=result, error=error)

    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()

    # Disable set_recheck (nosense in Zabbix)
    def set_recheck(self, info_dict):
        pass
Exemple #9
0
class ZabbixServer(GenericServer):
    """
       special treatment for Zabbix, taken from Check_MK Multisite JSON API
    """
    TYPE = 'Zabbix'
    zapi = None

    def __init__(self, **kwds):
        GenericServer.__init__(self, **kwds)

        # Prepare all urls needed by nagstamon - 
        self.urls = {}
        self.statemap = {}

        # Entries for monitor default actions in context menu
        self.MENU_ACTIONS = ["Recheck", "Acknowledge", "Downtime"]
        self.username = conf.servers[self.get_name()].username
        self.password = conf.servers[self.get_name()].password


    def _login(self):
        try:
            self.zapi = ZabbixAPI(server=self.monitor_url, path="", log_level=0)
            self.zapi.login(self.username, self.password)
        except ZabbixAPIException:
            result, error = self.Error(sys.exc_info())
            return Result(result=result, error=error)


    def init_HTTP(self):

        self.statemap = {
            'UNREACH': 'UNREACHABLE',
            'CRIT': 'CRITICAL',
            'WARN': 'WARNING',
            'UNKN': 'UNKNOWN',
            'PEND': 'PENDING',
            '0': 'OK',
            '1': 'UNKNOWN',
            '2': 'WARNING',
            '5': 'CRITICAL',
            '3': 'WARNING',
            '4': 'CRITICAL'}
        GenericServer.init_HTTP(self)


    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 = {
                    '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'],
                }

                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"]

                        # 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 _open_browser(self, url):
        webbrowser.open(url)

        if conf.debug_mode == True:
            self.Debug(server=self.get_name(), debug="Open web page " + url)


    def open_services(self):
        self._open_browser(self.urls['human_services'])


    def open_hosts(self):
        self._open_browser(self.urls['human_hosts'])


    def open_monitor(self, host, service=""):
        """
        open monitor from treeview context menu
        """

        if service == "":
            url = self.urls['human_host'] + urllib.parse.urlencode(
                {'x': 'site=' + self.hosts[host].site + '&host=' + host}).replace('x=', '%26')
        else:
            url = self.urls['human_service'] + urllib.parse.urlencode(
                {'x': 'site=' + self.hosts[host].site + '&host=' + host + '&service=' + service}).replace('x=', '%26')

        if conf.debug_mode == True:
            self.Debug(server=self.get_name(), host=host, service=service,
                       debug="Open host/service monitor web page " + url)
        webbrowser.open(url)


    def GetHost(self, host):
        """
        find out ip or hostname of given host to access hosts/devices which do not appear in DNS but
        have their ip saved in Nagios
        """

        # the fasted method is taking hostname as used in monitor
        if conf.connect_by_host == True:
            return Result(result=host)

        ip = ""

        try:
            if host in self.hosts:
                ip = self.hosts[host].address

            if conf.debug_mode == True:
                self.Debug(server=self.get_name(), host=host, debug="IP of %s:" % host + " " + ip)

            if conf.connect_by_dns == True:
                try:
                    address = socket.gethostbyaddr(ip)[0]
                except:
                    address = ip
            else:
                address = ip
        except ZabbixError:
            result, error = self.Error(sys.exc_info())
            return Result(result=result, error=error)

        return Result(result=address)

    def _set_recheck(self, host, service):
        pass

    def get_start_end(self, host):
        return time.strftime("%Y-%m-%d %H:%M"), time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time() + 7200))

    def _action(self, site, host, service, specific_params):
        params = {
            'site': self.hosts[host].site,
            'host': host,
        }
        params.update(specific_params)

        if self.zapi is None:
            self._login()
        events = []
        for e in self.zapi.event.get({'triggerids': params['triggerids'],
                                      'hide_unknown': True,
                                      'sortfield': 'clock',
                                      'sortorder': 'desc'}):
            events.append(e['eventid'])
        self.zapi.event.acknowledge({'eventids': events, 'message': params['message']})

    def _set_downtime(self, host, service, author, comment, fixed, start_time, end_time, hours, minutes):
        pass

    def _set_acknowledge(self, host, service, author, comment, sticky, notify, persistent, all_services=[]):
        triggerid = self.hosts[host].services[service].triggerid
        p = {
            'message': '%s: %s' % (author, comment),
            'triggerids': [triggerid],
        }
        self._action(self.hosts[host].site, host, service, p)

        # acknowledge all services on a host when told to do so
        for s in all_services:
            self._action(self.hosts[host].site, host, s, p)
Exemple #10
0
class ZabbixServer(GenericServer):
    """
       special treatment for Zabbix, taken from Check_MK Multisite JSON API
    """
    TYPE = 'Zabbix'
    zapi = None

    def __init__(self, **kwds):
        GenericServer.__init__(self, **kwds)

        # Prepare all urls needed by nagstamon -
        self.urls = {}
        self.statemap = {}

        # Entries for monitor default actions in context menu
        self.MENU_ACTIONS = ["Recheck", "Acknowledge", "Downtime"]
        self.username = conf.servers[self.get_name()].username
        self.password = conf.servers[self.get_name()].password

    def _login(self):
        try:
            self.zapi = ZabbixAPI(server=self.monitor_url,
                                  path="",
                                  log_level=0)
            self.zapi.login(self.username, self.password)
        except ZabbixAPIException:
            result, error = self.Error(sys.exc_info())
            return Result(result=result, error=error)

    def init_HTTP(self):

        self.statemap = {
            'UNREACH': 'UNREACHABLE',
            'CRIT': 'CRITICAL',
            'WARN': 'WARNING',
            'UNKN': 'UNKNOWN',
            'PEND': 'PENDING',
            '0': 'OK',
            '1': 'UNKNOWN',
            '2': 'WARNING',
            '5': 'CRITICAL',
            '3': 'WARNING',
            '4': 'CRITICAL'
        }
        GenericServer.init_HTTP(self)

    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 _open_browser(self, url):
        webbrowser.open(url)

        if conf.debug_mode == True:
            self.Debug(server=self.get_name(), debug="Open web page " + url)

    def open_services(self):
        self._open_browser(self.urls['human_services'])

    def open_hosts(self):
        self._open_browser(self.urls['human_hosts'])

    def open_monitor(self, host, service=""):
        """
        open monitor from treeview context menu
        """

        if service == "":
            url = self.urls['human_host'] + urllib.parse.urlencode({
                'x':
                'site=' + self.hosts[host].site + '&host=' + host
            }).replace('x=', '%26')
        else:
            url = self.urls['human_service'] + urllib.parse.urlencode({
                'x':
                'site=' + self.hosts[host].site + '&host=' + host +
                '&service=' + service
            }).replace('x=', '%26')

        if conf.debug_mode == True:
            self.Debug(server=self.get_name(),
                       host=host,
                       service=service,
                       debug="Open host/service monitor web page " + url)
        webbrowser.open(url)

    def GetHost(self, host):
        """
        find out ip or hostname of given host to access hosts/devices which do not appear in DNS but
        have their ip saved in Nagios
        """

        # the fasted method is taking hostname as used in monitor
        if conf.connect_by_host == True:
            return Result(result=host)

        ip = ""

        try:
            if host in self.hosts:
                ip = self.hosts[host].address

            if conf.debug_mode == True:
                self.Debug(server=self.get_name(),
                           host=host,
                           debug="IP of %s:" % host + " " + ip)

            if conf.connect_by_dns == True:
                try:
                    address = socket.gethostbyaddr(ip)[0]
                except:
                    address = ip
            else:
                address = ip
        except ZabbixError:
            result, error = self.Error(sys.exc_info())
            return Result(result=result, error=error)

        return Result(result=address)

    def _set_recheck(self, host, service):
        pass

    def get_start_end(self, host):
        return time.strftime("%Y-%m-%d %H:%M"), time.strftime(
            "%Y-%m-%d %H:%M", time.localtime(time.time() + 7200))

    def _action(self, site, host, service, specific_params):
        params = {
            'site': self.hosts[host].site,
            'host': host,
        }
        params.update(specific_params)

        if self.zapi is None:
            self._login()
        events = []
        for e in self.zapi.event.get({
                'triggerids': params['triggerids'],
                'hide_unknown': True,
                'sortfield': 'clock',
                'sortorder': 'desc'
        }):
            events.append(e['eventid'])
        self.zapi.event.acknowledge({
            'eventids': events,
            'message': params['message']
        })

    def _set_downtime(self, host, service, author, comment, fixed, start_time,
                      end_time, hours, minutes):
        pass

    def _set_acknowledge(self,
                         host,
                         service,
                         author,
                         comment,
                         sticky,
                         notify,
                         persistent,
                         all_services=[]):
        triggerid = self.hosts[host].services[service].triggerid
        p = {
            'message': '%s: %s' % (author, comment),
            'triggerids': [triggerid],
        }
        self._action(self.hosts[host].site, host, service, p)

        # acknowledge all services on a host when told to do so
        for s in all_services:
            self._action(self.hosts[host].site, host, s, p)
Exemple #11
0
class ZabbixServer(GenericServer):
    """
       special treatment for Zabbix, taken from Check_MK Multisite JSON API
    """
    TYPE = 'Zabbix'
    zapi = None

    # A Monitor CGI URL is not necessary so hide it in settings
    # autologin is used only by Centreon
    DISABLED_CONTROLS = [
        "label_monitor_cgi_url", "input_entry_monitor_cgi_url",
        "input_checkbutton_use_autologin", "label_autologin_key",
        "input_entry_autologin_key", "input_checkbutton_use_display_name_host",
        "input_checkbutton_use_display_name_service"
    ]

    def __init__(self, **kwds):
        GenericServer.__init__(self, **kwds)

        # Prepare all urls needed by nagstamon -
        self.urls = {}
        self.statemap = {}

        # Entries for monitor default actions in context menu
        self.MENU_ACTIONS = ["Recheck", "Acknowledge", "Downtime"]
        self.username = self.conf.servers[self.get_name()].username
        self.password = self.conf.servers[self.get_name()].password

    def _login(self):
        try:
            self.zapi = ZabbixAPI(server=self.monitor_url,
                                  path="",
                                  log_level=0)
            self.zapi.login(self.username, self.password)
        except ZabbixAPIException:
            result, error = self.Error(sys.exc_info())
            return Result(result=result, error=error)

    def init_HTTP(self):

        self.statemap = {
            'UNREACH': 'UNREACHABLE',
            'CRIT': 'CRITICAL',
            'WARN': 'WARNING',
            'UNKN': 'UNKNOWN',
            'PEND': 'PENDING',
            '0': 'OK',
            '1': 'UNKNOWN',
            '2': 'WARNING',
            '5': 'CRITICAL',
            '3': 'WARNING',
            '4': 'CRITICAL'
        }
        GenericServer.init_HTTP(self)

    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':
                    Actions.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',
                        'withUnacknowledgedEvents':
                        True,
                        'groupids':
                        hostgroup_ids,
                        "monitored":
                        True,
                        "filter": {
                            'value': 1
                        }
                    })
                else:
                    zabbix_triggers = self.zapi.trigger.get({
                        'sortfield':
                        'lastchange',
                        'withUnacknowledgedEvents':
                        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 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, 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':
                    Actions.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)
Exemple #12
0
class ZabbixServer(GenericServer):

    """
       special treatment for Zabbix, taken from Check_MK Multisite JSON API
    """
    TYPE = 'Zabbix'
    zapi = None

    def __init__(self, **kwds):
        GenericServer.__init__(self, **kwds)

        # Prepare all urls needed by nagstamon -
        self.urls = {}
        # self.statemap = {}
        self.statemap = {
            'UNREACH': 'UNREACHABLE',
            'CRIT': 'CRITICAL',
            'WARN': 'WARNING',
            'UNKN': 'UNKNOWN',
            'PEND': 'PENDING',
            '0': 'OK',
            '1': 'UNKNOWN',
            '2': 'WARNING',
            '5': 'CRITICAL',
            '3': 'WARNING',
            '4': 'CRITICAL'}

        # Entries for monitor default actions in context menu
        self.MENU_ACTIONS = ["Recheck", "Acknowledge", "Downtime"]
        self.username = conf.servers[self.get_name()].username
        self.password = conf.servers[self.get_name()].password

    def _login(self):
        try:
            self.zapi = ZabbixAPI(server=self.monitor_url, path="", log_level=0)
            self.zapi.login(self.username, self.password)
        except ZabbixAPIException:
            result, error = self.Error(sys.exc_info())
            return Result(result=result, error=error)

    """
    def init_HTTP(self):

        # not necessary to be initialized wit hevery HTTP request
        self.statemap = {
            'UNREACH': 'UNREACHABLE',
            'CRIT': 'CRITICAL',
            'WARN': 'WARNING',
            'UNKN': 'UNKNOWN',
            'PEND': 'PENDING',
            '0': 'OK',
            '1': 'UNKNOWN',
            '2': 'WARNING',
            '5': 'CRITICAL',
            '3': 'WARNING',
            '4': 'CRITICAL'}
        GenericServer.init_HTTP(self)
    """

    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', 'skipDependent': True, '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 _open_browser(self, url):
        webbrowser_open(url)

        if conf.debug_mode is True:
            self.Debug(server=self.get_name(), debug="Open web page " + url)

    def open_services(self):
        self._open_browser(self.urls['human_services'])

    def open_hosts(self):
        self._open_browser(self.urls['human_hosts'])

    def open_monitor(self, host, service=""):
        """
            open monitor from treeview context menu
        """

        if service == "":
            url = self.urls['human_host'] + urllib.parse.urlencode(
                {'x': 'site=' + self.hosts[host].site + '&host=' + host}).replace('x=', '%26')
        else:
            url = self.urls['human_service'] + urllib.parse.urlencode(
                {'x': 'site=' + self.hosts[host].site + '&host=' + host + '&service=' + service}).replace('x=', '%26')

        if conf.debug_mode is True:
            self.Debug(server=self.get_name(), host=host, service=service,
                       debug="Open host/service monitor web page " + url)
        webbrowser_open(url)

    # def GetHost(self, host):
        # """
            # find out ip or hostname of given host to access hosts/devices which do not appear in DNS but
            # have their ip saved in Nagios
        # """

        # # the fasted method is taking hostname as used in monitor
        # if conf.connect_by_host is True:
            # return Result(result=host)

        # ip = ""

        # try:
            # if host in self.hosts:
                # ip = self.hosts[host].address
            # if conf.debug_mode is True:
                # self.Debug(server=self.get_name(), host=host, debug="IP of %s:" % host + " " + ip)

            # if conf.connect_by_dns is True:
                # try:
                    # address = socket.gethostbyaddr(ip)[0]
                # except socket.herror:
                    # address = ip
            # else:
                # address = ip
        # except ZabbixError:
            # result, error = self.Error(sys.exc_info())
            # return Result(result=result, error=error)

        # return Result(result=address)

    def _set_recheck(self, host, service):
        pass

    def get_start_end(self, host):
        return time.strftime("%Y-%m-%d %H:%M"), time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time() + 7200))

    def _action(self, site, host, service, specific_params):
        params = {
            'site': self.hosts[host].site,
            'host': host,
        }
        params.update(specific_params)

        if self.zapi is None:
            self._login()
        events = []
        for e in self.zapi.event.get({'triggerids': params['triggerids'],
                                      # from zabbix 2.2 should be used "objectids" that instead of "triggerids"
                                      'objectids': params['triggerids'],
                                      'hide_unknown': True,
                                      'sortfield': 'clock',
                                      'sortorder': 'DESC'}):
            # stop at first event in "OK" status
            if e['value'] == '0':
                break
            events.append(e['eventid'])
        self.zapi.event.acknowledge({'eventids': events, 'message': params['message']})

    def _set_downtime(self, host, service, author, comment, fixed, start_time, end_time, hours, minutes):
        pass

    def _set_acknowledge(self, host, service, author, comment, sticky, notify, persistent, all_services=[]):
        triggerid = self.hosts[host].services[service].triggerid
        p = {
            'message': '%s: %s' % (author, comment),
            'triggerids': [triggerid],
        }
        self._action(self.hosts[host].site, host, service, p)

        # acknowledge all services on a host when told to do so
        for s in all_services:
            self._action(self.hosts[host].site, host, s, p)

    def nagiosify_service(self, service):
        """
            next dirty workaround to get Zabbix events to look Nagios-esque
        """
        if (" on " or " is ") in service:
            for separator in [" on ", " is "]:
                service = service.split(separator)[0]
        return(service)