From 7eecce0822d722445935d6013412f354c32091da Mon Sep 17 00:00:00 2001
From: "Th.L" <thl-cmk@outlook.com>
Date: Mon, 14 Jun 2021 21:18:31 +0200
Subject: [PATCH] update project

---
 agent_based/checkpoint_fw_ls.py          | 231 ++++++++++++++
 agent_based/checkpoint_fwm_ls.py         | 376 +++++++++++++++++++++++
 checkpoint_log_server.mkp                | Bin 5936 -> 6823 bytes
 packages/checkpoint_log_server           |  19 +-
 web/plugins/metrics/checkpoint_fw_log.py |  61 ++--
 web/plugins/wato/checkpoint_fwm_ls.py    |  54 ++--
 6 files changed, 673 insertions(+), 68 deletions(-)
 create mode 100644 agent_based/checkpoint_fw_ls.py
 create mode 100644 agent_based/checkpoint_fwm_ls.py

diff --git a/agent_based/checkpoint_fw_ls.py b/agent_based/checkpoint_fw_ls.py
new file mode 100644
index 0000000..d2ed960
--- /dev/null
+++ b/agent_based/checkpoint_fw_ls.py
@@ -0,0 +1,231 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# License: GNU General Public License v2
+#
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
+#
+# 2016-07-19 : monitor Check Point FW Log server status
+# 2016-07-24 : changed for check state
+# 2018-01-05 : fix inventory function
+# 2018-03-08 : changed snmp scan function and inventory function
+# 2018-03-15 : code cleanup
+# 2020-06-08 : changed snmp-scan function
+# 2021-06-14 : rewrite for cmk 2.0
+#
+# sample snmpwalk
+#
+# CHECKPOINT-MIB::fwLSConnOverall.0 = INTEGER: 0
+# CHECKPOINT-MIB::fwLSConnOverallDesc.0 = STRING: Security Gateway is reporting logs as defined
+# CHECKPOINT-MIB::fwLSConnIndex.1.0 = Gauge32: 1
+# CHECKPOINT-MIB::fwLSConnIndex.2.0 = Gauge32: 2
+# CHECKPOINT-MIB::fwLSConnName.1.0 = STRING: 10.140.2.203
+# CHECKPOINT-MIB::fwLSConnName.2.0 = STRING: 10.140.2.103
+# CHECKPOINT-MIB::fwLSConnState.1.0 = Gauge32: 0
+# CHECKPOINT-MIB::fwLSConnState.2.0 = Gauge32: 2
+# CHECKPOINT-MIB::fwLSConnStateDesc.1.0 = STRING: Log-Server Connected
+# CHECKPOINT-MIB::fwLSConnStateDesc.2.0 = STRING: Log-Server Disconnected
+# CHECKPOINT-MIB::fwLSConnSendRate.1.0 = Gauge32: 0
+# CHECKPOINT-MIB::fwLSConnSendRate.2.0 = Gauge32: 0
+# CHECKPOINT-MIB::fwLocalLoggingDesc.0 = STRING: Logs are written to log server
+# CHECKPOINT-MIB::fwLocalLoggingStat.0 = INTEGER: 0
+# CHECKPOINT-MIB::fwLocalLoggingWriteRate.0 = Gauge32: 0
+# CHECKPOINT-MIB::fwLoggingHandlingRate.0 = Gauge32: 0
+#
+# .1.3.6.1.4.1.2620.1.1.30.1.0 = INTEGER: 0
+# .1.3.6.1.4.1.2620.1.1.30.2.0 = STRING: "Security Gateway is reporting logs as defined"
+# .1.3.6.1.4.1.2620.1.1.30.3.1.1.1.0 = Gauge32: 1
+# .1.3.6.1.4.1.2620.1.1.30.3.1.1.2.0 = Gauge32: 2
+# .1.3.6.1.4.1.2620.1.1.30.3.1.2.1.0 = STRING: "10.140.2.203"
+# .1.3.6.1.4.1.2620.1.1.30.3.1.2.2.0 = STRING: "10.140.2.103"
+# .1.3.6.1.4.1.2620.1.1.30.3.1.3.1.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.1.30.3.1.3.2.0 = Gauge32: 2
+# .1.3.6.1.4.1.2620.1.1.30.3.1.4.1.0 = STRING: "Log-Server Connected"
+# .1.3.6.1.4.1.2620.1.1.30.3.1.4.2.0 = STRING: "Log-Server Disconnected"
+# .1.3.6.1.4.1.2620.1.1.30.3.1.5.1.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.1.30.3.1.5.2.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.1.30.4.0 = STRING: "Logs are written to log server"
+# .1.3.6.1.4.1.2620.1.1.30.5.0 = INTEGER: 0
+# .1.3.6.1.4.1.2620.1.1.30.6.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.1.30.7.0 = Gauge32: 0
+#
+#
+# sample info
+# log server running
+# [[[u'0', u'Security Gateway is reporting logs as defined', u'Logs are written to log server', u'0']],
+#  [[u'1', u'192.168.10.10', u'0', u'Log-Server Connected'],
+#   [u'2', u'192.168.10.11', u'2', u'Backup Log-Server Not Active']]]
+#
+# no log server
+# [[], []]
+#
+
+from typing import NamedTuple, List, Dict, Optional
+
+from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import (
+    DiscoveryResult,
+    CheckResult,
+    StringTable,
+)
+
+from cmk.base.plugins.agent_based.agent_based_api.v1 import (
+    register,
+    Service,
+    equals,
+    Result,
+    State,
+    Metric,
+    SNMPTree,
+    startswith,
+    all_of,
+    any_of,
+)
+
+
+class CheckPointFwLsOverAll(NamedTuple):
+    fwlsconnoverall: int
+    fwlsconnoveralldesc: str
+    fwlocalloggingdesc: str
+    fwlocalloggingstat: int
+    fwLocalLoggingWriteRate: Optional[int]
+    fwLoggingHandlingRate: Optional[int]
+
+
+class CheckPointFwLs(NamedTuple):
+    fwLSConnIndex: int
+    fwLSConnName: str
+    fwLSConnState: int
+    fwLSConnStateDesc: str
+    fwLSConnSendRate: Optional[int]
+
+
+def parse_checkpoint_fw_ls(string_table: List[StringTable]) -> Dict:
+    over_all, log_servers = string_table
+
+    fwlsconnoverall, fwlsconnoveralldesc, fwlocalloggingdesc, fwlocalloggingstat, fwLocalLoggingWriteRate, fwLoggingHandlingRate = \
+    over_all[0]
+    parsed = {}
+    parsed.update({'over all': CheckPointFwLsOverAll(
+        fwlsconnoverall=int(fwlsconnoverall),
+        fwlsconnoveralldesc=fwlsconnoveralldesc,
+        fwlocalloggingdesc=fwlocalloggingdesc,
+        fwlocalloggingstat=int(fwlocalloggingstat),
+        fwLocalLoggingWriteRate=int(fwLocalLoggingWriteRate) if fwLocalLoggingWriteRate.isdigit() else None,
+        fwLoggingHandlingRate=int(fwLoggingHandlingRate) if fwLoggingHandlingRate.isdigit() else None,
+    )})
+
+    for fwLSConnIndex, fwLSConnName, fwLSConnState, fwLSConnStateDesc, fwLSConnSendRate in log_servers:
+        parsed.update({fwLSConnName: CheckPointFwLs(
+            fwLSConnIndex=int(fwLSConnIndex),
+            fwLSConnName=fwLSConnName,
+            fwLSConnState=int(fwLSConnState),
+            fwLSConnStateDesc=fwLSConnStateDesc,
+            fwLSConnSendRate=int(fwLSConnSendRate) if fwLSConnSendRate.isdigit() else None,
+        )})
+
+    return parsed
+
+
+def discovery_checkpoint_fw_ls(section: Dict) -> DiscoveryResult:
+    for key in section.keys():
+        yield Service(item=key)
+
+
+def check_checkpoint_fw_ls(item, params, section: Dict) -> CheckResult:
+    fwLSConnState_des = {
+        0: 'Ok',
+        1: 'Error',
+        2: 'Not Active',
+    }
+
+    fwLocalLoggingStat = {
+        0: 'Logging to log servers',
+        1: 'Logging local configured',
+        2: 'Logging local due to connectivity',
+        3: 'Logging local due to high rate',
+    }
+
+    over_all = section['over all']
+
+    if item == 'over all':
+        if over_all.fwLocalLoggingWriteRate is not None and over_all.fwLoggingHandlingRate is not None:  # R80.10 and up
+            yield Metric(name='checkpoint_fw_ls_fwlocalloggingwriterate', value=over_all.fwLocalLoggingWriteRate)
+            yield Metric(name='checkpoint_fw_ls_fwlogginghandlingrate', value=over_all.fwLoggingHandlingRate)
+
+        yield Result(state=State(over_all.fwlsconnoverall), summary=over_all.fwlsconnoveralldesc)
+        if over_all.fwlocalloggingdesc != '':
+            if over_all.fwlocalloggingstat in [1, 3]:
+                yield Result(state=State.WARN, summary=over_all.fwlocalloggingdesc)
+            elif over_all.fwlocalloggingstat == 2:
+                yield Result(state=State.CRIT, summary=over_all.fwlocalloggingdesc)
+            else:
+                yield Result(state=State.OK, summary=over_all.fwlocalloggingdesc)
+    else:
+        try:
+            log_server = section[item]
+        except IndexError:
+            return
+
+        if log_server.fwLSConnSendRate is not None:  # R80.10 and up
+            yield Metric(name='checkpoint_fw_ls_fwlsconnsendrate', value=log_server.fwLSConnSendRate)
+
+        if log_server.fwLSConnState == 1:
+            yield Result(state=State.CRIT, summary='State: Connection error')
+        else:
+            yield Result(state=State.OK, summary=f'State: {log_server.fwLSConnStateDesc}')
+
+        exp_connection_state = params.get('exp_connection_status', 0)
+        mon_connection_state = params.get('mon_connection_state', 1)
+
+        if log_server.fwLSConnStateDesc.lower() != exp_connection_state.lower():
+            #print(log_server.fwLSConnStateDesc.lower())
+            #print(exp_connection_state.lower())
+            yield Result(state=State(mon_connection_state),
+                         summary=f'Expected connection state: {exp_connection_state}')
+
+
+register.snmp_section(
+    name='checkpoint_fw_ls',
+    parse_function=parse_checkpoint_fw_ls,
+    fetch=[
+        SNMPTree(
+            base='.1.3.6.1.4.1.2620.1.1.30',  # CHECKPOINT-MIB:fwLSConn
+            oids=[
+                '1',  # fwLSConnOverall
+                '2',  # fwLSConnOverallDesc
+                '4',  # fwLocalLoggingDesc
+                '5',  # fwLocalLoggingStat
+                '6',  # fwLocalLoggingWriteRate
+                '7',  # fwLoggingHandlingRate
+            ]
+        ),
+        SNMPTree(
+            base='.1.3.6.1.4.1.2620.1.1.30.3.1',  # CHECKPOINT-MIB::fwLSConnEntry
+            oids=[
+                '1',  # fwLSConnIndex
+                '2',  # fwLSConnName
+                '3',  # fwLSConnState
+                '4',  # fwLSConnStateDesc
+                '5',  # fwLSConnSendRate
+            ]
+        )
+
+    ],
+    detect=any_of(
+        startswith('.1.3.6.1.2.1.1.2.0', '.1.3.6.1.4.1.2620'),
+        all_of(
+            equals('.1.3.6.1.2.1.1.2.0', '.1.3.6.1.4.1.8072.3.2.10'),
+            equals('.1.3.6.1.4.1.2620.1.6.1.0', 'SVN Foundation'),
+        )
+    )
+)
+
+register.check_plugin(
+    name='checkpoint_fw_ls',
+    service_name='FW Log server %s',
+    discovery_function=discovery_checkpoint_fw_ls,
+    check_function=check_checkpoint_fw_ls,
+    check_default_parameters={},
+    check_ruleset_name='checkpoint_fw_ls',
+)
diff --git a/agent_based/checkpoint_fwm_ls.py b/agent_based/checkpoint_fwm_ls.py
new file mode 100644
index 0000000..5e0c1bf
--- /dev/null
+++ b/agent_based/checkpoint_fwm_ls.py
@@ -0,0 +1,376 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# License: GNU General Public License v2
+#
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
+#
+# 2016-07-29 :  monitor Check Point FWM log server status
+# 2018-05-08 :  changed snmp scan and inventory function
+# 2018-03-16 :  added R80.10 MIBs
+# 2018-05-30 :  removed empty OIDs CHECKPOINT-MIB::lsConnectedClientsEntry,
+#                                  CHECKPOINT-MIB::lsConnectedGatewaysEntry
+#                                  CHECKPOINT-MIB::lsLoggingInfo
+# 2020-06-08 : changed snmp-scan function
+# 2021-06-14 : rewrite for cmk 2.0
+#
+
+#
+# sample snmpwalk (R77.30)
+#
+# .1.3.6.1.4.1.2620.1.11.1.0 = STRING: "Check Point Log Server"
+# .1.3.6.1.4.1.2620.1.11.2.0 = INTEGER: 6
+# .1.3.6.1.4.1.2620.1.11.3.0 = INTEGER: 0
+# .1.3.6.1.4.1.2620.1.11.4.0 = INTEGER: 4663
+# .1.3.6.1.4.1.2620.1.11.5.0 = INTEGER: 1
+# .1.3.6.1.4.1.2620.1.11.101.0 = INTEGER: 0
+# .1.3.6.1.4.1.2620.1.11.102.0 = STRING: "OK"
+# .1.3.6.1.4.1.2620.1.11.103.0 = STRING: "OK"
+#
+# CHECKPOINT-MIB::lsProdName.0 = STRING: Check Point Log Server
+# CHECKPOINT-MIB::lsVerMajor.0 = INTEGER: 6
+# CHECKPOINT-MIB::lsVerMinor.0 = INTEGER: 0
+# CHECKPOINT-MIB::lsBuildNumber.0 = INTEGER: 4663
+# CHECKPOINT-MIB::lsFwmIsAlive.0 = INTEGER: 1
+# CHECKPOINT-MIB::lsStatCode.0 = INTEGER: 0
+# CHECKPOINT-MIB::lsStatShortDescr.0 = STRING: OK
+# CHECKPOINT-MIB::lsStatLongDescr.0 = STRING: OK
+#
+# sample snmpwalk (R80.10, SmartEvent Server)
+#
+# .1.3.6.1.4.1.2620.1.11.1.0 = STRING: "Check Point Log Server"
+# .1.3.6.1.4.1.2620.1.11.2.0 = INTEGER: 6
+# .1.3.6.1.4.1.2620.1.11.3.0 = INTEGER: 0
+# .1.3.6.1.4.1.2620.1.11.4.0 = INTEGER: 39081
+# .1.3.6.1.4.1.2620.1.11.5.0 = INTEGER: 1
+# .1.3.6.1.4.1.2620.1.11.14.1.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.2.0 = Gauge32: 1
+# .1.3.6.1.4.1.2620.1.11.14.3.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.4.1.1.1.0 = Gauge32: 1
+# .1.3.6.1.4.1.2620.1.11.14.4.1.2.1.0 = STRING: "Local Clients"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.3.1.0 = STRING: "Connected"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.4.1.0 = STRING: "N/A"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.5.1.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.5.1.0 = STRING: "20171"
+# .1.3.6.1.4.1.2620.1.11.14.5.2.0 = STRING: "2607010"
+# .1.3.6.1.4.1.2620.1.11.14.5.3.0 = STRING: "0"
+# .1.3.6.1.4.1.2620.1.11.14.5.4.0 = STRING: "9021"
+# .1.3.6.1.4.1.2620.1.11.14.5.5.0 = Gauge32: 4
+# .1.3.6.1.4.1.2620.1.11.14.5.6.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.5.7.0 = Gauge32: 10
+# .1.3.6.1.4.1.2620.1.11.14.5.8.0 = Gauge32: 1
+# .1.3.6.1.4.1.2620.1.11.14.5.9.0 = Gauge32: 10
+# .1.3.6.1.4.1.2620.1.11.14.5.10.0 = Gauge32: 1
+# .1.3.6.1.4.1.2620.1.11.14.5.11.0 = Gauge32: 27275
+# .1.3.6.1.4.1.2620.1.11.14.5.12.0 = Gauge32: 1001
+# .1.3.6.1.4.1.2620.1.11.14.5.13.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.6.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.101.0 = INTEGER: 0
+# .1.3.6.1.4.1.2620.1.11.102.0 = STRING: "OK"
+# .1.3.6.1.4.1.2620.1.11.103.0 = STRING: "OK"
+#
+# CHECKPOINT-MIB::lsProdName.0 = STRING: Check Point Log Server
+# CHECKPOINT-MIB::lsVerMajor.0 = INTEGER: 6
+# CHECKPOINT-MIB::lsVerMinor.0 = INTEGER: 0
+# CHECKPOINT-MIB::lsBuildNumber.0 = INTEGER: 39081
+# CHECKPOINT-MIB::lsFwmIsAlive.0 = INTEGER: 1
+# CHECKPOINT-MIB::lsLogReceiveRate.0 = Gauge32: 0
+# CHECKPOINT-MIB::lsLogReceiveRatePeak.0 = Gauge32: 1
+# CHECKPOINT-MIB::lsLogReceiveRate10Min.0 = Gauge32: 0
+# CHECKPOINT-MIB::lsGWIndex.1.0 = Gauge32: 1
+# CHECKPOINT-MIB::lsGWIP.1.0 = STRING: Local Clients
+# CHECKPOINT-MIB::lsGWState.1.0 = STRING: Connected
+# CHECKPOINT-MIB::lsGWLastLoginTime.1.0 = STRING: N/A
+# CHECKPOINT-MIB::lsGWLogReceiveRate.1.0 = Gauge32: 0
+# CHECKPOINT-MIB::lsIndexerInfoTotalReadLogs.0 = Wrong Type (should be Gauge32 or Unsigned32): STRING: "20171"
+# CHECKPOINT-MIB::lsIndexerInfoTotalUpdatesAndLogsIndexed.0 = Wrong Type (should be Gauge32 or Unsigned32): STRING: "2607010"
+# CHECKPOINT-MIB::lsIndexerInfoTotalReadLogsErrors.0 = Wrong Type (should be Gauge32 or Unsigned32): STRING: "0"
+# CHECKPOINT-MIB::lsIndexerInfoTotalUpdatesAndLogsIndexedErrors.0 = Wrong Type (should be Gauge32 or Unsigned32): STRING: "9021"
+# CHECKPOINT-MIB::lsIndexerInfoUpdatesAndLogsIndexedRate.0 = Gauge32: 4
+# CHECKPOINT-MIB::lsIndexerInfoReadLogsRate.0 = Gauge32: 0
+# CHECKPOINT-MIB::lsIndexerInfoUpdatesAndLogsIndexedRatePeak.0 = Gauge32: 10
+# CHECKPOINT-MIB::lsIndexerInfoReadLogsRatePeak.0 = Gauge32: 1
+# CHECKPOINT-MIB::lsIndexerInfo.9.0 = Gauge32: 10
+# CHECKPOINT-MIB::lsIndexerInfo.10.0 = Gauge32: 1
+# CHECKPOINT-MIB::lsIndexerInfo.11.0 = Gauge32: 27275
+# CHECKPOINT-MIB::lsIndexerInfo.12.0 = Gauge32: 1001
+# CHECKPOINT-MIB::lsIndexerInfo.13.0 = Gauge32: 0
+# CHECKPOINT-MIB::lsLogReceiveRate1Hour.0 = Gauge32: 0
+# CHECKPOINT-MIB::lsStatCode.0 = INTEGER: 0
+# CHECKPOINT-MIB::lsStatShortDescr.0 = STRING: OK
+# CHECKPOINT-MIB::lsStatLongDescr.0 = STRING: OK
+#
+# R80.10 MD Logserver
+# .1.3.6.1.4.1.2620.1.11.1.0 = STRING: "Check Point Log Server"
+# .1.3.6.1.4.1.2620.1.11.2.0 = INTEGER: 6
+# .1.3.6.1.4.1.2620.1.11.3.0 = INTEGER: 0
+# .1.3.6.1.4.1.2620.1.11.4.0 = INTEGER: 39081
+# .1.3.6.1.4.1.2620.1.11.5.0 = INTEGER: 0
+# .1.3.6.1.4.1.2620.1.11.14.1.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.2.0 = Gauge32: 1
+# .1.3.6.1.4.1.2620.1.11.14.3.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.4.1.1.1.0 = Gauge32: 1
+# .1.3.6.1.4.1.2620.1.11.14.4.1.2.1.0 = STRING: "Local Clients"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.3.1.0 = STRING: "Connected"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.4.1.0 = STRING: "N/A"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.5.1.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.5.1.0 = STRING: "94"
+# .1.3.6.1.4.1.2620.1.11.14.5.2.0 = STRING: "94"
+# .1.3.6.1.4.1.2620.1.11.14.5.3.0 = STRING: "0"
+# .1.3.6.1.4.1.2620.1.11.14.5.4.0 = STRING: "53"
+# .1.3.6.1.4.1.2620.1.11.14.5.5.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.5.6.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.5.7.0 = Gauge32: 1
+# .1.3.6.1.4.1.2620.1.11.14.5.8.0 = Gauge32: 1
+# .1.3.6.1.4.1.2620.1.11.14.5.9.0 = Gauge32: 1
+# .1.3.6.1.4.1.2620.1.11.14.5.10.0 = Gauge32: 1
+# .1.3.6.1.4.1.2620.1.11.14.5.11.0 = Gauge32: 2
+# .1.3.6.1.4.1.2620.1.11.14.5.12.0 = Gauge32: 2
+# .1.3.6.1.4.1.2620.1.11.14.5.13.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.6.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.101.0 = INTEGER: 2
+# .1.3.6.1.4.1.2620.1.11.102.0 = STRING: "Problem"
+# .1.3.6.1.4.1.2620.1.11.103.0 = STRING: "Log Server is not running"
+#
+# sample info
+# [[[u'Check Point Log Server', u'6', u'0', u'4663', u'1', u'0', u'OK', u'OK']], []]
+#
+# no logserver active
+# [[], []]
+#
+
+from typing import NamedTuple, List, Optional
+
+from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import (
+    DiscoveryResult,
+    CheckResult,
+    StringTable,
+)
+
+from cmk.base.plugins.agent_based.agent_based_api.v1 import (
+    register,
+    Service,
+    equals,
+    Result,
+    State,
+    Metric,
+    SNMPTree,
+    startswith,
+    all_of,
+    any_of,
+)
+
+
+class CheckPointFwmR77(NamedTuple):
+    lsprodname: int
+    lsvermajor: str
+    lsverminor: str
+    lsbuildnumber: int
+    lsfwmisalive: int
+    lsstatcode: int
+    lsstatshortdescr: str
+    lsstatlongdescr: str
+
+
+class CheckPointFwmR80(NamedTuple):
+    TotalReadLogs: int
+    TotalUpdatesAndLogsIndexed: int
+    TotalReadLogsErrors: int
+    TotalUpdatesAndLogsIndexedErrors: int
+    UpdatesAndLogsIndexedRate: int
+    ReadLogsRate: int
+    UpdatesAndLogsIndexedRatePeak: int
+    ReadLogsRatePeak: int
+
+
+class CheckPointFwm(NamedTuple):
+    R77: CheckPointFwmR77
+    R80: Optional[CheckPointFwmR80]
+
+
+def parse_checkpoint_fwm_ls(string_table: List[StringTable]) -> CheckPointFwm:
+    r77, r80_indexer = string_table
+    lsprodname, lsvermajor, lsverminor, lsbuildnumber, lsfwmisalive, lsstatcode, lsstatshortdescr, lsstatlongdescr = \
+        r77[0]
+
+    checkpointfwmr77 = CheckPointFwmR77(
+        lsprodname=lsprodname,
+        lsvermajor=lsvermajor,
+        lsverminor=lsverminor,
+        lsbuildnumber=lsbuildnumber,
+        lsfwmisalive=int(lsfwmisalive),
+        lsstatcode=int(lsstatcode),
+        lsstatshortdescr=lsstatshortdescr,
+        lsstatlongdescr=lsstatlongdescr,
+    )
+
+    checkpointfwmr80 = None
+
+    try:
+        r80_indexer = r80_indexer[0]
+    except IndexError:
+        return CheckPointFwm(
+            R77=checkpointfwmr77,
+            R80=checkpointfwmr80,
+        )
+
+    if len(r80_indexer) == 8:
+        TotalReadLogs, TotalUpdatesAndLogsIndexed, TotalReadLogsErrors, TotalUpdatesAndLogsIndexedErrors, \
+        UpdatesAndLogsIndexedRate, ReadLogsRate, UpdatesAndLogsIndexedRatePeak, ReadLogsRatePeak = r80_indexer
+
+        checkpointfwmr80 = CheckPointFwmR80(
+            TotalReadLogs=int(TotalReadLogs),
+            TotalUpdatesAndLogsIndexed=int(TotalUpdatesAndLogsIndexed),
+            TotalReadLogsErrors=int(TotalReadLogsErrors),
+            TotalUpdatesAndLogsIndexedErrors=int(TotalUpdatesAndLogsIndexedErrors),
+            UpdatesAndLogsIndexedRate=int(UpdatesAndLogsIndexedRate),
+            ReadLogsRate=int(ReadLogsRate),
+            UpdatesAndLogsIndexedRatePeak=int(UpdatesAndLogsIndexedRatePeak),
+            ReadLogsRatePeak=int(ReadLogsRatePeak),
+        )
+
+    return CheckPointFwm(
+        R77=checkpointfwmr77,
+        R80=checkpointfwmr80,
+    )
+
+
+def discovery_checkpoint_fwm_ls(section: CheckPointFwm) -> DiscoveryResult:
+    yield Service()
+
+
+def check_checkpoint_fwm_ls(params, section: CheckPointFwm) -> CheckResult:
+    yield Result(state=State.OK,
+                 summary=f'{section.R77.lsprodname}, version: {section.R77.lsvermajor}.{section.R77.lsverminor}, Build: {section.R77.lsbuildnumber}')
+
+    if not params.get('ignore_status_on_r80_10'):
+        if section.R77.lsfwmisalive != 1:
+            yield Result(state=State.CRIT, summary='Is not alive')
+        if section.R77.lsstatcode != 0:
+            yield Result(state=State.CRIT,
+                         summary=f'Status: {section.R77.lsstatshortdescr}, {section.R77.lsstatlongdescr}')
+    if section.R80 is not None:
+        yield Metric(name='checkpoint_fwm_ls_totalreadlogs', value=section.R80.TotalReadLogs)
+        yield Metric(name='checkpoint_fwm_ls_totalupdatesandlogsindexed', value=section.R80.TotalUpdatesAndLogsIndexed)
+        yield Metric(name='checkpoint_fwm_ls_totalreadlogserrors', value=section.R80.TotalReadLogsErrors)
+        yield Metric(name='checkpoint_fwm_ls_totalupdatesandlogsindexederrors', value=section.R80.TotalUpdatesAndLogsIndexedErrors)
+        yield Metric(name='checkpoint_fwm_ls_updatesandlogsindexedrate', value=section.R80.UpdatesAndLogsIndexedRate)
+        yield Metric(name='checkpoint_fwm_ls_updatesandlogsindexedratepeak', value=section.R80.UpdatesAndLogsIndexedRatePeak)
+        yield Metric(name='checkpoint_fwm_ls_readlogsrate', value=section.R80.ReadLogsRate)
+        yield Metric(name='checkpoint_fwm_ls_readlogsratepeak', value=section.R80.ReadLogsRatePeak)
+
+
+register.snmp_section(
+    name='checkpoint_fwm_ls',
+    parse_function=parse_checkpoint_fwm_ls,
+    fetch=[
+        SNMPTree(
+            base='.1.3.6.1.4.1.2620.1.11',  # CHECKPOINT-MIB::ls
+            oids=[
+                '1',  # lsProdName
+                '2',  # lsVerMajor
+                '3',  # lsVerMinor
+                '4',  # lsBuildNumber
+                '5',  # lsFwmIsAlive
+                '101',  # lsStatCode
+                '102',  # lsStatShortDescr
+                '103',  # lsStatLongDescr
+            ]
+        ),
+        SNMPTree(
+            base='.1.3.6.1.4.1.2620.1.11.14.5',  # CHECKPOINT-MIB::lsIndexerInfo
+            oids=[
+                '1',  # lsIndexerInfoTotalReadLogs
+                '2',  # lsIndexerInfoTotalUpdatesAndLogsIndexed
+                '3',  # lsIndexerInfoTotalReadLogsErrors
+                '4',  # lsIndexerInfoTotalUpdatesAndLogsIndexedErrors
+                '5',  # lsIndexerInfoUpdatesAndLogsIndexedRate
+                '6',  # lsIndexerInfoReadLogsRate
+                '7',  # lsIndexerInfoUpdatesAndLogsIndexedRatePeak
+                '8',  # lsIndexerInfoReadLogsRatePeak
+                # '9',   # lsIndexerInfo_9
+                # '10',  # lsIndexerInfo_10
+                # '11',  # lsIndexerInfo_11
+                # '12',  # lsIndexerInfo_12
+                # '13',  # lsIndexerInfo_13
+            ]
+        )
+
+    ],
+    detect=any_of(
+        startswith('.1.3.6.1.2.1.1.2.0', '.1.3.6.1.4.1.2620'),
+        all_of(
+            equals('.1.3.6.1.2.1.1.2.0', '.1.3.6.1.4.1.8072.3.2.10'),
+            equals('.1.3.6.1.4.1.2620.1.6.1.0', 'SVN Foundation'),
+        )
+    )
+)
+
+register.check_plugin(
+    name='checkpoint_fwm_ls',
+    service_name='FWM Log Server',
+    discovery_function=discovery_checkpoint_fwm_ls,
+    check_function=check_checkpoint_fwm_ls,
+    check_default_parameters={'ignore_status_on_r80_10': False, },
+    check_ruleset_name='checkpoint_fwm_ls',
+)
+
+# ('.1.3.6.1.4.1.2620.1.11.14', [  # CHECKPOINT-MIB::lsLoggingInfo
+#     '1',  # lsLogReceiveRate
+#     '2',  # lsLogReceiveRatePeak
+#     '3',  # lsLogReceiveRate10Min
+#     '6',  # lsLogReceiveRate1Hour
+# ]),
+
+# OMD[build]:~$ snmpwalk -v2c -c komsa/alf-r81 -ObentU simulant .1.3.6.1.4.1.2620.1.11.14.4.1
+# .1.3.6.1.4.1.2620.1.11.14.4.1.1.1.0 = Gauge32: 1
+# .1.3.6.1.4.1.2620.1.11.14.4.1.1.2.0 = Gauge32: 2
+# .1.3.6.1.4.1.2620.1.11.14.4.1.1.3.0 = Gauge32: 3
+# .1.3.6.1.4.1.2620.1.11.14.4.1.1.4.0 = Gauge32: 4
+# .1.3.6.1.4.1.2620.1.11.14.4.1.1.5.0 = Gauge32: 5
+# .1.3.6.1.4.1.2620.1.11.14.4.1.1.6.0 = Gauge32: 6
+# .1.3.6.1.4.1.2620.1.11.14.4.1.1.7.0 = Gauge32: 7
+# .1.3.6.1.4.1.2620.1.11.14.4.1.2.1.0 = STRING: "Local Clients"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.2.2.0 = STRING: "bill01"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.2.3.0 = STRING: "bill02"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.2.4.0 = STRING: "donald01"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.2.5.0 = STRING: "donald02"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.2.6.0 = STRING: "charlie02"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.2.7.0 = STRING: "charlie01"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.3.1.0 = STRING: "Connected"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.3.2.0 = STRING: "Connected"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.3.3.0 = STRING: "Connected"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.3.4.0 = STRING: "Connected"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.3.5.0 = STRING: "Connected"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.3.6.0 = STRING: "Connected"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.3.7.0 = STRING: "Connected"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.4.1.0 = STRING: "N/A"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.4.2.0 = STRING: "Tue Feb  9 13:51:34 2021"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.4.3.0 = STRING: "Tue Feb  9 13:51:34 2021"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.4.4.0 = STRING: "Tue Feb  9 13:51:34 2021"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.4.5.0 = STRING: "Tue Feb  9 13:51:34 2021"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.4.6.0 = STRING: "Tue Feb  9 13:51:34 2021"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.4.7.0 = STRING: "Tue Feb  9 13:51:34 2021"
+# .1.3.6.1.4.1.2620.1.11.14.4.1.5.1.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.4.1.5.2.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.4.1.5.3.0 = Gauge32: 837
+# .1.3.6.1.4.1.2620.1.11.14.4.1.5.4.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.4.1.5.5.0 = Gauge32: 1
+# .1.3.6.1.4.1.2620.1.11.14.4.1.5.6.0 = Gauge32: 0
+# .1.3.6.1.4.1.2620.1.11.14.4.1.5.7.0 = Gauge32: 5
+
+# ('.1.3.6.1.4.1.2620.1.11.14.4.1', [  # CHECKPOINT-MIB::lsConnectedGatewaysEntry
+#     '1',  # lsGWIndex
+#     '2',  # lsGWIP
+#     '3',  # lsGWState
+#     '4',  # lsGWLastLoginTime
+#     '5',  # lsGWLogReceiveRate
+#      ]),
+# ('.1.3.6.1.4.1.2620.1.11.14.7.1', [  # CHECKPOINT-MIB::lsConnectedClientsEntry
+#     '1',   # lsIndex
+#     '2',   # lsClientName
+#     '3',   # lsClientHost
+#     '4',   # lsClientDbLock
+#     '5',   # lsClientDbLock
+#     ]),
diff --git a/checkpoint_log_server.mkp b/checkpoint_log_server.mkp
index 126699a5e6c73459a33ebd136b273a74b2f7b317..35bd0d170acf040e2fde2f544beba74e342d9d6e 100644
GIT binary patch
literal 6823
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

literal 5936
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

diff --git a/packages/checkpoint_log_server b/packages/checkpoint_log_server
index 3019e8d..023d05d 100644
--- a/packages/checkpoint_log_server
+++ b/packages/checkpoint_log_server
@@ -1,13 +1,16 @@
-{'author': u'Th.L. (thl-cmk[at]outlook[dot]com)',
- 'description': u'Monitors Check Point Log service status. \nCreates one check on the management server and one check for each log server on the gateway.\n',
+{'author': 'Th.L. (thl-cmk[at]outlook[dot]com)',
+ 'description': 'Monitors Check Point Log service status. \n'
+                'Creates one check on the management server and one check for '
+                'each log server on the gateway.\n',
  'download_url': 'https://thl-cmk.hopto.org',
- 'files': {'checkman': ['checkpoint_fw_ls', 'checkpoint_fwm_ls'],
-           'checks': ['checkpoint_fw_ls', 'checkpoint_fwm_ls'],
+ 'files': {'agent_based': ['checkpoint_fw_ls.py', 'checkpoint_fwm_ls.py'],
+           'checkman': ['checkpoint_fw_ls', 'checkpoint_fwm_ls'],
            'web': ['plugins/metrics/checkpoint_fw_log.py',
                    'plugins/wato/checkpoint_fwm_ls.py']},
  'name': 'checkpoint_log_server',
  'num_files': 6,
- 'title': u'Check Point Log service status',
- 'version': '20200608.v0.1.2d',
- 'version.min_required': '1.2.8b8',
- 'version.packaged': '1.4.0p38'}
\ No newline at end of file
+ 'title': 'Check Point Log service status',
+ 'version': '20210614.v0.2',
+ 'version.min_required': '2.0.0',
+ 'version.packaged': '2021.04.10',
+ 'version.usable_until': None}
\ No newline at end of file
diff --git a/web/plugins/metrics/checkpoint_fw_log.py b/web/plugins/metrics/checkpoint_fw_log.py
index a53ef72..4f184c8 100644
--- a/web/plugins/metrics/checkpoint_fw_log.py
+++ b/web/plugins/metrics/checkpoint_fw_log.py
@@ -1,5 +1,5 @@
-#!/usr/bin/python
-# -*- encoding: utf-8; py-indent-offset: 4 -*-
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
 #
 # License: GNU General Public License v2
 #
@@ -10,12 +10,13 @@
 # Check Point Logserver metrics plugins
 # checkpoint_fw_ls / checkpoint_fwm_ls
 #
+from cmk.gui.i18n import _
 
-##############################################################################
-#
-# define units for perfdata
-#
-##############################################################################
+from cmk.gui.plugins.metrics import (
+    metric_info,
+    graph_info,
+    perfometer_info
+)
 
 ##############################################################################
 #
@@ -82,74 +83,50 @@ metric_info['checkpoint_fwm_ls_readlogsratepeak'] = {
     'color': '22/a',
 }
 
-##############################################################################
-#
-# map perfdata to metric
-#
-##############################################################################
-
-
-check_metrics['check_mk-checkpoint_fw_ls'] = {
-    'fwlocalloggingwriterate': {'name': 'checkpoint_fw_ls_localloggingwriterate', },
-    'fwlogginghandlingrate': {'name': 'checkpoint_fw_ls_logginghandlingrate', },
-    'fwlsconnsendrate': {'name': 'checkpoint_fw_ls_lsconnsendrate', },
-}
-check_metrics['check_mk-checkpoint_fwm_ls'] = {
-    'totalreadlogs': {'name': 'checkpoint_fwm_ls_totalreadlogs', },
-    'totalupdatesandlogsindexed': {'name': 'checkpoint_fwm_ls_totalupdatesandlogsindexed', },
-    'totalreadlogserrors': {'name': 'checkpoint_fwm_ls_totalreadlogserrors', },
-    'totalupdatesandlogsindexederrors': {'name': 'checkpoint_fwm_ls_totalupdatesandlogsindexederrors', },
-    'updatesandlogsindexedrate': {'name': 'checkpoint_fwm_ls_updatesandlogsindexedrate', },
-    'updatesandlogsindexedratepeak': {'name': 'checkpoint_fwm_ls_updatesandlogsindexedratepeak', },
-    'readlogsrate': {'name': 'checkpoint_fwm_ls_readlogsrate', },
-    'readlogsratepeak': {'name': 'checkpoint_fwm_ls_readlogsratepeak', }
-
-}
-
 ##############################################################################
 #
 # how to graph perdata
 #
 ##############################################################################
 
-graph_info.append({
+graph_info['checkpoint_fw_ls.over_all'] = {
     'title': _('Check Point Firewall Logserver: over all'),
     'metrics': [
         ('checkpoint_fw_ls_localloggingwriterate', 'line'),
         ('checkpoint_fw_ls_logginghandlingrate', 'line'),
     ],
-})
+}
 
-graph_info.append({
+graph_info['checkpoint_fw_ls.gateway'] = {
     'title': _('Check Point Firewall Log server'),
     'metrics': [
         ('checkpoint_fw_ls_lsconnsendrate', 'line'),
     ],
-})
+}
 
-graph_info.append({
+graph_info['checkpoint_fwm_ls.management'] = {
     'title': _('Check Point Management Firewall Log server'),
     'metrics': [
         ('checkpoint_fwm_ls_updatesandlogsindexedratepeak', 'line'),
         ('checkpoint_fwm_ls_updatesandlogsindexedrate', 'line'),
     ],
-})
+}
 
-graph_info.append({
+graph_info['checkpoint_fwm_ls.read_logs'] = {
     'title': _('Check Point Management Firewall Log server read logs'),
     'metrics': [
         ('checkpoint_fwm_ls_totalreadlogserrors', 'line'),
         ('checkpoint_fwm_ls_totalreadlogs', 'line'),
     ],
-})
+}
 
-graph_info.append({
+graph_info['checkpoint_fwm_ls.updates'] = {
     'title': _('Check Point Management Firewall Log server updates and logs indexed'),
     'metrics': [
         ('checkpoint_fwm_ls_totalupdatesandlogsindexederrors', 'line'),
         ('checkpoint_fwm_ls_totalupdatesandlogsindexed', 'line'),
     ],
-})
+}
 
 ##############################################################################
 #
@@ -170,4 +147,4 @@ perfometer_info.append(('stacked', [
         'half_value': 1000.0,
         'exponent': 2,
     },
-]))
\ No newline at end of file
+]))
diff --git a/web/plugins/wato/checkpoint_fwm_ls.py b/web/plugins/wato/checkpoint_fwm_ls.py
index 2eed3c7..7e424a0 100644
--- a/web/plugins/wato/checkpoint_fwm_ls.py
+++ b/web/plugins/wato/checkpoint_fwm_ls.py
@@ -1,25 +1,43 @@
-#!/usr/bin/python
-# -*- encoding: utf-8; py-indent-offset: 4 -*-
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
 #
 # License: GNU General Public License v2
 #
 # Author: thl-cmk[at]outlook[dot]com
 # URL   : https://thl-cmk.hopto.org
 #
-register_check_parameters(
-    subgroup_applications,
-    'checkpoint_fwm_ls',
-    _('Check Point Firewall Mangement Log Server'),
-    Dictionary(
-        elements=[
-            ('ignore_status_on_r80_10',
-             FixedValue(
-                 True,
-                 help=_('Ignore status and alive on Check Point R80.10'),
-                 title=_('Ignore status and alive on Check Point R80.10'),
-             )),
-        ],
-    ),
-    None,
-    match_type='dict',
+from cmk.gui.i18n import _
+from cmk.gui.valuespec import (
+    Dictionary,
+    TextAscii,
+    FixedValue,
 )
+
+from cmk.gui.plugins.wato import (
+    CheckParameterRulespecWithItem,
+    rulespec_registry,
+    RulespecGroupCheckParametersNetworking,
+)
+
+
+def _parameter_valuespec_checkpoint_fwm_ls():
+    return Dictionary(elements=[
+        ('ignore_status_on_r80_10',
+         FixedValue(
+             True,
+             title=_('Ignore status and alive on Check Point R80.10'),
+             totext=_('enabled'),
+             default_value=False,
+         )),
+    ])
+
+
+rulespec_registry.register(
+    CheckParameterRulespecWithItem(
+        check_group_name='checkpoint_fwm_ls',
+        group=RulespecGroupCheckParametersNetworking,
+        item_spec=lambda: TextAscii(title=_('Check Point Firewall management log server'), ),
+        match_type='dict',
+        parameter_valuespec=_parameter_valuespec_checkpoint_fwm_ls,
+        title=lambda: _('Check Point Firewall management log server'),
+    ))
-- 
GitLab