mirror of
				https://github.com/KevinMidboe/mktxp-no-cli.git
				synced 2025-10-29 17:50:23 +00:00 
			
		
		
		
	DS refactor, fixes/optimizations
This commit is contained in:
		| @@ -11,24 +11,27 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from http.server import HTTPServer | from http.server import HTTPServer | ||||||
| from datetime import datetime | from datetime import datetime | ||||||
| from prometheus_client.core import REGISTRY | from prometheus_client.core import REGISTRY | ||||||
| from prometheus_client import MetricsHandler, start_http_server | from prometheus_client import MetricsHandler, start_http_server | ||||||
| from mktxp.cli.config.config import config_handler | from mktxp.cli.config.config import config_handler | ||||||
| from mktxp.collectors_handler import CollectorsHandler | from mktxp.collectors_handler import CollectorsHandler | ||||||
| from mktxp.metrics_handler import RouterMetricsHandler | from mktxp.router_entries_handler import RouterEntriesHandler | ||||||
|  |  | ||||||
| from mktxp.cli.output.capsman_out import CapsmanOutput | from mktxp.cli.output.capsman_out import CapsmanOutput | ||||||
| from mktxp.cli.output.wifi_out import WirelessOutput | from mktxp.cli.output.wifi_out import WirelessOutput | ||||||
|  | from mktxp.cli.output.dhcp_out import DHCPOutput | ||||||
|  |  | ||||||
|  |  | ||||||
| class MKTXPProcessor: | class MKTXPProcessor: | ||||||
|     ''' Base Export Processing |     ''' Base Export Processing | ||||||
|     '''     |     '''     | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def start(): |     def start(): | ||||||
|         router_metrics_handler = RouterMetricsHandler() |         router_entries_handler = RouterEntriesHandler() | ||||||
|         REGISTRY.register(CollectorsHandler(router_metrics_handler)) |         REGISTRY.register(CollectorsHandler(router_entries_handler)) | ||||||
|         MKTXPProcessor.run(port=config_handler._entry().port) |         MKTXPProcessor.run(port=config_handler._entry().port) | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
| @@ -45,13 +48,18 @@ class MKTXPCLIProcessor: | |||||||
|     '''     |     '''     | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def capsman_clients(entry_name): |     def capsman_clients(entry_name): | ||||||
|         router_metric = RouterMetricsHandler.router_metric(entry_name) |         router_entry = RouterEntriesHandler.router_entry(entry_name) | ||||||
|         if router_metric: |         if router_entry: | ||||||
|             CapsmanOutput.clients_summary(router_metric) |             CapsmanOutput.clients_summary(router_entry) | ||||||
|          |          | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def wifi_clients(entry_name): |     def wifi_clients(entry_name): | ||||||
|         router_metric = RouterMetricsHandler.router_metric(entry_name) |         router_entry = RouterEntriesHandler.router_entry(entry_name) | ||||||
|         if router_metric: |         if router_entry: | ||||||
|             WirelessOutput.clients_summary(router_metric) |             WirelessOutput.clients_summary(router_entry) | ||||||
|          |          | ||||||
|  |     @staticmethod | ||||||
|  |     def dhcp_clients(entry_name): | ||||||
|  |         router_entry = RouterEntriesHandler.router_entry(entry_name) | ||||||
|  |         if router_entry: | ||||||
|  |             DHCPOutput.clients_summary(router_entry) | ||||||
|   | |||||||
| @@ -12,9 +12,10 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
| [MKTXP] | [MKTXP] | ||||||
|     port = 49090 |     port = 49090		# default metrics HTTP server port | ||||||
|     socket_timeout = 2 |     bandwidth_test_interval = 420	# Interval between periodic bandwidth tests | ||||||
|     initial_delay_on_failure = 120 |  | ||||||
|     max_delay_on_failure = 900 |     socket_timeout = 2	# Socket connection timeout | ||||||
|     delay_inc_div = 5 |     initial_delay_on_failure = 120	# Delay untill next connection attempt to a RouterOS Device | ||||||
|     bandwidth_test_interval = 420 |     max_delay_on_failure = 900		# Max delay untill next connection attempt to a RouterOS Device | ||||||
|  |     delay_inc_div = 5				# Delay increment factor | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| import sys | import sys | ||||||
| import subprocess | import subprocess | ||||||
| import mktxp.cli.checks.chk_pv | import mktxp.cli.checks.chk_pv | ||||||
| @@ -20,6 +21,7 @@ from mktxp.cli.options import MKTXPOptionsParser, MKTXPCommands | |||||||
| from mktxp.cli.config.config import config_handler, ConfigEntry | from mktxp.cli.config.config import config_handler, ConfigEntry | ||||||
| from mktxp.basep import MKTXPProcessor, MKTXPCLIProcessor | from mktxp.basep import MKTXPProcessor, MKTXPCLIProcessor | ||||||
|  |  | ||||||
|  |  | ||||||
| class MKTXPDispatcher: | class MKTXPDispatcher: | ||||||
|     ''' Base MKTXP Commands Dispatcher |     ''' Base MKTXP Commands Dispatcher | ||||||
|     ''' |     ''' | ||||||
| @@ -92,7 +94,7 @@ class MKTXPDispatcher: | |||||||
|  |  | ||||||
|     def print(self, args): |     def print(self, args): | ||||||
|         if not (args['wifi_clients'] or args['capsman_clients']): |         if not (args['wifi_clients'] or args['capsman_clients']): | ||||||
|             print("Select metric option(s) to print out, or run 'mktxp print' -h to find out more") |             print("Select metric option(s) to print out, or run 'mktxp print -h' to find out more") | ||||||
|  |  | ||||||
|         if args['wifi_clients']: |         if args['wifi_clients']: | ||||||
|             MKTXPCLIProcessor.wifi_clients(args['entry_name']) |             MKTXPCLIProcessor.wifi_clients(args['entry_name']) | ||||||
| @@ -100,6 +102,10 @@ class MKTXPDispatcher: | |||||||
|         if args['capsman_clients']: |         if args['capsman_clients']: | ||||||
|             MKTXPCLIProcessor.capsman_clients(args['entry_name']) |             MKTXPCLIProcessor.capsman_clients(args['entry_name']) | ||||||
|  |  | ||||||
|  |         if args['dhcp_clients']: | ||||||
|  |             MKTXPCLIProcessor.dhcp_clients(args['entry_name']) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def main(): | def main(): | ||||||
|     MKTXPDispatcher().dispatch() |     MKTXPDispatcher().dispatch() | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| import os | import os | ||||||
| import pkg_resources | import pkg_resources | ||||||
| from argparse import ArgumentParser, HelpFormatter | from argparse import ArgumentParser, HelpFormatter | ||||||
| @@ -132,6 +133,9 @@ Selected metrics info can be printed on the command line. For more information, | |||||||
|                 help = "WiFi clients metrics", |                 help = "WiFi clients metrics", | ||||||
|                 action = 'store_true') |                 action = 'store_true') | ||||||
|  |  | ||||||
|  |         optional_args_group.add_argument('-dc', '--dhcp_clients', dest='dhcp_clients', | ||||||
|  |                 help = "DHCP clients metrics", | ||||||
|  |                 action = 'store_true') | ||||||
|  |  | ||||||
|     # Options checking |     # Options checking | ||||||
|     def _check_args(self, args, parser): |     def _check_args(self, args, parser): | ||||||
|   | |||||||
| @@ -21,16 +21,17 @@ from mktxp.cli.config.config import config_handler | |||||||
| class BaseOutputProcessor: | class BaseOutputProcessor: | ||||||
|     OutputCapsmanEntry = namedtuple('OutputCapsmanEntry', ['dhcp_name', 'dhcp_address', 'mac_address', 'rx_signal', 'interface', 'ssid', 'tx_rate', 'rx_rate', 'uptime']) |     OutputCapsmanEntry = namedtuple('OutputCapsmanEntry', ['dhcp_name', 'dhcp_address', 'mac_address', 'rx_signal', 'interface', 'ssid', 'tx_rate', 'rx_rate', 'uptime']) | ||||||
|     OutputWiFiEntry = namedtuple('OutputWiFiEntry', ['dhcp_name', 'dhcp_address', 'mac_address', 'signal_strength', 'signal_to_noise', 'interface', 'tx_rate', 'rx_rate', 'uptime']) |     OutputWiFiEntry = namedtuple('OutputWiFiEntry', ['dhcp_name', 'dhcp_address', 'mac_address', 'signal_strength', 'signal_to_noise', 'interface', 'tx_rate', 'rx_rate', 'uptime']) | ||||||
|  |     OutputDHCPEntry = namedtuple('OutputDHCPEntry', ['host_name', 'comment', 'address', 'active_address', 'mac_address', 'server', 'expires_after']) | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def augment_record(router_metric, registration_record, dhcp_lease_records): |     def augment_record(router_entry, registration_record, dhcp_lease_records): | ||||||
|         try: |         try: | ||||||
|             dhcp_lease_record = next((dhcp_lease_record for dhcp_lease_record in dhcp_lease_records if dhcp_lease_record['mac_address']==registration_record['mac_address'])) |             dhcp_lease_record = next((dhcp_lease_record for dhcp_lease_record in dhcp_lease_records if dhcp_lease_record['mac_address']==registration_record['mac_address'])) | ||||||
|             dhcp_name = dhcp_lease_record.get('host_name') |             dhcp_name = dhcp_lease_record.get('host_name') | ||||||
|             dhcp_comment = dhcp_lease_record.get('comment') |             dhcp_comment = dhcp_lease_record.get('comment') | ||||||
|  |  | ||||||
|             if dhcp_name and dhcp_comment: |             if dhcp_name and dhcp_comment: | ||||||
|                 dhcp_name = f'{dhcp_name[0:20]} ({dhcp_comment[0:20]})' if not router_metric.router_entry.use_comments_over_names else dhcp_comment |                 dhcp_name = f'{dhcp_name[0:20]} ({dhcp_comment[0:20]})' if not router_entry.config_entry.use_comments_over_names else dhcp_comment | ||||||
|             elif dhcp_comment: |             elif dhcp_comment: | ||||||
|                 dhcp_name = dhcp_comment |                 dhcp_name = dhcp_comment | ||||||
|             else: |             else: | ||||||
| @@ -49,8 +50,11 @@ class BaseOutputProcessor: | |||||||
|             registration_record['rx_bytes'] = registration_record['bytes'].split(',')[1] |             registration_record['rx_bytes'] = registration_record['bytes'].split(',')[1] | ||||||
|             del registration_record['bytes'] |             del registration_record['bytes'] | ||||||
|  |  | ||||||
|  |         if registration_record.get('tx_rate'): | ||||||
|             registration_record['tx_rate'] = BaseOutputProcessor.parse_rates(registration_record['tx_rate']) |             registration_record['tx_rate'] = BaseOutputProcessor.parse_rates(registration_record['tx_rate']) | ||||||
|  |         if registration_record.get('rx_rate'): | ||||||
|             registration_record['rx_rate'] = BaseOutputProcessor.parse_rates(registration_record['rx_rate']) |             registration_record['rx_rate'] = BaseOutputProcessor.parse_rates(registration_record['rx_rate']) | ||||||
|  |         if registration_record.get('uptime'): | ||||||
|             registration_record['uptime'] = naturaldelta(BaseOutputProcessor.parse_timedelta_seconds(registration_record['uptime']), months=True, minimum_unit='seconds', when=None) |             registration_record['uptime'] = naturaldelta(BaseOutputProcessor.parse_timedelta_seconds(registration_record['uptime']), months=True, minimum_unit='seconds', when=None) | ||||||
|  |  | ||||||
|         if registration_record.get('signal_strength'): |         if registration_record.get('signal_strength'): | ||||||
|   | |||||||
| @@ -11,27 +11,31 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from tabulate import tabulate    | from tabulate import tabulate    | ||||||
| from mktxp.cli.output.base_out import BaseOutputProcessor | from mktxp.cli.output.base_out import BaseOutputProcessor | ||||||
|  | from mktxp.datasources.dhcp_ds import DHCPMetricsDataSource | ||||||
|  | from mktxp.datasources.capsman_ds import CapsmanRegistrationsMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
| class CapsmanOutput: | class CapsmanOutput: | ||||||
|     ''' CAPsMAN CLI Output |     ''' CAPsMAN CLI Output | ||||||
|     '''     |     '''     | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def clients_summary(router_metric): |     def clients_summary(router_entry): | ||||||
|         registration_labels = ['interface', 'ssid', 'mac_address', 'rx_signal', 'uptime', 'tx_rate', 'rx_rate'] |         registration_labels = ['interface', 'ssid', 'mac_address', 'rx_signal', 'uptime', 'tx_rate', 'rx_rate'] | ||||||
|         registration_records = router_metric.capsman_registration_table_records(registration_labels, False) |         registration_records = CapsmanRegistrationsMetricsDataSource.metric_records(router_entry, metric_labels = registration_labels, add_router_id = False) | ||||||
|         if not registration_records: |         if not registration_records: | ||||||
|             print('No CAPsMAN registration records') |             print('No CAPsMAN registration records') | ||||||
|             return  |             return  | ||||||
|  |  | ||||||
|         # translate / trim / augment registration records |         # translate / trim / augment registration records | ||||||
|         dhcp_lease_labels = ['host_name', 'comment', 'address', 'mac_address'] |         dhcp_lease_labels = ['host_name', 'comment', 'address', 'mac_address'] | ||||||
|         dhcp_lease_records = router_metric.dhcp_lease_records(dhcp_lease_labels, False) |         dhcp_lease_records = DHCPMetricsDataSource.metric_records(router_entry, metric_labels = dhcp_lease_labels, add_router_id = False)    | ||||||
|  |  | ||||||
|         dhcp_rt_by_interface = {} |         dhcp_rt_by_interface = {} | ||||||
|         for registration_record in sorted(registration_records, key = lambda rt_record: rt_record['rx_signal'], reverse=True): |         for registration_record in sorted(registration_records, key = lambda rt_record: rt_record['rx_signal'], reverse=True): | ||||||
|             BaseOutputProcessor.augment_record(router_metric, registration_record, dhcp_lease_records) |             BaseOutputProcessor.augment_record(router_entry, registration_record, dhcp_lease_records) | ||||||
|  |  | ||||||
|             interface = registration_record['interface'] |             interface = registration_record['interface'] | ||||||
|             if interface in dhcp_rt_by_interface.keys(): |             if interface in dhcp_rt_by_interface.keys(): | ||||||
|   | |||||||
							
								
								
									
										48
									
								
								mktxp/cli/output/dhcp_out.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								mktxp/cli/output/dhcp_out.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from tabulate import tabulate    | ||||||
|  | from mktxp.cli.output.base_out import BaseOutputProcessor | ||||||
|  | from mktxp.datasources.dhcp_ds import DHCPMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class DHCPOutput: | ||||||
|  |     ''' DHCP Clients CLI Output | ||||||
|  |     '''     | ||||||
|  |     @staticmethod | ||||||
|  |     def clients_summary(router_entry): | ||||||
|  |         dhcp_lease_labels = ['host_name', 'comment', 'active_address', 'address', 'mac_address', 'server', 'expires_after'] | ||||||
|  |         dhcp_lease_records = DHCPMetricsDataSource.metric_records(router_entry, metric_labels = dhcp_lease_labels, add_router_id = False) | ||||||
|  |         if not dhcp_lease_records: | ||||||
|  |             print('No DHCP registration records') | ||||||
|  |             return  | ||||||
|  |  | ||||||
|  |         dhcp_by_server = {} | ||||||
|  |         for dhcp_lease_record in sorted(dhcp_lease_records, key = lambda dhcp_record: dhcp_record['active_address'], reverse=True): | ||||||
|  |             server = dhcp_lease_record['server'] | ||||||
|  |             if server in dhcp_by_server.keys(): | ||||||
|  |                 dhcp_by_server[server].append(dhcp_lease_record) | ||||||
|  |             else: | ||||||
|  |                 dhcp_by_server[server] = [dhcp_lease_record]          | ||||||
|  |  | ||||||
|  |         num_records = 0 | ||||||
|  |         output_table = [] | ||||||
|  |         for key in dhcp_by_server.keys(): | ||||||
|  |             for record in dhcp_by_server[key]: | ||||||
|  |                 output_table.append(BaseOutputProcessor.OutputDHCPEntry(**record)) | ||||||
|  |                 num_records += 1 | ||||||
|  |             output_table.append({}) | ||||||
|  |         print() | ||||||
|  |         print(tabulate(output_table, headers = "keys",  tablefmt="github")) | ||||||
|  |         print(tabulate([{0:'DHCP Clients:', 1:num_records}], tablefmt="text")) | ||||||
| @@ -11,27 +11,31 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from tabulate import tabulate    | from tabulate import tabulate    | ||||||
| from mktxp.cli.output.base_out import BaseOutputProcessor | from mktxp.cli.output.base_out import BaseOutputProcessor | ||||||
|  | from mktxp.datasources.dhcp_ds import DHCPMetricsDataSource | ||||||
|  | from mktxp.datasources.wireless_ds import WirelessMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
| class WirelessOutput: | class WirelessOutput: | ||||||
|     ''' Wireless Clients CLI Output |     ''' Wireless Clients CLI Output | ||||||
|     '''     |     '''     | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def clients_summary(router_metric): |     def clients_summary(router_entry): | ||||||
|         registration_labels = ['interface', 'mac_address', 'signal_strength', 'uptime', 'tx_rate', 'rx_rate', 'signal_to_noise'] |         registration_labels = ['interface', 'mac_address', 'signal_strength', 'uptime', 'tx_rate', 'rx_rate', 'signal_to_noise'] | ||||||
|         registration_records = router_metric.wireless_registration_table_records(registration_labels, False) |         registration_records = WirelessMetricsDataSource.metric_records(router_entry, metric_labels = registration_labels, add_router_id = False) | ||||||
|         if not registration_records: |         if not registration_records: | ||||||
|             print('No wireless registration records') |             print('No wireless registration records') | ||||||
|             return  |             return  | ||||||
|  |  | ||||||
|         # translate / trim / augment registration records |         # translate / trim / augment registration records | ||||||
|         dhcp_lease_labels = ['host_name', 'comment', 'address', 'mac_address'] |         dhcp_lease_labels = ['host_name', 'comment', 'address', 'mac_address'] | ||||||
|         dhcp_lease_records = router_metric.dhcp_lease_records(dhcp_lease_labels, False) |         dhcp_lease_records = DHCPMetricsDataSource.metric_records(router_entry, metric_labels = dhcp_lease_labels, add_router_id = False)    | ||||||
|  |  | ||||||
|         dhcp_rt_by_interface = {} |         dhcp_rt_by_interface = {} | ||||||
|         for registration_record in sorted(registration_records, key = lambda rt_record: rt_record['signal_strength'], reverse=True): |         for registration_record in sorted(registration_records, key = lambda rt_record: rt_record['signal_strength'], reverse=True): | ||||||
|             BaseOutputProcessor.augment_record(router_metric, registration_record, dhcp_lease_records) |             BaseOutputProcessor.augment_record(router_entry, registration_record, dhcp_lease_records) | ||||||
|  |  | ||||||
|             interface = registration_record['interface'] |             interface = registration_record['interface'] | ||||||
|             if interface in dhcp_rt_by_interface.keys(): |             if interface in dhcp_rt_by_interface.keys(): | ||||||
|   | |||||||
| @@ -12,16 +12,19 @@ | |||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | import socket | ||||||
| import speedtest | import speedtest | ||||||
| from datetime import datetime | from datetime import datetime | ||||||
| from multiprocessing import Pool | from multiprocessing import Pool | ||||||
| from mktxp.cli.config.config import config_handler | from mktxp.cli.config.config import config_handler | ||||||
| from mktxp.collectors.base_collector import BaseCollector | from mktxp.collectors.base_collector import BaseCollector | ||||||
|  |  | ||||||
|  |  | ||||||
| result_list = [{'download': 0, 'upload': 0, 'ping': 0}] | result_list = [{'download': 0, 'upload': 0, 'ping': 0}] | ||||||
| def get_result(bandwidth_dict): | def get_result(bandwidth_dict): | ||||||
|     result_list[0] = bandwidth_dict |     result_list[0] = bandwidth_dict | ||||||
|  |  | ||||||
|  |  | ||||||
| class BandwidthCollector(BaseCollector): | class BandwidthCollector(BaseCollector): | ||||||
|     ''' MKTXP collector |     ''' MKTXP collector | ||||||
|     '''     |     '''     | ||||||
| @@ -53,8 +56,21 @@ class BandwidthCollector(BaseCollector): | |||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def bandwidth_worker(): |     def bandwidth_worker(): | ||||||
|  |         if BandwidthCollector.inet_connected(): | ||||||
|             bandwidth_test = speedtest.Speedtest() |             bandwidth_test = speedtest.Speedtest() | ||||||
|             bandwidth_test.get_best_server() |             bandwidth_test.get_best_server() | ||||||
|             bandwidth_test.download() |             bandwidth_test.download() | ||||||
|             bandwidth_test.upload() |             bandwidth_test.upload() | ||||||
|             return bandwidth_test.results.dict() |             return bandwidth_test.results.dict() | ||||||
|  |         else: | ||||||
|  |             return {'download': 0, 'upload': 0, 'ping': 0} | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def inet_connected(host="8.8.8.8", port=53, timeout=3): | ||||||
|  |         try: | ||||||
|  |             socket.setdefaulttimeout(timeout) | ||||||
|  |             socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port)) | ||||||
|  |             return True | ||||||
|  |         except socket.error as exc: | ||||||
|  |             return False | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ | |||||||
| from prometheus_client.core import GaugeMetricFamily, CounterMetricFamily, InfoMetricFamily | from prometheus_client.core import GaugeMetricFamily, CounterMetricFamily, InfoMetricFamily | ||||||
| from mktxp.cli.config.config import MKTXPConfigKeys | from mktxp.cli.config.config import MKTXPConfigKeys | ||||||
|       |       | ||||||
|  |       | ||||||
| class BaseCollector: | class BaseCollector: | ||||||
|     ''' Base Collector methods |     ''' Base Collector methods | ||||||
|         For use by custom collectors |         For use by custom collectors | ||||||
|   | |||||||
| @@ -11,43 +11,47 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from mktxp.cli.output.base_out import BaseOutputProcessor | from mktxp.cli.output.base_out import BaseOutputProcessor | ||||||
| from mktxp.cli.config.config import MKTXPConfigKeys | from mktxp.cli.config.config import MKTXPConfigKeys | ||||||
| from mktxp.collectors.base_collector import BaseCollector | from mktxp.collectors.base_collector import BaseCollector | ||||||
|  | from mktxp.datasources.dhcp_ds import DHCPMetricsDataSource | ||||||
|  | from mktxp.datasources.capsman_ds import CapsmanCapsMetricsDataSource, CapsmanRegistrationsMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
| class CapsmanCollector(BaseCollector): | class CapsmanCollector(BaseCollector): | ||||||
|     ''' CAPsMAN Metrics collector |     ''' CAPsMAN Metrics collector | ||||||
|     '''     |     '''     | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def collect(router_metric): |     def collect(router_entry): | ||||||
|         remote_caps_labels = ['identity', 'version', 'base_mac', 'board', 'base_mac'] |         remote_caps_labels = ['identity', 'version', 'base_mac', 'board', 'base_mac'] | ||||||
|         remote_caps_records = router_metric.capsman_remote_caps_records(remote_caps_labels) |         remote_caps_records = CapsmanCapsMetricsDataSource.metric_records(router_entry, metric_labels = remote_caps_labels) | ||||||
|         if remote_caps_records: |         if remote_caps_records: | ||||||
|             remote_caps_metrics = BaseCollector.info_collector('capsman_remote_caps', 'CAPsMAN remote caps', remote_caps_records, remote_caps_labels) |             remote_caps_metrics = BaseCollector.info_collector('capsman_remote_caps', 'CAPsMAN remote caps', remote_caps_records, remote_caps_labels) | ||||||
|             yield remote_caps_metrics |             yield remote_caps_metrics | ||||||
|  |  | ||||||
|         registration_labels = ['interface', 'ssid', 'mac_address', 'tx_rate', 'rx_rate', 'rx_signal', 'uptime', 'bytes'] |         registration_labels = ['interface', 'ssid', 'mac_address', 'tx_rate', 'rx_rate', 'rx_signal', 'uptime', 'bytes'] | ||||||
|         registration_records = router_metric.capsman_registration_table_records(registration_labels) |         registration_records = CapsmanRegistrationsMetricsDataSource.metric_records(router_entry, metric_labels = registration_labels) | ||||||
|         if registration_records: |         if registration_records: | ||||||
|             # calculate number of registrations per interface |             # calculate number of registrations per interface | ||||||
|             registration_per_interface = {} |             registration_per_interface = {} | ||||||
|             for registration_record in registration_records: |             for registration_record in registration_records: | ||||||
|                 registration_per_interface[registration_record['interface']] = registration_per_interface.get(registration_record['interface'], 0) + 1 |                 registration_per_interface[registration_record['interface']] = registration_per_interface.get(registration_record['interface'], 0) + 1 | ||||||
|             # compile registrations-per-interface records |             # compile registrations-per-interface records | ||||||
|             registration_per_interface_records = [{ MKTXPConfigKeys.ROUTERBOARD_NAME: router_metric.router_id[MKTXPConfigKeys.ROUTERBOARD_NAME], |             registration_per_interface_records = [{ MKTXPConfigKeys.ROUTERBOARD_NAME: router_entry.router_id[MKTXPConfigKeys.ROUTERBOARD_NAME], | ||||||
|                                             MKTXPConfigKeys.ROUTERBOARD_ADDRESS: router_metric.router_id[MKTXPConfigKeys.ROUTERBOARD_ADDRESS], |                                             MKTXPConfigKeys.ROUTERBOARD_ADDRESS: router_entry.router_id[MKTXPConfigKeys.ROUTERBOARD_ADDRESS], | ||||||
|                                             'interface': key, 'count': value} for key, value in registration_per_interface.items()] |                                             'interface': key, 'count': value} for key, value in registration_per_interface.items()] | ||||||
|             # yield registrations-per-interface metrics |             # yield registrations-per-interface metrics | ||||||
|             registration_per_interface_metrics = BaseCollector.gauge_collector('capsman_registrations_count', 'Number of active registration per CAPsMAN interface', registration_per_interface_records, 'count', ['interface']) |             registration_per_interface_metrics = BaseCollector.gauge_collector('capsman_registrations_count', 'Number of active registration per CAPsMAN interface', registration_per_interface_records, 'count', ['interface']) | ||||||
|             yield registration_per_interface_metrics |             yield registration_per_interface_metrics | ||||||
|  |  | ||||||
|             # the client info metrics |             # the client info metrics | ||||||
|             if router_metric.router_entry.capsman_clients: |             if router_entry.config_entry.capsman_clients: | ||||||
|                 # translate / trim / augment registration records |                 # translate / trim / augment registration records | ||||||
|                 dhcp_lease_labels = ['mac_address', 'address', 'host_name', 'comment'] |                 dhcp_lease_labels = ['mac_address', 'address', 'host_name', 'comment'] | ||||||
|                 dhcp_lease_records = router_metric.dhcp_lease_records(dhcp_lease_labels) |                 dhcp_lease_records = DHCPMetricsDataSource.metric_records(router_entry, metric_labels = dhcp_lease_labels) | ||||||
|                 for registration_record in registration_records: |                 for registration_record in registration_records: | ||||||
|                     BaseOutputProcessor.augment_record(router_metric, registration_record, dhcp_lease_records) |                     BaseOutputProcessor.augment_record(router_entry, registration_record, dhcp_lease_records) | ||||||
|                      |                      | ||||||
|                 tx_byte_metrics = BaseCollector.counter_collector('capsman_clients_tx_bytes', 'Number of sent packet bytes', registration_records, 'tx_bytes', ['dhcp_name']) |                 tx_byte_metrics = BaseCollector.counter_collector('capsman_clients_tx_bytes', 'Number of sent packet bytes', registration_records, 'tx_bytes', ['dhcp_name']) | ||||||
|                 yield tx_byte_metrics |                 yield tx_byte_metrics | ||||||
|   | |||||||
| @@ -11,17 +11,19 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from mktxp.cli.config.config import MKTXPConfigKeys | from mktxp.cli.config.config import MKTXPConfigKeys | ||||||
| from mktxp.collectors.base_collector import BaseCollector | from mktxp.collectors.base_collector import BaseCollector | ||||||
|  | from mktxp.datasources.dhcp_ds import DHCPMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
| class DHCPCollector(BaseCollector): | class DHCPCollector(BaseCollector): | ||||||
|     ''' DHCP Metrics collector |     ''' DHCP Metrics collector | ||||||
|     '''     |     '''     | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def collect(router_metric): |     def collect(router_entry): | ||||||
|         dhcp_lease_labels = ['active_address', 'mac_address', 'host_name', 'comment', 'server', 'expires_after'] |         dhcp_lease_labels = ['active_address', 'address', 'mac_address', 'host_name', 'comment', 'server', 'expires_after'] | ||||||
|         dhcp_lease_records = router_metric.dhcp_lease_records(dhcp_lease_labels) |         dhcp_lease_records = DHCPMetricsDataSource.metric_records(router_entry, metric_labels = dhcp_lease_labels)    | ||||||
|         if dhcp_lease_records: |         if dhcp_lease_records: | ||||||
|             # calculate number of leases per DHCP server |             # calculate number of leases per DHCP server | ||||||
|             dhcp_lease_servers = {} |             dhcp_lease_servers = {} | ||||||
| @@ -29,8 +31,8 @@ class DHCPCollector(BaseCollector): | |||||||
|                 dhcp_lease_servers[dhcp_lease_record['server']] = dhcp_lease_servers.get(dhcp_lease_record['server'], 0) + 1 |                 dhcp_lease_servers[dhcp_lease_record['server']] = dhcp_lease_servers.get(dhcp_lease_record['server'], 0) + 1 | ||||||
|  |  | ||||||
|             # compile leases-per-server records |             # compile leases-per-server records | ||||||
|             dhcp_lease_servers_records = [{ MKTXPConfigKeys.ROUTERBOARD_NAME: router_metric.router_id[MKTXPConfigKeys.ROUTERBOARD_NAME], |             dhcp_lease_servers_records = [{ MKTXPConfigKeys.ROUTERBOARD_NAME: router_entry.router_id[MKTXPConfigKeys.ROUTERBOARD_NAME], | ||||||
|                                             MKTXPConfigKeys.ROUTERBOARD_ADDRESS: router_metric.router_id[MKTXPConfigKeys.ROUTERBOARD_ADDRESS], |                                             MKTXPConfigKeys.ROUTERBOARD_ADDRESS: router_entry.router_id[MKTXPConfigKeys.ROUTERBOARD_ADDRESS], | ||||||
|                                             'server': key, 'count': value} for key, value in dhcp_lease_servers.items()] |                                             'server': key, 'count': value} for key, value in dhcp_lease_servers.items()] | ||||||
|              |              | ||||||
|             # yield lease-per-server metrics |             # yield lease-per-server metrics | ||||||
| @@ -38,7 +40,7 @@ class DHCPCollector(BaseCollector): | |||||||
|             yield dhcp_lease_server_metrics |             yield dhcp_lease_server_metrics | ||||||
|  |  | ||||||
|             # active lease metrics |             # active lease metrics | ||||||
|             if router_metric.router_entry.dhcp_lease: |             if router_entry.config_entry.dhcp_lease: | ||||||
|                 dhcp_lease_metrics = BaseCollector.info_collector('dhcp_lease', 'DHCP Active Leases', dhcp_lease_records, dhcp_lease_labels) |                 dhcp_lease_metrics = BaseCollector.info_collector('dhcp_lease', 'DHCP Active Leases', dhcp_lease_records, dhcp_lease_labels) | ||||||
|                 yield dhcp_lease_metrics |                 yield dhcp_lease_metrics | ||||||
|              |              | ||||||
| @@ -11,34 +11,37 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
| from mktxp.collectors.base_collector import BaseCollector |  | ||||||
| from mktxp.cli.config.config import MKTXPConfigKeys | from mktxp.cli.config.config import MKTXPConfigKeys | ||||||
|  | from mktxp.collectors.base_collector import BaseCollector | ||||||
|  | from mktxp.datasources.firewall_ds import FirewallMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
| class FirewallCollector(BaseCollector): | class FirewallCollector(BaseCollector): | ||||||
|     ''' Firewall rules traffic metrics collector |     ''' Firewall rules traffic metrics collector | ||||||
|     '''     |     '''     | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def collect(router_metric): |     def collect(router_entry): | ||||||
|         # initialize all pool counts, including those currently not used |         # initialize all pool counts, including those currently not used | ||||||
|         firewall_labels = ['chain', 'action', 'bytes', 'comment'] |         firewall_labels = ['chain', 'action', 'bytes', 'comment'] | ||||||
|          |          | ||||||
|         firewall_filter_records = router_metric.firewall_records(firewall_labels)    |         firewall_filter_records = FirewallMetricsDataSource.metric_records(router_entry, metric_labels = firewall_labels)    | ||||||
|         if firewall_filter_records:            |         if firewall_filter_records:            | ||||||
|             metris_records = [FirewallCollector.metric_record(router_metric, record) for record in firewall_filter_records] |             metris_records = [FirewallCollector.metric_record(router_entry, record) for record in firewall_filter_records] | ||||||
|             firewall_filter_metrics = BaseCollector.counter_collector('firewall_filter', 'Total amount of bytes matched by firewall rules', metris_records, 'bytes', ['name']) |             firewall_filter_metrics = BaseCollector.counter_collector('firewall_filter', 'Total amount of bytes matched by firewall rules', metris_records, 'bytes', ['name']) | ||||||
|             yield firewall_filter_metrics |             yield firewall_filter_metrics | ||||||
|  |  | ||||||
|         firewall_raw_records = router_metric.firewall_records(firewall_labels, raw = True)         |         firewall_raw_records = FirewallMetricsDataSource.metric_records(router_entry, metric_labels = firewall_labels, raw = True)         | ||||||
|         if firewall_raw_records:       |         if firewall_raw_records:       | ||||||
|             metris_records = [FirewallCollector.metric_record(router_metric, record) for record in firewall_raw_records]      |             metris_records = [FirewallCollector.metric_record(router_entry, record) for record in firewall_raw_records]      | ||||||
|             firewall_raw_metrics = BaseCollector.counter_collector('firewall_raw', 'Total amount of bytes matched by raw firewall rules', metris_records, 'bytes', ['name']) |             firewall_raw_metrics = BaseCollector.counter_collector('firewall_raw', 'Total amount of bytes matched by raw firewall rules', metris_records, 'bytes', ['name']) | ||||||
|             yield firewall_raw_metrics |             yield firewall_raw_metrics | ||||||
|  |  | ||||||
|     # Helpers |     # Helpers | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def metric_record(router_metric, firewall_record): |     def metric_record(router_entry, firewall_record): | ||||||
|         name = f"| {firewall_record['chain']} | {firewall_record['action']} | {firewall_record['comment']}" |         name = f"| {firewall_record['chain']} | {firewall_record['action']} | {firewall_record['comment']}" | ||||||
|         bytes = firewall_record['bytes'] |         bytes = firewall_record['bytes'] | ||||||
|         return {MKTXPConfigKeys.ROUTERBOARD_NAME: router_metric.router_id[MKTXPConfigKeys.ROUTERBOARD_NAME], |         return {MKTXPConfigKeys.ROUTERBOARD_NAME: router_entry.router_id[MKTXPConfigKeys.ROUTERBOARD_NAME], | ||||||
|                 MKTXPConfigKeys.ROUTERBOARD_ADDRESS: router_metric.router_id[MKTXPConfigKeys.ROUTERBOARD_ADDRESS], |                 MKTXPConfigKeys.ROUTERBOARD_ADDRESS: router_entry.router_id[MKTXPConfigKeys.ROUTERBOARD_ADDRESS], | ||||||
|                 'name': name, 'bytes': bytes} |                 'name': name, 'bytes': bytes} | ||||||
|   | |||||||
| @@ -11,16 +11,18 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from mktxp.collectors.base_collector import BaseCollector | from mktxp.collectors.base_collector import BaseCollector | ||||||
|  | from mktxp.datasources.health_ds import HealthMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
| class HealthCollector(BaseCollector): | class HealthCollector(BaseCollector): | ||||||
|     ''' System Health Metrics collector |     ''' System Health Metrics collector | ||||||
|     '''     |     '''     | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def collect(router_metric): |     def collect(router_entry): | ||||||
|         health_labels = ['voltage', 'temperature'] |         health_labels = ['voltage', 'temperature'] | ||||||
|         health_records = router_metric.health_records(health_labels)         |         health_records = HealthMetricsDataSource.metric_records(router_entry, metric_labels = health_labels)    | ||||||
|         if health_records: |         if health_records: | ||||||
|             voltage_metrics = BaseCollector.gauge_collector('system_routerboard_voltage', 'Supplied routerboard voltage', health_records, 'voltage') |             voltage_metrics = BaseCollector.gauge_collector('system_routerboard_voltage', 'Supplied routerboard voltage', health_records, 'voltage') | ||||||
|             yield voltage_metrics |             yield voltage_metrics | ||||||
|   | |||||||
| @@ -11,15 +11,18 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from mktxp.collectors.base_collector import BaseCollector | from mktxp.collectors.base_collector import BaseCollector | ||||||
|  | from mktxp.datasources.identity_ds import IdentityMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
| class IdentityCollector(BaseCollector): | class IdentityCollector(BaseCollector): | ||||||
|     ''' System Identity Metrics collector |     ''' System Identity Metrics collector | ||||||
|     '''      |     '''      | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def collect(router_metric): |     def collect(router_entry): | ||||||
|         identity_labels = ['name'] |         identity_labels = ['name'] | ||||||
|         identity_records = router_metric.identity_records(identity_labels)         |         identity_records = IdentityMetricsDataSource.metric_records(router_entry, metric_labels = identity_labels)                 | ||||||
|         if identity_records: |         if identity_records: | ||||||
|             identity_metrics = BaseCollector.info_collector('system_identity', 'System identity', identity_records, identity_labels) |             identity_metrics = BaseCollector.info_collector('system_identity', 'System identity', identity_records, identity_labels) | ||||||
|             yield identity_metrics |             yield identity_metrics | ||||||
|   | |||||||
| @@ -11,20 +11,23 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from mktxp.collectors.base_collector import BaseCollector | from mktxp.collectors.base_collector import BaseCollector | ||||||
|  | from mktxp.datasources.interface_ds import InterfaceTrafficMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
| class InterfaceCollector(BaseCollector): | class InterfaceCollector(BaseCollector): | ||||||
|     ''' Router Interface Metrics collector |     ''' Router Interface Metrics collector | ||||||
|     '''         |     '''         | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def collect(router_metric): |     def collect(router_entry): | ||||||
|         interface_traffic_labels = ['name', 'comment', 'rx_byte', 'tx_byte', 'rx_packet', 'tx_packet', 'rx_error', 'tx_error', 'rx_drop', 'tx_drop'] |         interface_traffic_labels = ['name', 'comment', 'rx_byte', 'tx_byte', 'rx_packet', 'tx_packet', 'rx_error', 'tx_error', 'rx_drop', 'tx_drop'] | ||||||
|         interface_traffic_records = router_metric.interface_traffic_records(interface_traffic_labels) |         interface_traffic_records = InterfaceTrafficMetricsDataSource.metric_records(router_entry, metric_labels = interface_traffic_labels)    | ||||||
|  |  | ||||||
|         if interface_traffic_records: |         if interface_traffic_records: | ||||||
|             for interface_traffic_record in interface_traffic_records: |             for interface_traffic_record in interface_traffic_records: | ||||||
|                 if interface_traffic_record.get('comment'): |                 if interface_traffic_record.get('comment'): | ||||||
|                     interface_traffic_record['name'] = interface_traffic_record['comment'] if router_metric.router_entry.use_comments_over_names \ |                     interface_traffic_record['name'] = interface_traffic_record['comment'] if router_entry.config_entry.use_comments_over_names \ | ||||||
|                                                                                 else f"{interface_traffic_record['name']} ({interface_traffic_record['comment']})" |                                                                                 else f"{interface_traffic_record['name']} ({interface_traffic_record['comment']})" | ||||||
|  |  | ||||||
|             rx_byte_metric = BaseCollector.counter_collector('interface_rx_byte', 'Number of received bytes', interface_traffic_records, 'rx_byte', ['name']) |             rx_byte_metric = BaseCollector.counter_collector('interface_rx_byte', 'Number of received bytes', interface_traffic_records, 'rx_byte', ['name']) | ||||||
|   | |||||||
| @@ -11,14 +11,17 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from mktxp.collectors.base_collector import BaseCollector | from mktxp.collectors.base_collector import BaseCollector | ||||||
|  | from mktxp.datasources.mktxp_ds import MKTXPMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
| class MKTXPCollector(BaseCollector): | class MKTXPCollector(BaseCollector): | ||||||
|     ''' System Identity Metrics collector |     ''' System Identity Metrics collector | ||||||
|     '''      |     '''      | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def collect(router_metric): |     def collect(router_entry): | ||||||
|         mktxp_records = router_metric.mktxp_records()         |         mktxp_records = MKTXPMetricsDataSource.metric_records(router_entry) | ||||||
|         if mktxp_records: |         if mktxp_records: | ||||||
|             mktxp_duration_metric = BaseCollector.counter_collector('collection_time', 'Total time spent collecting metrics in milliseconds', mktxp_records, 'duration', ['name']) |             mktxp_duration_metric = BaseCollector.counter_collector('collection_time', 'Total time spent collecting metrics in milliseconds', mktxp_records, 'duration', ['name']) | ||||||
|             yield mktxp_duration_metric |             yield mktxp_duration_metric | ||||||
|   | |||||||
| @@ -11,16 +11,19 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from mktxp.collectors.base_collector import BaseCollector | from mktxp.collectors.base_collector import BaseCollector | ||||||
| from mktxp.cli.output.base_out import BaseOutputProcessor | from mktxp.cli.output.base_out import BaseOutputProcessor | ||||||
|  | from mktxp.datasources.interface_ds import InterfaceMonitorMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
| class MonitorCollector(BaseCollector): | class MonitorCollector(BaseCollector): | ||||||
|     ''' Ethernet Interface Monitor Metrics collector |     ''' Ethernet Interface Monitor Metrics collector | ||||||
|     '''     |     '''     | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def collect(router_metric): |     def collect(router_entry): | ||||||
|         monitor_labels = ('status', 'rate', 'full_duplex', 'name') |         monitor_labels = ('status', 'rate', 'full_duplex', 'name') | ||||||
|         monitor_records = router_metric.interface_monitor_records(monitor_labels, include_comments = True) |         monitor_records = InterfaceMonitorMetricsDataSource.metric_records(router_entry, metric_labels = monitor_labels, include_comments = True)    | ||||||
|         if monitor_records: |         if monitor_records: | ||||||
|             # translate records to appropriate values |             # translate records to appropriate values | ||||||
|             for monitor_record in monitor_records: |             for monitor_record in monitor_records: | ||||||
|   | |||||||
| @@ -11,28 +11,31 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from mktxp.cli.config.config import MKTXPConfigKeys | from mktxp.cli.config.config import MKTXPConfigKeys | ||||||
| from mktxp.collectors.base_collector import BaseCollector | from mktxp.collectors.base_collector import BaseCollector | ||||||
|  | from mktxp.datasources.pool_ds import PoolMetricsDataSource, PoolUsedMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
| class PoolCollector(BaseCollector): | class PoolCollector(BaseCollector): | ||||||
|     ''' IP Pool Metrics collector |     ''' IP Pool Metrics collector | ||||||
|     '''     |     '''     | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def collect(router_metric): |     def collect(router_entry): | ||||||
|         # initialize all pool counts, including those currently not used |         # initialize all pool counts, including those currently not used | ||||||
|         pool_records = router_metric.pool_records(['name']) |         pool_records = PoolMetricsDataSource.metric_records(router_entry, metric_labels = ['name'])    | ||||||
|         if pool_records: |         if pool_records: | ||||||
|             pool_used_labels = ['pool'] |             pool_used_labels = ['pool'] | ||||||
|             pool_used_counts = {pool_record['name']: 0 for pool_record in pool_records} |             pool_used_counts = {pool_record['name']: 0 for pool_record in pool_records} | ||||||
|  |  | ||||||
|             # for pools in usage, calculate the current numbers |             # for pools in usage, calculate the current numbers | ||||||
|             pool_used_records = router_metric.pool_used_records(pool_used_labels) |             pool_used_records = PoolUsedMetricsDataSource.metric_records(router_entry, metric_labels = pool_used_labels)    | ||||||
|             for pool_used_record in pool_used_records: |             for pool_used_record in pool_used_records: | ||||||
|                 pool_used_counts[pool_used_record['pool']] = pool_used_counts.get(pool_used_record['pool'], 0) + 1 |                 pool_used_counts[pool_used_record['pool']] = pool_used_counts.get(pool_used_record['pool'], 0) + 1 | ||||||
|  |  | ||||||
|            # compile used-per-pool records |            # compile used-per-pool records | ||||||
|             used_per_pool_records = [{ MKTXPConfigKeys.ROUTERBOARD_NAME: router_metric.router_id[MKTXPConfigKeys.ROUTERBOARD_NAME], |             used_per_pool_records = [{ MKTXPConfigKeys.ROUTERBOARD_NAME: router_entry.router_id[MKTXPConfigKeys.ROUTERBOARD_NAME], | ||||||
|                                        MKTXPConfigKeys.ROUTERBOARD_ADDRESS: router_metric.router_id[MKTXPConfigKeys.ROUTERBOARD_ADDRESS], |                                        MKTXPConfigKeys.ROUTERBOARD_ADDRESS: router_entry.router_id[MKTXPConfigKeys.ROUTERBOARD_ADDRESS], | ||||||
|                                        'pool': key, 'count': value} for key, value in pool_used_counts.items()] |                                        'pool': key, 'count': value} for key, value in pool_used_counts.items()] | ||||||
|              |              | ||||||
|             # yield used-per-pool metrics |             # yield used-per-pool metrics | ||||||
|   | |||||||
| @@ -11,20 +11,23 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from mktxp.collectors.base_collector import BaseCollector | from mktxp.collectors.base_collector import BaseCollector | ||||||
| from mktxp.cli.output.base_out import BaseOutputProcessor | from mktxp.cli.output.base_out import BaseOutputProcessor | ||||||
|  | from mktxp.datasources.system_resource_ds import SystemResourceMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
| class SystemResourceCollector(BaseCollector): | class SystemResourceCollector(BaseCollector): | ||||||
|     ''' System Resource Metrics collector |     ''' System Resource Metrics collector | ||||||
|     '''         |     '''         | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def collect(router_metric): |     def collect(router_entry): | ||||||
|         resource_labels = ['uptime', 'version', 'free_memory', 'total_memory',  |         resource_labels = ['uptime', 'version', 'free_memory', 'total_memory',  | ||||||
|                            'cpu', 'cpu_count', 'cpu_frequency', 'cpu_load',  |                            'cpu', 'cpu_count', 'cpu_frequency', 'cpu_load',  | ||||||
|                            'free_hdd_space', 'total_hdd_space',  |                            'free_hdd_space', 'total_hdd_space',  | ||||||
|                            'architecture_name', 'board_name'] |                            'architecture_name', 'board_name'] | ||||||
|                                     |                                     | ||||||
|         resource_records = router_metric.system_resource_records(resource_labels) |         resource_records = SystemResourceMetricsDataSource.metric_records(router_entry, metric_labels = resource_labels)    | ||||||
|         if resource_records: |         if resource_records: | ||||||
|             # translate records to appropriate values |             # translate records to appropriate values | ||||||
|             translated_fields = ['uptime']         |             translated_fields = ['uptime']         | ||||||
|   | |||||||
| @@ -11,21 +11,24 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from mktxp.cli.config.config import MKTXPConfigKeys | from mktxp.cli.config.config import MKTXPConfigKeys | ||||||
| from mktxp.collectors.base_collector import BaseCollector | from mktxp.collectors.base_collector import BaseCollector | ||||||
|  | from mktxp.datasources.route_ds import RouteMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
| class RouteCollector(BaseCollector): | class RouteCollector(BaseCollector): | ||||||
|     ''' IP Route Metrics collector |     ''' IP Route Metrics collector | ||||||
|     '''         |     '''         | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def collect(router_metric): |     def collect(router_entry): | ||||||
|         route_labels = ['connect', 'dynamic', 'static', 'bgp', 'ospf'] |         route_labels = ['connect', 'dynamic', 'static', 'bgp', 'ospf'] | ||||||
|         route_records = router_metric.route_records(route_labels) |         route_records = RouteMetricsDataSource.metric_records(router_entry, metric_labels = route_labels)    | ||||||
|         if route_records:        |         if route_records:        | ||||||
|             # compile total routes records |             # compile total routes records | ||||||
|             total_routes = len(route_records) |             total_routes = len(route_records) | ||||||
|             total_routes_records = [{ MKTXPConfigKeys.ROUTERBOARD_NAME: router_metric.router_id[MKTXPConfigKeys.ROUTERBOARD_NAME], |             total_routes_records = [{ MKTXPConfigKeys.ROUTERBOARD_NAME: router_entry.router_id[MKTXPConfigKeys.ROUTERBOARD_NAME], | ||||||
|                                       MKTXPConfigKeys.ROUTERBOARD_ADDRESS: router_metric.router_id[MKTXPConfigKeys.ROUTERBOARD_ADDRESS], |                                       MKTXPConfigKeys.ROUTERBOARD_ADDRESS: router_entry.router_id[MKTXPConfigKeys.ROUTERBOARD_ADDRESS], | ||||||
|                                       'count': total_routes |                                       'count': total_routes | ||||||
|                                     }] |                                     }] | ||||||
|             total_routes_metrics = BaseCollector.gauge_collector('routes_total_routes', 'Overall number of routes in RIB', total_routes_records, 'count') |             total_routes_metrics = BaseCollector.gauge_collector('routes_total_routes', 'Overall number of routes in RIB', total_routes_records, 'count') | ||||||
| @@ -40,8 +43,8 @@ class RouteCollector(BaseCollector): | |||||||
|                         routes_per_protocol[route_label] += 1  |                         routes_per_protocol[route_label] += 1  | ||||||
|  |  | ||||||
|             # compile route-per-protocol records |             # compile route-per-protocol records | ||||||
|             route_per_protocol_records = [{ MKTXPConfigKeys.ROUTERBOARD_NAME: router_metric.router_id[MKTXPConfigKeys.ROUTERBOARD_NAME], |             route_per_protocol_records = [{ MKTXPConfigKeys.ROUTERBOARD_NAME: router_entry.router_id[MKTXPConfigKeys.ROUTERBOARD_NAME], | ||||||
|                                             MKTXPConfigKeys.ROUTERBOARD_ADDRESS: router_metric.router_id[MKTXPConfigKeys.ROUTERBOARD_ADDRESS], |                                             MKTXPConfigKeys.ROUTERBOARD_ADDRESS: router_entry.router_id[MKTXPConfigKeys.ROUTERBOARD_ADDRESS], | ||||||
|                                             'protocol': key, 'count': value} for key, value in routes_per_protocol.items()] |                                             'protocol': key, 'count': value} for key, value in routes_per_protocol.items()] | ||||||
|              |              | ||||||
|             # yield route-per-protocol metrics |             # yield route-per-protocol metrics | ||||||
|   | |||||||
| @@ -11,16 +11,21 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from mktxp.cli.output.base_out import BaseOutputProcessor | from mktxp.cli.output.base_out import BaseOutputProcessor | ||||||
| from mktxp.collectors.base_collector import BaseCollector | from mktxp.collectors.base_collector import BaseCollector | ||||||
|  | from mktxp.datasources.dhcp_ds import DHCPMetricsDataSource | ||||||
|  | from mktxp.datasources.wireless_ds import WirelessMetricsDataSource | ||||||
|  | from mktxp.datasources.interface_ds import InterfaceMonitorMetricsDataSource | ||||||
|  |  | ||||||
|  |  | ||||||
| class WLANCollector(BaseCollector): | class WLANCollector(BaseCollector): | ||||||
|     ''' Wireless Metrics collector |     ''' Wireless Metrics collector | ||||||
|     '''     |     '''     | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def collect(router_metric): |     def collect(router_entry): | ||||||
|         monitor_labels = ['channel', 'noise_floor', 'overall_tx_ccq', 'registered_clients'] |         monitor_labels = ['channel', 'noise_floor', 'overall_tx_ccq', 'registered_clients'] | ||||||
|         monitor_records = router_metric.interface_monitor_records(monitor_labels, 'wireless') |         monitor_records = InterfaceMonitorMetricsDataSource.metric_records(router_entry, metric_labels = monitor_labels, kind = 'wireless')    | ||||||
|         if monitor_records: |         if monitor_records: | ||||||
|             # sanitize records for relevant labels |             # sanitize records for relevant labels | ||||||
|             noise_floor_records = [monitor_record for monitor_record in monitor_records if monitor_record.get('noise_floor')] |             noise_floor_records = [monitor_record for monitor_record in monitor_records if monitor_record.get('noise_floor')] | ||||||
| @@ -40,15 +45,15 @@ class WLANCollector(BaseCollector): | |||||||
|                 yield registered_clients_metrics |                 yield registered_clients_metrics | ||||||
|  |  | ||||||
|         # the client info metrics |         # the client info metrics | ||||||
|         if router_metric.router_entry.wireless_clients: |         if router_entry.config_entry.wireless_clients: | ||||||
|             registration_labels = ['interface', 'ssid', 'mac_address', 'tx_rate', 'rx_rate', 'uptime', 'bytes', 'signal_to_noise', 'tx_ccq', 'signal_strength'] |             registration_labels = ['interface', 'ssid', 'mac_address', 'tx_rate', 'rx_rate', 'uptime', 'bytes', 'signal_to_noise', 'tx_ccq', 'signal_strength'] | ||||||
|             registration_records = router_metric.wireless_registration_table_records(registration_labels) |             registration_records = WirelessMetricsDataSource.metric_records(router_entry, metric_labels = registration_labels) | ||||||
|             if registration_records: |             if registration_records: | ||||||
|                 dhcp_lease_labels = ['mac_address', 'address', 'host_name', 'comment'] |                 dhcp_lease_labels = ['mac_address', 'address', 'host_name', 'comment'] | ||||||
|                 dhcp_lease_records = router_metric.dhcp_lease_records(dhcp_lease_labels) |                 dhcp_lease_records = DHCPMetricsDataSource.metric_records(router_entry, metric_labels = dhcp_lease_labels) | ||||||
|        |        | ||||||
|                 for registration_record in registration_records: |                 for registration_record in registration_records: | ||||||
|                     BaseOutputProcessor.augment_record(router_metric, registration_record, dhcp_lease_records)                 |                     BaseOutputProcessor.augment_record(router_entry, registration_record, dhcp_lease_records)                 | ||||||
|  |  | ||||||
|                 tx_byte_metrics = BaseCollector.counter_collector('wlan_clients_tx_bytes', 'Number of sent packet bytes', registration_records, 'tx_bytes', ['dhcp_name']) |                 tx_byte_metrics = BaseCollector.counter_collector('wlan_clients_tx_bytes', 'Number of sent packet bytes', registration_records, 'tx_bytes', ['dhcp_name']) | ||||||
|                 yield tx_byte_metrics |                 yield tx_byte_metrics | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| from timeit import default_timer | from timeit import default_timer | ||||||
| from mktxp.collectors.dhcp_collector import DHCPCollector | from mktxp.collectors.dhcp_collector import DHCPCollector | ||||||
| from mktxp.collectors.interface_collector import InterfaceCollector | from mktxp.collectors.interface_collector import InterfaceCollector | ||||||
| @@ -30,73 +31,73 @@ from mktxp.collectors.mktxp_collector import MKTXPCollector | |||||||
| class CollectorsHandler: | class CollectorsHandler: | ||||||
|     ''' MKTXP Collectors Handler |     ''' MKTXP Collectors Handler | ||||||
|     ''' |     ''' | ||||||
|     def __init__(self, metrics_handler): |     def __init__(self, entries_handler): | ||||||
|         self.metrics_handler = metrics_handler |         self.entries_handler = entries_handler | ||||||
|         self.bandwidthCollector = BandwidthCollector() |         self.bandwidthCollector = BandwidthCollector() | ||||||
|  |  | ||||||
|     def collect(self): |     def collect(self): | ||||||
|         # process mktxp internal metrics |         # process mktxp internal metrics | ||||||
|         yield from self.bandwidthCollector.collect() |         yield from self.bandwidthCollector.collect() | ||||||
|  |  | ||||||
|         for router_metric in self.metrics_handler.router_metrics:            |         for router_entry in self.entries_handler.router_entries: | ||||||
|             if not router_metric.api_connection.is_connected(): |             if not router_entry.api_connection.is_connected(): | ||||||
|                 # let's pick up on things in the next run |                 # let's pick up on things in the next run | ||||||
|                 router_metric.api_connection.connect() |                 router_entry.api_connection.connect() | ||||||
|                 continue |                 continue | ||||||
|  |  | ||||||
|             start = default_timer() |             start = default_timer() | ||||||
|             yield from IdentityCollector.collect(router_metric) |             yield from IdentityCollector.collect(router_entry) | ||||||
|             router_metric.time_spent['IdentityCollector'] += default_timer() - start |             router_entry.time_spent['IdentityCollector'] += default_timer() - start | ||||||
|  |  | ||||||
|             start = default_timer() |             start = default_timer() | ||||||
|             yield from SystemResourceCollector.collect(router_metric) |             yield from SystemResourceCollector.collect(router_entry) | ||||||
|             router_metric.time_spent['SystemResourceCollector'] += default_timer() - start |             router_entry.time_spent['SystemResourceCollector'] += default_timer() - start | ||||||
|  |  | ||||||
|             start = default_timer() |             start = default_timer() | ||||||
|             yield from HealthCollector.collect(router_metric) |             yield from HealthCollector.collect(router_entry) | ||||||
|             router_metric.time_spent['HealthCollector'] += default_timer() - start |             router_entry.time_spent['HealthCollector'] += default_timer() - start | ||||||
|  |  | ||||||
|             if router_metric.router_entry.dhcp: |             if router_entry.config_entry.dhcp: | ||||||
|                 start = default_timer() |                 start = default_timer() | ||||||
|                 yield from DHCPCollector.collect(router_metric)                 |                 yield from DHCPCollector.collect(router_entry)                 | ||||||
|                 router_metric.time_spent['DHCPCollector'] += default_timer() - start |                 router_entry.time_spent['DHCPCollector'] += default_timer() - start | ||||||
|  |  | ||||||
|             if router_metric.router_entry.pool: |             if router_entry.config_entry.pool: | ||||||
|                 start = default_timer() |                 start = default_timer() | ||||||
|                 yield from PoolCollector.collect(router_metric) |                 yield from PoolCollector.collect(router_entry) | ||||||
|                 router_metric.time_spent['PoolCollector'] += default_timer() - start |                 router_entry.time_spent['PoolCollector'] += default_timer() - start | ||||||
|              |              | ||||||
|             if router_metric.router_entry.interface: |             if router_entry.config_entry.interface: | ||||||
|                 start = default_timer() |                 start = default_timer() | ||||||
|                 yield from InterfaceCollector.collect(router_metric) |                 yield from InterfaceCollector.collect(router_entry) | ||||||
|                 router_metric.time_spent['InterfaceCollector'] += default_timer() - start |                 router_entry.time_spent['InterfaceCollector'] += default_timer() - start | ||||||
|  |  | ||||||
|             if router_metric.router_entry.firewall: |             if router_entry.config_entry.firewall: | ||||||
|                 start = default_timer() |                 start = default_timer() | ||||||
|                 yield from FirewallCollector.collect(router_metric) |                 yield from FirewallCollector.collect(router_entry) | ||||||
|                 router_metric.time_spent['FirewallCollector'] += default_timer() - start |                 router_entry.time_spent['FirewallCollector'] += default_timer() - start | ||||||
|              |              | ||||||
|             if router_metric.router_entry.monitor: |             if router_entry.config_entry.monitor: | ||||||
|                 start = default_timer() |                 start = default_timer() | ||||||
|                 yield from MonitorCollector.collect(router_metric) |                 yield from MonitorCollector.collect(router_entry) | ||||||
|                 router_metric.time_spent['MonitorCollector'] += default_timer() - start |                 router_entry.time_spent['MonitorCollector'] += default_timer() - start | ||||||
|              |              | ||||||
|             if router_metric.router_entry.route: |             if router_entry.config_entry.route: | ||||||
|                 start = default_timer() |                 start = default_timer() | ||||||
|                 yield from RouteCollector.collect(router_metric) |                 yield from RouteCollector.collect(router_entry) | ||||||
|                 router_metric.time_spent['RouteCollector'] += default_timer() - start |                 router_entry.time_spent['RouteCollector'] += default_timer() - start | ||||||
|         |         | ||||||
|             if router_metric.router_entry.wireless: |             if router_entry.config_entry.wireless: | ||||||
|                 start = default_timer() |                 start = default_timer() | ||||||
|                 yield from WLANCollector.collect(router_metric) |                 yield from WLANCollector.collect(router_entry) | ||||||
|                 router_metric.time_spent['WLANCollector'] += default_timer() - start |                 router_entry.time_spent['WLANCollector'] += default_timer() - start | ||||||
|  |  | ||||||
|             if router_metric.router_entry.capsman: |             if router_entry.config_entry.capsman: | ||||||
|                 start = default_timer() |                 start = default_timer() | ||||||
|                 yield from CapsmanCollector.collect(router_metric) |                 yield from CapsmanCollector.collect(router_entry) | ||||||
|                 router_metric.time_spent['CapsmanCollector'] += default_timer() - start |                 router_entry.time_spent['CapsmanCollector'] += default_timer() - start | ||||||
|              |              | ||||||
|             yield from MKTXPCollector.collect(router_metric) |             yield from MKTXPCollector.collect(router_entry) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										0
									
								
								mktxp/datasources/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								mktxp/datasources/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										39
									
								
								mktxp/datasources/base_ds.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								mktxp/datasources/base_ds.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class BaseDSProcessor: | ||||||
|  |     ''' Base Metrics DataSource processing | ||||||
|  |     '''              | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def trimmed_records(router_entry, *, router_records = [], metric_labels = [], add_router_id = True, translation_table = {}): | ||||||
|  |         if len(metric_labels) == 0 and len(router_records) > 0: | ||||||
|  |             metric_labels = router_records[0].keys() | ||||||
|  |         metric_labels = set(metric_labels)       | ||||||
|  |  | ||||||
|  |         labeled_records = [] | ||||||
|  |         dash2_ = lambda x : x.replace('-', '_') | ||||||
|  |         for router_record in router_records: | ||||||
|  |             translated_record = {dash2_(key): value for (key, value) in router_record.items() if dash2_(key) in metric_labels} | ||||||
|  |  | ||||||
|  |             if add_router_id: | ||||||
|  |                 for key, value in router_entry.router_id.items(): | ||||||
|  |                     translated_record[key] = value | ||||||
|  |              | ||||||
|  |             # translate fields if needed | ||||||
|  |             for key, func in translation_table.items(): | ||||||
|  |                 translated_record[key] = func(translated_record.get(key)) | ||||||
|  |             labeled_records.append(translated_record) | ||||||
|  |              | ||||||
|  |         return labeled_records | ||||||
							
								
								
									
										41
									
								
								mktxp/datasources/capsman_ds.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								mktxp/datasources/capsman_ds.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from mktxp.datasources.base_ds import BaseDSProcessor | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class CapsmanCapsMetricsDataSource: | ||||||
|  |     ''' Caps Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod | ||||||
|  |     def metric_records(router_entry, *, metric_labels = []): | ||||||
|  |         try: | ||||||
|  |             remote_caps_records = router_entry.api_connection.router_api().get_resource('/caps-man/remote-cap').get() | ||||||
|  |             return BaseDSProcessor.trimmed_records(router_entry, router_records = remote_caps_records, metric_labels = metric_labels) | ||||||
|  |         except Exception as exc: | ||||||
|  |             print(f'Error getting caps-man remote caps info from router{router_entry.router_name}@{router_entry.config_entry.hostname}: {exc}') | ||||||
|  |             return None | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class CapsmanRegistrationsMetricsDataSource: | ||||||
|  |     ''' Capsman Registrations Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod | ||||||
|  |     def metric_records(router_entry, *, metric_labels = [],  add_router_id = True): | ||||||
|  |         try: | ||||||
|  |             registration_table_records = router_entry.api_connection.router_api().get_resource('/caps-man/registration-table').get() | ||||||
|  |             return BaseDSProcessor.trimmed_records(router_entry, router_records = registration_table_records, metric_labels = metric_labels, add_router_id = add_router_id) | ||||||
|  |         except Exception as exc: | ||||||
|  |             print(f'Error getting caps-man registration table info from router{router_entry.router_name}@{router_entry.config_entry.hostname}: {exc}') | ||||||
|  |             return None | ||||||
							
								
								
									
										43
									
								
								mktxp/datasources/dhcp_ds.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								mktxp/datasources/dhcp_ds.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from mktxp.datasources.base_ds import BaseDSProcessor | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class DHCPMetricsDataSource: | ||||||
|  |     ''' DHCP Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod | ||||||
|  |     def metric_records(router_entry, *, metric_labels = [], add_router_id = True): | ||||||
|  |         try: | ||||||
|  |             #dhcp_lease_records = router_entry.api_connection.router_api().get_resource('/ip/dhcp-server/lease').get(status='bound') | ||||||
|  |             dhcp_lease_records = router_entry.api_connection.router_api().get_resource('/ip/dhcp-server/lease').call('print', {'active':''}) | ||||||
|  |  | ||||||
|  |             # translation rules | ||||||
|  |             translation_table = {} | ||||||
|  |             if 'comment' in metric_labels: | ||||||
|  |                 translation_table['comment'] = lambda c: c if c else ''            | ||||||
|  |             if 'host_name' in metric_labels: | ||||||
|  |                 translation_table['host_name'] = lambda c: c if c else ''            | ||||||
|  |             if 'expires_after' in metric_labels: | ||||||
|  |                 translation_table['expires_after'] = lambda c: c if c else ''         | ||||||
|  |             if 'active_address' in metric_labels: | ||||||
|  |                 translation_table['active_address'] = lambda c: c if c else ''         | ||||||
|  |  | ||||||
|  |             return BaseDSProcessor.trimmed_records(router_entry, router_records = dhcp_lease_records, metric_labels = metric_labels, add_router_id = add_router_id, translation_table = translation_table) | ||||||
|  |         except Exception as exc: | ||||||
|  |             print(f'Error getting dhcp info from router{router_entry.router_name}@{router_entry.config_entry.hostname}: {exc}') | ||||||
|  |             return None | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										39
									
								
								mktxp/datasources/firewall_ds.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								mktxp/datasources/firewall_ds.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from mktxp.datasources.base_ds import BaseDSProcessor | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class FirewallMetricsDataSource: | ||||||
|  |     ''' Firewall Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod | ||||||
|  |     def metric_records(router_entry, *, metric_labels = [], raw = False, matching_only = True): | ||||||
|  |         try: | ||||||
|  |             filter_path = '/ip/firewall/filter' if not raw else '/ip/firewall/raw' | ||||||
|  |             firewall_records = router_entry.api_connection.router_api().get_resource(filter_path).call('print', {'stats':'', 'all':''}) | ||||||
|  |             if matching_only: | ||||||
|  |                 firewall_records = [record for record in firewall_records if int(record.get('bytes', '0')) > 0] | ||||||
|  |  | ||||||
|  |             # translation rules | ||||||
|  |             translation_table = {} | ||||||
|  |             if 'comment' in metric_labels: | ||||||
|  |                 translation_table['comment'] = lambda c: c if c else ''            | ||||||
|  |  | ||||||
|  |             return BaseDSProcessor.trimmed_records(router_entry, router_records = firewall_records, metric_labels = metric_labels, translation_table = translation_table) | ||||||
|  |         except Exception as exc: | ||||||
|  |             print(f'Error getting firewall filters info from router{router_entry.router_name}@{router_entry.config_entry.hostname}: {exc}') | ||||||
|  |             return None | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										28
									
								
								mktxp/datasources/health_ds.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								mktxp/datasources/health_ds.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from mktxp.datasources.base_ds import BaseDSProcessor | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class HealthMetricsDataSource: | ||||||
|  |     ''' Health Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod | ||||||
|  |     def metric_records(router_entry, *, metric_labels = []): | ||||||
|  |         try: | ||||||
|  |             health_records = router_entry.api_connection.router_api().get_resource('/system/health').get() | ||||||
|  |             return BaseDSProcessor.trimmed_records(router_entry, router_records = health_records, metric_labels = metric_labels) | ||||||
|  |         except Exception as exc: | ||||||
|  |             print(f'Error getting system health info from router{router_entry.router_name}@{router_entry.config_entry.hostname}: {exc}') | ||||||
|  |             return None | ||||||
							
								
								
									
										28
									
								
								mktxp/datasources/identity_ds.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								mktxp/datasources/identity_ds.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from mktxp.datasources.base_ds import BaseDSProcessor | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class IdentityMetricsDataSource: | ||||||
|  |     ''' Identity Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod | ||||||
|  |     def metric_records(router_entry, *, metric_labels = []): | ||||||
|  |         try: | ||||||
|  |             identity_records = router_entry.api_connection.router_api().get_resource('/system/identity').get() | ||||||
|  |             return BaseDSProcessor.trimmed_records(router_entry, router_records = identity_records, metric_labels = metric_labels) | ||||||
|  |         except Exception as exc: | ||||||
|  |             print(f'Error getting system identity info from router{router_entry.router_name}@{router_entry.config_entry.hostname}: {exc}') | ||||||
|  |             return None | ||||||
							
								
								
									
										59
									
								
								mktxp/datasources/interface_ds.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								mktxp/datasources/interface_ds.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from mktxp.datasources.base_ds import BaseDSProcessor | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class InterfaceTrafficMetricsDataSource: | ||||||
|  |     ''' Interface Traffic Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod | ||||||
|  |     def metric_records(router_entry, *, metric_labels = []): | ||||||
|  |         try: | ||||||
|  |             traffic_records = router_entry.api_connection.router_api().get_resource('/interface').get(running='yes', disabled='no') | ||||||
|  |             return BaseDSProcessor.trimmed_records(router_entry, router_records = traffic_records, metric_labels = metric_labels) | ||||||
|  |         except Exception as exc: | ||||||
|  |             print(f'Error getting interface traffic info from router{router_entry.router_name}@{router_entry.config_entry.hostname}: {exc}') | ||||||
|  |             return None | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class InterfaceMonitorMetricsDataSource: | ||||||
|  |     ''' Interface Monitor Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod | ||||||
|  |     def metric_records(router_entry, *, metric_labels = [], kind = 'ethernet', include_comments = False, running_only = True): | ||||||
|  |         try: | ||||||
|  |             interfaces = router_entry.api_connection.router_api().get_resource(f'/interface/{kind}').get() | ||||||
|  |             interface_names = [(interface['name'], interface.get('comment'), interface.get('running')) for interface in interfaces] | ||||||
|  |  | ||||||
|  |             interface_monitor_records = [] | ||||||
|  |             for int_num, interface_name in enumerate(interface_names): | ||||||
|  |                 interface_monitor_record = {} | ||||||
|  |                 if not running_only or interface_name[2] == 'true': | ||||||
|  |                     interface_monitor_record = router_entry.api_connection.router_api().get_resource(f'/interface/{kind}').call('monitor', {'once':'', 'numbers':f'{int_num}'})[0] | ||||||
|  |                 else: | ||||||
|  |                     # unless explicitly requested, no need to do a monitor call for not running interfaces                     | ||||||
|  |                     interface_monitor_record = {'name': interface_name[0], 'status': 'no-link'} | ||||||
|  |  | ||||||
|  |                 if include_comments and interface_name[1]: | ||||||
|  |                     # combines names with comments | ||||||
|  |                     interface_monitor_record['name'] = interface_name[1] if router_entry.config_entry.use_comments_over_names else \ | ||||||
|  |                                                                                                         f"{interface_name[0]} ({interface_name[1]})"                                 | ||||||
|  |                 interface_monitor_records.append(interface_monitor_record) | ||||||
|  |                  | ||||||
|  |             return BaseDSProcessor.trimmed_records(router_entry, router_records = interface_monitor_records, metric_labels = metric_labels) | ||||||
|  |         except Exception as exc: | ||||||
|  |             print(f'Error getting {kind} interface monitor info from router{router_entry.router_name}@{router_entry.config_entry.hostname}: {exc}') | ||||||
|  |             return None | ||||||
|  |  | ||||||
							
								
								
									
										29
									
								
								mktxp/datasources/mktxp_ds.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								mktxp/datasources/mktxp_ds.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from mktxp.datasources.base_ds import BaseDSProcessor | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class MKTXPMetricsDataSource: | ||||||
|  |     ''' MKTXP Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod | ||||||
|  |     def metric_records(router_entry): | ||||||
|  |         mktxp_records = [] | ||||||
|  |         for key in router_entry.time_spent.keys(): | ||||||
|  |             mktxp_records.append({'name': key, 'duration': router_entry.time_spent[key]})            | ||||||
|  |  | ||||||
|  |         # translation rules             | ||||||
|  |         translation_table = {'duration': lambda d: d*1000} | ||||||
|  |         return BaseDSProcessor.trimmed_records(router_entry, router_records = mktxp_records, translation_table = translation_table) | ||||||
							
								
								
									
										41
									
								
								mktxp/datasources/pool_ds.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								mktxp/datasources/pool_ds.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from mktxp.datasources.base_ds import BaseDSProcessor | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class PoolMetricsDataSource: | ||||||
|  |     ''' Pool Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod | ||||||
|  |     def metric_records(router_entry, *, metric_labels = []): | ||||||
|  |         try: | ||||||
|  |             pool_records = router_entry.api_connection.router_api().get_resource('/ip/pool').get() | ||||||
|  |             return BaseDSProcessor.trimmed_records(router_entry, router_records = pool_records, metric_labels = metric_labels) | ||||||
|  |         except Exception as exc: | ||||||
|  |             print(f'Error getting pool info from router{router_entry.router_name}@{router_entry.config_entry.hostname}: {exc}') | ||||||
|  |             return None | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class PoolUsedMetricsDataSource: | ||||||
|  |     ''' Pool/Used Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod | ||||||
|  |     def metric_records(router_entry, *, metric_labels = []): | ||||||
|  |         try: | ||||||
|  |             pool_used_records = router_entry.api_connection.router_api().get_resource('/ip/pool/used').get() | ||||||
|  |             return BaseDSProcessor.trimmed_records(router_entry, router_records = pool_used_records, metric_labels = metric_labels) | ||||||
|  |         except Exception as exc: | ||||||
|  |             print(f'Error getting pool used info from router{router_entry.router_name}@{router_entry.config_entry.hostname}: {exc}') | ||||||
|  |             return None | ||||||
							
								
								
									
										28
									
								
								mktxp/datasources/route_ds.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								mktxp/datasources/route_ds.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from mktxp.datasources.base_ds import BaseDSProcessor | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class RouteMetricsDataSource: | ||||||
|  |     ''' Routes Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod | ||||||
|  |     def metric_records(router_entry, *, metric_labels = []): | ||||||
|  |         try: | ||||||
|  |             route_records = router_entry.api_connection.router_api().get_resource('/ip/route').get(active='yes') | ||||||
|  |             return BaseDSProcessor.trimmed_records(router_entry, router_records = route_records, metric_labels = metric_labels) | ||||||
|  |         except Exception as exc: | ||||||
|  |             print(f'Error getting routes info from router{router_entry.router_name}@{router_entry.config_entry.hostname}: {exc}') | ||||||
|  |             return None | ||||||
							
								
								
									
										29
									
								
								mktxp/datasources/routerboard_ds.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								mktxp/datasources/routerboard_ds.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from mktxp.datasources.base_ds import BaseDSProcessor | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class RouterboardMetricsDataSource: | ||||||
|  |     ''' Routerboard Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod | ||||||
|  |     def metric_records(router_entry, *, metric_labels = []): | ||||||
|  |         try: | ||||||
|  |             routerboard_records = router_entry.api_connection.router_api().get_resource('/system/routerboard').get() | ||||||
|  |             return BaseDSProcessor.trimmed_records(router_entry, router_records = routerboard_records, metric_labels = metric_labels) | ||||||
|  |         except Exception as exc: | ||||||
|  |             print(f'Error getting system routerboard info from router{router_entry.router_name}@{router_entry.config_entry.hostname}: {exc}') | ||||||
|  |             return None | ||||||
|  |  | ||||||
							
								
								
									
										28
									
								
								mktxp/datasources/system_resource_ds.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								mktxp/datasources/system_resource_ds.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from mktxp.datasources.base_ds import BaseDSProcessor | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class SystemResourceMetricsDataSource: | ||||||
|  |     ''' System Resource Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod     | ||||||
|  |     def metric_records(router_entry, *, metric_labels = []): | ||||||
|  |         try: | ||||||
|  |             system_resource_records = router_entry.api_connection.router_api().get_resource('/system/resource').get() | ||||||
|  |             return BaseDSProcessor.trimmed_records(router_entry, router_records = system_resource_records, metric_labels = metric_labels) | ||||||
|  |         except Exception as exc: | ||||||
|  |             print(f'Error getting system resource info from router{router_entry.router_name}@{router_entry.config_entry.hostname}: {exc}') | ||||||
|  |             return None | ||||||
							
								
								
									
										30
									
								
								mktxp/datasources/wireless_ds.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								mktxp/datasources/wireless_ds.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from mktxp.datasources.base_ds import BaseDSProcessor | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class WirelessMetricsDataSource: | ||||||
|  |     ''' Wireless Metrics data provider | ||||||
|  |     '''              | ||||||
|  |     @staticmethod | ||||||
|  |     def metric_records(router_entry, *, metric_labels = [], add_router_id = True): | ||||||
|  |         try: | ||||||
|  |             registration_table_records = router_entry.api_connection.router_api().get_resource('/interface/wireless/registration-table').get() | ||||||
|  |             return BaseDSProcessor.trimmed_records(router_entry, router_records = registration_table_records, metric_labels = metric_labels, add_router_id = add_router_id) | ||||||
|  |         except Exception as exc: | ||||||
|  |             print(f'Error getting wireless registration table info from router{router_entry.router_name}@{router_entry.config_entry.hostname}: {exc}') | ||||||
|  |             return None | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -11,12 +11,14 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| import ssl | import ssl | ||||||
| import socket | import socket | ||||||
| from datetime import datetime | from datetime import datetime | ||||||
| from routeros_api import RouterOsApiPool | from routeros_api import RouterOsApiPool | ||||||
| from mktxp.cli.config.config import config_handler | from mktxp.cli.config.config import config_handler | ||||||
|  |  | ||||||
|  |  | ||||||
| class RouterAPIConnectionError(Exception): | class RouterAPIConnectionError(Exception): | ||||||
|     pass |     pass | ||||||
|  |  | ||||||
| @@ -24,24 +26,24 @@ class RouterAPIConnectionError(Exception): | |||||||
| class RouterAPIConnection: | class RouterAPIConnection: | ||||||
|     ''' Base wrapper interface for the routeros_api library |     ''' Base wrapper interface for the routeros_api library | ||||||
|     '''             |     '''             | ||||||
|     def __init__(self, router_name, router_entry): |     def __init__(self, router_name, config_entry): | ||||||
|         self.router_name = router_name |         self.router_name = router_name | ||||||
|         self.router_entry = router_entry |         self.config_entry = config_entry | ||||||
|         self.last_failure_timestamp = self.successive_failure_count = 0 |         self.last_failure_timestamp = self.successive_failure_count = 0 | ||||||
|          |          | ||||||
|         ctx = None |         ctx = None | ||||||
|         if self.router_entry.use_ssl and self.router_entry.no_ssl_certificate: |         if self.config_entry.use_ssl and self.config_entry.no_ssl_certificate: | ||||||
|             ctx = ssl.create_default_context() |             ctx = ssl.create_default_context() | ||||||
|             ctx.set_ciphers('ADH:@SECLEVEL=0')        |             ctx.set_ciphers('ADH:@SECLEVEL=0')        | ||||||
|  |  | ||||||
|         self.connection = RouterOsApiPool( |         self.connection = RouterOsApiPool( | ||||||
|                 host = self.router_entry.hostname, |                 host = self.config_entry.hostname, | ||||||
|                 username = self.router_entry.username, |                 username = self.config_entry.username, | ||||||
|                 password = self.router_entry.password, |                 password = self.config_entry.password, | ||||||
|                 port = self.router_entry.port, |                 port = self.config_entry.port, | ||||||
|                 plaintext_login = True, |                 plaintext_login = True, | ||||||
|                 use_ssl = self.router_entry.use_ssl, |                 use_ssl = self.config_entry.use_ssl, | ||||||
|                 ssl_verify = self.router_entry.ssl_certificate_verify, |                 ssl_verify = self.config_entry.ssl_certificate_verify, | ||||||
|                 ssl_context = ctx) |                 ssl_context = ctx) | ||||||
|          |          | ||||||
|         self.connection.socket_timeout = config_handler._entry().socket_timeout |         self.connection.socket_timeout = config_handler._entry().socket_timeout | ||||||
| @@ -62,7 +64,7 @@ class RouterAPIConnection: | |||||||
|         if self.is_connected() or self._in_connect_timeout(connect_time.timestamp()): |         if self.is_connected() or self._in_connect_timeout(connect_time.timestamp()): | ||||||
|             return |             return | ||||||
|         try: |         try: | ||||||
|             print(f'Connecting to router {self.router_name}@{self.router_entry.hostname}') |             print(f'Connecting to router {self.router_name}@{self.config_entry.hostname}') | ||||||
|             self.api = self.connection.get_api() |             self.api = self.connection.get_api() | ||||||
|             self._set_connect_state(success = True, connect_time = connect_time) |             self._set_connect_state(success = True, connect_time = connect_time) | ||||||
|         except (socket.error, socket.timeout, Exception) as exc: |         except (socket.error, socket.timeout, Exception) as exc: | ||||||
| @@ -78,11 +80,11 @@ class RouterAPIConnection: | |||||||
|         connect_delay = self._connect_delay() |         connect_delay = self._connect_delay() | ||||||
|         if (connect_timestamp - self.last_failure_timestamp) < connect_delay: |         if (connect_timestamp - self.last_failure_timestamp) < connect_delay: | ||||||
|             if not quiet:  |             if not quiet:  | ||||||
|                 print(f'{self.router_name}@{self.router_entry.hostname}: in connect timeout, {int(connect_delay - (connect_timestamp - self.last_failure_timestamp))}secs remaining') |                 print(f'{self.router_name}@{self.config_entry.hostname}: in connect timeout, {int(connect_delay - (connect_timestamp - self.last_failure_timestamp))}secs remaining') | ||||||
|                 print(f'Successive failure count: {self.successive_failure_count}') |                 print(f'Successive failure count: {self.successive_failure_count}') | ||||||
|             return True |             return True | ||||||
|         if not quiet:  |         if not quiet:  | ||||||
|             print(f'{self.router_name}@{self.router_entry.hostname}: OK to connect') |             print(f'{self.router_name}@{self.config_entry.hostname}: OK to connect') | ||||||
|             if self.last_failure_timestamp > 0: |             if self.last_failure_timestamp > 0: | ||||||
|                 print(f'Seconds since last failure: {connect_timestamp - self.last_failure_timestamp}') |                 print(f'Seconds since last failure: {connect_timestamp - self.last_failure_timestamp}') | ||||||
|                 print(f'Prior successive failure count: {self.successive_failure_count}') |                 print(f'Prior successive failure count: {self.successive_failure_count}') | ||||||
| @@ -98,12 +100,12 @@ class RouterAPIConnection: | |||||||
|         if success: |         if success: | ||||||
|             self.last_failure_timestamp = 0 |             self.last_failure_timestamp = 0 | ||||||
|             self.successive_failure_count = 0 |             self.successive_failure_count = 0 | ||||||
|             print(f'{connect_time.strftime("%Y-%m-%d %H:%M:%S")} Connection to router {self.router_name}@{self.router_entry.hostname} has been established') |             print(f'{connect_time.strftime("%Y-%m-%d %H:%M:%S")} Connection to router {self.router_name}@{self.config_entry.hostname} has been established') | ||||||
|         else: |         else: | ||||||
|             self.api = None |             self.api = None | ||||||
|             self.successive_failure_count += 1 |             self.successive_failure_count += 1 | ||||||
|             self.last_failure_timestamp = connect_time.timestamp()  |             self.last_failure_timestamp = connect_time.timestamp()  | ||||||
|             print(f'{connect_time.strftime("%Y-%m-%d %H:%M:%S")} Connection to router {self.router_name}@{self.router_entry.hostname} has failed: {exc}') |             print(f'{connect_time.strftime("%Y-%m-%d %H:%M:%S")} Connection to router {self.router_name}@{self.config_entry.hostname} has failed: {exc}') | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,28 +13,28 @@ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| from mktxp.cli.config.config import config_handler | from mktxp.cli.config.config import config_handler | ||||||
| from mktxp.router_metric import RouterMetric | from mktxp.router_entry import RouterEntry | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class RouterMetricsHandler: | class RouterEntriesHandler: | ||||||
|     ''' Handles RouterOS entries defined in MKTXP config  |     ''' Handles RouterOS entries defined in MKTXP config  | ||||||
|     '''          |     '''          | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         self.router_metrics = [] |         self.router_entries = [] | ||||||
|         for router_name in config_handler.registered_entries(): |         for router_name in config_handler.registered_entries(): | ||||||
|             entry = config_handler.entry(router_name) |             entry = config_handler.entry(router_name) | ||||||
|             if entry.enabled: |             if entry.enabled: | ||||||
|                 self.router_metrics.append(RouterMetric(router_name)) |                 self.router_entries.append(RouterEntry(router_name)) | ||||||
| 
 | 
 | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def router_metric(entry_name, enabled_only = False): |     def router_entry(entry_name, enabled_only = False): | ||||||
|         router_metric = None |         router_entry = None | ||||||
|         for router_name in config_handler.registered_entries(): |         for router_name in config_handler.registered_entries(): | ||||||
|             if router_name == entry_name: |             if router_name == entry_name: | ||||||
|                 if enabled_only: |                 if enabled_only: | ||||||
|                     entry = config_handler.entry(router_name) |                     entry = config_handler.entry(router_name) | ||||||
|                     if not entry.enabled: |                     if not entry.enabled: | ||||||
|                         break |                         break | ||||||
|                 router_metric = RouterMetric(router_name) |                 router_entry = RouterEntry(router_name) | ||||||
|                 break |                 break | ||||||
|         return router_metric |         return router_entry | ||||||
							
								
								
									
										41
									
								
								mktxp/router_entry.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								mktxp/router_entry.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | # coding=utf8 | ||||||
|  | ## Copyright (c) 2020 Arseniy Kuznetsov | ||||||
|  | ## | ||||||
|  | ## This program is free software; you can redistribute it and/or | ||||||
|  | ## modify it under the terms of the GNU General Public License | ||||||
|  | ## as published by the Free Software Foundation; either version 2 | ||||||
|  | ## of the License, or (at your option) any later version. | ||||||
|  | ## | ||||||
|  | ## This program is distributed in the hope that it will be useful, | ||||||
|  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from mktxp.cli.config.config import config_handler, MKTXPConfigKeys | ||||||
|  | from mktxp.router_connection import RouterAPIConnection | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class RouterEntry: | ||||||
|  |     ''' RouterOS Entry | ||||||
|  |     '''                  | ||||||
|  |     def __init__(self, router_name): | ||||||
|  |         self.router_name = router_name | ||||||
|  |         self.config_entry  = config_handler.entry(router_name) | ||||||
|  |         self.api_connection = RouterAPIConnection(router_name, self.config_entry) | ||||||
|  |         self.router_id = { | ||||||
|  |             MKTXPConfigKeys.ROUTERBOARD_NAME: self.router_name, | ||||||
|  |             MKTXPConfigKeys.ROUTERBOARD_ADDRESS: self.config_entry.hostname | ||||||
|  |             } | ||||||
|  |         self.time_spent =  { 'IdentityCollector': 0, | ||||||
|  |                             'SystemResourceCollector': 0, | ||||||
|  |                             'HealthCollector': 0, | ||||||
|  |                             'DHCPCollector': 0, | ||||||
|  |                             'PoolCollector': 0, | ||||||
|  |                             'InterfaceCollector': 0, | ||||||
|  |                             'FirewallCollector': 0, | ||||||
|  |                             'MonitorCollector': 0, | ||||||
|  |                             'RouteCollector': 0, | ||||||
|  |                             'WLANCollector': 0, | ||||||
|  |                             'CapsmanCollector': 0 | ||||||
|  |                             }             | ||||||
| @@ -1,201 +0,0 @@ | |||||||
| # coding=utf8 |  | ||||||
| ## Copyright (c) 2020 Arseniy Kuznetsov |  | ||||||
| ## |  | ||||||
| ## This program is free software; you can redistribute it and/or |  | ||||||
| ## modify it under the terms of the GNU General Public License |  | ||||||
| ## as published by the Free Software Foundation; either version 2 |  | ||||||
| ## of the License, or (at your option) any later version. |  | ||||||
| ## |  | ||||||
| ## This program is distributed in the hope that it will be useful, |  | ||||||
| ## but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
| ## GNU General Public License for more details. |  | ||||||
|  |  | ||||||
|  |  | ||||||
| from mktxp.cli.config.config import config_handler, MKTXPConfigKeys |  | ||||||
| from mktxp.router_connection import RouterAPIConnection |  | ||||||
|  |  | ||||||
| class RouterMetric: |  | ||||||
|     ''' RouterOS Metrics data provider |  | ||||||
|     '''              |  | ||||||
|     def __init__(self, router_name): |  | ||||||
|         self.router_name = router_name |  | ||||||
|         self.router_entry  = config_handler.entry(router_name) |  | ||||||
|         self.api_connection = RouterAPIConnection(router_name, self.router_entry) |  | ||||||
|         self.router_id = { |  | ||||||
|             MKTXPConfigKeys.ROUTERBOARD_NAME: self.router_name, |  | ||||||
|             MKTXPConfigKeys.ROUTERBOARD_ADDRESS: self.router_entry.hostname |  | ||||||
|             } |  | ||||||
|         self.time_spent =  { 'IdentityCollector': 0, |  | ||||||
|                             'SystemResourceCollector': 0, |  | ||||||
|                             'HealthCollector': 0, |  | ||||||
|                             'DHCPCollector': 0, |  | ||||||
|                             'PoolCollector': 0, |  | ||||||
|                             'InterfaceCollector': 0, |  | ||||||
|                             'FirewallCollector': 0, |  | ||||||
|                             'MonitorCollector': 0, |  | ||||||
|                             'RouteCollector': 0, |  | ||||||
|                             'WLANCollector': 0, |  | ||||||
|                             'CapsmanCollector': 0 |  | ||||||
|                             }             |  | ||||||
|  |  | ||||||
|     def identity_records(self, identity_labels = []): |  | ||||||
|         try: |  | ||||||
|             identity_records = self.api_connection.router_api().get_resource('/system/identity').get() |  | ||||||
|             return self._trimmed_records(identity_records, identity_labels) |  | ||||||
|         except Exception as exc: |  | ||||||
|             print(f'Error getting system identity info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |  | ||||||
|             return None |  | ||||||
|  |  | ||||||
|     def routerboard_records(self, routerboard_labels = []): |  | ||||||
|         try: |  | ||||||
|             routerboard_records = self.api_connection.router_api().get_resource('/system/routerboard').get() |  | ||||||
|             return self._trimmed_records(routerboard_records, routerboard_labels) |  | ||||||
|         except Exception as exc: |  | ||||||
|             print(f'Error getting system routerboard info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |  | ||||||
|             return None |  | ||||||
|  |  | ||||||
|     def health_records(self, health_labels = []): |  | ||||||
|         try: |  | ||||||
|             health_records = self.api_connection.router_api().get_resource('/system/health').get() |  | ||||||
|             return self._trimmed_records(health_records, health_labels) |  | ||||||
|         except Exception as exc: |  | ||||||
|             print(f'Error getting system health info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |  | ||||||
|             return None |  | ||||||
|  |  | ||||||
|     def system_resource_records(self, resource_labels = []): |  | ||||||
|         try: |  | ||||||
|             system_resource_records = self.api_connection.router_api().get_resource('/system/resource').get() |  | ||||||
|             return self._trimmed_records(system_resource_records, resource_labels) |  | ||||||
|         except Exception as exc: |  | ||||||
|             print(f'Error getting system resource info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |  | ||||||
|             return None |  | ||||||
|  |  | ||||||
|     def dhcp_lease_records(self, dhcp_lease_labels = [], add_router_id = True): |  | ||||||
|         try: |  | ||||||
|             #dhcp_lease_records = self.api_connection.router_api().get_resource('/ip/dhcp-server/lease').get(status='bound') |  | ||||||
|             dhcp_lease_records = self.api_connection.router_api().get_resource('/ip/dhcp-server/lease').call('print', {'active':''}) |  | ||||||
|             return self._trimmed_records(dhcp_lease_records, dhcp_lease_labels, add_router_id) |  | ||||||
|         except Exception as exc: |  | ||||||
|             print(f'Error getting dhcp info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |  | ||||||
|             return None |  | ||||||
|  |  | ||||||
|     def interface_traffic_records(self, interface_traffic_labels = []): |  | ||||||
|         try: |  | ||||||
|             traffic_records = self.api_connection.router_api().get_resource('/interface').get(running='yes', disabled='no') |  | ||||||
|             return self._trimmed_records(traffic_records, interface_traffic_labels) |  | ||||||
|         except Exception as exc: |  | ||||||
|             print(f'Error getting interface traffic info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |  | ||||||
|             return None |  | ||||||
|  |  | ||||||
|     def interface_monitor_records(self, interface_monitor_labels = [], kind = 'ethernet', include_comments = False): |  | ||||||
|         try: |  | ||||||
|             interfaces = self.api_connection.router_api().get_resource(f'/interface/{kind}').get() |  | ||||||
|             interface_names = [(interface['name'], interface.get('comment'), interface.get('running')) for interface in interfaces] |  | ||||||
|  |  | ||||||
|             interface_monitor = lambda int_num : self.api_connection.router_api().get_resource(f'/interface/{kind}').call('monitor', {'once':'', 'numbers':f'{int_num}'}) |  | ||||||
|             interface_monitor_records = [interface_monitor(int_num)[0] for int_num in range(len(interface_names))] |  | ||||||
|  |  | ||||||
|             if include_comments: |  | ||||||
|                 # combine interfaces names with comments |  | ||||||
|                 for interface_monitor_record in interface_monitor_records: |  | ||||||
|                     for interface_name in interface_names: |  | ||||||
|                         if interface_name[1] and interface_name[0] == interface_monitor_record['name']: |  | ||||||
|                             interface_monitor_record['name'] = interface_name[1] if self.router_entry.use_comments_over_names else \ |  | ||||||
|                                                                                  f"{interface_name[0]} ({interface_name[1]})" |  | ||||||
|             return self._trimmed_records(interface_monitor_records, interface_monitor_labels) |  | ||||||
|         except Exception as exc: |  | ||||||
|             print(f'Error getting {kind} interface monitor info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |  | ||||||
|             return None |  | ||||||
|  |  | ||||||
|     def pool_records(self, pool_labels = []): |  | ||||||
|         try: |  | ||||||
|             pool_records = self.api_connection.router_api().get_resource('/ip/pool').get() |  | ||||||
|             return self._trimmed_records(pool_records, pool_labels) |  | ||||||
|         except Exception as exc: |  | ||||||
|             print(f'Error getting pool info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |  | ||||||
|             return None |  | ||||||
|  |  | ||||||
|     def pool_used_records(self, pool_used_labels = []): |  | ||||||
|         try: |  | ||||||
|             pool_used_records = self.api_connection.router_api().get_resource('/ip/pool/used').get() |  | ||||||
|             return self._trimmed_records(pool_used_records, pool_used_labels) |  | ||||||
|         except Exception as exc: |  | ||||||
|             print(f'Error getting pool used info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |  | ||||||
|             return None |  | ||||||
|  |  | ||||||
|     def route_records(self, route_labels = []): |  | ||||||
|         try: |  | ||||||
|             route_records = self.api_connection.router_api().get_resource('/ip/route').get(active='yes') |  | ||||||
|             return self._trimmed_records(route_records, route_labels) |  | ||||||
|         except Exception as exc: |  | ||||||
|             print(f'Error getting routes info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |  | ||||||
|             return None |  | ||||||
|              |  | ||||||
|     def wireless_registration_table_records(self, registration_table_labels = [], add_router_id = True): |  | ||||||
|         try: |  | ||||||
|             registration_table_records = self.api_connection.router_api().get_resource('/interface/wireless/registration-table').get() |  | ||||||
|             return self._trimmed_records(registration_table_records, registration_table_labels, add_router_id) |  | ||||||
|         except Exception as exc: |  | ||||||
|             print(f'Error getting wireless registration table info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |  | ||||||
|             return None |  | ||||||
|  |  | ||||||
|     def capsman_remote_caps_records(self, remote_caps_labels = []): |  | ||||||
|         try: |  | ||||||
|             remote_caps_records = self.api_connection.router_api().get_resource('/caps-man/remote-cap').get() |  | ||||||
|             return self._trimmed_records(remote_caps_records, remote_caps_labels) |  | ||||||
|         except Exception as exc: |  | ||||||
|             print(f'Error getting caps-man remote caps info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |  | ||||||
|             return None |  | ||||||
|  |  | ||||||
|     def capsman_registration_table_records(self, registration_table_labels = [], add_router_id = True): |  | ||||||
|         try: |  | ||||||
|             registration_table_records = self.api_connection.router_api().get_resource('/caps-man/registration-table').get() |  | ||||||
|             return self._trimmed_records(registration_table_records, registration_table_labels, add_router_id) |  | ||||||
|         except Exception as exc: |  | ||||||
|             print(f'Error getting caps-man registration table info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |  | ||||||
|             return None |  | ||||||
|  |  | ||||||
|     def firewall_records(self, firewall_labels = [], raw = False, matching_only = True): |  | ||||||
|         try: |  | ||||||
|             filter_path = '/ip/firewall/filter' if not raw else '/ip/firewall/raw' |  | ||||||
|             firewall_records = self.api_connection.router_api().get_resource(filter_path).call('print', {'stats':'', 'all':''}) |  | ||||||
|             if matching_only: |  | ||||||
|                 firewall_records = [record for record in firewall_records if int(record.get('bytes', '0')) > 0] |  | ||||||
|             # translation rules |  | ||||||
|             translation_table = {} |  | ||||||
| #            if 'id' in firewall_labels: |  | ||||||
| #                translation_table['id'] = lambda id: str(int(id[1:], 16) - 1) |  | ||||||
|             if 'comment' in firewall_labels: |  | ||||||
|                 translation_table['comment'] = lambda c: c if c else '' |  | ||||||
|             return self._trimmed_records(firewall_records, firewall_labels, translation_table = translation_table) |  | ||||||
|         except Exception as exc: |  | ||||||
|             print(f'Error getting firewall filters info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |  | ||||||
|             return None |  | ||||||
|  |  | ||||||
|     def mktxp_records(self): |  | ||||||
|         mktxp_records = [] |  | ||||||
|         for key in self.time_spent.keys(): |  | ||||||
|             mktxp_records.append({'name': key, 'duration': self.time_spent[key]}) |  | ||||||
|         # translation rules             |  | ||||||
|         translation_table = {'duration': lambda d: d*1000} |  | ||||||
|         return self._trimmed_records(mktxp_records, translation_table = translation_table) |  | ||||||
|  |  | ||||||
|     # Helpers |  | ||||||
|     def _trimmed_records(self, router_records, metric_labels = [], add_router_id = True, translation_table = {}): |  | ||||||
|         if len(metric_labels) == 0 and len(router_records) > 0: |  | ||||||
|             metric_labels = router_records[0].keys() |  | ||||||
|         metric_labels = set(metric_labels)       |  | ||||||
|  |  | ||||||
|         labeled_records = [] |  | ||||||
|         dash2_ = lambda x : x.replace('-', '_') |  | ||||||
|         for router_record in router_records: |  | ||||||
|             translated_record = {dash2_(key): value for (key, value) in router_record.items() if dash2_(key) in metric_labels} |  | ||||||
|             if add_router_id: |  | ||||||
|                 for key, value in self.router_id.items(): |  | ||||||
|                     translated_record[key] = value |  | ||||||
|             # translate fields if needed |  | ||||||
|             for key, func in translation_table.items(): |  | ||||||
|                 translated_record[key] = func(translated_record.get(key)) |  | ||||||
|             labeled_records.append(translated_record) |  | ||||||
|         return labeled_records |  | ||||||
| @@ -11,6 +11,7 @@ | |||||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| import os, sys, shlex, tempfile, shutil, re | import os, sys, shlex, tempfile, shutil, re | ||||||
| import subprocess, hashlib | import subprocess, hashlib | ||||||
| from timeit import default_timer | from timeit import default_timer | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user