From c3a4c18975d8f90725d884c5f79cb82e7f955988 Mon Sep 17 00:00:00 2001
From: "th.l" <thl-cmk@outlook.com>
Date: Sat, 31 Jul 2021 16:38:04 +0200
Subject: [PATCH] update project

---
 agent_based/cisco_flash.py           | 256 +++++++++++++++++++
 agent_based/inv_cisco_flash.py       | 352 +++++++++++++++++++++++++++
 cisco_flash.mkp                      | Bin 6794 -> 8138 bytes
 packages/cisco_flash                 |  24 +-
 web/plugins/metrics/cisco_flash.py   |  93 ++++---
 web/plugins/views/inv_cisco_flash.py |  83 +++----
 web/plugins/wato/cisco_flash.py      |  81 +++---
 web/plugins/wato/inv_cisco_flash.py  | 199 +++++++--------
 8 files changed, 856 insertions(+), 232 deletions(-)
 create mode 100644 agent_based/cisco_flash.py
 create mode 100644 agent_based/inv_cisco_flash.py

diff --git a/agent_based/cisco_flash.py b/agent_based/cisco_flash.py
new file mode 100644
index 0000000..9f6e0eb
--- /dev/null
+++ b/agent_based/cisco_flash.py
@@ -0,0 +1,256 @@
+#!/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  : 2019-10-28
+#
+# Monitor status of Cisco flash file systems
+#
+# 2019-10-28: initial release
+# 2019-11-04: added wato for cisco_flash
+# 2021-07-31: rewritten for CMK 2.0
+#
+# snmpwalk sample
+#
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.2.1.1 = INTEGER: 1
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.2.2.1 = INTEGER: 1
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.3.1.1 = INTEGER: 1
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.3.2.1 = INTEGER: 1
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.4.1.1 = Gauge32: 2908606464
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.4.2.1 = Gauge32: 4294967295
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.5.1.1 = Gauge32: 1756741632
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.5.2.1 = Gauge32: 4294967295
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.6.1.1 = Gauge32: 624
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.6.2.1 = Gauge32: 0
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.7.1.1 = INTEGER: 3
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.7.2.1 = INTEGER: 3
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.8.1.1 = INTEGER: 3
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.8.2.1 = INTEGER: 3
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.9.1.1 = INTEGER: 3
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.9.2.1 = INTEGER: 3
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.10.1.1 = STRING: "bootflash"
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.10.2.1 = STRING: "usb0"
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.11.1.1 = INTEGER: 2
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.11.2.1 = INTEGER: 2
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.12.1.1 = INTEGER: 63
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.12.2.1 = INTEGER: 63
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.13.1.1 = Counter64: 2908606464
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.13.2.1 = Counter64: 16424566784
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.14.1.1 = Counter64: 1756741632
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.14.2.1 = Counter64: 16424558592
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.15.1.1 = INTEGER: 10
+# .1.3.6.1.4.1.9.9.10.1.1.4.1.1.15.2.1 = INTEGER: 10
+#
+# sample info
+#
+# [
+#  [u'1.1', u'2908606464', u'1758527488', u'446', u'3', u'bootflash', u'2', u'2908606464', u'1758527488', u'10'],
+#  [u'2.1', u'4294967295', u'4294967295', u'0', u'3', u'usb0', u'2', u'16423845888', u'7506280448', u'10']
+# ]
+#
+#
+
+from dataclasses import dataclass
+from typing import Optional, Dict
+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,
+    SNMPTree,
+    contains,
+    check_levels,
+    OIDEnd,
+    Result,
+    render,
+    State,
+    Metric,
+    all_of,
+    exists,
+)
+
+
+@dataclass
+class Partition:
+    size: Optional[int] = None
+    freespace: Optional[int] = None
+    usedspace: Optional[int] = None
+    index: Optional[int] = None
+    flashindex: Optional[int] = None
+    neederasure: Optional[bool] = None
+    lowspacenotifythreshold: Optional[int] = None
+    filecount: Optional[int] = None
+
+
+_partneederasure = {
+    '1': True,
+    '2': False,
+}
+
+
+###########################################################################
+#
+#  DATA Parser function
+#
+###########################################################################
+
+
+def parse_cisco_flash(string_table: StringTable) -> Dict[str, Partition]:
+    partitions: Dict[str, Partition] = {}
+
+    for cflPartition in string_table:
+        cflpartOID_END, cflpartSize, cflpartFreeSpace, cflpartFileCount, cflpartName, cflpartNeedErasure, \
+        cflpartSizeExtended, cflpartFreeSpaceExtended, cflpartLowSpaceNotifThreshold = cflPartition
+
+        cflDevIndex, cflPartIndex = cflpartOID_END.split('.')
+
+        cflpartFreeSpace = int(cflpartFreeSpace) if cflpartFreeSpace.isdigit() else None
+        cflpartFreeSpaceExtended = int(cflpartFreeSpaceExtended) if cflpartFreeSpaceExtended.isdigit() else None
+        cflpartSize = int(cflpartSize) if cflpartSize.isdigit() else None
+        cflpartSizeExtended = int(cflpartSizeExtended) if cflpartSizeExtended.isdigit() else None
+
+        freespace = cflpartFreeSpaceExtended if cflpartFreeSpaceExtended else cflpartFreeSpace
+        size = cflpartSizeExtended if cflpartSizeExtended else cflpartSize
+
+        if size > 0:
+            partitions.update({
+                cflpartName: Partition(
+                    index=int(cflPartIndex) if cflPartIndex.isdigit() else None,
+                    flashindex=int(cflDevIndex) if cflDevIndex.isdigit() else None,
+                    size=size,
+                    freespace=freespace,
+                    usedspace=size - freespace,
+                    filecount=int(cflpartFileCount) if cflpartFileCount.isdigit() else None,
+                    neederasure=_partneederasure.get(cflpartNeedErasure, None),
+                    lowspacenotifythreshold=int(
+                        cflpartLowSpaceNotifThreshold) if cflpartLowSpaceNotifThreshold.isdigit() else None
+                )})
+
+    return partitions
+
+
+###########################################################################
+#
+#  INVENTORY function
+#
+###########################################################################
+
+
+def discovery_cisco_flash(section: Dict[str, Partition]) -> DiscoveryResult:
+    for key in section:
+        yield Service(item=key)
+
+
+###########################################################################
+#
+#  CHECK function
+#
+###########################################################################
+
+
+def check_cisco_flash(item, params, section: Dict[str, Partition]) -> CheckResult:
+    try:
+        partition = section[item]
+    except KeyError:
+        return
+
+    if partition.lowspacenotifythreshold:
+        spacewarn = partition.size - ((partition.size / 100) * partition.lowspacenotifythreshold)
+    else:
+        spacewarn = partition.size
+
+    yield from check_levels(
+        value=partition.usedspace,
+        label='Space used',
+        metric_name='cisco_flash_partusedspace',
+        render_func=render.disksize,
+        levels_upper=(spacewarn, partition.size - 10),
+        boundaries=(0, partition.size),
+    )
+
+    percentused = 100 * partition.usedspace / partition.size
+
+    yield from check_levels(
+        value=percentused,
+        label='Percent',
+        levels_upper=params['levels_upper_percent'],
+        render_func=render.percent,
+        boundaries=(0, 100),
+        metric_name='cisco_flash_percent_used'
+    )
+
+    if partition.neederasure:
+        yield Result(state=State.WARN, notice='Partition needs erasure')
+
+    yield Metric(
+        value=partition.filecount,
+        name='cisco_flash_partfilecount',
+        boundaries=(0, None)
+    )
+
+    for key, value in [
+        ('Device index', partition.flashindex),
+        ('Partition index', partition.index),
+        ('Partition need erasure', partition.neederasure),
+        ('Partition low space notify threshold', partition.lowspacenotifythreshold),
+    ]:
+        if value:
+            yield Result(state=State.OK, notice=f'{key}: {value}')
+
+    size = max(partition.size, 1)  # for size = 0 --> div/0
+    size = size / 1000 / 1000
+    usedspace = partition.usedspace / 1000 / 1000
+    freespace = partition.freespace / 1000 / 1000
+
+    yield Result(state=State.OK, notice=f'Used: {usedspace:.2f} of {size:.2f} MB, {freespace:.2f} MB free')
+
+    if partition.filecount:
+        yield Result(state=State.OK, summary=f'File count: {partition.filecount}')
+
+
+###########################################################################
+#
+#  SNMP section
+#
+###########################################################################
+
+
+register.snmp_section(
+    name='cisco_flash',
+    parse_function=parse_cisco_flash,
+    fetch=SNMPTree(
+        base='.1.3.6.1.4.1.9.9.10.1.1.4.1.1',  #
+        oids=[
+            OIDEnd(),
+            '4',  # ciscoFlashPartitionSize
+            '5',  # ciscoFlashPartitionFreeSpace
+            '6',  # ciscoFlashPartitionFileCount
+            '10',  # ciscoFlashPartitionName
+            '11',  # ciscoFlashPartitionNeedErasure
+            '13',  # ciscoFlashPartitionSizeExtended
+            '14',  # ciscoFlashPartitionFreeSpaceExtended
+            '15',  # ciscoFlashPartitionLowSpaceNotifThreshold
+        ]
+    ),
+    detect=all_of(
+        contains('.1.3.6.1.2.1.1.1.0', 'cisco'),  # sysDescr
+        exists('.1.3.6.1.4.1.9.9.10.1.1.4.1.1.10.*'),  # CISCO-FLASH-MIB::ciscoFlashDevicesSupported
+    ))
+
+register.check_plugin(
+    name='cisco_flash',
+    service_name='Flash partition %s',
+    discovery_function=discovery_cisco_flash,
+    check_function=check_cisco_flash,
+    check_default_parameters={
+        'levels_upper_percent': (85, 90),
+    },
+    check_ruleset_name='cisco_flash',
+)
diff --git a/agent_based/inv_cisco_flash.py b/agent_based/inv_cisco_flash.py
new file mode 100644
index 0000000..2a23f76
--- /dev/null
+++ b/agent_based/inv_cisco_flash.py
@@ -0,0 +1,352 @@
+#!/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  : 2019-10-22 
+#
+# invetory of cisco flash devices
+#
+# 2019-10-22 : initial release
+# 2021-07-31: rewritten for CMK 2.0
+#
+#
+
+from typing import List, Dict, Any
+from dataclasses import dataclass
+from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import (
+    StringTable,
+    InventoryResult,
+)
+
+from cmk.base.plugins.agent_based.agent_based_api.v1 import (
+    OIDEnd,
+)
+
+from cmk.base.plugins.agent_based.agent_based_api.v1 import (
+    register,
+    SNMPTree,
+    TableRow,
+    exists,
+    all_of,
+    contains,
+)
+
+
+@dataclass
+class Section:
+    flash_devices: List[Dict[str, Any]]
+    flash_chips: List[Dict[str, Any]]
+    flash_partitions: List[Dict[str, Any]]
+
+
+_DevProgrammingJumper = {
+    '1': 'installed',
+    '2': 'not installed',
+    '3': 'unknown',
+}
+
+_DevRemovable = {
+    '1': True,
+    '2': False,
+}
+
+_PartStatus = {
+    '1': 'Read Only',
+    '2': 'run from flash',
+    '3': 'Read Write',
+}
+
+_PartChecksumAlgorithm = {
+    '1': 'simple Checksum',
+    '2': 'undefined',
+    '3': 'simple CRC',
+}
+
+_PartUpgradeMethod = {
+    '1': 'unkown',
+    '2': 'rxboot Flash Load Helper',
+    '3': 'direct',
+}
+
+_PartNeedErasure = {
+    '1': True,
+    '2': False,
+}
+
+
+def parse_inv_cisco_flash(string_table: List[StringTable]) -> Section:
+    cflDevices, cflChips, cflPartitions = string_table
+
+    flash_devices = []
+    for cflDevice in cflDevices:
+        clfOID_END, cflDevSize, cflDevMinPartitionSize, cflDevMaxPartitions, cflDevPartitions, cflDevChipCount, \
+        cflDevName, cflDevDescr, cflDevController, cflDevProgrammingJumper, cflDevInitTime, cflDevRemovable, \
+        cflDevPhyEntIndex, cflDevNameExtended, cflDevSizeExtended, cflDevMinPartitionSizeExtended = cflDevice
+
+        cflDevSize = int(cflDevSize) if cflDevSize.isdigit() else None
+        cflDevSizeExtended = int(cflDevSizeExtended) if cflDevSizeExtended.isdigit() else None
+        cflDevMinPartitionSize = int(cflDevMinPartitionSize) if cflDevMinPartitionSize.isdigit() else None
+        cflDevMinPartitionSizeExtended = int(
+            cflDevMinPartitionSizeExtended) if cflDevMinPartitionSizeExtended.isdigit() else None
+
+        # change sizes to MB
+        size = cflDevSizeExtended if cflDevSizeExtended else cflDevSize
+        size = size / 1024 / 1024 if size else None
+
+        minpartitionsize = cflDevMinPartitionSizeExtended if cflDevMinPartitionSizeExtended else cflDevMinPartitionSize
+        minpartitionsize = minpartitionsize / 1024 / 1024 if minpartitionsize else None
+
+        flash_device = {}
+        for key, value in [
+            ('index', clfOID_END),
+            ('name', cflDevName),
+            ('description', cflDevDescr),
+            ('controller', cflDevController),
+            ('programmingjumper', _DevProgrammingJumper.get(cflDevProgrammingJumper)),
+            ('inittime', cflDevInitTime),
+            ('removable', _DevRemovable.get(cflDevRemovable)),
+            ('nameextended', cflDevNameExtended),
+            ('physentindex', cflDevPhyEntIndex),
+            ('size', size),
+            ('minpartitionsize', minpartitionsize),
+            ('maxprtitions', cflDevMaxPartitions),
+            ('partitions', cflDevPartitions),
+            ('chipcount', cflDevChipCount),
+        ]:
+            if value:
+                flash_device.update({key: value})
+        flash_devices.append(flash_device)
+
+    flash_chips = []
+
+    for cflChip in cflChips:
+        cflOID_END, cflChipCode, cflChipDescr, cflChipWriteRetries, cflChipEraseRetries, cflChipMaxWriteRetries, \
+        cflChipMaxEraseRetries = cflChip
+
+        cflDevIndex, cflChipIndex = cflOID_END.split('.')
+
+        flash_chip = {}
+        for key, value in [
+            ('index', cflChipIndex),
+            ('flashindex', cflDevIndex),
+            ('code', cflChipCode),
+            ('description', cflChipDescr),
+            ('writeretries', cflChipWriteRetries),
+            ('eraseretries', cflChipEraseRetries),
+            ('maxwriteretries', cflChipMaxWriteRetries),
+            ('maxeraseretries', cflChipMaxEraseRetries),
+        ]:
+            if value:
+                flash_chip.update({key: value})
+
+        flash_chips.append(flash_chip)
+
+    flash_partitions = []
+    for cflPartition in cflPartitions:
+        cflpartOID_END, cflpartStartChip, cflpartEndChip, cflpartSize, cflpartFreeSpace, cflpartFileCount, \
+        cflpartChecksumAlgorithm, cflpartStatus, cflpartUpgradeMethod, cflpartName, cflpartNeedErasure, \
+        cflpartFileNameLength, cflpartSizeExtended, cflpartFreeSpaceExtended, \
+        cflpartLowSpaceNotifThreshold = cflPartition
+
+        cflDevIndex, cflPartIndex = cflpartOID_END.split('.')
+
+        cflpartSize = int(cflpartSize) if cflpartSize.isdigit() else None
+        cflpartFreeSpace = int(cflpartFreeSpace) if cflpartFreeSpace.isdigit() else None
+        cflpartSizeExtended = int(cflpartSizeExtended) if cflpartSizeExtended.isdigit() else None
+        cflpartFreeSpaceExtended = int(cflpartFreeSpaceExtended) if cflpartFreeSpaceExtended.isdigit() else None
+
+        # change sizes to MB
+        size = cflpartSizeExtended if cflpartSizeExtended else cflpartSize
+        size = size / 1024 / 1024 if size else None
+
+        freespace = cflpartFreeSpaceExtended if cflpartFreeSpaceExtended else cflpartFreeSpace
+        freespace = freespace / 1024 / 1024 if freespace else None
+
+        flash_partition = {}
+        for key, value in [
+            ('index', cflPartIndex),
+            ('flashindex', cflDevIndex),
+            ('startchip', cflpartStartChip),
+            ('endchip', cflpartEndChip),
+            ('filecount', cflpartFileCount),
+            ('crcsumalgo', _PartChecksumAlgorithm.get(cflpartChecksumAlgorithm)),
+            ('status', _PartStatus.get(cflpartStatus)),
+            ('upgrademethod', _PartUpgradeMethod.get(cflpartUpgradeMethod)),
+            ('name', cflpartName),
+            ('neederasure', _PartNeedErasure.get(cflpartNeedErasure)),
+            ('filenamelength', cflpartFileNameLength),
+            ('lowspacenotifythreshold', cflpartLowSpaceNotifThreshold),
+            ('size', size),
+            ('freespace', freespace),
+        ]:
+            if value:
+                flash_partition.update({key: value})
+
+        flash_partitions.append(flash_partition)
+
+    return Section(
+        flash_devices=flash_devices,
+        flash_chips=flash_chips,
+        flash_partitions=flash_partitions
+    )
+
+
+def inventory_cisco_flash(params, section: Section) -> InventoryResult:
+    flash_devices = section.flash_devices
+    flash_chips = section.flash_chips
+    flash_partitions = section.flash_partitions
+
+    # inventory of cisco flash devices
+    removecolumns = []
+    disabled = False
+    # 
+    if params:
+        disabled = params.get('cflDeviceDisable', disabled)
+        # get list of columns to remove from inventory
+        removecolumns = params.get('cflDeviceRemovecolumns', removecolumns)
+
+    if not disabled:
+
+        path = ['hardware', 'components', 'flash', 'devices']
+
+        for flash_device in flash_devices:
+            key_columns = {'index': flash_device['index'], }
+            flash_device.pop('index')
+            for key in flash_device.keys():
+                if key in removecolumns:
+                    flash_device.pop(key)
+
+            yield TableRow(
+                path=path,
+                key_columns=key_columns,
+                inventory_columns=flash_device
+            )
+
+    # inventory of cisco flash chips
+
+    removecolumns = []
+    disabled = False
+
+    if params:
+        disabled = params.get('cflChipDisable', disabled)
+        # get list of columns to remove from inventory
+        removecolumns = params.get('cflChipRemovecolumns', removecolumns)
+
+    if not disabled:
+        path = ['hardware', 'components', 'flash', 'chips']
+
+        for flash_chip in flash_chips:
+            key_columns = {'index': flash_chip['index'], 'flashindex': flash_chip['flashindex']}
+            flash_chip.pop('index')
+            flash_chip.pop('flashindex')
+            for key in flash_chip.keys():
+                if key in removecolumns:
+                    flash_chip.pop(key)
+
+            yield TableRow(
+                path=path,
+                key_columns=key_columns,
+                inventory_columns=flash_chip
+            )
+
+    # inventory of cisco flash partitions
+
+    removecolumns = []
+    disabled = False
+
+    if params:
+        disabled = params.get('cflPartitionDisable', disabled)
+        # get list of columns to remove from inventory
+        removecolumns = params.get('cflPartitionRemovecolumns', removecolumns)
+
+    if not disabled:
+        path = ['hardware', 'components', 'flash', 'partitions']
+
+        for flash_partition in flash_partitions:
+            key_columns = {'index': flash_partition['index'], 'flashindex': flash_partition['flashindex']}
+            flash_partition.pop('index')
+            flash_partition.pop('flashindex')
+            for key in flash_partition.keys():
+                if key in removecolumns:
+                    flash_partition.pop(key)
+
+            yield TableRow(
+                path=path,
+                key_columns=key_columns,
+                inventory_columns=flash_partition
+            )
+
+
+register.snmp_section(
+    name='inv_cisco_flash',
+    parse_function=parse_inv_cisco_flash,
+    fetch=[
+        SNMPTree(
+            base='.1.3.6.1.4.1.9.9.10.1.1.2.1',  #
+            oids=[
+                OIDEnd(),  # ifIndex
+                '2',  # ciscoFlashDeviceSize
+                '3',  # ciscoFlashDeviceMinPartitionSize
+                '4',  # ciscoFlashDeviceMaxPartitions
+                '5',  # ciscoFlashDevicePartitions
+                '6',  # ciscoFlashDeviceChipCount
+                '7',  # ciscoFlashDeviceName
+                '8',  # ciscoFlashDeviceDescr
+                '9',  # ciscoFlashDeviceController
+                '11',  # ciscoFlashDeviceProgrammingJumper
+                '12',  # ciscoFlashDeviceInitTime
+                '13',  # ciscoFlashDeviceRemovable
+                '14',  # ciscoFlashPhyEntIndex
+                '15',  # ciscoFlashDeviceNameExtended
+                '16',  # ciscoFlashDeviceSizeExtended
+                '17',  # ciscoFlashDeviceMinPartitionSizeExtended
+            ]
+        ),
+        SNMPTree(
+            base='.1.3.6.1.4.1.9.9.10.1.1.3.1.1',  #
+            oids=[
+                OIDEnd(),  # ifIndex
+                '2',  # ciscoFlashChipCode
+                '3',  # ciscoFlashChipDescr
+                '4',  # ciscoFlashChipWriteRetries
+                '5',  # ciscoFlashChipEraseRetries
+                '6',  # ciscoFlashChipMaxWriteRetries
+                '7',  # ciscoFlashChipMaxEraseRetries
+            ]
+        ),
+        SNMPTree(
+            base='.1.3.6.1.4.1.9.9.10.1.1.4.1.1',  #
+            oids=[
+                OIDEnd(),  # ifIndex
+                '2',  # ciscoFlashPartitionStartChip
+                '3',  # ciscoFlashPartitionEndChip
+                '4',  # ciscoFlashPartitionSize
+                '5',  # ciscoFlashPartitionFreeSpace
+                '6',  # ciscoFlashPartitionFileCount
+                '7',  # ciscoFlashPartitionChecksumAlgorithm
+                '8',  # ciscoFlashPartitionStatus
+                '9',  # ciscoFlashPartitionUpgradeMethod
+                '10',  # ciscoFlashPartitionName
+                '11',  # ciscoFlashPartitionNeedErasure
+                '12',  # ciscoFlashPartitionFileNameLength
+                '13',  # ciscoFlashPartitionSizeExtended
+                '14',  # ciscoFlashPartitionFreeSpaceExtended
+                '15',  # ciscoFlashPartitionLowSpaceNotifThreshold
+            ]
+        ),
+    ],
+    detect=all_of(
+        contains('.1.3.6.1.2.1.1.1.0', 'cisco'),
+        exists('.1.3.6.1.4.1.9.9.10.1.1.1.*'),  # CISCO-FLASH-MIB::ciscoFlashDevicesSupported
+    )
+)
+
+register.inventory_plugin(
+    name='inv_cisco_flash',
+    inventory_function=inventory_cisco_flash,
+    inventory_default_parameters={},
+    inventory_ruleset_name='inv_cisco_flash',
+)
diff --git a/cisco_flash.mkp b/cisco_flash.mkp
index 03216bd3d176ddaac49f9f0f7a47d8f3cefc7450..21fecb02981367afda43d078598a16f17dda2ee0 100644
GIT binary patch
literal 8138
zcmai&Q&c4m!0oe*Ns}f_#$?wt87JGeZB1_SNv9^;wr#skwwsLe{nvfHcir!8Kkc`@
z)^GpFV~~*KjNpx7Ag0!?rjCXdcE+w&%s<$Eu(R=SuzRquv2d{1+d4sA3fa1D@Fu-X
z8U`!aM9+hmR52(1l)HImbkg$3(59MsoQ?0R%;A_hD<tX&zqh79-rQj+pl>LZqc1bM
z#IOHQ;cTJj20IA0BYX9I^SkTafr<?me`FQC1#h36oX9w?y83)1E}Wz1@ZL1=`1}NY
zkB71bwPNEP3Nw^xTp7Z3uQ_Bg4UCfEzMa><b<63D&5NX0u>iIXnB;Lq&{zS-#xC5b
zn)V&0*uIMU+6Ps*tY`^mMFcZH>u<KaWR?SbcHwWI<9nN>q3v8mJ9ljO#oy@%$oEl+
zsg2zjrN_R-Mvgm6XeQ{40QR|b=huq*jV>jlB8p-e#~2OC61o>WF+c^O+eY%6FQ91|
zQ1yy&iqkZCz^S_w&qHGu?D4bFEJ<>tfs{egEJXp;M>VXQe8{f*PQ;a8rlfGRQwH_9
zm!B6MHCR9Vocbbs4t~JEOE?Z1J@X7Ej7!MVlt1EFRktj_)8E!JQXh-0Tj;!0qA4Rq
z!$HYRX|SXC7)^rnbT^tdktYT-#v6DLG)Od;Dpj*T5dG7hw!<U&#>q3fd>oty2kR-J
zJZ<B?_U6VlRp=Ybn%nc-Sggts%}6|y4>mOw7zy20Upd8C9K0GwEyn(^Jd>!*wzGP!
zE-<d#TBG4S65L;K|I^Wx7oIeH)dncBPVicl5)Oy%@`d_%>izVDU`O=*wSpiP<bPa4
zch^DUO(1_=-XL!BISwrlfWSeS$!B8e`g>qn6?mu?g3Zaj7I(o>k!O-q7u|G3l$h}W
z#e`MZIDO;ys>UM`smrYdnAvf+NQzNo!oFbh?ODU1da{?)94f1=EjlQl--gD~QN@eV
zQSq9xvs8%hbu(VY66eU4&9vYn`lh3ZPssryB5>eUM_Y1$(MWg|2J$uhyE%KliV8+c
zQQVLae|~<1ct!TOzk#nwvtA$tLDf5$yr1#uRz4#Grk|{pFRg{I)1yR3mzZ178-Z?u
zUXzdC55~ODUhdJoHs&D`yK7*K1zvu^rx0;sy~GD*d4!PQhuE+0NCi&3Pa!evGRZ@I
z$lY~0V&lG!lA-B;#x~-65?eTP6VH<Yr)}3$^_(tCmZhw#n<nySC3r#qHjbazQpuCo
zjlVb<v>{7?x)*!{W?eB}zsEu%*lvs@#d6V;Icax)W&v{hzTet|X4NNWX}G2(jZmQB
z<4Xa3uZLx9VuTh8NM8}w{)x`vgtwX#_x*?oU3y)AV3oP3UKTdLZtuFv6$t4Of4=5>
zuQ~3;{9HYMyk*Tu@Fef)4tRULPya`p@XwQm=ptvr=t(d9TUv{Qj~JrARon6O7*crf
zTrIS{VF~HuU(CPpf8J)|o9D^!@8RV*_{kn6Ljz#fKkiBK?@1pb&?8ZZ_;qFe#8mNE
ziOz#l56qtQ6g_4RU#{8&!9oO|P@IO{0Rd09%<^An2H18NmT3q5vw7oYvJu?6OtxMX
ztX>5cQtXDUX2VK*1e7g!48qx3is!6alNFzSkmM&kNe+D8SaI?TTZ@V?S@wk5JcYZj
zk!ODuauf|ztIt%#%@4>xia_B0hPCNyJX3N*&Zl5cQ71s%RHU~?wRnF}8Yn2pXB<DU
z8~Gt%6nH;9Nl!BS^mX%mpYKuP&-}c)5Wj4|DkQa1DKa#9cP`2(!0#aT_4~9F-F-;q
zbZsWEDY73wqa#Wn6lR2zb~~DR;a>AARh#}mBbD5Hsy$b0ZM5&<6waUE1z5cXx1rbi
z3Kr88u&U>!dyS9&j&zA@`>3m3-PWKcZ{<M$?ITB=s>rTxEUPnDb@ww2>ebF3BMYN|
z#>RRDoKH7)*Nu?|4)P~wdx&+i*Yor4!b)Uxi8diMixUArtG*0SQ_8yi{(7}^ZZsWO
zA@RqGZDws?Q@Zx8_YvdSapkFGHw045qXbG<pMC|b5niyqq+B+~5;<IaV9I~gOY%L0
z9H9B|Isobq;8TRc)n92rcn9_9BcUjpcH@X0@7#q!Dp;W;C5f5%R<SjCFS}ffideMU
zFtokcacOxX;1q#LCQB<B8z&~)=qxqa&xE_U#C0KG`EJQFD;%W)cJKXHc0n-oR>K>t
zh0bUNfuW%h$uQ@)7|wKKYxYC3`#L5i=FQZYvUcOe=!`vi+(l4bxum_z&9!_M0J@0E
zca`Yc#3j&CFY0$aoOWG!@7PQK%t9_0i+N+y7D{WBfYajjb-zOK@g2V1_45XS|C-<e
z`3{|vljO%85BXNA{3jCndnS)l#Jln&s&`Mfj1s}|p`a}N^?)t#2D@W-rIO&M`4Wnb
z4Q<WIl7L#UVt9WJ?{Aeght9{YLUYf{W_2c0gRi+EWSb1#4!DlW{g*zsn;lR<dzj)#
z*{)I(&{6|!C{x>y0;W2da5{S-OuvHqq2ppuxm;B-9-kwVZH|NkxjADhO_LZ7$daAQ
zlH8S2O}((akyu1NK>{9T_zE1wu?%ul5$QN34o6*o)o_`nU;hCt-zaz4bJi8XHks~l
zrUk!Cq#7}Hg^cecI8SlXm}Uy`97pA+@BGbVYVgQD=qbm(?~7-rLNr4S5MGp5yBwQL
zD&|_7I7(GPD3x&@JTsUT6q%Z)?C{{~$xKYa?@AIqWmq}_R2gv%OU6y-`hS-<{FTg!
zlEU(iWqQ>S9~k&?dtUPw@@6cx>CNrGB&9#@Qc1=?G+LqHJMtp!BjdOR#lU-@()mD#
z_RAz^{SK!+6Uyd|^4HVd@d|68w^rS)btA)%N@c{iu#RW}vks_K8W;i<oGn@FLw{7X
zx*hjuK2TKKV{A3<9cq_9sf020nAglf*P^a8%U1ho8Ru)d&!uE~9yRV!(Go)^f0%md
z0<DO{Ox_eKn(PuatAWe5`ZJD<cD3|nkIP4jBDJ*xW|740mg^b7PMEpRjpjMDL!{&+
z6jXZqb<*ds6Az{vFViGG^9HOxn<clEbpKOv;UQBpS;JsNQ5z&A#qNJ>WPj{%Fy}Sz
z5<Ln7SS2+=yECVO8xupdLQf$0s&njH$iP7_bB_yXuw|GMfRt5rgHQr&tdxH9!fRA%
z)pl@Mi%wgN6YJq;7o(jeRU7?n{n<QAAo|^IY2)K#=s2D<WQ%xMSGO7`K~5g-ubswZ
z+YOhCf8f-JsdmxXbUM{~Q<5=NnU1<~n1G;W<4_5o{Y1D7>S8D$&913q?B&n56JS+!
zbToBVtulX`6aP|w4JEu>zXIHDbJ)S~FH<#3C*FmII(|g+{MqlhO_v|%tlqY)7mgHT
z9qcc|gq!A7OctYzPsK)rc?HeL-oxvn6nqCzl^>fO{BCMG){>;R@!eH<8ItNvF?eSt
zqSjOIRf@)3HLs2d^ox29jc#u-0&emCrW-sLrvm`eI|YZ8NY6@nkJO_vA<PP8fx%Oo
zL&+8;Vo*9xo&H@_2&HY-+h5ro4IOSM@Y}C%8~x|`S&j@YyBY;%7-7&mB-Cq*7Aotk
zyIQE3lfYy<5~X#@O$E>@2@gnYXtV)D@$cyNKy87fTYr^7e*2P=>OgUtM=MG1?^=k`
zfKd4mGpi&~Uuh17Zp{gtPzex5Ga3HCK&W1?0nZA7<UFe?7WLP_C4Nm_C4u%s2<`V{
zT*)~d*G$pxSvU5&Ys~eed%z1~|0}=V1Xb)in-*>4y^UvlgzLjWKX8k=<3sQV9dD=K
z)8SzaqT_bY^WA-4gr`W{NWF@mQ*_VGr~qY{hwdDnu<P#IVHOw75hFUgjMo6w*d6;(
zgjVj@1E5+hRqmVnli&zb6^t5_7HzB1Lb06&TuA(0)aG7k4pp4Y`9Z08j-_k1K&oNN
zD`)XoV|l;*`AjT?4)I0E=Y8f@IgolU@Xw!YQ!g+{FD5R;bT9C1KkzloJcxaWsgUr9
zn}g<`<#bgd*~7y3C1VlveD6wznFHTi+fBwbO4g8#;;SiN7Xupy8NXYWn3`$9;HSNc
zNxfLi-RDKW>`L0d1GZZ<+HUHy@m56*cQNhmLn|ivjIr9T+2cZ_R&@;=@Q%&@mN)9u
zz-lz*<_gAi?|8on*xV{}e}6LS_Yvm3LF`J!V3x*PxYJ2y!(RmGi_q9;&{;xnh<nJ|
z_lf+9D{fF|mS^jDhh#<w$Y@Il4msS94_116mZEWrpuvtxBjyHQByR*xkeg_1n`sbK
zKM6i1kYpy*DbrR>DKUvMfdrLNr~RlX>eF<>J!<tY_UI<rs#=At1KyOV3D^XQDlsHz
z@f3atx58mA5P5$qbmoFK0<jw9AIcVg6t<e@p>+tAP!*My&GDuV-=cJC4!4mn>L;t7
za5~JT?x9Uk%k8RM91&v|IF`gSuSx0N@sCS;lt>E_a^56%pAcDREk<8_pCp0wzS;qy
zTv)=3A}HGvn;9rQYm1yE&|L99l|tVYWD5A($VcS5eUbpxM28o`%#MbLQEnO0I954Y
z%1?V8`Dl0$BbM2GM~x@xXo6_O@+gsdB@j+WK2QBkJM^2$R3lS#lq~m9p-?@;;y8oX
zZ*C<!Iw=kjrpghZgOk{rg`#{?g5Psle~b=ZU{QiAdAXP2LGm@hL&Ta$hGSE{+3dg}
zMZuRs4If>Jyf3wp4fNpo3KbezLUk6$A-3DuI6?CPkMCgZNp6;+U<Nyb#^;gja{e^7
zMNA-<t!h8$&|-u|Hy`IwC$lh+Eg9}tYG~k*Y?Z8S+Ug!2*KLZd`IqW2BJ*NJGf<W=
z&A_{Uhl-1u8+OMy1<<y$GtM|XtwnaO9Eem4fXd&)Otc>AhV>fKG$($t$S&GQ-B)Ux
zbciy7<(`Has`ht&R&kp7_i=Kje`W%n38l%Mi0AA3uTaiNrOQAZwQ(`czJgc#Ftn3@
z+*EsraOMbI=Q)|b|6X>=`jbM+(9fiyW99@|*@BXnhM@~??R<1SosmsV)?u10PdEix
zHC3rt!B}49t8dm9njRI;gdBVck_s&2GI@K2#*HZ@mM0vB>Yvtw@D`fQvQcm!Kg@B|
z@6^ZDvX%3cE08K07#klxi9^wKs#x)v4V4J|is&bFvU$%JOqiXNvP>Q0zsj%HkLVsd
z8f8}s@x(JT{l)+SRc)GU!zaj_;OB(JqP0+d1p-22%+}VpJn9Co0Z}HMJ*z#4F%f=2
zx&2b{t()$Tot|iWo(j3-yn`y{H61oh^J9hU^mW8^jn}g@12j)$?M|?QVg=S|_PXBb
z$VdF;Y(9q<=Fj3|JE>ALRtUq>@TL(QYvUi(Twm)_R;$bL(#K*+crqDKKa1tlTzuP2
z9yzI2Vk^fb<g6UEGR-90V!w$q)NkVX>f?s4Ri|(t9dR&L$LQ%i;b<#-4ez3%^)Imw
zs74A(fNTd^<o?p&Oedqu8(;rQ8CVnXJ3#s4xk&rvm+zU{)GylcYejo)+93jMG^`D&
z$r+isM{K#dsQgMh*t*&Wk?Kt>ycGRQ|DnvEBc_h$w5t5&#A*{#$leEXae?6zWE!PL
zjPGtm)3Zlp0%NdJ?9FowS`5MT6qsvrcy2j^ZX?q?#|F1<Ct*Yux<u1ZY0n0rT9@dg
z-qPWiVV?f`cDgzzpFYO>kIHXiSHy|24SiLRN+VObC>jMI9ggp*<h^Yg5wezT<uV%x
z4*9O3As%8!sroiKAC6=H1`pVp>-?4p45n2uckhmJwx~=5MYmXzx>zo;xUcN;lN7J>
z1JO8^k#_VqZPHT7eo@VG^~Ig<e=dEyp*wUr(K@naKrAZg{r+6?b*Ea|GXI^0iUEab
zb}7XA<gzNW|H1LQ#G1aus_efxd^p!FIibfn4B8Q!t@J2;+$GG`Py>qKeEhRPIVokF
z>2kLSW}kDelAr>ojeL{XBQks@)&WDgu39Yt22JNdA71o{wC?yC3-9IlV%u?`ZBc*K
zl73o}p+Dl%L|OC6-;fps<imHD7}_sbSrrA;ol@D0a`!7Llbv=Fmz!h~x;Mp+(S^*p
z<#UZLA9{Z(w#alhSS6R2f34VHH&0$Lt%h{?so3=pVvm<Z7g_0I7br#PosU#tp5up=
zw-m~|t0^=^nW-rx2`G-^jV$36JsX7ksl-)A)E}+R*rFtN+>TQpQkW<o=hsw+G#1ly
zr0K&;DEJ-)w4)@sT-3R>sppa}$+i6Wm7yAUCUA&QzHiahkTjtES!joNQIHqv^6%~A
z-0En>IybM)v?N&N3#kA)XZ^{lb#5ZQK{kSp_U^oQI>J|BN!W3Wj7tY@t8tL@g)6t!
z9J7V@3M<{?Yjl3QkZb-tf(>j%MKr6-J_3-ZWVTs`F?JNg(C^}HNh+>sd614rHY@$|
z^6~Ob`0LAbycEO3{e?j{jrIG7v?Bylis@kjo3D;3P)J2cJO%HCsm?{WDN_GocSIjs
z29jBz7bNl&g8_?xM#yH=8wCCT3y{AQ9lq~<EP(;_m!HQ0Lmx9;R3n>^ciu}@s<a$I
ztGAUL$QjyeXs}ga3D3p;OU=ipk=b;hKbmwW+zgFhYPCkod#wq~a!}<KYUgE$zUJ;Q
zbzVhNyj1Pp2orP{Fum-2<cq)~2N^CHbv_HD?J>mLi_|mnyifJ(tHVLxf=gVK<})@&
z0Ac{yjKD>bne7p6HMv2oj6A*eZ&$P$0X)`@b6wymf2=8He1{pi&j|1@`Oml0F0Q8=
z-og8nK*FhbJp+B6@n8YdnA#w_Yfuu+&^eTD7k8UMJF*N=O>HEbMu`*xoD>%vD_wHL
z70mnrBk0)NI64_)af<RP7eub+i`)h!7((#dt8a*s4bVxnt-40s$S3od!Qo6LYeKZ+
z6~O2U|Bq52N*qX)50URe8Wa6S7=`pJOiDP3tzH@@T)0mc<<~a^2bRtlynuZk^_##0
z_$}fdTHSEx`6i~$AW3`}lff3Ty=^R>^kjVZI-KV<Z37IFb7@U^1N}RCl$uVyp#d#s
z4_E8P@%n;2VRS*&&}>39_+x!>wUc!@-~q`SX>wrJ=5Cq-SfiT2O*73?Kc@4cI>=e{
z1igc>Np4g?os2%G=nWk(+d43fL>gV6<j(X9B@&>Yi>YcS$2u({+rrd`DFX5t<`~<)
zxew&5D>KJ&UzV+NGc_x~)fZbivQ(%~(xdaPW!kC2%Kbga&KZfsj=xf~v*Irv(bP9O
z<`5Np$I{P+DS4=$BcEHsODby1Vc>uT^Hf?a+L@+nL&4;v=M~UDoi9WK$P<}IG7!ET
z1%H$rOxEA<kX2SZrn&zzF3lCbZWC+gM-={@GvFoK0`)LDfvp>jWJ)|~N~@tnW>w>!
zIY^Df^>eaSb*UOSU+Z1P*@aP~ZE$A`n1j(~MJtdS{qQW#AnU**^C`YIHU45$|0%wL
zak5Y0!KBhUI^Kgo$<&#lj@2IfW%y`u9O}1F>X_vhB=21b=lQ#kLLpjLE-4^IMjb76
z)dh#@G&%E_1l~{IF(pUNS^9si+%A^cKSBHz776YI*+O3c6{w8H+xLT9;$%6>L#Uvb
zlYYz@<-Q7E!&a;kyWbfMb*8!coiK2cXjnM#eWpdKo#|?vTg(+?Zd|j;)yVnW|J(Es
zGW)rN0!L>72wD3g@gSG?64%A^jOUpVDCd}`U6lAI&`^Y|pp~b;Z~SEs<)<qz|M&)&
zFFatLgb#LPFi;pl@NL7GSSsS!z)3okvA$aYXv|idlNd^l`HK^rUO2Y50|(Zcp*Zv>
z^Le@DxdS3_y7=GG3q5sd10}0pzZi8(2kUau{=dcY|FL&r3GCXmWBg>~WGDw$KlHvE
z^Te`19pg*#!6<@Hg+xyH5I=A=lG4VNKl5Q@cx8Z0S9JH{W|T4`aE@9JxwF_0WhAP=
z^=nez5ya4K!tK4PNMv-a_tgo^o`irE=<qKB0pu|ri9Y%@o;YS{8vs=6pJnaZ8F0iR
z%}G5V6C@fDt-Eh7D{_Y!5(9Nu%#ZW^1#I~Fs=9N^9?krcr*|a4=>z{mrrH&<Wb28~
zy=qIQS(_ZvZR-*W=+3wIckaG7l9vhXlL+i?(pU`r0CFGyZb232@m3AXx2OU&%Xe}5
zg@91`y!tzXx--4M#;s)EhKdA-+|7pke6_plDgW7J*zqi-7!sB)sd5SxPTa@nlIT>6
z+wtUASCKE;jBu=Y77W`B6Nbe;Mee5B+{ks&+2Ilmv$_6wtf)%cvkvq5=O(YC7$I17
zT<_wT)66650ybC>&15+K_+93-CI)0!!pOhio3?PSa}Y#_^$zV{Rs?wQmiKN~@sw*m
z;=_B5420l!r0ACpU#(~9|EP1l0^bQ<9C*Y@H2SmVI+)2Jud{b))y0VC%9FfC{!9#u
zI)~+tjO)QiybrMSXjdqko*8RsoL+~N{CS!>3e+U)`h$sTNd#U%bGrXemZBjP?7cg(
z{QyJ$y9|L`xTMRz|E&MG6gLyp_&<4^2EV#X`z~;n=d=mJ3J&Bf5NWx3T+4;9AFB?k
z3Zu{7O|ixtJl1CEn=GdC5Z=n6b*v3}<vy1iCpJIE`2^?r5V!lwI1X4TQdyYRXK6Ob
ziK4CqT54L9BOo#cEu)tAj(@vL509Y_7&1N9sBxwVxUhJl@K>$4`D3WMIL2hfp;0*q
zuXwR{xE%3!UBFe>JGk?{EQF)b^H6%2^=*rl>OVF&lv1A@>{9*_<#`mR`R6vcpqH>F
znnKWAGpDi#Z*_MHPJly2Kra}~NMn7>f6Q~5!oaNRVcrhZynGMUZ&E#|+8h#x8?N@=
zDQCSM?;q;$L6TcdHBH%CQ#H#lJZk8m0JgAGtCe4Vm!?Wj-`O&HD`k6RW?;!GJu{^S
z9DrKtkJ4xy>Qdj&hIHi0^wpRziyc^b)?|hQF&W2D12MUOm=<mcYAW$Mf1F*(8)Frl
zD`YK@u5DIuji&EOBF8;XiAq#oR8uC=Tn!UA4p#3^I8d!8v#!1=NLUQ?J$R;&5ZW>D
z@3T6*u^iNLp&o_|GM^R4S$3T2acg2H<6d4lTuMGEoYCEb#lNT8Y=@fIY+k7ga80*{
zN!Mbg6icP|UVw$|`fxPa{YfXEEWF8GdG$-ZG3lL#CgPCf*8X~K??!i08kel44tso=
z+H*U6B{2409<CYE!RF~8w4J$1D0G%E>}~PAk$ZX2X7upaNUUnrjfq?oS`9o7Q$3bA
z)gx@hk&_;e1$TEr$DB2gv@>+T(c&g{OJM|fP4U|W@!0hJ)Y2<cpFH#TV&><TqUNKu
z{z!2D*U@aQUah1%bV!=HOnW}3xU|=>r|+xV?Z>}t{iEhQ<-2nckM6zdaDn1JWp#tS
z;6fhG+UCHLALM#np&!xt)8Ps7DAl$137#{W<#-DmhUi{GE=hUCnUH;g*0e>)11M!z
zXnJ~{Un|ZKfogB<0e`u+8xJg-Do^FX=>CUw1#+7wK;2qTv7f9~gXG=)<!=&#_ky>P
zmfkzeAxj&1rDgoCv|)g?HnP9B&(w6i*KGdYBY?3!fxV#(`W`iQMyc@kFY$PDFN5UP
zAyUPnm`1;$IeIAWOa`qDRF_N>wk$AWvi=j0HWRwEVmFhxs;#R{=Jx}V#iu^#o4*N0
zSqS}Tv+gbr!_a4Nzk*)M_*ea`V<WV@p<nV`HcRQHF!G~x_|CyEVt_&O21Pdpz-*jC
zqp1(=cPY~Pki2*y-kXiC-JZ6V8f^{MA#D}iJD)4N(F)L#wp0&pPAQ8*UA}2cJ;9qS
zPe)XPOrYu&uKD<wVg<IRIgs`202(WZ-FhAWe&dL;h8{=W&(mGlb3`S+kV0e(-OSk|
zKEMQBRuj8_{I~fgURNZpFNVJ+y_v+wU%LeanJLs1d^}yP@M^QJdq75w)jnjP71A6B
z85vNnIf0x%$-k!&K_IfXhRf3d6L+E?u7uw+GAc-c8@>v3+g?0wpPqw<GuOcz6Xr-$
zb>6hfj}^`1xS^gz82enz=~1V4yZ5A=M~}G;vj9!#9L*6ajiZSLfB#yH%^mPWsoDss
zN(#swM%iZ<O76bX9BH2YH(_~}tWnAbAV}-f6$h@31NlY`F-aPjLn*D<C8ixvo`u*@
z?sSQyHf0H0Dj^c*uCYb^GOM}5;Ie|#Y9o*eL%9(cW@bLao?NymVX9KI&X-KIJ54b2
z`#LxZ&)*UiOSVHh11rU!CMCE#jXD8E;8&1l9V4~V`J+#e)%mAl_F&!l5^|Qev(|AI
zBh4}hJ3;4Ph8cR^D_$)Z3JX>ln?!gj8G4j~ncjYGFUtLC59kQ*3~aQ=YS|LKHa!*Z
zQRBCTL)pSv)0u9YCY+b5QEL)+!!;gj`Y>-i?TzCuQq}HPH0Em1u6Ih-9W?K8r6qY$
zjA<y?EYNB@#}J-qf_>QAY)y0m`$eEdmF`>Y;3Tzbzhu9JJ{kZ+?yM#;(P!R1SjK<r
zc@J@d5J3C~i2wCplfe{&I_divTgqGwLXpXHMPJIk0V$)sS%ujANaJ|w8Akh~)`$6o
z<iAjljI;5pE!&j39t0}#_b0pTd86kbbX62KZxA=Vx^p0nMMG%jFMs(OTNZoj8Zib1
ztg~CrfDZRyQjerXcxBs#fP{J&>srkLo~+uTgR!ywpRf!k<Kc>z??-^meD?npkpA!g
QlJm|==8>WYMF<V`KZX(s?f?J)

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

diff --git a/packages/cisco_flash b/packages/cisco_flash
index 4389a03..6b51347 100644
--- a/packages/cisco_flash
+++ b/packages/cisco_flash
@@ -1,15 +1,21 @@
-{'author': u'Th.L. (thl-cmk[at]outlook[dot]com)',
- 'description': u'Cisco flash plugins:\n - snmp_cisco_flash: inventory plugin for Cisco flash memory\n - cisco_flash: check for Cisco partitions\n\n- 2020-05-13: added support for CMK1.6x\n',
+{'author': 'Th.L. (thl-cmk[at]outlook[dot]com)',
+ 'description': 'Cisco flash plugins:\n'
+                ' - inv_cisco_flash: inventory plugin for Cisco flash memory\n'
+                ' - cisco_flash: check for Cisco partitions\n'
+                '\n'
+                '- 2020-05-13: added support for CMK1.6x\n'
+                '- 2021-07-31: rewritten for CMK 2.0\n',
  'download_url': 'https://thl-cmk.hopto.org',
- 'files': {'checks': ['cisco_flash'],
-           'inventory': ['snmp_cisco_flash'],
+ 'files': {'agent_based': ['cisco_flash.py', 'inv_cisco_flash.py'],
+           'checkman': ['cisco_flash'],
            'web': ['plugins/metrics/cisco_flash.py',
                    'plugins/views/inv_cisco_flash.py',
                    'plugins/wato/cisco_flash.py',
                    'plugins/wato/inv_cisco_flash.py']},
  'name': 'cisco_flash',
- 'num_files': 6,
- 'title': u'Cisco flash plugins',
- 'version': '20200513v.0.2c',
- 'version.min_required': '1.4.0p35',
- 'version.packaged': '1.6.0p8'}
\ No newline at end of file
+ 'num_files': 7,
+ 'title': 'Cisco flash plugins',
+ 'version': '20210731v.0.3',
+ 'version.min_required': '2.0.0',
+ 'version.packaged': '2021.07.14',
+ 'version.usable_until': None}
\ No newline at end of file
diff --git a/web/plugins/metrics/cisco_flash.py b/web/plugins/metrics/cisco_flash.py
index 28a3bbe..2c1805f 100644
--- a/web/plugins/metrics/cisco_flash.py
+++ b/web/plugins/metrics/cisco_flash.py
@@ -1,56 +1,47 @@
-#!/usr/bin/python
-# -*- encoding: utf-8; py-indent-offset: 4 -*-
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
 #
-# Cisco flash metrics plugin
-#
-# Author: Th.L.
+# License: GNU General Public License v2
+
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
 # Date  : 2019-10-28
 #
+# Cisco flash metrics plugin
 #
-
-#####################################################################################################################
-#
-# define units for perfdata
+# change log
+# 2019-10-28: initial release
+# 2021-07-31: rewritten for CMK 2.0
 #
-#####################################################################################################################
 
+from cmk.gui.i18n import _
 
-#####################################################################################################################
-#
-# define metrics for perfdata
-#
-#####################################################################################################################
+from cmk.gui.plugins.metrics import (
+    metric_info,
+    graph_info,
+    perfometer_info
+
+)
 
 metric_info['cisco_flash_partusedspace'] = {
     'title': _('Sapce used'),
     'unit': 'bytes',
+    'color': '36/a',
+}
+
+metric_info['cisco_flash_percent_used'] = {
+    'title': _('Percent used'),
+    'unit': '%',
     'color': '26/a',
 }
+
 metric_info['cisco_flash_partfilecount'] = {
     'title': _('# of files'),
     'unit': 'count',
     'color': '21/a',
 }
 
-
-######################################################################################################################
-#
-# map perfdata to metric, not really necessary but makes sure to use the right metrics
-#
-######################################################################################################################
-
-check_metrics['check_mk-cisco_flash'] = {
-    'partusedspace': {'name': 'cisco_flash_partusedspace', 'scale': MB},
-    'partfilecount': {'name': 'cisco_flash_partfilecount', },
-}
-
-######################################################################################################################
-#
-# how to graph perdata 
-#
-######################################################################################################################
-
-graph_info.append({
+graph_info['cisco_flash_space_used'] = {
     'title': _('Space used'),
     'metrics': [
         ('cisco_flash_partusedspace', 'area'),
@@ -60,32 +51,36 @@ graph_info.append({
         ('cisco_flash_partusedspace:warn', _('warn')),
     ],
     "range": (0, "cisco_flash_partusedspace:max"),
-})
+}
+
+graph_info['cisco_flash_percent_used'] = {
+    'title': _('Percent used'),
+    'metrics': [
+        ('cisco_flash_percent_used', 'area'),
+    ],
+    'scalars': [
+        ('cisco_flash_percent_used:crit', _('crit')),
+        ('cisco_flash_percent_used:warn', _('warn')),
+    ],
+    "range": (0, 100),
+}
 
-graph_info.append({
+graph_info['cisco_flash_files_on_partition'] = {
     'title': _('# of files on partition'),
     'metrics': [
         ('cisco_flash_partfilecount', 'area'),
     ],
-})
-
-######################################################################################################################
-#
-# define perf-o-meter 
-#
-######################################################################################################################
+}
 
 perfometer_info.append(('stacked', [
     {
-        'type': 'logarithmic',
-        'metric': 'cisco_flash_partusedspace',
-        'half_value': 2592000.0,
-        'exponent': 2,
+        'type': 'linear',
+        'segments': ['cisco_flash_percent_used'],
+        'total': 100,
     },
     {
         'type': 'linear',
-        'segments': ['cisco_flash_partfilecount',
-                     ],
+        'segments': ['cisco_flash_partfilecount'],
         'total': 100000,
     }
 ]))
diff --git a/web/plugins/views/inv_cisco_flash.py b/web/plugins/views/inv_cisco_flash.py
index 631c20b..2738b89 100644
--- a/web/plugins/views/inv_cisco_flash.py
+++ b/web/plugins/views/inv_cisco_flash.py
@@ -1,53 +1,53 @@
-#!/usr/bin/python
-# -*- encoding: utf-8; py-indent-offset: 4 -*-
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
 
-try:
-   from cmk.gui.plugins.views.inventory import (
-       declare_invtable_view,
-       render_inv_dicttable,
-   )
-except:
-   pass
+
+from cmk.gui.plugins.views import (
+    inventory_displayhints, )
+from cmk.gui.i18n import _
+from cmk.gui.plugins.views.inventory import declare_invtable_view
 
 inventory_displayhints.update({
-    '.hardware.components.flash.devices:': {'title': _('Flash devices'), 'render': render_inv_dicttable,
-                               'keyorder': ['index', 'name', 'description', 'size', ],
-                               'view': 'invflashdevices_of_host',
-                               },
+    '.hardware.components.flash.devices:': {
+        'title': _('Flash devices'),
+        'keyorder': ['index', 'name', 'description', 'size', ],
+        'view': 'invflashdevices_of_host',
+    },
 
-    '.hardware.components.flash.devices:*.index'            : {'title': _('Index'), },
-    '.hardware.components.flash.devices:*.size'             : {'title': _('Size (MB)'), },
-    '.hardware.components.flash.devices:*.minpartitionsize' : {'title': _('min. partition size (MB)'), },
-    '.hardware.components.flash.devices:*.maxprtitions'     : {'title': _('max. partitions'), },
-    '.hardware.components.flash.devices:*.chipcount'        : {'title': _('Chip count'), },
-    '.hardware.components.flash.devices:*.name'             : {'title': _('Name'), },
-    '.hardware.components.flash.devices:*.description'      : {'title': _('Description'), },
-    '.hardware.components.flash.devices:*.controller'       : {'title': _('Controller'), },
+    '.hardware.components.flash.devices:*.index': {'title': _('Index'), },
+    '.hardware.components.flash.devices:*.size': {'title': _('Size (MB)'), },
+    '.hardware.components.flash.devices:*.minpartitionsize': {'title': _('min. partition size (MB)'), },
+    '.hardware.components.flash.devices:*.maxprtitions': {'title': _('max. partitions'), },
+    '.hardware.components.flash.devices:*.chipcount': {'title': _('Chip count'), },
+    '.hardware.components.flash.devices:*.name': {'title': _('Name'), },
+    '.hardware.components.flash.devices:*.description': {'title': _('Description'), },
+    '.hardware.components.flash.devices:*.controller': {'title': _('Controller'), },
     '.hardware.components.flash.devices:*.programmingjumper': {'title': _('Programming jumper'), },
-    '.hardware.components.flash.devices:*.inittime'         : {'title': _('Init time'), },
-    '.hardware.components.flash.devices:*.removable'        : {'title': _('Removable'), },
-    '.hardware.components.flash.devices:*.physentindex'     : {'title': _('Phys entity index'), },
-    '.hardware.components.flash.devices:*.nameextended'     : {'title': _('Name extended'), },
-
+    '.hardware.components.flash.devices:*.inittime': {'title': _('Init time'), },
+    '.hardware.components.flash.devices:*.removable': {'title': _('Removable'), },
+    '.hardware.components.flash.devices:*.physentindex': {'title': _('Phys entity index'), },
+    '.hardware.components.flash.devices:*.nameextended': {'title': _('Name extended'), },
 
-    '.hardware.components.flash.chips:': {'title': _('Flash chips'),  'render'  : render_inv_dicttable,
-                                            'keyorder': ['flashindex', 'index', 'description', ],
-                                            'view': 'invflashchips_of_host',
-                                            },
+    '.hardware.components.flash.chips:': {
+        'title': _('Flash chips'),
+        'keyorder': ['flashindex', 'index', 'description', ],
+        'view': 'invflashchips_of_host',
+    },
 
-    '.hardware.components.flash.chips:*.index'          : {'title': _('Index'), },
-    '.hardware.components.flash.chips:*.flashindex'     : {'title': _('Device index'), },
-    '.hardware.components.flash.chips:*.code'           : {'title': _('Code'), },
-    '.hardware.components.flash.chips:*.description'    : {'title': _('Description'), },
-    '.hardware.components.flash.chips:*.writeretries'   : {'title': _('Write retries'), },
-    '.hardware.components.flash.chips:*.eraseretries'   : {'title': _('Erase retries'), },
+    '.hardware.components.flash.chips:*.index': {'title': _('Index'), },
+    '.hardware.components.flash.chips:*.flashindex': {'title': _('Device index'), },
+    '.hardware.components.flash.chips:*.code': {'title': _('Code'), },
+    '.hardware.components.flash.chips:*.description': {'title': _('Description'), },
+    '.hardware.components.flash.chips:*.writeretries': {'title': _('Write retries'), },
+    '.hardware.components.flash.chips:*.eraseretries': {'title': _('Erase retries'), },
     '.hardware.components.flash.chips:*.maxwriteretries': {'title': _('max. write retries'), },
     '.hardware.components.flash.chips:*.maxeraseretries': {'title': _('max. erasure retries'), },
 
-    '.hardware.components.flash.partitions:': {'title': _('Flash partitions'),  'render'  : render_inv_dicttable,
-                                          'keyorder': ['flashindex', 'index', 'name', 'size', 'freespace', 'filecount', ],
-                                          'view': 'invflashpartitions_of_host',
-                                          },
+    '.hardware.components.flash.partitions:': {
+        'title': _('Flash partitions'),
+        'keyorder': ['flashindex', 'index', 'name', 'size', 'freespace', 'filecount', ],
+        'view': 'invflashpartitions_of_host',
+    },
 
     '.hardware.components.flash.partitions:*.index': {'title': _('Index'), },
     '.hardware.components.flash.partitions:*.flashindex': {'title': _('Device index'), },
@@ -67,4 +67,5 @@ inventory_displayhints.update({
 
 declare_invtable_view('invflashdevices', '.hardware.components.flash.devices:', _('Flash devices'), _('Flash devices'))
 declare_invtable_view('invflashchips', '.hardware.components.flash.chips:', _('Flash chips'), _('Flash chips'))
-declare_invtable_view('invflashpartitions', '.hardware.components.flash.partitions:', _('Flash partitions'), _('Flash partitions'))
+declare_invtable_view('invflashpartitions', '.hardware.components.flash.partitions:', _('Flash partitions'),
+                      _('Flash partitions'))
diff --git a/web/plugins/wato/cisco_flash.py b/web/plugins/wato/cisco_flash.py
index fa76364..e64ce86 100644
--- a/web/plugins/wato/cisco_flash.py
+++ b/web/plugins/wato/cisco_flash.py
@@ -1,45 +1,56 @@
-#!/usr/bin/python
-# -*- encoding: utf-8; py-indent-offset: 4 -*-
-
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
 #
-# Check_MK cisco_flash WATO plugin
+# License: GNU General Public License v2
+
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
+# Date  : 2019-11-04
 #
-# Author: Th.L.
-# Date: 2019-11-04
 #
+# Check_MK cisco_flash WATO plugin
 #
+# 2019-11-04: initial release
+# 2021-07-31: rewritten for CMK 2.0
 #
 #
+from cmk.gui.i18n import _
+from cmk.gui.valuespec import (
+    Dictionary,
+    Integer,
+    TextAscii,
+    Tuple,
+)
+
+from cmk.gui.plugins.wato import (
+    CheckParameterRulespecWithItem,
+    rulespec_registry,
+    RulespecGroupCheckParametersNetworking,
+)
 
-register_check_parameters(
-    subgroup_networking,
-    'cisco_flash',
-    _('Cisco Flash'),
-    Dictionary(
-        help=_(''),
+
+def _parameter_valuespec_cisco_flash():
+    return Dictionary(
         elements=[
-            ('warn_level_percent',
-             Integer(
-                 title=_('Warning if above percentage of used space'),
-                 label=_('Warning if above percentage of used space'),
-                 help=_('Warning if above percentage of used space'),
-                 default_value=85,
-                 allow_empty=False,
-                 minvalue=1,
-                 maxvalue=100
-             )),
-            ('crit_level_percent',
-             Integer(
-                 title=_('Critical  if above percentage of used space'),
-                 label=_('Critical  if above percentage of used space'),
-                 help=_('Critical  if above percentage of used space'),
-                 default_value=90,
-                 allow_empty=False,
-                 minvalue=1,
-                 maxvalue=100
+            ('levels_upper_percent',
+             Tuple(
+                 title=_('Levels for usage in %'),
+                 elements=[
+                     Integer(title=_('Warning at'), unit='%', default_value=85, minvalue=0, maxvalue=100),
+                     Integer(title=_('Critical at'), unit='%', default_value=90, minvalue=0, maxvalue=100)
+                 ],
+
              )),
         ],
-    ),
-    TextAscii(title=_('Cisco flash')),
-    match_type='dict',
-)
+    )
+
+
+rulespec_registry.register(
+    CheckParameterRulespecWithItem(
+        check_group_name='cisco_flash',
+        group=RulespecGroupCheckParametersNetworking,
+        item_spec=lambda: TextAscii(title=_('Partition specific configuration'), ),
+        match_type='dict',
+        parameter_valuespec=_parameter_valuespec_cisco_flash,
+        title=lambda: _('Cisco flash'),
+    ))
diff --git a/web/plugins/wato/inv_cisco_flash.py b/web/plugins/wato/inv_cisco_flash.py
index c4f9d83..fbb73ba 100644
--- a/web/plugins/wato/inv_cisco_flash.py
+++ b/web/plugins/wato/inv_cisco_flash.py
@@ -1,14 +1,38 @@
-#!/usr/bin/python
-# -*- encoding: utf-8; py-indent-offset: 4 -*-
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# License: GNU General Public License v2
 
-cflDeviceRemovecolumns = [
-#    ('index', 'Index'),
-#    ('size', 'Size (MB)'),
-#    ('minpartitionsize', 'min. partition size (MB)'),
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
+# Date  : 2019-10-28
+#
+# Cisco flash metrics plugin
+#
+# change log
+# 2019-10-28: initial release
+# 2021-07-31: rewritten for CMK 2.0
+
+
+from cmk.gui.i18n import _
+from cmk.gui.plugins.wato import (
+    HostRulespec,
+    rulespec_registry,
+)
+from cmk.gui.valuespec import (
+    Dictionary,
+    FixedValue,
+    ListChoice,
+)
+
+from cmk.gui.plugins.wato.inventory import (
+    RulespecGroupInventory,
+)
+
+_inv_cisco_flash_cflDeviceRemovecolumns = [
+    ('minpartitionsize', 'min. partition size (MB)'),
     ('maxprtitions', 'max. partitions'),
     ('chipcount', 'Chip count'),
-#    ('name', 'Name'),
-#    ('description', 'Description'),
     ('controller', 'Controller'),
     ('programmingjumper', 'Programming jumper'),
     ('inittime', 'Init time'),
@@ -16,28 +40,20 @@ cflDeviceRemovecolumns = [
     ('physentindex', 'Phys entity index'),
     ('nameextended', 'Name extended'),
 ]
-cflPartitionRemovecolumns = [
-#    ('index', 'Index'),
-#    ('flashindex', 'Device index'),
+
+_inv_cisco_flash_cflPartitionRemovecolumns = [
     ('startchip', 'Start chip'),
     ('endchip', 'End chip'),
-#    ('size', 'Size (MB)'),
-#    ('freespace', 'Free space (MB)'),
-#    ('filecount', 'File count'),
     ('crcsumalgo', 'Checksumm algorithm'),
     ('status', 'Status'),
     ('upgrademethod', 'Upgrade method'),
-#    ('name', 'Name'),
     ('neederasure', 'Need erasure'),
     ('filenamelength', 'File name length'),
     ('lowspacenotifythreshold', 'Low space notify threshold (%)'),
 ]
 
-cflChipRemovecolumns = [
-#    ('index', 'Index'),
-#    ('flashindex', 'Device index'),
+_inv_cisco_flash_cflChipRemovecolumns = [
     ('code', 'Code'),
-#    ('description', 'Description'),
     ('writeretries', 'Write retries'),
     ('eraseretries', 'Erase retries'),
     ('maxwriteretries', 'max. write retries'),
@@ -45,83 +61,70 @@ cflChipRemovecolumns = [
 ]
 
 
-register_rule('inventory', 'inv_parameters:inv_cisco_flash',
-              Dictionary(
-                  title=_('Cisco flash inventory'),
-                  elements=[
-                      ('cflDeviceDisable',
-                       FixedValue(
-                           True,
-                           title=_('disable Flash device inventory'),
-                       )),
-                      ('cflPartitionDisable',
-                       FixedValue(
-                           True,
-                           title=_('disable Flash partition inventory'),
-                       )),
-                      ('cflChipDisable',
-                       FixedValue(
-                           True,
-                           title=_('disable Flash chips inventory'),
-                       )),
-                      ('cflDeviceRemovecolumns',
-                       ListChoice(
-                           title=_('list of columns to remove from flash devices'),
-                           label=_('list of columns to remove from flash devices'),
-                           help=_('information to remove from inventory'),
-                           choices=cflDeviceRemovecolumns,
-                           default_value=[
-                               # 'size',
-                               # 'minpartitionsize',
-                               # 'maxprtitions',
-                               'chipcount',
-                               'controller',
-                               'programmingjumper',
-                               'inittime',
-                               # 'removable',
-                               'physentindex',
-                               'nameextended',
-                           ],
-                       )),
-                      ('cflPartitionRemovecolumns',
-                       ListChoice(
-                           title=_('list of columns to remove from flash partitions'),
-                           label=_('list of columns to remove from flash partitions'),
-                           help=_('information to remove from inventory'),
-                           choices=cflPartitionRemovecolumns,
-                           default_value=[
-                               # 'index',
-                               # 'flashindex',
-                               'startchip',
-                               'endchip',
-                               #'size',
-                               #'freespace',
-                               # 'filecount',
-                               # 'crcsumalgo',
-                               # 'status',
-                               # 'upgrademethod',
-                               # 'name',
-                               # 'neederasure',
-                               # 'filenamelength',
-                               # 'lowspacenotifythreshold',
+def _valuespec_inv_cisco_flash():
+    return Dictionary(
+        title=_('Cisco flash inventory'),
+        elements=[
+            ('cflDeviceDisable',
+             FixedValue(
+                 True,
+                 title=_('disable Flash device inventory'),
+             )),
+            ('cflPartitionDisable',
+             FixedValue(
+                 True,
+                 title=_('disable Flash partition inventory'),
+             )),
+            ('cflChipDisable',
+             FixedValue(
+                 True,
+                 title=_('disable Flash chips inventory'),
+             )),
+            ('cflDeviceRemovecolumns',
+             ListChoice(
+                 title=_('list of columns to remove from flash devices'),
+                 help=_('information to remove from inventory'),
+                 choices=_inv_cisco_flash_cflDeviceRemovecolumns,
+                 default_value=[
+                     'chipcount',
+                     'controller',
+                     'programmingjumper',
+                     'inittime',
+                     'physentindex',
+                     'nameextended',
+                 ],
+             )),
+            ('cflPartitionRemovecolumns',
+             ListChoice(
+                 title=_('list of columns to remove from flash partitions'),
+                 help=_('information to remove from inventory'),
+                 choices=_inv_cisco_flash_cflPartitionRemovecolumns,
+                 default_value=[
+                     'startchip',
+                     'endchip',
+                 ],
+             )),
+            ('cflChipRemovecolumns',
+             ListChoice(
+                 title=_('list of columns to remove from flash chips'),
+                 help=_('information to remove from inventory'),
+                 choices=_inv_cisco_flash_cflChipRemovecolumns,
+                 default_value=[
+                     'code',
+                     'writeretries',
+                     'eraseretries',
+                     'maxwriteretries',
+                     'maxeraseretries'
+                 ],
+             )),
+        ],
+    )
+
 
-                           ],
-                       )),
-                      ('cflChipRemovecolumns',
-                       ListChoice(
-                           title=_('list of columns to remove from flash chips'),
-                           label=_('list of columns to remove from flash chips'),
-                           help=_('information to remove from inventory'),
-                           choices=cflChipRemovecolumns,
-                           default_value=[
-                               'code',
-                               'writeretries',
-                               'eraseretries',
-                               'maxwriteretries',
-                               'maxeraseretries'
-                           ],
-                       )),
-                  ],
-              ),
-              match='dict',
-              )
+rulespec_registry.register(
+    HostRulespec(
+        group=RulespecGroupInventory,
+        match_type='dict',
+        name='inv_parameters:inv_cisco_flash',
+        valuespec=_valuespec_inv_cisco_flash,
+    ))
-- 
GitLab