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