Collection of CheckMK checks (see https://checkmk.com/). All checks and plugins are provided as is. Absolutely no warranty. Send any comments to thl-cmk[at]outlook[dot]com

Skip to content
Snippets Groups Projects
Commit 6e02550e authored by thl-cmk's avatar thl-cmk :flag_na:
Browse files

update project

parent ae6128c2
No related branches found
No related tags found
No related merge requests found
[PACKAGE]: ../../raw/master/mkp/cisco_meraki-1.2.5-2023-11-13.mkp "cisco_meraki-1.2.5-2023-11-13.mkp"
[PACKAGE]: ../../raw/master/mkp/cisco_meraki-1.2.6-20231117.mkp "cisco_meraki-1.2.6-20231117.mkp"
[SDK]: ../../raw/master/mkp/MerkaiSDK-1.39.0-202311-10.mkp "MerkaiSDK-1.39.0-202311-10.mkpp"
# Cisco Meraki special agent
......
#!/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 : 2023-11-13
# File : cisco_meraki_org_cellular_uplinks.py (check plugin)
from dataclasses import dataclass
from datetime import datetime
from _collections_abc import Mapping
from cmk.base.plugins.agent_based.agent_based_api.v1 import (
register,
Result,
Service,
State,
Metric,
render,
)
from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import (
CheckResult,
DiscoveryResult,
StringTable,
)
from cmk.base.plugins.agent_based.utils.cisco_meraki import (
load_json,
)
_LAST_REPORTED_AT = "%Y-%m-%dT%H:%M:%SZ"
@dataclass(frozen=True)
class CellularUplink:
apn: str
connection_type: str
dns1: str
dns2: str
gateway: str
iccid: str
interface: str
ip: str
model: str
provider: str
public_ip: str
signal_type: str
status: str
rsrp: int
rsrq: int
sent: int | None
received: int | None
@dataclass(frozen=True)
class CellularUplinkHA:
enabled: bool
role: str
@dataclass(frozen=True)
class CellularGateway:
serial: str
model: str
last_reported_at: datetime
# network_name: str
uplinks: Mapping[str, CellularUplink]
high_availability: CellularUplinkHA
__cellular_uplinks = [
{
"highAvailability": {
"enabled": False,
"role": "primary"
},
"lastReportedAt": "2023-11-13T19:52:06Z",
"model": "MG41",
"networkId": "L_575897802350007343",
"serial": "Q2ZY-XLHP-Z8ND",
"uplinks": [
{
"apn": "web.vodafone.de",
"connectionType": "lte",
"dns1": None,
"dns2": None,
"gateway": None,
"iccid": "89492027206029876518",
"interface": "cellular",
"ip": None,
"model": "integrated",
"provider": "vodafone.de",
"publicIp": "109.42.243.39",
"signalStat": {
"rsrp": "-111",
"rsrq": "-8"
},
"signalType": None,
"status": "active"
}
]
}
]
def parse_cellular_uplinks(string_table: StringTable) -> CellularGateway | None:
json_data = load_json(string_table)
json_data = json_data[0]
return CellularGateway(
serial=json_data['serial'],
model=json_data['model'],
last_reported_at=datetime.strptime(json_data['lastReportedAt'], _LAST_REPORTED_AT),
# network_name=json_data['networkName'],
high_availability=CellularUplinkHA(
enabled=json_data['highAvailability']['enabled'],
role=json_data['highAvailability']['role'],
),
uplinks={
uplink['interface']: CellularUplink(
apn=uplink['apn'],
connection_type=uplink['connectionType'],
dns1=uplink['dns1'],
dns2=uplink['dns2'],
gateway=uplink['gateway'],
iccid=uplink['iccid'],
interface=uplink['interface'],
ip=uplink['ip'],
model=uplink['model'],
provider=uplink['provider'],
public_ip=uplink['publicIp'],
signal_type=uplink['signalType'],
status=uplink['status'],
rsrp=uplink['signalStat']['rsrp'],
rsrq=uplink['signalStat']['rsrq'],
received=uplink.get('received', None),
sent=uplink.get('sent', None),
) for uplink in json_data['uplinks']
},
)
register.agent_section(
name="cisco_meraki_org_cellular_uplinks",
parse_function=parse_cellular_uplinks,
)
def discover_cellular_uplinks(section: CellularGateway) -> DiscoveryResult:
for uplink in section.uplinks.keys():
yield Service(item=uplink)
def check_cellular_uplinks(item: str, params: Mapping[str, any], section: CellularGateway) -> CheckResult:
try:
uplink: CellularUplink = section.uplinks[item]
except KeyError:
return None
if uplink.status not in ['active']:
yield Result(state=State(params.get('status_not_active', 1)), summary=f'Status: {uplink.status}')
else:
yield Result(state=State.OK, summary=f'Status: {uplink.status}')
yield Result(state=State.OK, notice=f'IP: {uplink.ip}')
yield Result(state=State.OK, notice=f'APN: {uplink.apn}')
yield Result(state=State.OK, notice=f'Provider: {uplink.provider}')
yield Result(state=State.OK, summary=f'Public IP: {uplink.public_ip}')
yield Result(state=State.OK, summary=f'Connection type: {uplink.connection_type}')
yield Result(state=State.OK, notice=f'ICCID: {uplink.iccid}')
yield Result(state=State.OK, notice=f'Signal type: {uplink.signal_type}')
# yield Result(state=State.OK, notice=f'Network: {section.network_name}')
if uplink.rsrp:
yield Result(state=State.OK, summary=f'RSRP: {uplink.rsrp} dBm')
if uplink.rsrp:
yield Result(state=State.OK, summary=f'RSRQ: {uplink.rsrq} dB')
if uplink.received:
yield Result(state=State.OK, summary=f'in: {render.networkbandwidth(uplink.received)}')
yield Metric(name='if_in_bps', value=uplink.received * 8)
if uplink.sent:
yield Result(state=State.OK, summary=f'Out: {render.networkbandwidth(uplink.sent)}')
yield Metric(name='if_out_bps', value=uplink.sent * 8)
# not needed, will show in device status
# yield from check_last_reported_ts(last_reported_ts=section.last_reported_at.timestamp())
# not sure if this is usefully, need system with H/A enabled=True to check
yield Result(state=State.OK, notice=f'H/A enabled: {section.high_availability.enabled}')
yield Result(state=State.OK, notice=f'H/A role: {section.high_availability.role}')
yield Result(state=State.OK, notice=f'Gateway: {uplink.gateway}')
# yield Result(state=State.OK, notice=f'IP assigned by: {uplink.ip_assigned_by}')
yield Result(state=State.OK, notice=f'DNS 1: {uplink.dns1}')
yield Result(state=State.OK, notice=f'DNS 2: {uplink.dns2}')
register.check_plugin(
name='cisco_meraki_org_cellular_uplinks',
service_name='Cellular Uplink %s',
discovery_function=discover_cellular_uplinks,
check_function=check_cellular_uplinks,
check_default_parameters={},
check_ruleset_name='cisco_meraki_org_cellular_uplinks',
)
......@@ -216,6 +216,7 @@ register.check_plugin(
#
# inventory license overview
#
# ToDo: add senors (MS)
def inventory_licenses_overview(section: Section | None) -> InventoryResult:
path = ['software', 'applications', 'cisco_meraki', 'licenses']
for org_id, org_data in section.items():
......
......@@ -31,6 +31,7 @@ _SEC_NAME_NETWORKS: Final = "networks"
_SEC_NAME_WIRELESS_ETHERNET_STATUSES: Final = "wireless-ethernet-statuses"
_SEC_NAME_WIRELESS_DEVICE_STATUS: Final = "wireless-device-status"
_SEC_NAME_ORGANISATIONS: Final = "organisations"
_SEC_NAME_CELLULAR_UPLINKS: Final = "cellular-uplinks"
def load_json(string_table: StringTable) -> Sequence[MerakiAPIData]:
......
......@@ -72,6 +72,7 @@ from cmk.base.plugins.agent_based.utils.cisco_meraki import (
_SEC_NAME_WIRELESS_ETHERNET_STATUSES,
_SEC_NAME_WIRELESS_DEVICE_STATUS,
_SEC_NAME_ORGANISATIONS,
_SEC_NAME_CELLULAR_UPLINKS,
)
_LOGGER = logging.getLogger("agent_cisco_meraki")
......@@ -87,6 +88,7 @@ _API_NAME_DEVICE_TYPE_SWITCH: Final = 'switch'
_API_NAME_DEVICE_TYPE_SENSOR: Final = 'sensor'
_API_NAME_DEVICE_TYPE_APPLIANCE: Final = 'appliance'
_API_NAME_DEVICE_TYPE_CAMERA: Final = 'camera'
_API_NAME_DEVICE_TYPE_CELLULAR: Final = 'cellularGateway'
_SECTION_NAME_MAP = {
_SEC_NAME_LICENSES_OVERVIEW: "licenses_overview",
......@@ -100,7 +102,8 @@ _SECTION_NAME_MAP = {
_SEC_NAME_NETWORKS: "networks",
_SEC_NAME_WIRELESS_ETHERNET_STATUSES: "wireless_ethernet_statuses",
_SEC_NAME_WIRELESS_DEVICE_STATUS: "wireless_device_status",
_SEC_NAME_ORGANISATIONS: "organisations"
_SEC_NAME_ORGANISATIONS: "organisations",
_SEC_NAME_CELLULAR_UPLINKS: "cellular_uplinks",
}
_MIN_CACHE_INTERVAL = 300
......@@ -219,6 +222,7 @@ class MerakiNetwork:
# | |--> MerakiGetOrganizationApplianceVpnStatuses -> ex. 60+
# | |--> MerakiGetOrganizationSensorReadingsLatest -> ex. 60+
# | |--> MerakiGetOrganizationWirelessDevicesEthernetStatuses -> ex. 60+
# | |--> MerakiGetOrganizationCellularGatewayUplinkStatuses -> ex. 60.
# |
# |--\ MerakiSectionSerial
# | - adds serial as parameter
......@@ -474,6 +478,20 @@ class MerakiGetDeviceWirelessStatus(MerakiSectionSerial):
return []
class MerakiGetOrganizationCellularGatewayUplinkStatuses(MerakiSectionOrg):
@property
def name(self):
return f'getOrganizationCellularGatewayUplinkStatuses_{self._org_id}'
def get_live_data(self):
try:
return self._config.dashboard.cellularGateway.getOrganizationCellularGatewayUplinkStatuses(
self._org_id, total_pages="all"
)
except meraki.exceptions.APIError as e:
_LOGGER.debug("Organisation ID: %r: Get cellular gateways uplink statuses: %r", self._org_id, e)
return []
#
# Main run
#
......@@ -610,7 +628,7 @@ class MerakiOrganisation:
for sensor_reading in MerakiGetOrganizationSensorReadingsLatest(
config=self.config,
org_id=self.organisation_id,
cache_interval=60 * randrange(300)
cache_interval=_MIN_CACHE_INTERVAL + randrange(_RANDOM_CACHE_INTERVAL)
).get_data(use_cache=self.config.use_cache):
if piggyback := self._get_device_piggyback(sensor_reading, devices_by_serial):
yield self._make_section(
......@@ -714,6 +732,20 @@ class MerakiOrganisation:
piggyback=self._adjust_piggyback(host=piggyback),
)
if devices_by_type.get(_API_NAME_DEVICE_TYPE_CELLULAR):
if _SEC_NAME_CELLULAR_UPLINKS in self.config.section_names:
for gateway in MerakiGetOrganizationCellularGatewayUplinkStatuses(
config=self.config,
org_id=self.organisation_id,
cache_interval=_MIN_CACHE_INTERVAL + randrange(_RANDOM_CACHE_INTERVAL)
).get_data(use_cache=self.config.use_cache):
if piggyback := self._get_device_piggyback(gateway, devices_by_serial):
yield self._make_section(
name=_SEC_NAME_CELLULAR_UPLINKS,
data=gateway,
piggyback=self._adjust_piggyback(host=piggyback),
)
def add_adjust_piggyback(self, adjust_piggyback_list: Sequence[str, str, str, str, str]):
for args_org_type, args_organisation, args_case, args_prefix, args_suffix in adjust_piggyback_list:
if ((args_org_type == 'org_id' and self.organisation_id == args_organisation)
......@@ -907,6 +939,7 @@ def _need_devices(section_names: Sequence[str]) -> bool:
_SEC_NAME_SWITCH_PORTS_STATUSES,
_SEC_NAME_WIRELESS_ETHERNET_STATUSES,
_SEC_NAME_WIRELESS_DEVICE_STATUS,
_SEC_NAME_CELLULAR_UPLINKS,
]
)
......@@ -924,6 +957,7 @@ def _need_organisations(section_names: Sequence[str]) -> bool:
_SEC_NAME_SWITCH_PORTS_STATUSES,
_SEC_NAME_WIRELESS_ETHERNET_STATUSES,
_SEC_NAME_WIRELESS_DEVICE_STATUS,
_SEC_NAME_CELLULAR_UPLINKS,
]
)
......
File added
......@@ -12,20 +12,21 @@
'cisco_meraki_switch_ports_statuses.py',
'cisco_meraki_org_wireless_device_status.py',
'cisco_meraki_org_wireless_ethernet_statuses.py',
'cisco_meraki_organisations.py'],
'cisco_meraki_organisations.py',
'cisco_meraki_org_cellular_uplinks.py'],
'agents': ['special/agent_cisco_meraki'],
'checks': ['agent_cisco_meraki'],
'gui': ['metrics/cisco_meraki.py',
'views/cisco_meraki.py',
'wato/agent_cisco_meraki.py',
'wato/check_parameters/cisco_meraki_org_appliance_uplinks.py',
'wato/check_parameters/cisco_meraki_org_appliance_vpns.py',
'wato/check_parameters/cisco_meraki_org_device_status.py',
'wato/check_parameters/cisco_meraki_org_licenses_overviewi.py'],
'lib': ['python3/cmk/special_agents/agent_cisco_meraki.py']},
'lib': ['python3/cmk/special_agents/agent_cisco_meraki.py'],
'web': ['plugins/views/cisco_meraki.py']},
'name': 'cisco_meraki',
'title': 'Cisco Meraki special agent',
'version': '1.2.5-2023-11-13',
'version': '1.2.6-20231117',
'version.min_required': '2.2.0p11',
'version.packaged': '2.2.0p11',
'version.packaged': '2.2.0p14',
'version.usable_until': '2.3.0b1'}
#!/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 : 2023-11-02
# File : cisco_meraki.py (views)
# 2023-11-17: moved file from local/lib/ structure to local/share/ structure to avoid errors in web.log
from cmk.gui.views.inventory.registry import inventory_displayhints
from cmk.gui.i18n import _l
inventory_displayhints.update({
'.software.applications.cisco_meraki.': {'title': _l('Cisco Meraki Cloud'), },
'.software.applications.cisco_meraki.licenses:': {
'title': _l('Licensed devices overview'),
'keyorder': ['org_id', 'org_name', 'summary'],
'view': 'invciscomerakilicensesoverview_of_host',
},
'.software.applications.cisco_meraki.licenses:*.org_id': {'title': _l('Organisation ID'), 'short': _l('Org ID')},
'.software.applications.cisco_meraki.licenses:*.org_name': {
'title': _l('Organisation Name'),
'short': _l('Org Name')
},
'.software.applications.cisco_meraki.licenses:*.sm': {'title': _l('Systems Manager (SM)'), 'short': _l('SM')},
'.software.applications.cisco_meraki.licenses:*.mg': {'title': _l('Gateways (MG)'), 'short': _l('MG')},
'.software.applications.cisco_meraki.licenses:*.ms': {'title': _l('Switches (MS)'), 'short': _l('MS')},
'.software.applications.cisco_meraki.licenses:*.mx': {'title': _l('Security/SD-WAN (MX)'), 'short': _l('MX')},
'.software.applications.cisco_meraki.licenses:*.mv': {'title': _l('Video (MV)'), 'short': _l('MV')},
'.software.applications.cisco_meraki.licenses:*.mr': {
'title': _l('Access Points/Wireless (MR)'),
'short': _l('MR')
},
'.software.applications.cisco_meraki.licenses:*.summary': {'title': _l('Summary'), },
'.software.applications.cisco_meraki.device_info.': {
'title': _l('Device Info'),
'keyorder': [
'organisation_id',
'organisation_name',
'network_id',
'network_name',
'address',
],
},
'.software.applications.cisco_meraki.device_info.organisation_id': {'title': _l('Organisation ID')},
'.software.applications.cisco_meraki.device_info.organisation_name': {'title': _l('Organisation Name')},
'.software.applications.cisco_meraki.device_info.network_id': {'title': _l('Network ID')},
'.software.applications.cisco_meraki.device_info.network_name': {'title': _l('Network Name')},
'.software.applications.cisco_meraki.device_info.address': {'title': _l('Address')},
'.software.applications.cisco_meraki.organisations:': {
'title': _l('Organisation overview'),
'keyorder': ['org_id', 'org_name', 'api', 'licensing', 'cloud', 'url'],
'view': 'invciscomerakiorganisationoverview_of_host',
},
'.software.applications.cisco_meraki.organisations:*.org_id': {
'title': _l('Organisation ID'),
'short': _l('Org ID')
},
'.software.applications.cisco_meraki.organisations:*.org_name': {
'title': _l('Organisation name'),
'short': _l('Org name')
},
'.software.applications.cisco_meraki.organisations:*.api': {'title': _l('API status'), 'short': _l('API')},
'.software.applications.cisco_meraki.organisations:*.licensing': {
'title': _l('Licensing model'),
'short': _l('Licensing')
},
'.software.applications.cisco_meraki.organisations:*.cloud': {'title': _l('Cloud region'), 'short': _l('Cloud')},
'.software.applications.cisco_meraki.organisations:*.url': {'title': _l('URL'), 'short': _l('URL')},
})
# cleanup build in display hints
# inventory_displayhints.pop('.software.configuration.organisation')
# inventory_displayhints.pop('.software.configuration.organisation.organisation_id')
# inventory_displayhints.pop('.software.configuration.organisation.organisation_name')
# inventory_displayhints.pop('.software.configuration.organisation.network_id')
# inventory_displayhints.pop('.software.configuration.organisation.address')
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment