From 8f2f876d29ad01bab26cd16bf0cded41e0e9335c Mon Sep 17 00:00:00 2001 From: "Th.L" <thl-cmk@outlook.com> Date: Thu, 25 Mar 2021 10:57:42 +0100 Subject: [PATCH] update project --- agent_based/cisco_asyncos_license.py | 236 ++++++++++++++++++++++ agent_based/cisco_asyncos_resources.py | 99 +++++++++ checks/cisco_asyncos_resources | 63 ------ cisco_asyncos.mkp | Bin 11777 -> 11972 bytes packages/cisco_asyncos | 8 +- web/plugins/wato/cisco_asyncos_license.py | 76 ++++--- 6 files changed, 387 insertions(+), 95 deletions(-) create mode 100644 agent_based/cisco_asyncos_license.py create mode 100644 agent_based/cisco_asyncos_resources.py delete mode 100644 checks/cisco_asyncos_resources diff --git a/agent_based/cisco_asyncos_license.py b/agent_based/cisco_asyncos_license.py new file mode 100644 index 0000000..3d8bc5a --- /dev/null +++ b/agent_based/cisco_asyncos_license.py @@ -0,0 +1,236 @@ +#!/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 +# Date : 2020-02-10 +# +# monitors license status of Cisco IronPort Appliances (ESA/SMA/WSA) +# Tested with: C380, M380, C370, M670, S370 +# +# 2021-03-25: rewrite for CMK2.0 +# +# sample snmpwalk: +# +# OMD[cmk16x]:~$ snmpwalk -v2c -c public localhost -m ASYNCOS-MAIL-MIB -ObentU keyExpirationTable +# .1.3.6.1.4.1.15497.1.1.1.12.1.1.1 = INTEGER: 1 +# .1.3.6.1.4.1.15497.1.1.1.12.1.1.2 = INTEGER: 2 +# .1.3.6.1.4.1.15497.1.1.1.12.1.1.3 = INTEGER: 3 +# .1.3.6.1.4.1.15497.1.1.1.12.1.1.4 = INTEGER: 4 +# .1.3.6.1.4.1.15497.1.1.1.12.1.1.5 = INTEGER: 5 +# .1.3.6.1.4.1.15497.1.1.1.12.1.1.6 = INTEGER: 6 +# .1.3.6.1.4.1.15497.1.1.1.12.1.1.7 = INTEGER: 7 +# .1.3.6.1.4.1.15497.1.1.1.12.1.1.8 = INTEGER: 8 +# .1.3.6.1.4.1.15497.1.1.1.12.1.1.9 = INTEGER: 9 +# .1.3.6.1.4.1.15497.1.1.1.12.1.1.10 = INTEGER: 10 +# .1.3.6.1.4.1.15497.1.1.1.12.1.1.11 = INTEGER: 11 +# .1.3.6.1.4.1.15497.1.1.1.12.1.2.1 = STRING: Bounce Verification +# .1.3.6.1.4.1.15497.1.1.1.12.1.2.2 = STRING: Data Loss Prevention +# .1.3.6.1.4.1.15497.1.1.1.12.1.2.3 = STRING: External Threat Feeds +# .1.3.6.1.4.1.15497.1.1.1.12.1.2.4 = STRING: File Analysis +# .1.3.6.1.4.1.15497.1.1.1.12.1.2.5 = STRING: File Reputation +# .1.3.6.1.4.1.15497.1.1.1.12.1.2.6 = STRING: Incoming Mail Handling +# .1.3.6.1.4.1.15497.1.1.1.12.1.2.7 = STRING: IronPort Anti-Spam +# .1.3.6.1.4.1.15497.1.1.1.12.1.2.8 = STRING: IronPort Email Encryption +# .1.3.6.1.4.1.15497.1.1.1.12.1.2.9 = STRING: McAfee +# .1.3.6.1.4.1.15497.1.1.1.12.1.2.10 = STRING: Outbreak Filters +# .1.3.6.1.4.1.15497.1.1.1.12.1.2.11 = STRING: Sophos Anti-Virus +# .1.3.6.1.4.1.15497.1.1.1.12.1.3.1 = INTEGER: 1 +# .1.3.6.1.4.1.15497.1.1.1.12.1.3.2 = INTEGER: 2 +# .1.3.6.1.4.1.15497.1.1.1.12.1.3.3 = INTEGER: 2 +# .1.3.6.1.4.1.15497.1.1.1.12.1.3.4 = INTEGER: 2 +# .1.3.6.1.4.1.15497.1.1.1.12.1.3.5 = INTEGER: 2 +# .1.3.6.1.4.1.15497.1.1.1.12.1.3.6 = INTEGER: 1 +# .1.3.6.1.4.1.15497.1.1.1.12.1.3.7 = INTEGER: 2 +# .1.3.6.1.4.1.15497.1.1.1.12.1.3.8 = INTEGER: 2 +# .1.3.6.1.4.1.15497.1.1.1.12.1.3.9 = INTEGER: 2 +# .1.3.6.1.4.1.15497.1.1.1.12.1.3.10 = INTEGER: 2 +# .1.3.6.1.4.1.15497.1.1.1.12.1.3.11 = INTEGER: 2 +# .1.3.6.1.4.1.15497.1.1.1.12.1.4.1 = Gauge32: 0 +# .1.3.6.1.4.1.15497.1.1.1.12.1.4.2 = Gauge32: 0 +# .1.3.6.1.4.1.15497.1.1.1.12.1.4.3 = Gauge32: 32542740 +# .1.3.6.1.4.1.15497.1.1.1.12.1.4.4 = Gauge32: 32542804 +# .1.3.6.1.4.1.15497.1.1.1.12.1.4.5 = Gauge32: 32542804 +# .1.3.6.1.4.1.15497.1.1.1.12.1.4.6 = Gauge32: 0 +# .1.3.6.1.4.1.15497.1.1.1.12.1.4.7 = Gauge32: 32542740 +# .1.3.6.1.4.1.15497.1.1.1.12.1.4.8 = Gauge32: 0 +# .1.3.6.1.4.1.15497.1.1.1.12.1.4.9 = Gauge32: 1463722 +# .1.3.6.1.4.1.15497.1.1.1.12.1.4.10 = Gauge32: 32542740 +# .1.3.6.1.4.1.15497.1.1.1.12.1.4.11 = Gauge32: 32542740 +# +# OMD[cmk16x]:~$ snmpwalk -v2c -c public localhost -m ASYNCOS-MAIL-MIB keyExpirationTable +# ASYNCOS-MAIL-MIB::keyExpirationIndex.1 = INTEGER: 1 +# ASYNCOS-MAIL-MIB::keyExpirationIndex.2 = INTEGER: 2 +# ASYNCOS-MAIL-MIB::keyExpirationIndex.3 = INTEGER: 3 +# ASYNCOS-MAIL-MIB::keyExpirationIndex.4 = INTEGER: 4 +# ASYNCOS-MAIL-MIB::keyExpirationIndex.5 = INTEGER: 5 +# ASYNCOS-MAIL-MIB::keyExpirationIndex.6 = INTEGER: 6 +# ASYNCOS-MAIL-MIB::keyExpirationIndex.7 = INTEGER: 7 +# ASYNCOS-MAIL-MIB::keyExpirationIndex.8 = INTEGER: 8 +# ASYNCOS-MAIL-MIB::keyExpirationIndex.9 = INTEGER: 9 +# ASYNCOS-MAIL-MIB::keyExpirationIndex.10 = INTEGER: 10 +# ASYNCOS-MAIL-MIB::keyExpirationIndex.11 = INTEGER: 11 +# ASYNCOS-MAIL-MIB::keyDescription.1 = STRING: Bounce Verification +# ASYNCOS-MAIL-MIB::keyDescription.2 = STRING: Data Loss Prevention +# ASYNCOS-MAIL-MIB::keyDescription.3 = STRING: External Threat Feeds +# ASYNCOS-MAIL-MIB::keyDescription.4 = STRING: File Analysis +# ASYNCOS-MAIL-MIB::keyDescription.5 = STRING: File Reputation +# ASYNCOS-MAIL-MIB::keyDescription.6 = STRING: Incoming Mail Handling +# ASYNCOS-MAIL-MIB::keyDescription.7 = STRING: IronPort Anti-Spam +# ASYNCOS-MAIL-MIB::keyDescription.8 = STRING: IronPort Email Encryption +# ASYNCOS-MAIL-MIB::keyDescription.9 = STRING: McAfee +# ASYNCOS-MAIL-MIB::keyDescription.10 = STRING: Outbreak Filters +# ASYNCOS-MAIL-MIB::keyDescription.11 = STRING: Sophos Anti-Virus +# ASYNCOS-MAIL-MIB::keyIsPerpetual.1 = INTEGER: true(1) +# ASYNCOS-MAIL-MIB::keyIsPerpetual.2 = INTEGER: false(2) +# ASYNCOS-MAIL-MIB::keyIsPerpetual.3 = INTEGER: false(2) +# ASYNCOS-MAIL-MIB::keyIsPerpetual.4 = INTEGER: false(2) +# ASYNCOS-MAIL-MIB::keyIsPerpetual.5 = INTEGER: false(2) +# ASYNCOS-MAIL-MIB::keyIsPerpetual.6 = INTEGER: true(1) +# ASYNCOS-MAIL-MIB::keyIsPerpetual.7 = INTEGER: false(2) +# ASYNCOS-MAIL-MIB::keyIsPerpetual.8 = INTEGER: false(2) +# ASYNCOS-MAIL-MIB::keyIsPerpetual.9 = INTEGER: false(2) +# ASYNCOS-MAIL-MIB::keyIsPerpetual.10 = INTEGER: false(2) +# ASYNCOS-MAIL-MIB::keyIsPerpetual.11 = INTEGER: false(2) +# ASYNCOS-MAIL-MIB::keySecondsUntilExpire.1 = Gauge32: 0 +# ASYNCOS-MAIL-MIB::keySecondsUntilExpire.2 = Gauge32: 0 +# ASYNCOS-MAIL-MIB::keySecondsUntilExpire.3 = Gauge32: 32542740 +# ASYNCOS-MAIL-MIB::keySecondsUntilExpire.4 = Gauge32: 32542804 +# ASYNCOS-MAIL-MIB::keySecondsUntilExpire.5 = Gauge32: 32542804 +# ASYNCOS-MAIL-MIB::keySecondsUntilExpire.6 = Gauge32: 0 +# ASYNCOS-MAIL-MIB::keySecondsUntilExpire.7 = Gauge32: 32542740 +# ASYNCOS-MAIL-MIB::keySecondsUntilExpire.8 = Gauge32: 0 +# ASYNCOS-MAIL-MIB::keySecondsUntilExpire.9 = Gauge32: 1463722 +# ASYNCOS-MAIL-MIB::keySecondsUntilExpire.10 = Gauge32: 32542740 +# ASYNCOS-MAIL-MIB::keySecondsUntilExpire.11 = Gauge32: 32542740 +# + +import time +from typing import Mapping, List, NamedTuple + +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, + check_levels, + Result, + SNMPTree, + contains, + State, + render, +) + + +def get_isperpetual(isperpetual): + s_status = { + '1': True, + '2': False + } + return s_status.get(isperpetual, False) + + +class CiscoAsyncosLicense(NamedTuple): + perpetual: bool + secondsuntilexpire: int + daysuntilexpire: int + expiredate: str + + +# [[ +# ['Bounce Verification', '1', '0'], +# ['Data Loss Prevention', '2', '0'], +# ['External Threat Feeds', '2', '32542740'], +# ['File Analysis', '2', '32542804'], +# ['File Reputation', '2', '32542804'], +# ['Incoming Mail Handling', '1', '0'], +# ['IronPort Anti-Spam', '2', '32542740'], +# ['IronPort Email Encryption', '2', '0'], +# ['McAfee', '2', '1463722'], +# ['Outbreak Filters', '2', '32542740'], +# ['Sophos Anti-Virus', '2', '32542740'] +# ]] +def parse_cisco_asyncos_license(string_table: List[StringTable]) -> Mapping[str, CiscoAsyncosLicense]: + licenses = {} + for license, isperpetual, secondsuntilexpire in string_table[0]: + licenses.update({license: CiscoAsyncosLicense( + perpetual=get_isperpetual(isperpetual), + secondsuntilexpire=int(secondsuntilexpire), + daysuntilexpire=int(secondsuntilexpire) // 3600 // 24, + expiredate=time.strftime("%d %b %Y", time.localtime(time.time() + int(secondsuntilexpire))) + )}) + return licenses + + +# { +# 'Bounce Verification': CiscoAsyncosLicense(perpetual=True, secondsuntilexpire=0, daysuntilexpire=0, expiredate='25 Mar 2021'), +# 'Data Loss Prevention': CiscoAsyncosLicense(perpetual=False, secondsuntilexpire=0, daysuntilexpire=0, expiredate='25 Mar 2021'), +# 'External Threat Feeds': CiscoAsyncosLicense(perpetual=False, secondsuntilexpire=32542740, daysuntilexpire=376, expiredate='06 Apr 2022'), +# 'File Analysis': CiscoAsyncosLicense(perpetual=False, secondsuntilexpire=32542804, daysuntilexpire=376, expiredate='06 Apr 2022'), +# 'File Reputation': CiscoAsyncosLicense(perpetual=False, secondsuntilexpire=32542804, daysuntilexpire=376, expiredate='06 Apr 2022'), +# 'Incoming Mail Handling': CiscoAsyncosLicense(perpetual=True, secondsuntilexpire=0, daysuntilexpire=0, expiredate='25 Mar 2021'), +# 'IronPort Anti-Spam': CiscoAsyncosLicense(perpetual=False, secondsuntilexpire=32542740, daysuntilexpire=376, expiredate='06 Apr 2022'), +# 'IronPort Email Encryption': CiscoAsyncosLicense(perpetual=False, secondsuntilexpire=0, daysuntilexpire=0, expiredate='25 Mar 2021'), +# 'McAfee': CiscoAsyncosLicense(perpetual=False, secondsuntilexpire=1463722, daysuntilexpire=16, expiredate='11 Apr 2021'), +# 'Outbreak Filters': CiscoAsyncosLicense(perpetual=False, secondsuntilexpire=32542740, daysuntilexpire=376, expiredate='06 Apr 2022'), +# 'Sophos Anti-Virus': CiscoAsyncosLicense(perpetual=False, secondsuntilexpire=32542740, daysuntilexpire=376, expiredate='06 Apr 2022') +# } + +def discovery_cisco_asyncos_license(section: Mapping[str, CiscoAsyncosLicense]) -> DiscoveryResult: + yield Service() + +# Parameters({'expire': (400, 360), 'features_ignore': ['Data Loss Prevention']}) +def check_cisco_asyncos_license(params, section: Mapping[str, CiscoAsyncosLicense]) -> CheckResult: + features_ignore = params.get('features_ignore', []) + warn, crit = params.get('expire') + ignore_count = 0 + for license in section.keys(): + if section[license].perpetual: + yield Result(state=State.OK, notice='%s is perpetual (will not expire)' % license) + elif license in features_ignore: + yield Result(state=State.OK, notice='%s will expire at %s (%s days). Feature ignored!' % (license, section[license].expiredate, section[license].daysuntilexpire)) + ignore_count += 1 + elif section[license].secondsuntilexpire == 0: + yield Result(state=State.CRIT, notice='%s has expired or is not licensed' % license) + else: + if section[license].daysuntilexpire < crit: + state = State.CRIT + elif section[license].daysuntilexpire < warn: + state = State.WARN + else: + state = State.OK + + yield Result(state=state, notice='%s will expire at %s (%s days)' % (license, section[license].expiredate, section[license].daysuntilexpire)) + + yield Result(state=State.OK, summary='%d/%d Features found/ignored' % (len(section.keys()), ignore_count)) + +register.snmp_section( + name='cisco_asyncos_license', + parse_function=parse_cisco_asyncos_license, + fetch=[ + SNMPTree( + base='.1.3.6.1.4.1.15497.1.1.1.12.1', # ASYNCOS-MAIL-MIB::keyExpirationEntry + oids=[ + '2', # keyDescription + '3', # keyIsPerpetual + '4', # keySecondsUntilExpire + ] + ), + ], + detect=contains('.1.3.6.1.2.1.1.1.0', 'AsyncOS'), +) + +register.check_plugin( + name='cisco_asyncos_license', + service_name='License', + discovery_function=discovery_cisco_asyncos_license, + check_function=check_cisco_asyncos_license, + check_default_parameters={'expire': (30, 7)}, + check_ruleset_name='cisco_asyncos_license', +) diff --git a/agent_based/cisco_asyncos_resources.py b/agent_based/cisco_asyncos_resources.py new file mode 100644 index 0000000..0f4cda0 --- /dev/null +++ b/agent_based/cisco_asyncos_resources.py @@ -0,0 +1,99 @@ +#!/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 +# Date : 2020-03-08 +# +# monitors status Cisco IronPort Appliances (ESA) system resources +# Tested with: C380, C370 +# +# 2021-03-25: rewrite for CMK2.0 +# +# .1.3.6.1.4.1.15497.1.1.1.6.0 = INTEGER: 1 +# +# ASYNCOS-MAIL-MIB::resourceConservationReason.0 = INTEGER: noResourceConservation(1) +# +# +from typing import Mapping, List, NamedTuple + +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, + check_levels, + Result, + SNMPTree, + contains, + State, + render, +) + + +def get_status_readable(st: str) -> str: + states = { + '1': 'none', + '2': 'memory shortage', + '3': 'queue space shortage', + '4': 'queue Full', + } + return states.get(st, st) + + +def get_cmk_state(st: str) -> State: + states = { + '1': State.OK, + '2': State.WARN, + '3': State.WARN, + '4': State.CRIT, + } + return states.get(st, State.CRIT) + + +class CiscoAsyncosResources(NamedTuple): + state: State + status_readable: str + + +def parse_cisco_asyncos_bandwidth(string_table: List[StringTable]) -> CiscoAsyncosResources: + return CiscoAsyncosResources( + state=get_cmk_state(string_table[0][0][0]), + status_readable=get_status_readable(string_table[0][0][0]) + ) + + +def discovery_cisco_asyncos_resources(section: CiscoAsyncosResources) -> DiscoveryResult: + yield Service() + + +def check_cisco_asyncos_resources(section: CiscoAsyncosResources) -> CheckResult: + yield Result(state=section.state, notice='Resource conservation %s' % section.status_readable) + + +register.snmp_section( + name='cisco_asyncos_resources', + parse_function=parse_cisco_asyncos_bandwidth, + fetch=[ + SNMPTree( + base='.1.3.6.1.4.1.15497.1.1.1', # ASYNCOS-MAIL-MIB + oids=[ + '6', # resourceConservationReason + ] + ), + ], + detect=contains('.1.3.6.1.2.1.1.1.0', 'AsyncOS'), +) + +register.check_plugin( + name='cisco_asyncos_resources', + service_name='Resources', + discovery_function=discovery_cisco_asyncos_resources, + check_function=check_cisco_asyncos_resources, +) diff --git a/checks/cisco_asyncos_resources b/checks/cisco_asyncos_resources deleted file mode 100644 index 761a5bb..0000000 --- a/checks/cisco_asyncos_resources +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/python -# -*- encoding: utf-8; py-indent-offset: 4 -*- -# -# Author: Th.L. -# Date: 08-03-2020 -# -# monitors status Cisco IronPort Appliances (ESA) system resources -# Tested with: C380, C370 -# -# check_mk is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation in version 2. check_mk is distributed -# in the hope that it will be useful, but WITHOUT ANY WARRANTY; with- -# out even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. See the GNU General Public License for more de- -# tails. You should have received a copy of the GNU General Public -# License along with GNU Make; see the file COPYING. If not, write -# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, -# Boston, MA 02110-1301 USA. -# -# .1.3.6.1.4.1.15497.1.1.1.6.0 = INTEGER: 1 -# -# ASYNCOS-MAIL-MIB::resourceConservationReason.0 = INTEGER: noResourceConservation(1) -# -# sample info -# [[u'1', u'1']] -# - - -def inventory_cisco_asyncos_resources(info): - if len(info[0]) == 1: - return [(None, None)] - - -def check_cisco_asyncos_resources(_no_item, _no_params, info): - if len(info[0]) == 1: - recsourceStatus = info[0][0] - recsourceStatus = int(recsourceStatus) - - if recsourceStatus == 1: - yield 0, 'no resource conservation' - elif recsourceStatus ==2: - yield 1, 'Resource conservation: memory shortage' - elif recsourceStatus ==3: - yield 1, 'Resource conservation: queue space shortage' - elif recsourceStatus == 4: - yield 2, 'Resource conservation: queue Full' - - -check_info['cisco_asyncos_resources'] = { - 'inventory_function': inventory_cisco_asyncos_resources, - 'check_function': check_cisco_asyncos_resources, - 'service_description': 'Resources', - 'has_perfdata': False, - 'snmp_info': ( - '.1.3.6.1.4.1.15497.1.1.1', # ASYNCOS-MAIL-MIB - [ - '6', # resourceConservationReason - ]), - 'snmp_scan_function': lambda oid: oid('.1.3.6.1.2.1.1.1.0').find('AsyncOS') != -1, - # 'snmp_scan_function': scan_cisco_asyncos, - # 'includes': ['cisco_asyncos.include'], -} diff --git a/cisco_asyncos.mkp b/cisco_asyncos.mkp index d957f13594041c7efc82b37b452320063c94c037..048e9c6c3a99532a19865e7e3de65e825043c284 100644 GIT binary patch literal 11972 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≷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 Mmp;pZw1R^CFU;29F8}}l literal 11777 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 diff --git a/packages/cisco_asyncos b/packages/cisco_asyncos index 513ab34..96321b6 100644 --- a/packages/cisco_asyncos +++ b/packages/cisco_asyncos @@ -35,10 +35,10 @@ 'cisco_asyncos_conn.py', 'cisco_asyncos_dns.py', 'cisco_asyncos_messageage.py', - 'cisco_asyncos_queue.py'], - 'checks': ['cisco_asyncos_license', - 'cisco_asyncos_update', - 'cisco_asyncos_resources'], + 'cisco_asyncos_queue.py', + 'cisco_asyncos_resources.py', + 'cisco_asyncos_license.py'], + 'checks': ['cisco_asyncos_update'], 'web': ['plugins/wato/cisco_asyncos_license.py', 'plugins/wato/cisco_asyncos_queue.py', 'plugins/wato/cisco_asyncos_update.py', diff --git a/web/plugins/wato/cisco_asyncos_license.py b/web/plugins/wato/cisco_asyncos_license.py index 95fd5ef..bd4accb 100644 --- a/web/plugins/wato/cisco_asyncos_license.py +++ b/web/plugins/wato/cisco_asyncos_license.py @@ -1,31 +1,51 @@ -#!/usr/bin/python -# -*- encoding: utf-8; py-indent-offset: 4 -*- +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- # # -register_check_parameters( - subgroup_applications, - 'cisco_asyncos_license', - _('Cisco AsyncOS license'), - Dictionary( - # help=_(''), - elements=[ - ('features_ignore', - ListOfStrings( - title=_('license features to ignore'), - orientation='vertical', - help=_('there will be no warning/critical if this features are expired' - 'Examples: McAfee, IronPort Email Encryption, Data Loss Prevention, etc.'), - ) - ), - ('expire', - Tuple( - title=_('Levels for licence expiration in days'), - elements=[ - Integer(title=_('Warning'), default_value=30, unit=_('days before expiration')), - Integer(title=_('Critical'), default_value=7, unit=_('days before expiration')), - ])), - ], - ), - None, - match_type='dict', +from cmk.gui.i18n import _ +from cmk.gui.valuespec import ( + Dictionary, + Integer, + TextAscii, + ListOfStrings, + Tuple, ) + +from cmk.gui.plugins.wato import ( + CheckParameterRulespecWithItem, + rulespec_registry, + RulespecGroupCheckParametersNetworking, +) + + +def _parameter_valuespec_cisco_asyncos_license(): + return Dictionary(elements=[ + ('features_ignore', + ListOfStrings( + title=_('License features to ignore'), + orientation='vertical', + allow_empty=False, + # valuespec=Integer(minvalue=1, maxvalue=99), + help=_('there will be no warning/critical if this features are expired' + 'Examples: McAfee, IronPort Email Encryption, Data Loss Prevention, etc.'), + ) + ), + ('expire', + Tuple( + title=_('Levels for licence expiration in days'), + elements=[ + Integer(title=_('Warning'), default_value=30, unit=_('days before expiration')), + Integer(title=_('Critical'), default_value=7, unit=_('days before expiration')), + ])), + ]) + + +rulespec_registry.register( + CheckParameterRulespecWithItem( + check_group_name='cisco_asyncos_license', + group=RulespecGroupCheckParametersNetworking, + item_spec=lambda: TextAscii(title=_('Cisco AsyncOS license'), ), + match_type='dict', + parameter_valuespec=_parameter_valuespec_cisco_asyncos_license, + title=lambda: _('Cisco AsyncOS license'), + )) -- GitLab