diff --git a/README.md b/README.md index 781da5faf08e135c499ea22fad8ffaffa64dbb35..38083b336cdc0ca8733d56b2be5cf4db30242816 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[PACKAGE]: ../../raw/master/mkp/cisco_meraki-1.4.1-20241217.mkp "cisco_meraki-1.4.1-20241217.mkp" +[PACKAGE]: ../../raw/master/mkp/cisco_meraki-1.4.2-20250104.mkp "cisco_meraki-1.4.2-20250104.mkp" [SDK]: ../../raw/master/mkp/MerakiSDK-1.52.0-20241116.mkp "MerakiSDK-1.52.0-20241116.mkp" # Cisco Meraki special agent diff --git a/mkp/cisco_meraki-1.4.2-20250104.mkp b/mkp/cisco_meraki-1.4.2-20250104.mkp new file mode 100644 index 0000000000000000000000000000000000000000..f506f10af7ce9924efabb819c0a539db8e78bc0d Binary files /dev/null and b/mkp/cisco_meraki-1.4.2-20250104.mkp differ diff --git a/source/cmk_addons_plugins/meraki/lib/agent.py b/source/cmk_addons_plugins/meraki/lib/agent.py index 50516cab9144fb91b7938b72da60eacc39b6a532..b13c979ce67ab1ac6f89740892657ea41cfae7fb 100644 --- a/source/cmk_addons_plugins/meraki/lib/agent.py +++ b/source/cmk_addons_plugins/meraki/lib/agent.py @@ -42,11 +42,17 @@ # 2024-11-16: fixed crash on missing items in MerakiGetOrganizationSwitchPortsStatusesBySwitch (ThX to Stephan Bergfeld) # 2024-11-23: added appliance port api call -> not yet active # 2024-12-13: fixed crash in SwitchPortStatus if response has no data (>Response [503}>) +# 2025-01-04: added "use network as prefix" option + +# Deprecation information +# https://developer.cisco.com/meraki/api-v1/deprecated-operations/#deprecated-operations +# # ToDo: create inventory from Networks, is per organisation, not sure where/how to put this in the inventory # ToDo: list Connected Datacenters like Umbrella https://developer.cisco.com/meraki/api-v1/list-data-centers/ # ToDo: https://developer.cisco.com/meraki/api-v1/list-tunnels/ # ToDo: https://developer.cisco.com/meraki/api-v1/get-organization-wireless-clients-overview-by-device/ +# ToDo: https://developer.cisco.com/meraki/api-v1/get-device-lldp-cdp/ # if the following is available (right now only with early access enabled) # ToDO: https://developer.cisco.com/meraki/api-v1/get-organization-switch-ports-statuses-by-switch/ # (done) @@ -69,12 +75,10 @@ from json import JSONDecodeError from logging import getLogger from os import environ from pathlib import Path -# from random import randrange from requests import request, RequestException from time import strftime, gmtime, time as now_time from time import time_ns from typing import Final, TypedDict, Any, List -# from urllib.request import getproxies import meraki # type: ignore[import] @@ -92,91 +96,91 @@ from cmk_addons.plugins.meraki.lib.utils import ( MerakiNetwork, # parameter names - _SEC_NAME_APPLIANCE_UPLINKS, - _SEC_NAME_APPLIANCE_PORTS, - _SEC_NAME_APPLIANCE_UPLINKS_USAGE, - _SEC_NAME_APPLIANCE_VPNS, - _SEC_NAME_APPLIANCE_PERFORMANCE, - _SEC_NAME_CELLULAR_UPLINKS, - _SEC_NAME_DEVICE_INFO, - _SEC_NAME_DEVICE_STATUSES, - _SEC_NAME_DEVICE_UPLINKS_INFO, - _SEC_NAME_LICENSES_OVERVIEW, - _SEC_NAME_NETWORKS, - _SEC_NAME_ORGANISATIONS, - _SEC_NAME_ORG_API_REQUESTS, - _SEC_NAME_SENSOR_READINGS, - _SEC_NAME_SWITCH_PORTS_STATUSES, - _SEC_NAME_WIRELESS_DEVICE_STATUS, - _SEC_NAME_WIRELESS_ETHERNET_STATUSES, + SEC_NAME_APPLIANCE_UPLINKS, + SEC_NAME_APPLIANCE_PORTS, + SEC_NAME_APPLIANCE_UPLINKS_USAGE, + SEC_NAME_APPLIANCE_VPNS, + SEC_NAME_APPLIANCE_PERFORMANCE, + SEC_NAME_CELLULAR_UPLINKS, + SEC_NAME_DEVICE_INFO, + SEC_NAME_DEVICE_STATUSES, + SEC_NAME_DEVICE_UPLINKS_INFO, + SEC_NAME_LICENSES_OVERVIEW, + SEC_NAME_NETWORKS, + SEC_NAME_ORGANISATIONS, + SEC_NAME_ORG_API_REQUESTS, + SEC_NAME_SENSOR_READINGS, + SEC_NAME_SWITCH_PORTS_STATUSES, + SEC_NAME_WIRELESS_DEVICE_STATUS, + SEC_NAME_WIRELESS_ETHERNET_STATUSES, # Early Access - _SEC_NAME_ORG_SWITCH_PORTS_STATUSES, + SEC_NAME_ORG_SWITCH_PORTS_STATUSES, # api cache defaults per section - _SEC_CACHE_APPLIANCE_PERFORMANCE, - _SEC_CACHE_APPLIANCE_UPLINKS_USAGE, - _SEC_CACHE_APPLIANCE_UPLINKS, - _SEC_CACHE_APPLIANCE_VPNS, - _SEC_CACHE_CELLULAR_UPLINKS, - _SEC_CACHE_DEVICE_INFO, - _SEC_CACHE_DEVICE_STATUSES, - _SEC_CACHE_DEVICE_UPLINKS_INFO, - _SEC_CACHE_LICENSES_OVERVIEW, - _SEC_CACHE_NETWORKS, - _SEC_CACHE_ORG_API_REQUESTS, - _SEC_CACHE_ORG_SWITCH_PORTS_STATUSES, - _SEC_CACHE_ORGANISATIONS, - _SEC_CACHE_SENSOR_READINGS, - _SEC_CACHE_SWITCH_PORTS_STATUSES, - _SEC_CACHE_WIRELESS_DEVICE_STATUS, - _SEC_CACHE_WIRELESS_ETHERNET_STATUSES, - _SEC_CACHE_APPLIANCE_PORTS, + SEC_CACHE_APPLIANCE_PERFORMANCE, + SEC_CACHE_APPLIANCE_UPLINKS_USAGE, + SEC_CACHE_APPLIANCE_UPLINKS, + SEC_CACHE_APPLIANCE_VPNS, + SEC_CACHE_CELLULAR_UPLINKS, + SEC_CACHE_DEVICE_INFO, + SEC_CACHE_DEVICE_STATUSES, + SEC_CACHE_DEVICE_UPLINKS_INFO, + SEC_CACHE_LICENSES_OVERVIEW, + SEC_CACHE_NETWORKS, + SEC_CACHE_ORG_API_REQUESTS, + SEC_CACHE_ORG_SWITCH_PORTS_STATUSES, + SEC_CACHE_ORGANISATIONS, + SEC_CACHE_SENSOR_READINGS, + SEC_CACHE_SWITCH_PORTS_STATUSES, + SEC_CACHE_WIRELESS_DEVICE_STATUS, + SEC_CACHE_WIRELESS_ETHERNET_STATUSES, + SEC_CACHE_APPLIANCE_PORTS, ) -_MERAKI_SDK_MIN_VERSION: Final = '1.46.0' - -_LOGGER = getLogger('agent_cisco_meraki') - -_API_NAME_API: Final = 'api' -_API_NAME_DEVICE_NAME: Final = 'name' -_API_NAME_DEVICE_PRODUCT_TYPE: Final = 'productType' -_API_NAME_DEVICE_SERIAL: Final = 'serial' -_API_NAME_DEVICE_TYPE_APPLIANCE: Final = 'appliance' -_API_NAME_DEVICE_TYPE_CAMERA: Final = 'camera' -_API_NAME_DEVICE_TYPE_CELLULAR: Final = 'cellularGateway' -_API_NAME_DEVICE_TYPE_SENSOR: Final = 'sensor' -_API_NAME_DEVICE_TYPE_SWITCH: Final = 'switch' -_API_NAME_DEVICE_TYPE_WIRELESS: Final = 'wireless' -_API_NAME_ENABLED: Final = 'enabled' -_API_NAME_NETWORK_ID: Final = 'networkId' -_API_NAME_ORGANISATION_ID: Final = 'id' -_API_NAME_ORGANISATION_NAME: Final = 'name' +MERAKI_SDK_MIN_VERSION: Final = '1.46.0' + +LOGGER = getLogger('agent_cisco_meraki') + +API_NAME_API: Final = 'api' +API_NAME_DEVICE_NAME: Final = 'name' +API_NAME_DEVICE_PRODUCT_TYPE: Final = 'productType' +API_NAME_DEVICE_SERIAL: Final = 'serial' +API_NAME_DEVICE_TYPE_APPLIANCE: Final = 'appliance' +API_NAME_DEVICE_TYPE_CAMERA: Final = 'camera' +API_NAME_DEVICE_TYPE_CELLULAR: Final = 'cellularGateway' +API_NAME_DEVICE_TYPE_SENSOR: Final = 'sensor' +API_NAME_DEVICE_TYPE_SWITCH: Final = 'switch' +API_NAME_DEVICE_TYPE_WIRELESS: Final = 'wireless' +API_NAME_ENABLED: Final = 'enabled' +API_NAME_NETWORK_ID: Final = 'networkId' +API_NAME_ORGANISATION_ID: Final = 'id' +API_NAME_ORGANISATION_NAME: Final = 'name' # map section parameter name to python name (do we really need this, why not use the name ('-' -> '_')? -_SECTION_NAME_MAP = { - _SEC_NAME_APPLIANCE_UPLINKS: 'appliance_uplinks', - _SEC_NAME_APPLIANCE_UPLINKS_USAGE: 'appliance_uplinks_usage', - _SEC_NAME_APPLIANCE_PORTS: 'appliance_ports', - _SEC_NAME_APPLIANCE_VPNS: 'appliance_vpns', - _SEC_NAME_APPLIANCE_PERFORMANCE: 'appliance_performance', - _SEC_NAME_CELLULAR_UPLINKS: 'cellular_uplinks', - _SEC_NAME_DEVICE_INFO: 'device_info', - _SEC_NAME_DEVICE_STATUSES: 'device_status', - _SEC_NAME_DEVICE_UPLINKS_INFO: 'device_uplinks_info', - _SEC_NAME_LICENSES_OVERVIEW: 'licenses_overview', - _SEC_NAME_NETWORKS: 'networks', - _SEC_NAME_ORGANISATIONS: 'organisations', - _SEC_NAME_ORG_API_REQUESTS: 'api_requests_by_organization', - _SEC_NAME_SENSOR_READINGS: 'sensor_readings', - _SEC_NAME_SWITCH_PORTS_STATUSES: 'switch_ports_statuses', - _SEC_NAME_WIRELESS_DEVICE_STATUS: 'wireless_device_status', - _SEC_NAME_WIRELESS_ETHERNET_STATUSES: 'wireless_ethernet_statuses', +SECTION_NAME_MAP = { + SEC_NAME_APPLIANCE_UPLINKS: 'appliance_uplinks', + SEC_NAME_APPLIANCE_UPLINKS_USAGE: 'appliance_uplinks_usage', + SEC_NAME_APPLIANCE_PORTS: 'appliance_ports', + SEC_NAME_APPLIANCE_VPNS: 'appliance_vpns', + SEC_NAME_APPLIANCE_PERFORMANCE: 'appliance_performance', + SEC_NAME_CELLULAR_UPLINKS: 'cellular_uplinks', + SEC_NAME_DEVICE_INFO: 'device_info', + SEC_NAME_DEVICE_STATUSES: 'device_status', + SEC_NAME_DEVICE_UPLINKS_INFO: 'device_uplinks_info', + SEC_NAME_LICENSES_OVERVIEW: 'licenses_overview', + SEC_NAME_NETWORKS: 'networks', + SEC_NAME_ORGANISATIONS: 'organisations', + SEC_NAME_ORG_API_REQUESTS: 'api_requests_by_organization', + SEC_NAME_SENSOR_READINGS: 'sensor_readings', + SEC_NAME_SWITCH_PORTS_STATUSES: 'switch_ports_statuses', + SEC_NAME_WIRELESS_DEVICE_STATUS: 'wireless_device_status', + SEC_NAME_WIRELESS_ETHERNET_STATUSES: 'wireless_ethernet_statuses', # Early Access - _SEC_NAME_ORG_SWITCH_PORTS_STATUSES: 'org_switch_ports_statuses', + SEC_NAME_ORG_SWITCH_PORTS_STATUSES: 'org_switch_ports_statuses', } -# _MIN_CACHE_INTERVAL = 300 -# _RANDOM_CACHE_INTERVAL = 300 +# MIN_CACHE_INTERVAL = 300 +# RANDOM_CACHE_INTERVAL = 300 MerakiCacheFilePath = Path(tmp_dir) / 'agents' / 'agent_cisco_meraki' MerakiAPIData = Mapping[str, object] @@ -192,7 +196,7 @@ MerakiAPIData = Mapping[str, object] # '----------------------------------------------------------------------' -def _configure_meraki_dashboard( +def configure_meraki_dashboard( api_key: str, debug: bool, proxy: str | None, @@ -218,15 +222,16 @@ def _configure_meraki_dashboard( @dataclass(frozen=True) class MerakiConfig: - dashboard: meraki.DashboardAPI - hostname: str # section_names: Sequence[str] + api_key: str # needed for Early Access + dashboard: meraki.DashboardAPI excluded_sections: Sequence[str] - use_cache: bool + hostname: str + net_id_as_prefix: bool org_id_as_prefix: bool - api_key: str # needed for Early Access proxy: str # needed for Early Access timespan: int + use_cache: bool cache_per_section: CachePerSection | None = None @@ -374,7 +379,7 @@ class MerakiGetOrganizations(MerakiSection): total_pages='all', ) except meraki.exceptions.APIError as e: - _LOGGER.debug('Get organisations: %r', e) + LOGGER.debug('Get organisations: %r', e) return [] @@ -387,7 +392,7 @@ class MerakiGetOrganization(MerakiSectionOrg): try: return self._config.dashboard.organizations.getOrganization(self._org_id) except meraki.exceptions.APIError as e: - _LOGGER.debug(f'Get organisation by id {self._org_id}: {e}') + LOGGER.debug(f'Get organisation by id {self._org_id}: {e}') return {} @@ -410,7 +415,7 @@ class MerakiGetOrganizationApiRequestsOverviewResponseCodesByInterval(MerakiSect ) except meraki.APIError as e: - _LOGGER.debug(f'Get API requests by id {self._org_id}: {e}') + LOGGER.debug(f'Get API requests by id {self._org_id}: {e}') return {} @@ -425,7 +430,7 @@ class MerakiGetOrganizationLicensesOverview(MerakiSectionOrg): self._org_id, ) except meraki.exceptions.APIError as e: - _LOGGER.debug('Organisation ID: %r: Get license overview: %r', self._org_id, e) + LOGGER.debug('Organisation ID: %r: Get license overview: %r', self._org_id, e) return [] @@ -441,7 +446,7 @@ class MerakiGetOrganizationDevices(MerakiSectionOrg): total_pages='all', ) except meraki.exceptions.APIError as e: - _LOGGER.debug('Organisation ID: %r: Get devices: %r', self._org_id, e) + LOGGER.debug('Organisation ID: %r: Get devices: %r', self._org_id, e) return {} @@ -457,7 +462,7 @@ class MerakiGetOrganizationNetworks(MerakiSectionOrg): total_pages='all', ) except meraki.exceptions.APIError as e: - _LOGGER.debug('Organisation ID: %r: Get networks: %r', self._org_id, e) + LOGGER.debug('Organisation ID: %r: Get networks: %r', self._org_id, e) return [] @@ -473,7 +478,7 @@ class MerakiGetOrganizationDevicesStatuses(MerakiSectionOrg): total_pages='all', ) except meraki.exceptions.APIError as e: - _LOGGER.debug('Organisation ID: %r: Get device statuses: %r', self._org_id, e) + LOGGER.debug('Organisation ID: %r: Get device statuses: %r', self._org_id, e) return [] @@ -489,7 +494,7 @@ class MerakiGetOrganizationDevicesUplinksAddressesByDevice(MerakiSectionOrg): total_pages='all', ) except meraki.exceptions.APIError as e: - _LOGGER.debug('Organisation ID: %r: Get device statuses: %r', self._org_id, e) + LOGGER.debug('Organisation ID: %r: Get device statuses: %r', self._org_id, e) return [] @@ -505,7 +510,7 @@ class MerakiGetOrganizationApplianceUplinkStatuses(MerakiSectionOrg): total_pages='all', ) except meraki.exceptions.APIError as e: - _LOGGER.debug('Organisation ID: %r: Get Appliance uplink status by network: %r', self._org_id, e) + LOGGER.debug('Organisation ID: %r: Get Appliance uplink status by network: %r', self._org_id, e) return [] @@ -516,7 +521,7 @@ class MerakiGetOrganizationApplianceUplinksUsageByNetwork(MerakiSectionOrg): def get_live_data(self): if meraki.__version__ < '1.39.0': - _LOGGER.debug(f'Meraki SDK is to old. Installed: {meraki.__version__}, excepted: 1.39.0') + LOGGER.debug(f'Meraki SDK is to old. Installed: {meraki.__version__}, excepted: 1.39.0') return [] try: return self._config.dashboard.appliance.getOrganizationApplianceUplinksUsageByNetwork( @@ -525,7 +530,7 @@ class MerakiGetOrganizationApplianceUplinksUsageByNetwork(MerakiSectionOrg): timespan=60 # default=86400 (one day), maximum=1209600 (14 days), needs to match value in check ) except meraki.exceptions.APIError as e: - _LOGGER.debug('Organisation ID: %r: Get Appliance uplink usage by network: %r', self._org_id, e) + LOGGER.debug('Organisation ID: %r: Get Appliance uplink usage by network: %r', self._org_id, e) return [] @@ -542,7 +547,7 @@ class MerakiGetOrganizationApplianceVpnStatuses(MerakiSectionOrg): ) except meraki.exceptions.APIError as e: - _LOGGER.debug('Organisation ID: %r: Get Appliance VPN status by network: %r', self._org_id, e) + LOGGER.debug('Organisation ID: %r: Get Appliance VPN status by network: %r', self._org_id, e) return [] @@ -557,8 +562,8 @@ class MerakiGetDeviceAppliancePerformance(MerakiSectionSerial): return self._config.dashboard.appliance.getDeviceAppliancePerformance( self._serial) except meraki.exceptions.APIError as e: - _LOGGER.debug('Serial: %r: Get appliance device performance: %r', - self._serial, e) + LOGGER.debug('Serial: %r: Get appliance device performance: %r', + self._serial, e) return [] @@ -574,7 +579,7 @@ class MerakiGetOrganizationSensorReadingsLatest(MerakiSectionOrg): total_pages='all', ) except meraki.exceptions.APIError as e: - _LOGGER.debug('Organisation ID: %r: Get sensor readings: %r', self._org_id, e) + LOGGER.debug('Organisation ID: %r: Get sensor readings: %r', self._org_id, e) return [] @@ -591,7 +596,7 @@ class MerakiGetDeviceSwitchPortsStatuses(MerakiSectionSerial): timespan=max(self._config.timespan, 900), ) except meraki.exceptions.APIError as e: - _LOGGER.debug('Serial: %r: Get Switch Port Statuses: %r', self._serial, e) + LOGGER.debug('Serial: %r: Get Switch Port Statuses: %r', self._serial, e) return [] @@ -602,7 +607,7 @@ class MerakiGetOrganizationWirelessDevicesEthernetStatuses(MerakiSectionOrg): def get_live_data(self): if meraki.__version__ < '1.39.0': - _LOGGER.debug(f'Meraki SDK is to old. Installed: {meraki.__version__}, expceted: 1.39.0') + LOGGER.debug(f'Meraki SDK is to old. Installed: {meraki.__version__}, expceted: 1.39.0') return [] try: return self._config.dashboard.wireless.getOrganizationWirelessDevicesEthernetStatuses( @@ -610,7 +615,7 @@ class MerakiGetOrganizationWirelessDevicesEthernetStatuses(MerakiSectionOrg): total_pages='all', ) except meraki.exceptions.APIError as e: - _LOGGER.debug('Organisation ID: %r: Get wireless devices ethernet statuses: %r', self._org_id, e) + LOGGER.debug('Organisation ID: %r: Get wireless devices ethernet statuses: %r', self._org_id, e) return [] @@ -623,7 +628,7 @@ class MerakiGetDeviceWirelessStatus(MerakiSectionSerial): try: return self._config.dashboard.wireless.getDeviceWirelessStatus(self._serial) except meraki.exceptions.APIError as e: - _LOGGER.debug('Serial: %r: Get wireless device status: %r', self._serial, e) + LOGGER.debug('Serial: %r: Get wireless device status: %r', self._serial, e) return [] @@ -639,7 +644,7 @@ class MerakiGetOrganizationCellularGatewayUplinkStatuses(MerakiSectionOrg): total_pages='all', ) except meraki.exceptions.APIError as e: - _LOGGER.debug('Organisation ID: %r: Get cellular gateways uplink statuses: %r', self._org_id, e) + LOGGER.debug('Organisation ID: %r: Get cellular gateways uplink statuses: %r', self._org_id, e) return [] @@ -675,12 +680,12 @@ class MerakiGetOrganizationSwitchPortsStatusesBySwitch(MerakiSectionOrg): timeout=3, ) except RequestException as e: - _LOGGER.debug('Organisation ID: %r: Get Ports statuses by switch: %r', self._org_id, e) + LOGGER.debug('Organisation ID: %r: Get Ports statuses by switch: %r', self._org_id, e) return [] try: _response = response.json() except JSONDecodeError: - _LOGGER.debug('Organisation ID: %r: Get Ports statuses by switch: %r', self._org_id, response) + LOGGER.debug('Organisation ID: %r: Get Ports statuses by switch: %r', self._org_id, response) return [] if _response: return _response.get('items', []) @@ -699,7 +704,7 @@ class MerakiGetNetworkAppliancePorts(MerakiSectionNetwork): # total_pages='all', ) except meraki.exceptions.APIError as e: - _LOGGER.debug('Network ID: %r: Get appliance ports: %r', self._network_id, e) + LOGGER.debug('Network ID: %r: Get appliance ports: %r', self._network_id, e) return [] @@ -717,11 +722,11 @@ class MerakiOrganisation: @property def organisation_id(self) -> str: - return self.organisation[_API_NAME_ORGANISATION_ID] + return self.organisation[API_NAME_ORGANISATION_ID] @property def organisation_name(self) -> str: - return self.organisation[_API_NAME_ORGANISATION_NAME] + return self.organisation[API_NAME_ORGANISATION_NAME] def query(self) -> Iterator[Section]: if organisation := MerakiGetOrganization( @@ -730,28 +735,28 @@ class MerakiOrganisation: cache_interval=self.config.cache_per_section.organisations, ).get_data(use_cache=self.config.use_cache): yield self._make_section( - name=_SEC_NAME_ORGANISATIONS, + name=SEC_NAME_ORGANISATIONS, data=organisation, ) - if not organisation[_API_NAME_API][_API_NAME_ENABLED]: + if not organisation[API_NAME_API][API_NAME_ENABLED]: # stop here if API is not enabled for this organisation return - if _SEC_NAME_ORG_API_REQUESTS not in self.config.excluded_sections: + if SEC_NAME_ORG_API_REQUESTS not in self.config.excluded_sections: if api_requests := MerakiGetOrganizationApiRequestsOverviewResponseCodesByInterval( config=self.config, org_id=self.organisation_id, cache_interval=self.config.cache_per_section.org_api_requests, ).get_data(use_cache=False): # here we want always life data yield self._make_section( - name=_SEC_NAME_ORG_API_REQUESTS, + name=SEC_NAME_ORG_API_REQUESTS, data={'org_id': self.organisation_id, 'requests': api_requests} ) - if _SEC_NAME_LICENSES_OVERVIEW not in self.config.excluded_sections: + if SEC_NAME_LICENSES_OVERVIEW not in self.config.excluded_sections: if licenses_overview := self._get_licenses_overview(): yield self._make_section( - name=_SEC_NAME_LICENSES_OVERVIEW, + name=SEC_NAME_LICENSES_OVERVIEW, data=licenses_overview, ) @@ -773,28 +778,18 @@ class MerakiOrganisation: devices_by_type = {} for _device in devices_by_serial.values(): - if not devices_by_type.get(_device[_API_NAME_DEVICE_PRODUCT_TYPE]): - devices_by_type[_device[_API_NAME_DEVICE_PRODUCT_TYPE]] = [] - devices_by_type[_device[_API_NAME_DEVICE_PRODUCT_TYPE]].append(_device) + if not devices_by_type.get(_device[API_NAME_DEVICE_PRODUCT_TYPE]): + devices_by_type[_device[API_NAME_DEVICE_PRODUCT_TYPE]] = [] + devices_by_type[_device[API_NAME_DEVICE_PRODUCT_TYPE]].append(_device) for device in devices_by_serial.values(): - try: - device_piggyback = device[_API_NAME_DEVICE_NAME] - except KeyError as e: - _LOGGER.debug( - 'Organisation ID: %r: Get device piggyback: %r', self.organisation_id, e - ) - continue - - if not device_piggyback: # skip devices without name, could use serial instead - device_piggyback = f'{device[_API_NAME_DEVICE_SERIAL]}-{device[_API_NAME_DEVICE_PRODUCT_TYPE]}' yield self._make_section( - name=_SEC_NAME_DEVICE_INFO, + name=SEC_NAME_DEVICE_INFO, data=device, - piggyback=self._adjust_piggyback(device_piggyback), + piggyback=self._get_device_piggyback(device, devices_by_serial) ) - if _SEC_NAME_DEVICE_STATUSES not in self.config.excluded_sections: + if SEC_NAME_DEVICE_STATUSES not in self.config.excluded_sections: for device_status in MerakiGetOrganizationDevicesStatuses( config=self.config, org_id=self.organisation_id, @@ -802,11 +797,11 @@ class MerakiOrganisation: ).get_data(use_cache=self.config.use_cache): if piggyback := self._get_device_piggyback(device_status, devices_by_serial): yield self._make_section( - name=_SEC_NAME_DEVICE_STATUSES, + name=SEC_NAME_DEVICE_STATUSES, data=device_status, - piggyback=self._adjust_piggyback(host=piggyback), + piggyback=piggyback, ) - if _SEC_NAME_DEVICE_UPLINKS_INFO not in self.config.excluded_sections: + if SEC_NAME_DEVICE_UPLINKS_INFO not in self.config.excluded_sections: for device_uplink in MerakiGetOrganizationDevicesUplinksAddressesByDevice( config=self.config, org_id=self.organisation_id, @@ -814,13 +809,13 @@ class MerakiOrganisation: ).get_data(use_cache=self.config.use_cache): if piggyback := self._get_device_piggyback(device_uplink, devices_by_serial): yield self._make_section( - name=_SEC_NAME_DEVICE_UPLINKS_INFO, + name=SEC_NAME_DEVICE_UPLINKS_INFO, data=device_uplink, - piggyback=self._adjust_piggyback(host=piggyback), + piggyback=piggyback, ) - if devices_by_type.get(_API_NAME_DEVICE_TYPE_SENSOR): - if _SEC_NAME_SENSOR_READINGS not in self.config.excluded_sections: + if devices_by_type.get(API_NAME_DEVICE_TYPE_SENSOR): + if SEC_NAME_SENSOR_READINGS not in self.config.excluded_sections: for sensor_reading in MerakiGetOrganizationSensorReadingsLatest( config=self.config, org_id=self.organisation_id, @@ -828,14 +823,14 @@ class MerakiOrganisation: ).get_data(use_cache=self.config.use_cache): if piggyback := self._get_device_piggyback(sensor_reading, devices_by_serial): yield self._make_section( - name=_SEC_NAME_SENSOR_READINGS, + name=SEC_NAME_SENSOR_READINGS, data=sensor_reading, - piggyback=self._adjust_piggyback(host=piggyback), + piggyback=piggyback, ) - if devices_by_type.get(_API_NAME_DEVICE_TYPE_APPLIANCE): + if devices_by_type.get(API_NAME_DEVICE_TYPE_APPLIANCE): usage_by_serial = {} - if _SEC_NAME_APPLIANCE_UPLINKS_USAGE not in self.config.excluded_sections: + if SEC_NAME_APPLIANCE_UPLINKS_USAGE not in self.config.excluded_sections: uplink_usage_by_network = MerakiGetOrganizationApplianceUplinksUsageByNetwork( config=self.config, org_id=self.organisation_id, @@ -846,13 +841,13 @@ class MerakiOrganisation: # usage_by_serial = {} for network in uplink_usage_by_network: for uplink in network['byUplink']: - usage_by_serial[uplink[_API_NAME_DEVICE_SERIAL]] = usage_by_serial.get( - uplink[_API_NAME_DEVICE_SERIAL], {} + usage_by_serial[uplink[API_NAME_DEVICE_SERIAL]] = usage_by_serial.get( + uplink[API_NAME_DEVICE_SERIAL], {} ) - usage_by_serial[uplink[_API_NAME_DEVICE_SERIAL]].update( + usage_by_serial[uplink[API_NAME_DEVICE_SERIAL]].update( { uplink['interface']: {'sent': uplink['sent'], 'received': uplink['received']}, - _API_NAME_DEVICE_SERIAL: uplink[_API_NAME_DEVICE_SERIAL] + API_NAME_DEVICE_SERIAL: uplink[API_NAME_DEVICE_SERIAL] } ) @@ -861,10 +856,10 @@ class MerakiOrganisation: # yield self._make_section( # name=_SEC_NAME_APPLIANCE_UPLINKS_USAGE, # data=usage_by_serial[appliance], - # piggyback=self._adjust_piggyback(host=piggyback), + # piggyback=piggyback, # ) - if _SEC_NAME_APPLIANCE_UPLINKS not in self.config.excluded_sections: + if SEC_NAME_APPLIANCE_UPLINKS not in self.config.excluded_sections: for appliance_uplinks in MerakiGetOrganizationApplianceUplinkStatuses( config=self.config, org_id=self.organisation_id, @@ -872,49 +867,47 @@ class MerakiOrganisation: ).get_data(use_cache=self.config.use_cache): if piggyback := self._get_device_piggyback(appliance_uplinks, devices_by_serial): # add network name - if self._networks.get(appliance_uplinks[_API_NAME_NETWORK_ID]): + if self._networks.get(appliance_uplinks[API_NAME_NETWORK_ID]): appliance_uplinks['networkName'] = self._networks[ - appliance_uplinks[_API_NAME_NETWORK_ID]].name + appliance_uplinks[API_NAME_NETWORK_ID]].name # add uplink usage - if appliance_usage := usage_by_serial.get(appliance_uplinks[_API_NAME_DEVICE_SERIAL], None): + if appliance_usage := usage_by_serial.get(appliance_uplinks[API_NAME_DEVICE_SERIAL], None): for uplink in appliance_uplinks['uplinks']: uplink.update(appliance_usage.get(uplink['interface'], {})) yield self._make_section( - name=_SEC_NAME_APPLIANCE_UPLINKS, + name=SEC_NAME_APPLIANCE_UPLINKS, data=appliance_uplinks, - piggyback=self._adjust_piggyback(host=piggyback), + piggyback=piggyback, ) - if _SEC_NAME_APPLIANCE_VPNS not in self.config.excluded_sections: + if SEC_NAME_APPLIANCE_VPNS not in self.config.excluded_sections: for appliance_vpn in MerakiGetOrganizationApplianceVpnStatuses( config=self.config, org_id=self.organisation_id, cache_interval=self.config.cache_per_section.appliance_vpns, ).get_data(use_cache=self.config.use_cache): - appliance_vpn.update({_API_NAME_DEVICE_SERIAL: appliance_vpn['deviceSerial']}) + appliance_vpn.update({API_NAME_DEVICE_SERIAL: appliance_vpn['deviceSerial']}) if piggyback := self._get_device_piggyback(appliance_vpn, devices_by_serial): yield self._make_section( - name=_SEC_NAME_APPLIANCE_VPNS, + name=SEC_NAME_APPLIANCE_VPNS, data=appliance_vpn, - piggyback=self._adjust_piggyback(host=piggyback), + piggyback=piggyback, ) - if _SEC_NAME_APPLIANCE_PERFORMANCE not in self.config.excluded_sections: - for device in devices_by_type[_API_NAME_DEVICE_TYPE_APPLIANCE]: + if SEC_NAME_APPLIANCE_PERFORMANCE not in self.config.excluded_sections: + for device in devices_by_type[API_NAME_DEVICE_TYPE_APPLIANCE]: appliance_performance = MerakiGetDeviceAppliancePerformance( config=self.config, - serial=device[_API_NAME_DEVICE_SERIAL], + serial=device[API_NAME_DEVICE_SERIAL], cache_interval=self.config.cache_per_section.appliance_performance, ).get_data(use_cache=self.config.use_cache) - if piggyback := self._get_device_piggyback({ - _API_NAME_DEVICE_SERIAL: device[_API_NAME_DEVICE_SERIAL] - }, devices_by_serial): + if piggyback := self._get_device_piggyback(device, devices_by_serial): yield self._make_section( - name=_SEC_NAME_APPLIANCE_PERFORMANCE, + name=SEC_NAME_APPLIANCE_PERFORMANCE, data=appliance_performance, - piggyback=self._adjust_piggyback(host=piggyback), + piggyback=piggyback, ) # if _SEC_NAME_APPLIANCE_PORTS not in self.config.excluded_sections and networks: @@ -971,25 +964,23 @@ class MerakiOrganisation: # } # ] - if devices_by_type.get(_API_NAME_DEVICE_TYPE_SWITCH): - if _SEC_NAME_SWITCH_PORTS_STATUSES not in self.config.excluded_sections: - for switch in devices_by_type[_API_NAME_DEVICE_TYPE_SWITCH]: + if devices_by_type.get(API_NAME_DEVICE_TYPE_SWITCH): + if SEC_NAME_SWITCH_PORTS_STATUSES not in self.config.excluded_sections: + for switch in devices_by_type[API_NAME_DEVICE_TYPE_SWITCH]: ports_statuses = MerakiGetDeviceSwitchPortsStatuses( config=self.config, - serial=switch[_API_NAME_DEVICE_SERIAL], + serial=switch[API_NAME_DEVICE_SERIAL], cache_interval=self.config.cache_per_section.switch_ports_statuses, ).get_data(use_cache=self.config.use_cache) - if piggyback := self._get_device_piggyback( - {_API_NAME_DEVICE_SERIAL: switch[_API_NAME_DEVICE_SERIAL]}, devices_by_serial - ): + if piggyback := self._get_device_piggyback(switch, devices_by_serial): yield self._make_section( - name=_SEC_NAME_SWITCH_PORTS_STATUSES, + name=SEC_NAME_SWITCH_PORTS_STATUSES, data=ports_statuses, - piggyback=self._adjust_piggyback(host=piggyback), + piggyback=piggyback, ) - if devices_by_type.get(_API_NAME_DEVICE_TYPE_WIRELESS): - if _SEC_NAME_WIRELESS_ETHERNET_STATUSES not in self.config.excluded_sections: + if devices_by_type.get(API_NAME_DEVICE_TYPE_WIRELESS): + if SEC_NAME_WIRELESS_ETHERNET_STATUSES not in self.config.excluded_sections: for device in MerakiGetOrganizationWirelessDevicesEthernetStatuses( config=self.config, org_id=self.organisation_id, @@ -997,29 +988,27 @@ class MerakiOrganisation: ).get_data(use_cache=self.config.use_cache): if piggyback := self._get_device_piggyback(device, devices_by_serial): yield self._make_section( - name=_SEC_NAME_WIRELESS_ETHERNET_STATUSES, + name=SEC_NAME_WIRELESS_ETHERNET_STATUSES, data=device, - piggyback=self._adjust_piggyback(host=piggyback), + piggyback=piggyback, ) - if _SEC_NAME_WIRELESS_DEVICE_STATUS not in self.config.excluded_sections: - for device in devices_by_type[_API_NAME_DEVICE_TYPE_WIRELESS]: + if SEC_NAME_WIRELESS_DEVICE_STATUS not in self.config.excluded_sections: + for device in devices_by_type[API_NAME_DEVICE_TYPE_WIRELESS]: wireless_statuses = MerakiGetDeviceWirelessStatus( config=self.config, - serial=device[_API_NAME_DEVICE_SERIAL], + serial=device[API_NAME_DEVICE_SERIAL], cache_interval=self.config.cache_per_section.wireless_device_status, ).get_data(use_cache=self.config.use_cache) - if piggyback := self._get_device_piggyback({ - _API_NAME_DEVICE_SERIAL: device[_API_NAME_DEVICE_SERIAL] - }, devices_by_serial): + if piggyback := self._get_device_piggyback(device, devices_by_serial): yield self._make_section( - name=_SEC_NAME_WIRELESS_DEVICE_STATUS, + name=SEC_NAME_WIRELESS_DEVICE_STATUS, data=wireless_statuses, - piggyback=self._adjust_piggyback(host=piggyback), + piggyback=piggyback, ) - if devices_by_type.get(_API_NAME_DEVICE_TYPE_CELLULAR): - if _SEC_NAME_CELLULAR_UPLINKS not in self.config.excluded_sections: + if devices_by_type.get(API_NAME_DEVICE_TYPE_CELLULAR): + if SEC_NAME_CELLULAR_UPLINKS not in self.config.excluded_sections: for gateway in MerakiGetOrganizationCellularGatewayUplinkStatuses( config=self.config, org_id=self.organisation_id, @@ -1027,13 +1016,13 @@ class MerakiOrganisation: ).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, + name=SEC_NAME_CELLULAR_UPLINKS, data=gateway, - piggyback=self._adjust_piggyback(host=piggyback), + piggyback=piggyback, ) # Early Access - if _SEC_NAME_ORG_SWITCH_PORTS_STATUSES not in self.config.excluded_sections: + if SEC_NAME_ORG_SWITCH_PORTS_STATUSES not in self.config.excluded_sections: for switch in MerakiGetOrganizationSwitchPortsStatusesBySwitch( config=self.config, org_id=self.organisation_id, @@ -1041,13 +1030,13 @@ class MerakiOrganisation: ).get_data(use_cache=self.config.use_cache): if piggyback := self._get_device_piggyback(switch, devices_by_serial): yield self._make_section( - name=_SEC_NAME_SWITCH_PORTS_STATUSES, + name=SEC_NAME_SWITCH_PORTS_STATUSES, data=switch, - piggyback=self._adjust_piggyback(host=piggyback), + piggyback=piggyback, ) def _add_networks(self, networks): - self._networks = {_API_NAME_ORGANISATION_NAME: self.organisation_name} + self._networks = {API_NAME_ORGANISATION_NAME: self.organisation_name} for network in networks: network.update({'organizationName': self.organisation_name}) self._networks[network['id']] = MerakiNetwork( @@ -1064,15 +1053,10 @@ class MerakiOrganisation: url=network['url'], ) yield self._make_section( - name=_SEC_NAME_NETWORKS, + name=SEC_NAME_NETWORKS, data=networks, ) - def _adjust_piggyback(self, host: str) -> str: - if self.config.org_id_as_prefix: - return f'{self.organisation_id}-{host}' - return host - def _get_licenses_overview(self) -> MerakiAPIData | None: def _update_licenses_overview( licenses_overview: dict[str, object] | None @@ -1101,13 +1085,13 @@ class MerakiOrganisation: { 'organisation_id': self.organisation_id, 'organisation_name': self.organisation_name, - 'network_name': self._networks.get(device.get(_API_NAME_NETWORK_ID)).name, + 'network_name': self._networks.get(device.get(API_NAME_NETWORK_ID)).name, } ) return device return { - str(device[_API_NAME_DEVICE_SERIAL]): _update_device(device) + str(device[API_NAME_DEVICE_SERIAL]): _update_device(device) for device in MerakiGetOrganizationDevices( config=self.config, org_id=self.organisation_id, @@ -1118,28 +1102,42 @@ class MerakiOrganisation: def _get_device_piggyback( self, device: MerakiAPIData, devices_by_serial: Mapping[str, MerakiAPIData] ) -> str | None: + LOGGER.critical(device) + prefix = '' + if self.config.org_id_as_prefix: + prefix=self.organisation_id +'-' + if self.config.net_id_as_prefix: + try: + prefix += device['networkId'] + '-' + except KeyError: + try: + prefix += device['network']['id'] + '-' + except KeyError: + # print(device) + pass + try: - serial = device[_API_NAME_DEVICE_SERIAL] - if devices_by_serial[serial][_API_NAME_DEVICE_NAME]: - return devices_by_serial[serial][_API_NAME_DEVICE_NAME] + serial = device[API_NAME_DEVICE_SERIAL] + if devices_by_serial[serial][API_NAME_DEVICE_NAME]: + return f'{prefix}{devices_by_serial[serial][API_NAME_DEVICE_NAME]}' else: - _LOGGER.debug(f'Host without name _get_device_piggyback serial: {serial}') - return None + LOGGER.debug(f'Host without name _get_device_piggyback, use serial: {serial}') + return f'{prefix}{serial}-{device[API_NAME_DEVICE_PRODUCT_TYPE]}' except KeyError as e: - _LOGGER.debug('Organisation ID: %r: Get device piggyback: %r', self.organisation_id, e) + LOGGER.debug('Organisation ID: %r: Get device piggyback: %r', self.organisation_id, e) return None @staticmethod def _make_section(*, name: str, data: MerakiAPIData, piggyback: str | None = None) -> Section: return Section( api_data_source=MerakiAPIDataSource.org, - name=_SECTION_NAME_MAP[name], + name=SECTION_NAME_MAP[name], data=data, piggyback=piggyback, ) -def _query_meraki_objects( +def query_meraki_objects( *, organisations: Sequence[MerakiOrganisation], ) -> Iterable[Section]: @@ -1147,7 +1145,7 @@ def _query_meraki_objects( yield from organisation.query() -def _write_sections(sections: Iterable[Section]) -> None: +def write_sections(sections: Iterable[Section]) -> None: sections_by_piggyback: dict = {} for section in sections: sections_by_piggyback.setdefault(section.piggyback, {}).setdefault( @@ -1201,6 +1199,7 @@ class Args(Namespace): hostname: str no_cache: bool org_id_as_prefix: bool + net_id_as_prefix: bool orgs: Sequence[str] proxy: str sections: Sequence[str] @@ -1229,7 +1228,7 @@ def parse_arguments(argv: Sequence[str] | None) -> Args: parser.add_argument( '--excluded-sections', nargs='*', - choices=list(_SECTION_NAME_MAP), + choices=list(SECTION_NAME_MAP), default=[], help='Sections that are excluded form data collected.', ) @@ -1265,31 +1264,37 @@ def parse_arguments(argv: Sequence[str] | None) -> Args: const=True, help='Use organisation ID as hostname prefix.' ) - + parser.add_argument( + '--net-id-as-prefix', + default=False, + action='store_const', + const=True, + help='Use network ID as hostname prefix.' + ) parser.add_argument( '--cache-per-section', nargs='+', type=int, help='List of cache time per section in minutes', default=[ - _SEC_CACHE_APPLIANCE_PERFORMANCE, - _SEC_CACHE_APPLIANCE_PORTS, - _SEC_CACHE_APPLIANCE_UPLINKS, - _SEC_CACHE_APPLIANCE_UPLINKS_USAGE, - _SEC_CACHE_APPLIANCE_VPNS, - _SEC_CACHE_CELLULAR_UPLINKS, - _SEC_CACHE_DEVICE_INFO, - _SEC_CACHE_DEVICE_STATUSES, - _SEC_CACHE_DEVICE_UPLINKS_INFO, - _SEC_CACHE_LICENSES_OVERVIEW, - _SEC_CACHE_NETWORKS, - _SEC_CACHE_ORGANISATIONS, - _SEC_CACHE_ORG_API_REQUESTS, - _SEC_CACHE_ORG_SWITCH_PORTS_STATUSES, - _SEC_CACHE_SENSOR_READINGS, - _SEC_CACHE_SWITCH_PORTS_STATUSES, - _SEC_CACHE_WIRELESS_DEVICE_STATUS, - _SEC_CACHE_WIRELESS_ETHERNET_STATUSES, + SEC_CACHE_APPLIANCE_PERFORMANCE, + SEC_CACHE_APPLIANCE_PORTS, + SEC_CACHE_APPLIANCE_UPLINKS, + SEC_CACHE_APPLIANCE_UPLINKS_USAGE, + SEC_CACHE_APPLIANCE_VPNS, + SEC_CACHE_CELLULAR_UPLINKS, + SEC_CACHE_DEVICE_INFO, + SEC_CACHE_DEVICE_STATUSES, + SEC_CACHE_DEVICE_UPLINKS_INFO, + SEC_CACHE_LICENSES_OVERVIEW, + SEC_CACHE_NETWORKS, + SEC_CACHE_ORGANISATIONS, + SEC_CACHE_ORG_API_REQUESTS, + SEC_CACHE_ORG_SWITCH_PORTS_STATUSES, + SEC_CACHE_SENSOR_READINGS, + SEC_CACHE_SWITCH_PORTS_STATUSES, + SEC_CACHE_WIRELESS_DEVICE_STATUS, + SEC_CACHE_WIRELESS_ETHERNET_STATUSES, ] ) @@ -1300,16 +1305,16 @@ def _need_devices(section_names: Sequence[str]) -> bool: return any( s not in section_names for s in [ - _SEC_NAME_APPLIANCE_UPLINKS, - _SEC_NAME_APPLIANCE_UPLINKS_USAGE, - _SEC_NAME_APPLIANCE_VPNS, - _SEC_NAME_CELLULAR_UPLINKS, - _SEC_NAME_DEVICE_STATUSES, - _SEC_NAME_DEVICE_UPLINKS_INFO, - _SEC_NAME_SENSOR_READINGS, - _SEC_NAME_SWITCH_PORTS_STATUSES, - _SEC_NAME_WIRELESS_DEVICE_STATUS, - _SEC_NAME_WIRELESS_ETHERNET_STATUSES, + SEC_NAME_APPLIANCE_UPLINKS, + SEC_NAME_APPLIANCE_UPLINKS_USAGE, + SEC_NAME_APPLIANCE_VPNS, + SEC_NAME_CELLULAR_UPLINKS, + SEC_NAME_DEVICE_STATUSES, + SEC_NAME_DEVICE_UPLINKS_INFO, + SEC_NAME_SENSOR_READINGS, + SEC_NAME_SWITCH_PORTS_STATUSES, + SEC_NAME_WIRELESS_DEVICE_STATUS, + SEC_NAME_WIRELESS_ETHERNET_STATUSES, ] ) @@ -1317,8 +1322,8 @@ def _need_devices(section_names: Sequence[str]) -> bool: def _get_organisations(config: MerakiConfig, org_ids: Sequence[str]) -> Sequence[_Organisation]: organisations = [ _Organisation( - id=organisation[_API_NAME_ORGANISATION_ID], - name=organisation[_API_NAME_ORGANISATION_NAME], + id=organisation[API_NAME_ORGANISATION_ID], + name=organisation[API_NAME_ORGANISATION_NAME], ) for organisation in MerakiGetOrganizations( config=config ).get_data(use_cache=config.use_cache) @@ -1326,7 +1331,7 @@ def _get_organisations(config: MerakiConfig, org_ids: Sequence[str]) -> Sequence if org_ids: organisations = [ - organisation for organisation in organisations if organisation[_API_NAME_ORGANISATION_ID] in org_ids + organisation for organisation in organisations if organisation[API_NAME_ORGANISATION_ID] in org_ids ] return organisations @@ -1353,16 +1358,16 @@ def get_proxy(raw_proxy: str) -> str | None: def agent_cisco_meraki_main(args: Args) -> int: - if meraki.__version__ < _MERAKI_SDK_MIN_VERSION: + if meraki.__version__ < MERAKI_SDK_MIN_VERSION: print( - f'This Agent needs at least Meraki SDK version {_MERAKI_SDK_MIN_VERSION}, installed is {meraki.__version__}' + f'This Agent needs at least Meraki SDK version {MERAKI_SDK_MIN_VERSION}, installed is {meraki.__version__}' ) exit(1) # don't remove used for runtime logging at the end start_time = time_ns() config = MerakiConfig( - dashboard=_configure_meraki_dashboard( + dashboard=configure_meraki_dashboard( args.apikey, args.debug, get_proxy(args.proxy) @@ -1372,6 +1377,7 @@ def agent_cisco_meraki_main(args: Args) -> int: excluded_sections=args.excluded_sections, use_cache=not args.no_cache, org_id_as_prefix=args.org_id_as_prefix, + net_id_as_prefix=args.net_id_as_prefix, api_key=args.apikey, proxy=get_proxy(args.proxy), timespan=60, @@ -1382,14 +1388,14 @@ def agent_cisco_meraki_main(args: Args) -> int: for organisation in _get_organisations(config, args.orgs) ] - sections = _query_meraki_objects( + sections = query_meraki_objects( organisations=organisations, ) - _write_sections(sections) + write_sections(sections) - _LOGGER.warning(f'Time taken: {(time_ns() - start_time) / 1e9}/s') - _LOGGER.warning(f'Meraki SDK version: {meraki.__version__}') + LOGGER.warning(f'Time taken: {(time_ns() - start_time) / 1e9}/s') + LOGGER.warning(f'Meraki SDK version: {meraki.__version__}') return 0 diff --git a/source/cmk_addons_plugins/meraki/lib/utils.py b/source/cmk_addons_plugins/meraki/lib/utils.py index 2301c95996f5a4436484f3db6aa791417910c34b..941ef4c525f4932e52ca4e9c6b04f332cf1f2131 100644 --- a/source/cmk_addons_plugins/meraki/lib/utils.py +++ b/source/cmk_addons_plugins/meraki/lib/utils.py @@ -23,48 +23,47 @@ from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import CheckResul MerakiAPIData = Mapping[str, object] # parameter names for agent options -_SEC_NAME_ORGANISATIONS: Final = '_organisations' # internal use runs always -_SEC_NAME_DEVICE_INFO: Final = '_device_info' # Not configurable, needed for piggyback -_SEC_NAME_NETWORKS: Final = '_networks' # internal use, runs always, needed for network names -_SEC_NAME_ORG_API_REQUESTS: Final = 'api-requests-by-organization' # internal use, runs always - -_SEC_NAME_APPLIANCE_UPLINKS: Final = 'appliance-uplinks' -_SEC_NAME_APPLIANCE_PORTS: Final = 'appliance-ports' -_SEC_NAME_APPLIANCE_UPLINKS_USAGE: Final = 'appliance-uplinks-usage' -_SEC_NAME_APPLIANCE_VPNS: Final = 'appliance-vpns' -_SEC_NAME_APPLIANCE_PERFORMANCE: Final = 'appliance-performance' -_SEC_NAME_CELLULAR_UPLINKS: Final = 'cellular-uplinks' -_SEC_NAME_DEVICE_STATUSES: Final = 'device-status' -_SEC_NAME_DEVICE_UPLINKS_INFO: Final = 'device-uplinks-info' -_SEC_NAME_LICENSES_OVERVIEW: Final = 'licenses-overview' -_SEC_NAME_SENSOR_READINGS: Final = 'sensor-readings' -_SEC_NAME_SWITCH_PORTS_STATUSES: Final = 'switch-ports-statuses' -_SEC_NAME_WIRELESS_DEVICE_STATUS: Final = 'wireless-device-status' -_SEC_NAME_WIRELESS_ETHERNET_STATUSES: Final = 'wireless-ethernet-statuses' - +SEC_NAME_ORGANISATIONS: Final = '_organisations' # internal use runs always +SEC_NAME_DEVICE_INFO: Final = '_device_info' # Not configurable, needed for piggyback +SEC_NAME_NETWORKS: Final = '_networks' # internal use, runs always, needed for network names +SEC_NAME_ORG_API_REQUESTS: Final = 'api-requests-by-organization' # internal use, runs always + +SEC_NAME_APPLIANCE_UPLINKS: Final = 'appliance-uplinks' +SEC_NAME_APPLIANCE_PORTS: Final = 'appliance-ports' +SEC_NAME_APPLIANCE_UPLINKS_USAGE: Final = 'appliance-uplinks-usage' +SEC_NAME_APPLIANCE_VPNS: Final = 'appliance-vpns' +SEC_NAME_APPLIANCE_PERFORMANCE: Final = 'appliance-performance' +SEC_NAME_CELLULAR_UPLINKS: Final = 'cellular-uplinks' +SEC_NAME_DEVICE_STATUSES: Final = 'device-status' +SEC_NAME_DEVICE_UPLINKS_INFO: Final = 'device-uplinks-info' +SEC_NAME_LICENSES_OVERVIEW: Final = 'licenses-overview' +SEC_NAME_SENSOR_READINGS: Final = 'sensor-readings' +SEC_NAME_SWITCH_PORTS_STATUSES: Final = 'switch-ports-statuses' +SEC_NAME_WIRELESS_DEVICE_STATUS: Final = 'wireless-device-status' +SEC_NAME_WIRELESS_ETHERNET_STATUSES: Final = 'wireless-ethernet-statuses' # api cache defaults per section -_SEC_CACHE_APPLIANCE_PERFORMANCE = 0 -_SEC_CACHE_APPLIANCE_UPLINKS_USAGE = 0 -_SEC_CACHE_APPLIANCE_UPLINKS = 60 -_SEC_CACHE_APPLIANCE_VPNS = 60 -_SEC_CACHE_CELLULAR_UPLINKS = 60 -_SEC_CACHE_DEVICE_INFO = 60 -_SEC_CACHE_DEVICE_STATUSES = 60 -_SEC_CACHE_DEVICE_UPLINKS_INFO = 60 -_SEC_CACHE_LICENSES_OVERVIEW = 600 -_SEC_CACHE_NETWORKS = 600 -_SEC_CACHE_ORG_API_REQUESTS = 0 -_SEC_CACHE_ORG_SWITCH_PORTS_STATUSES = 0 -_SEC_CACHE_ORGANISATIONS = 600 -_SEC_CACHE_SENSOR_READINGS = 0 -_SEC_CACHE_SWITCH_PORTS_STATUSES = 0 -_SEC_CACHE_WIRELESS_DEVICE_STATUS = 30 -_SEC_CACHE_WIRELESS_ETHERNET_STATUSES = 30 -_SEC_CACHE_APPLIANCE_PORTS = 30 +SEC_CACHE_APPLIANCE_PERFORMANCE = 0 +SEC_CACHE_APPLIANCE_UPLINKS_USAGE = 0 +SEC_CACHE_APPLIANCE_UPLINKS = 60 +SEC_CACHE_APPLIANCE_VPNS = 60 +SEC_CACHE_CELLULAR_UPLINKS = 60 +SEC_CACHE_DEVICE_INFO = 60 +SEC_CACHE_DEVICE_STATUSES = 60 +SEC_CACHE_DEVICE_UPLINKS_INFO = 60 +SEC_CACHE_LICENSES_OVERVIEW = 600 +SEC_CACHE_NETWORKS = 600 +SEC_CACHE_ORG_API_REQUESTS = 0 +SEC_CACHE_ORG_SWITCH_PORTS_STATUSES = 0 +SEC_CACHE_ORGANISATIONS = 600 +SEC_CACHE_SENSOR_READINGS = 0 +SEC_CACHE_SWITCH_PORTS_STATUSES = 0 +SEC_CACHE_WIRELESS_DEVICE_STATUS = 30 +SEC_CACHE_WIRELESS_ETHERNET_STATUSES = 30 +SEC_CACHE_APPLIANCE_PORTS = 30 # Early Access -_SEC_NAME_ORG_SWITCH_PORTS_STATUSES: Final = 'org-switch-ports-statuses' +SEC_NAME_ORG_SWITCH_PORTS_STATUSES: Final = 'org-switch-ports-statuses' @dataclass(frozen=True) diff --git a/source/cmk_plugins/cisco/rulesets/meraki.py b/source/cmk_plugins/cisco/rulesets/meraki.py index 244c40b32df6eadfbab475b43d566906866fa15f..aaefefa8c1465acb33d687eba08dd3bd76ef6834 100644 --- a/source/cmk_plugins/cisco/rulesets/meraki.py +++ b/source/cmk_plugins/cisco/rulesets/meraki.py @@ -31,60 +31,60 @@ from cmk.rulesets.v1.form_specs import ( from cmk.rulesets.v1.form_specs.validators import ValidationError, NumberInRange from cmk.rulesets.v1.rule_specs import SpecialAgent, Topic from cmk_addons.plugins.meraki.lib.utils import ( - _SEC_CACHE_APPLIANCE_PERFORMANCE, - _SEC_CACHE_APPLIANCE_UPLINKS_USAGE, - _SEC_CACHE_APPLIANCE_UPLINKS, - _SEC_CACHE_APPLIANCE_VPNS, - _SEC_CACHE_CELLULAR_UPLINKS, - _SEC_CACHE_DEVICE_INFO, - _SEC_CACHE_DEVICE_STATUSES, - _SEC_CACHE_DEVICE_UPLINKS_INFO, - _SEC_CACHE_LICENSES_OVERVIEW, - _SEC_CACHE_NETWORKS, - _SEC_CACHE_ORG_API_REQUESTS, - _SEC_CACHE_ORG_SWITCH_PORTS_STATUSES, - _SEC_CACHE_ORGANISATIONS, - _SEC_CACHE_SENSOR_READINGS, - _SEC_CACHE_SWITCH_PORTS_STATUSES, - _SEC_CACHE_WIRELESS_DEVICE_STATUS, - _SEC_CACHE_WIRELESS_ETHERNET_STATUSES, + SEC_CACHE_APPLIANCE_PERFORMANCE, + SEC_CACHE_APPLIANCE_UPLINKS_USAGE, + SEC_CACHE_APPLIANCE_UPLINKS, + SEC_CACHE_APPLIANCE_VPNS, + SEC_CACHE_CELLULAR_UPLINKS, + SEC_CACHE_DEVICE_INFO, + SEC_CACHE_DEVICE_STATUSES, + SEC_CACHE_DEVICE_UPLINKS_INFO, + SEC_CACHE_LICENSES_OVERVIEW, + SEC_CACHE_NETWORKS, + SEC_CACHE_ORG_API_REQUESTS, + SEC_CACHE_ORG_SWITCH_PORTS_STATUSES, + SEC_CACHE_ORGANISATIONS, + SEC_CACHE_SENSOR_READINGS, + SEC_CACHE_SWITCH_PORTS_STATUSES, + SEC_CACHE_WIRELESS_DEVICE_STATUS, + SEC_CACHE_WIRELESS_ETHERNET_STATUSES, ) -_SEC_NAME_APPLIANCE_UPLINKS = "appliance_uplinks" -_SEC_NAME_APPLIANCE_UPLINKS_USAGE = "appliance_uplinks_usage" -_SEC_NAME_APPLIANCE_VPNS = "appliance_vpns" -_SEC_NAME_APPLIANCE_PERFORMANCE = "appliance_performance" -_SEC_NAME_CELLULAR_UPLINKS = "cellular_uplinks" -_SEC_NAME_DEVICE_INFO = "device_info" -_SEC_NAME_DEVICE_STATUSES = "device_status" -_SEC_NAME_DEVICE_UPLINKS_INFO = "device_uplinks_info" -_SEC_NAME_LICENSES_OVERVIEW = "licenses_overview" -_SEC_NAME_NETWORKS = "networks" -_SEC_NAME_ORGANISATIONS = "organisations" -_SEC_NAME_ORG_API_REQUESTS = "api_requests_by_organization" -_SEC_NAME_SENSOR_READINGS = "sensor_readings" -_SEC_NAME_SWITCH_PORTS_STATUSES = "switch_ports_statuses" -_SEC_NAME_WIRELESS_DEVICE_STATUS = "wireless_device_status" -_SEC_NAME_WIRELESS_ETHERNET_STATUSES = "wireless_ethernet_statuses" -_SEC_NAME_ORG_SWITCH_PORTS_STATUSES = "org_switch_ports_statuses" +SEC_NAME_APPLIANCE_UPLINKS = 'appliance_uplinks' +SEC_NAME_APPLIANCE_UPLINKS_USAGE = 'appliance_uplinks_usage' +SEC_NAME_APPLIANCE_VPNS = 'appliance_vpns' +SEC_NAME_APPLIANCE_PERFORMANCE = 'appliance_performance' +SEC_NAME_CELLULAR_UPLINKS = 'cellular_uplinks' +SEC_NAME_DEVICE_INFO = 'device_info' +SEC_NAME_DEVICE_STATUSES = 'device_status' +SEC_NAME_DEVICE_UPLINKS_INFO = 'device_uplinks_info' +SEC_NAME_LICENSES_OVERVIEW = 'licenses_overview' +SEC_NAME_NETWORKS = 'networks' +SEC_NAME_ORGANISATIONS = 'organisations' +SEC_NAME_ORG_API_REQUESTS = 'api_requests_by_organization' +SEC_NAME_SENSOR_READINGS = 'sensor_readings' +SEC_NAME_SWITCH_PORTS_STATUSES = 'switch_ports_statuses' +SEC_NAME_WIRELESS_DEVICE_STATUS = 'wireless_device_status' +SEC_NAME_WIRELESS_ETHERNET_STATUSES = 'wireless_ethernet_statuses' +SEC_NAME_ORG_SWITCH_PORTS_STATUSES = 'org_switch_ports_statuses' -_SEC_TITLE_DEVICE_INFO = 'Device info (Organization)' -_SEC_TITLE_NETWORKS = 'Network info (Organization)' -_SEC_TITLE_ORGANISATIONS = 'Organization (Agent)' -_SEC_TITLE_ORG_API_REQUESTS = 'API request (Organizaion)' -_SEC_TITLE_APPLIANCE_UPLINKS = 'Appliances uplinks (Organizaion)' -_SEC_TITLE_APPLIANCE_UPLINKS_USAGE = 'Appliances uplinks usage (Organizaion)' -_SEC_TITLE_APPLIANCE_VPNS = 'Appliances VPNs (Organizaion)' -_SEC_TITLE_APPLIANCE_PERFORMANCE = 'Appliances Utilization (Device)' -_SEC_TITLE_CELLULAR_UPLINKS = 'Cellular devices uplinks (Organizaion)' -_SEC_TITLE_DEVICE_STATUSES = 'Devices status (Organizaion)' -_SEC_TITLE_DEVICE_UPLINKS_INFO = 'Devices uplink info (Organizaion)' -_SEC_TITLE_LICENSES_OVERVIEW = 'Licenses overview (Organizaion)' -_SEC_TITLE_SENSOR_READINGS = 'Sensors readings (Organizaion)' -_SEC_TITLE_SWITCH_PORTS_STATUSES = 'Switch ports status (Device)' -_SEC_TITLE_WIRELESS_ETHERNET_STATUSES = 'Wireless devices ethernet status (Organizaion)' -_SEC_TITLE_WIRELESS_DEVICE_STATUS = 'Wireless devices SSIDs status (Device)' -_SEC_TITLE_ORG_SWITCH_PORTS_STATUSES = 'Switch port status (Organizaion/Early Access)' +SEC_TITLE_DEVICE_INFO = 'Device info (Organization)' +SEC_TITLE_NETWORKS = 'Network info (Organization)' +SEC_TITLE_ORGANISATIONS = 'Organization (Agent)' +SEC_TITLE_ORG_API_REQUESTS = 'API request (Organization)' +SEC_TITLE_APPLIANCE_UPLINKS = 'Appliances uplinks (Organization)' +SEC_TITLE_APPLIANCE_UPLINKS_USAGE = 'Appliances uplinks usage (Organization)' +SEC_TITLE_APPLIANCE_VPNS = 'Appliances VPNs (Organization)' +SEC_TITLE_APPLIANCE_PERFORMANCE = 'Appliances Utilization (Device)' +SEC_TITLE_CELLULAR_UPLINKS = 'Cellular devices uplinks (Organization)' +SEC_TITLE_DEVICE_STATUSES = 'Devices status (Organization)' +SEC_TITLE_DEVICE_UPLINKS_INFO = 'Devices uplink info (Organization)' +SEC_TITLE_LICENSES_OVERVIEW = 'Licenses overview (Organization)' +SEC_TITLE_SENSOR_READINGS = 'Sensors readings (Organization)' +SEC_TITLE_SWITCH_PORTS_STATUSES = 'Switch ports status (Device)' +SEC_TITLE_WIRELESS_ETHERNET_STATUSES = 'Wireless devices ethernet status (Organization)' +SEC_TITLE_WIRELESS_DEVICE_STATUS = 'Wireless devices SSIDs status (Device)' +SEC_TITLE_ORG_SWITCH_PORTS_STATUSES = 'Switch port status (Organization/Early Access)' class DuplicateInList: # pylint: disable=too-few-public-methods @@ -97,7 +97,7 @@ class DuplicateInList: # pylint: disable=too-few-public-methods @staticmethod def _get_default_errmsg(_duplicates: Sequence) -> Message: - return Message(f"Duplicate element in list. Duplicate elements: {', '.join(_duplicates)}") + return Message(f'Duplicate element in list. Duplicate elements: {", ".join(_duplicates)}') def __call__(self, value: List[str] | None) -> None: if not isinstance(value, list): @@ -110,13 +110,13 @@ class DuplicateInList: # pylint: disable=too-few-public-methods def _migrate_to_valid_ident(value: object) -> Sequence[str]: if not isinstance(value, Iterable): - raise ValueError("Invalid value {value} for sections") + raise ValueError('Invalid value {value} for sections') - name_mapping = { - "licenses-overview": "licenses_overview", - "device-statuses": "device_statuses", - "sensor-readings": "sensor_readings", - } + # name_mapping = { + # 'licenses-overview': 'licenses_overview', + # 'device-statuses': 'device_statuses', + # 'sensor-readings': 'sensor_readings', + # } # return [name_mapping.get(s, s) for s in value] return [s.replace('-', '_') for s in value] @@ -124,135 +124,148 @@ def _migrate_to_valid_ident(value: object) -> Sequence[str]: def _form_special_agent_cisco_meraki() -> Dictionary: return Dictionary( - title=Title("Cisco Meraki"), + title=Title('Cisco Meraki'), elements={ - "api_key": DictElement( + 'api_key': DictElement( parameter_form=Password( - title=Title("API Key"), + title=Title('API Key'), migrate=migrate_to_password ), required=True, ), - "proxy": DictElement( + 'proxy': DictElement( parameter_form=Proxy( migrate=migrate_to_proxy ) ), - "no_cache": DictElement( + 'no_cache': DictElement( parameter_form=FixedValue( # BooleanChoice needs 2 clicks :-( - title=Title("Disable Cache"), + title=Title('Disable Cache'), help_text=Help( - "Never use cached information. By default the agent will cache received " - "data to avoid API limits and speed up the data retrievel." + 'Never use cached information. By default the agent will cache received ' + 'data to avoid API limits and speed up the data retrievel.' ), - label=Label("API Cache is disabled"), + label=Label('API Cache is disabled'), value=True, ) ), 'org_id_as_prefix': DictElement( parameter_form=FixedValue( value=True, - title=Title('Uese organisation ID as host prefix'), - label=Label("The Organization-id will be used as host name prefix"), + title=Title('Use Organisation-ID as host prefix'), + label=Label('The Organization-ID will be used as host name prefix'), help_text=Help( - 'The organisation ID will be used as prefix for the hostname (separated by a "\'"). Use ' + 'The Organisation-ID will be used as prefix for the hostname (separated by a -). Use ' 'this option together with a "Hostname translation for piggybacked hosts" to add a ' 'organisation prefix to the hosts from the Cisco Meraki cloud to avoid conflicting ' 'hostnames. You can also use this option along with the "Dynamic host management" to ' 'sort the host in organisation specific folders.' ) )), - "excluded_sections": DictElement( + 'net_id_as_prefix': DictElement( + parameter_form=FixedValue( + value=True, + title=Title('Use Network-ID as host prefix'), + label=Label('The Network-ID will be used as host name prefix'), + help_text=Help( + 'The Network-ID will be used as prefix for the hostname (separated by a -). Use ' + 'this option together with a "Hostname translation for piggybacked hosts" to add a ' + 'network prefix to the hosts from the Cisco Meraki cloud to avoid conflicting ' + 'hostnames. You can also use this option along with the "Dynamic host management" to ' + 'sort the host in location specific folders.' + ) + )), + 'excluded_sections': DictElement( parameter_form=MultipleChoice( - title=Title("Exclude Sections"), + title=Title('Exclude Sections'), elements=[ - MultipleChoiceElement(name=_SEC_NAME_ORG_API_REQUESTS, - title=Title(_SEC_TITLE_ORG_API_REQUESTS)), - MultipleChoiceElement(name=_SEC_NAME_APPLIANCE_UPLINKS, - title=Title(_SEC_TITLE_APPLIANCE_UPLINKS)), - MultipleChoiceElement(name=_SEC_NAME_APPLIANCE_UPLINKS_USAGE, - title=Title(_SEC_TITLE_APPLIANCE_UPLINKS_USAGE)), - MultipleChoiceElement(name=_SEC_NAME_APPLIANCE_VPNS, title=Title(_SEC_TITLE_APPLIANCE_VPNS)), - MultipleChoiceElement(name=_SEC_NAME_APPLIANCE_PERFORMANCE, - title=Title(_SEC_TITLE_APPLIANCE_PERFORMANCE)), - MultipleChoiceElement(name=_SEC_NAME_CELLULAR_UPLINKS, - title=Title(_SEC_TITLE_CELLULAR_UPLINKS)), - MultipleChoiceElement(name=_SEC_NAME_DEVICE_STATUSES, title=Title(_SEC_TITLE_DEVICE_STATUSES)), - MultipleChoiceElement(name=_SEC_NAME_DEVICE_UPLINKS_INFO, - title=Title(_SEC_TITLE_DEVICE_UPLINKS_INFO)), - MultipleChoiceElement(name=_SEC_NAME_LICENSES_OVERVIEW, - title=Title(_SEC_TITLE_LICENSES_OVERVIEW)), - MultipleChoiceElement(name=_SEC_NAME_SENSOR_READINGS, title=Title(_SEC_TITLE_SENSOR_READINGS)), - MultipleChoiceElement(name=_SEC_NAME_SWITCH_PORTS_STATUSES, - title=Title(_SEC_TITLE_SWITCH_PORTS_STATUSES)), - MultipleChoiceElement(name=_SEC_NAME_WIRELESS_ETHERNET_STATUSES, - title=Title(_SEC_TITLE_WIRELESS_ETHERNET_STATUSES)), - MultipleChoiceElement(name=_SEC_NAME_WIRELESS_DEVICE_STATUS, - title=Title(_SEC_TITLE_WIRELESS_DEVICE_STATUS)), - MultipleChoiceElement(name=_SEC_NAME_ORG_SWITCH_PORTS_STATUSES, - title=Title(_SEC_TITLE_ORG_SWITCH_PORTS_STATUSES)), + MultipleChoiceElement(name=SEC_NAME_ORG_API_REQUESTS, + title=Title(SEC_TITLE_ORG_API_REQUESTS)), + MultipleChoiceElement(name=SEC_NAME_APPLIANCE_UPLINKS, + title=Title(SEC_TITLE_APPLIANCE_UPLINKS)), + MultipleChoiceElement(name=SEC_NAME_APPLIANCE_UPLINKS_USAGE, + title=Title(SEC_TITLE_APPLIANCE_UPLINKS_USAGE)), + MultipleChoiceElement(name=SEC_NAME_APPLIANCE_VPNS, title=Title(SEC_TITLE_APPLIANCE_VPNS)), + MultipleChoiceElement(name=SEC_NAME_APPLIANCE_PERFORMANCE, + title=Title(SEC_TITLE_APPLIANCE_PERFORMANCE)), + MultipleChoiceElement(name=SEC_NAME_CELLULAR_UPLINKS, + title=Title(SEC_TITLE_CELLULAR_UPLINKS)), + MultipleChoiceElement(name=SEC_NAME_DEVICE_STATUSES, title=Title(SEC_TITLE_DEVICE_STATUSES)), + MultipleChoiceElement(name=SEC_NAME_DEVICE_UPLINKS_INFO, + title=Title(SEC_TITLE_DEVICE_UPLINKS_INFO)), + MultipleChoiceElement(name=SEC_NAME_LICENSES_OVERVIEW, + title=Title(SEC_TITLE_LICENSES_OVERVIEW)), + MultipleChoiceElement(name=SEC_NAME_SENSOR_READINGS, title=Title(SEC_TITLE_SENSOR_READINGS)), + MultipleChoiceElement(name=SEC_NAME_SWITCH_PORTS_STATUSES, + title=Title(SEC_TITLE_SWITCH_PORTS_STATUSES)), + MultipleChoiceElement(name=SEC_NAME_WIRELESS_ETHERNET_STATUSES, + title=Title(SEC_TITLE_WIRELESS_ETHERNET_STATUSES)), + MultipleChoiceElement(name=SEC_NAME_WIRELESS_DEVICE_STATUS, + title=Title(SEC_TITLE_WIRELESS_DEVICE_STATUS)), + MultipleChoiceElement(name=SEC_NAME_ORG_SWITCH_PORTS_STATUSES, + title=Title(SEC_TITLE_ORG_SWITCH_PORTS_STATUSES)), ], prefill=DefaultValue([ - _SEC_NAME_APPLIANCE_PERFORMANCE, - _SEC_NAME_SWITCH_PORTS_STATUSES, - _SEC_NAME_WIRELESS_DEVICE_STATUS, - _SEC_NAME_ORG_SWITCH_PORTS_STATUSES, + SEC_NAME_APPLIANCE_PERFORMANCE, + SEC_NAME_SWITCH_PORTS_STATUSES, + SEC_NAME_WIRELESS_DEVICE_STATUS, + SEC_NAME_ORG_SWITCH_PORTS_STATUSES, ]), # migrate=_migrate_to_valid_ident, ), required=True, ), - "orgs": DictElement( + 'orgs': DictElement( parameter_form=List( - element_template=String(macro_support=True), title=Title("Organizations"), + element_template=String(macro_support=True), title=Title('Organizations'), custom_validate=(DuplicateInList(),), ), ), - "cache_per_section": DictElement( + 'cache_per_section': DictElement( parameter_form=Dictionary( - title=Title("Set Cache time per section"), + title=Title('Set Cache time per section'), elements={ sec_name: DictElement( parameter_form=Integer( title=Title(sec_title), prefill=DefaultValue(sec_cache), - unit_symbol="minutes", + unit_symbol='minutes', custom_validate=(NumberInRange(min_value=0),) ) ) for sec_name, sec_title, sec_cache in [ - (_SEC_NAME_APPLIANCE_PERFORMANCE, _SEC_TITLE_APPLIANCE_PERFORMANCE, _SEC_CACHE_APPLIANCE_PERFORMANCE), - (_SEC_NAME_APPLIANCE_UPLINKS_USAGE, _SEC_TITLE_APPLIANCE_UPLINKS_USAGE, _SEC_CACHE_APPLIANCE_UPLINKS_USAGE), - (_SEC_NAME_APPLIANCE_UPLINKS, _SEC_TITLE_APPLIANCE_UPLINKS, _SEC_CACHE_APPLIANCE_UPLINKS), - (_SEC_NAME_APPLIANCE_VPNS, _SEC_TITLE_APPLIANCE_VPNS, _SEC_CACHE_APPLIANCE_VPNS), - (_SEC_NAME_CELLULAR_UPLINKS, _SEC_TITLE_CELLULAR_UPLINKS, _SEC_CACHE_CELLULAR_UPLINKS), - (_SEC_NAME_DEVICE_INFO, _SEC_TITLE_DEVICE_INFO, _SEC_CACHE_DEVICE_INFO), - (_SEC_NAME_DEVICE_STATUSES, _SEC_TITLE_DEVICE_STATUSES, _SEC_CACHE_DEVICE_STATUSES), - (_SEC_NAME_DEVICE_UPLINKS_INFO, _SEC_TITLE_DEVICE_UPLINKS_INFO, _SEC_CACHE_DEVICE_UPLINKS_INFO), - (_SEC_NAME_LICENSES_OVERVIEW, _SEC_TITLE_LICENSES_OVERVIEW, _SEC_CACHE_LICENSES_OVERVIEW), - (_SEC_NAME_NETWORKS, _SEC_TITLE_NETWORKS, _SEC_CACHE_NETWORKS), - (_SEC_NAME_ORG_API_REQUESTS, _SEC_TITLE_ORG_API_REQUESTS, _SEC_CACHE_ORG_API_REQUESTS), - (_SEC_NAME_ORG_SWITCH_PORTS_STATUSES, _SEC_TITLE_ORG_SWITCH_PORTS_STATUSES, _SEC_CACHE_ORG_SWITCH_PORTS_STATUSES), - (_SEC_NAME_ORGANISATIONS, _SEC_TITLE_ORGANISATIONS, _SEC_CACHE_ORGANISATIONS), - (_SEC_NAME_SENSOR_READINGS, _SEC_TITLE_SENSOR_READINGS, _SEC_CACHE_SENSOR_READINGS), - (_SEC_NAME_SWITCH_PORTS_STATUSES, _SEC_TITLE_SWITCH_PORTS_STATUSES, _SEC_CACHE_SWITCH_PORTS_STATUSES), - (_SEC_NAME_WIRELESS_DEVICE_STATUS, _SEC_TITLE_WIRELESS_DEVICE_STATUS, _SEC_CACHE_WIRELESS_DEVICE_STATUS), - (_SEC_NAME_WIRELESS_ETHERNET_STATUSES, _SEC_TITLE_WIRELESS_ETHERNET_STATUSES, _SEC_CACHE_WIRELESS_ETHERNET_STATUSES), + (SEC_NAME_APPLIANCE_PERFORMANCE, SEC_TITLE_APPLIANCE_PERFORMANCE, SEC_CACHE_APPLIANCE_PERFORMANCE), + (SEC_NAME_APPLIANCE_UPLINKS_USAGE, SEC_TITLE_APPLIANCE_UPLINKS_USAGE, SEC_CACHE_APPLIANCE_UPLINKS_USAGE), + (SEC_NAME_APPLIANCE_UPLINKS, SEC_TITLE_APPLIANCE_UPLINKS, SEC_CACHE_APPLIANCE_UPLINKS), + (SEC_NAME_APPLIANCE_VPNS, SEC_TITLE_APPLIANCE_VPNS, SEC_CACHE_APPLIANCE_VPNS), + (SEC_NAME_CELLULAR_UPLINKS, SEC_TITLE_CELLULAR_UPLINKS, SEC_CACHE_CELLULAR_UPLINKS), + (SEC_NAME_DEVICE_INFO, SEC_TITLE_DEVICE_INFO, SEC_CACHE_DEVICE_INFO), + (SEC_NAME_DEVICE_STATUSES, SEC_TITLE_DEVICE_STATUSES, SEC_CACHE_DEVICE_STATUSES), + (SEC_NAME_DEVICE_UPLINKS_INFO, SEC_TITLE_DEVICE_UPLINKS_INFO, SEC_CACHE_DEVICE_UPLINKS_INFO), + (SEC_NAME_LICENSES_OVERVIEW, SEC_TITLE_LICENSES_OVERVIEW, SEC_CACHE_LICENSES_OVERVIEW), + (SEC_NAME_NETWORKS, SEC_TITLE_NETWORKS, SEC_CACHE_NETWORKS), + (SEC_NAME_ORG_API_REQUESTS, SEC_TITLE_ORG_API_REQUESTS, SEC_CACHE_ORG_API_REQUESTS), + (SEC_NAME_ORG_SWITCH_PORTS_STATUSES, SEC_TITLE_ORG_SWITCH_PORTS_STATUSES, SEC_CACHE_ORG_SWITCH_PORTS_STATUSES), + (SEC_NAME_ORGANISATIONS, SEC_TITLE_ORGANISATIONS, SEC_CACHE_ORGANISATIONS), + (SEC_NAME_SENSOR_READINGS, SEC_TITLE_SENSOR_READINGS, SEC_CACHE_SENSOR_READINGS), + (SEC_NAME_SWITCH_PORTS_STATUSES, SEC_TITLE_SWITCH_PORTS_STATUSES, SEC_CACHE_SWITCH_PORTS_STATUSES), + (SEC_NAME_WIRELESS_DEVICE_STATUS, SEC_TITLE_WIRELESS_DEVICE_STATUS, SEC_CACHE_WIRELESS_DEVICE_STATUS), + (SEC_NAME_WIRELESS_ETHERNET_STATUSES, SEC_TITLE_WIRELESS_ETHERNET_STATUSES, SEC_CACHE_WIRELESS_ETHERNET_STATUSES), ] } ) ), - "sections": DictElement( + 'sections': DictElement( parameter_form=MultipleChoice( - title=Title("Sections"), + title=Title('Sections'), elements=[ MultipleChoiceElement( - name="licenses_overview", title=Title("Organization licenses overview") + name='licenses_overview', title=Title('Organization licenses overview') ), MultipleChoiceElement( - name="device_statuses", title=Title("Organization device statuses") + name='device_statuses', title=Title('Organization device statuses') ), MultipleChoiceElement( - name="sensor_readings", title=Title("Organization sensor readings") + name='sensor_readings', title=Title('Organization sensor readings') ), ], # migrate=_migrate_to_valid_ident, @@ -265,8 +278,8 @@ def _form_special_agent_cisco_meraki() -> Dictionary: rule_spec_cisco_meraki = SpecialAgent( - name="cisco_meraki", - title=Title("Cisco Meraki"), + name='cisco_meraki', + title=Title('Cisco Meraki'), topic=Topic.APPLICATIONS, parameter_form=_form_special_agent_cisco_meraki, ) diff --git a/source/cmk_plugins/collection/server_side_calls/cisco_meraki.py b/source/cmk_plugins/collection/server_side_calls/cisco_meraki.py index 9e91fac5dad3ba592db35063990511c5d5b2a940..9acf297fb9c21d510d6df2a7849e40bf29dbb078 100644 --- a/source/cmk_plugins/collection/server_side_calls/cisco_meraki.py +++ b/source/cmk_plugins/collection/server_side_calls/cisco_meraki.py @@ -27,6 +27,7 @@ __param = { ), 'no_cache': True, 'org_id_as_prefix': True, + 'net_id_as_prefix': True, 'excluded_sections': [ 'appliance_performance', 'switch_ports_statuses', @@ -82,6 +83,7 @@ class Params(BaseModel): orgs: Sequence[str] | None = None excluded_sections: Sequence[str] | None = None org_id_as_prefix: bool | None = None + net_id_as_prefix: bool | None = None no_cache: bool | None = None cache_per_section: CachePerSection | None = None @@ -153,6 +155,9 @@ def agent_cisco_meraki_arguments( if params.org_id_as_prefix is True: args.append("--org-id-as-prefix") + if params.net_id_as_prefix is True: + args.append("--net-id-as-prefix") + if params.no_cache is True: args.append("--no-cache") diff --git a/source/packages/cisco_meraki b/source/packages/cisco_meraki index 0687aaf2b189236c125c5ba846f8038ebc1de7f5..9704007fd5e2629fa5643bc60bfdcdc111e7f52b 100644 --- a/source/packages/cisco_meraki +++ b/source/packages/cisco_meraki @@ -63,7 +63,7 @@ 'web': ['plugins/views/cisco_meraki.py']}, 'name': 'cisco_meraki', 'title': 'Cisco Meraki special agent', - 'version': '1.4.1-20241217', + 'version': '1.4.2-20250104', 'version.min_required': '2.3.0b1', 'version.packaged': 'cmk-mkp-tool 0.2.0', 'version.usable_until': '2.4.0b1'}