mirror of
				https://github.com/KevinMidboe/mktxp-no-cli.git
				synced 2025-10-29 17:50:23 +00:00 
			
		
		
		
	cli options, fixes
This commit is contained in:
		| @@ -5,7 +5,7 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| <img src="http://www.akpdev.com/images/mktxp_b_t.png" width="460" height="600"> | <img src="http://www.akpdev.com/images/mktxp_b_t.png" width="460" height="620"> | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -28,8 +28,7 @@ class MKTXPProcessor: | |||||||
|     def start(): |     def start(): | ||||||
|         router_metrics_handler = RouterMetricsHandler() |         router_metrics_handler = RouterMetricsHandler() | ||||||
|         REGISTRY.register(CollectorsHandler(router_metrics_handler)) |         REGISTRY.register(CollectorsHandler(router_metrics_handler)) | ||||||
|         port=config_handler.mktxp_port() |         MKTXPProcessor.run(port=config_handler._entry().port) | ||||||
|         MKTXPProcessor.run(port=port) |  | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def run(server_class=HTTPServer, handler_class=MetricsHandler, port = None): |     def run(server_class=HTTPServer, handler_class=MetricsHandler, port = None): | ||||||
|   | |||||||
| @@ -13,3 +13,7 @@ | |||||||
|  |  | ||||||
| [MKTXP] | [MKTXP] | ||||||
|     port = 49090 |     port = 49090 | ||||||
|  |     socket_timeout = 2 | ||||||
|  |     initial_delay_on_failure = 120 | ||||||
|  |     max_delay_on_failure = 900 | ||||||
|  |     delay_inc_div = 5 | ||||||
|   | |||||||
| @@ -33,7 +33,8 @@ class MKTXPConfigKeys: | |||||||
|     PASSWD_KEY = 'password' |     PASSWD_KEY = 'password' | ||||||
|  |  | ||||||
|     SSL_KEY = 'use_ssl' |     SSL_KEY = 'use_ssl' | ||||||
|     SSL_CERTIFICATE = 'ssl_certificate' |     NO_SSL_CERTIFICATE = 'no_ssl_certificate' | ||||||
|  |     SSL_CERTIFICATE_VERIFY = 'ssl_certificate_verify' | ||||||
|  |  | ||||||
|     FE_DHCP_KEY = 'dhcp' |     FE_DHCP_KEY = 'dhcp' | ||||||
|     FE_DHCP_LEASE_KEY = 'dhcp_lease'     |     FE_DHCP_LEASE_KEY = 'dhcp_lease'     | ||||||
| @@ -46,6 +47,12 @@ class MKTXPConfigKeys: | |||||||
|     FE_CAPSMAN_KEY = 'capsman' |     FE_CAPSMAN_KEY = 'capsman' | ||||||
|     FE_CAPSMAN_CLIENTS_KEY = 'capsman_clients' |     FE_CAPSMAN_CLIENTS_KEY = 'capsman_clients' | ||||||
|  |  | ||||||
|  |     MKTXP_SOCKET_TIMEOUT = 'socket_timeout'     | ||||||
|  |     MKTXP_SOCKET_TIMEOUT = 'socket_timeout'    | ||||||
|  |     MKTXP_INITIAL_DELAY = 'initial_delay_on_failure' | ||||||
|  |     MKTXP_MAX_DELAY = 'max_delay_on_failure' | ||||||
|  |     MKTXP_INC_DIV = 'delay_inc_div' | ||||||
|  |  | ||||||
|     # UnRegistered entries placeholder |     # UnRegistered entries placeholder | ||||||
|     NO_ENTRIES_REGISTERED = 'NoEntriesRegistered' |     NO_ENTRIES_REGISTERED = 'NoEntriesRegistered' | ||||||
|  |  | ||||||
| @@ -53,15 +60,21 @@ class MKTXPConfigKeys: | |||||||
|     ROUTERBOARD_NAME = 'routerboard_name' |     ROUTERBOARD_NAME = 'routerboard_name' | ||||||
|     ROUTERBOARD_ADDRESS = 'routerboard_address' |     ROUTERBOARD_ADDRESS = 'routerboard_address' | ||||||
|  |  | ||||||
|     # Default ports |     # Default values | ||||||
|     DEFAULT_API_PORT = 8728 |     DEFAULT_API_PORT = 8728 | ||||||
|     DEFAULT_API_SSL_PORT = 8729 |     DEFAULT_API_SSL_PORT = 8729 | ||||||
|     DEFAULT_MKTXP_PORT = 49090 |     DEFAULT_MKTXP_PORT = 49090 | ||||||
|  |     DEFAULT_MKTXP_SOCKET_TIMEOUT = 2 | ||||||
|  |     DEFAULT_MKTXP_INITIAL_DELAY = 120 | ||||||
|  |     DEFAULT_MKTXP_MAX_DELAY = 900 | ||||||
|  |     DEFAULT_MKTXP_INC_DIV = 5 | ||||||
|  |  | ||||||
|     BOOLEAN_KEYS = [ENABLED_KEY, SSL_KEY, SSL_CERTIFICATE,   |     BOOLEAN_KEYS = (ENABLED_KEY, SSL_KEY, NO_SSL_CERTIFICATE, SSL_CERTIFICATE_VERIFY,  | ||||||
|                       FE_DHCP_KEY, FE_DHCP_LEASE_KEY, FE_DHCP_POOL_KEY, FE_INTERFACE_KEY,  |                       FE_DHCP_KEY, FE_DHCP_LEASE_KEY, FE_DHCP_POOL_KEY, FE_INTERFACE_KEY,  | ||||||
|                       FE_MONITOR_KEY, FE_ROUTE_KEY, FE_WIRELESS_KEY, FE_WIRELESS_CLIENTS_KEY, FE_CAPSMAN_KEY, FE_CAPSMAN_CLIENTS_KEY] |                       FE_MONITOR_KEY, FE_ROUTE_KEY, FE_WIRELESS_KEY, FE_WIRELESS_CLIENTS_KEY, FE_CAPSMAN_KEY, FE_CAPSMAN_CLIENTS_KEY) | ||||||
|  |      | ||||||
|     STR_KEYS = [HOST_KEY, USER_KEY, PASSWD_KEY] |     STR_KEYS = [HOST_KEY, USER_KEY, PASSWD_KEY] | ||||||
|  |     INT_KEYS = [PORT_KEY, MKTXP_SOCKET_TIMEOUT, MKTXP_INITIAL_DELAY, MKTXP_MAX_DELAY, MKTXP_INC_DIV] | ||||||
|  |  | ||||||
|     # MKTXP config entry nane |     # MKTXP config entry nane | ||||||
|     MKTXP_CONFIG_ENTRY_NAME = 'MKTXP' |     MKTXP_CONFIG_ENTRY_NAME = 'MKTXP' | ||||||
| @@ -70,12 +83,15 @@ class MKTXPConfigKeys: | |||||||
| class ConfigEntry: | class ConfigEntry: | ||||||
|     MKTXPEntry = namedtuple('MKTXPEntry', [MKTXPConfigKeys.ENABLED_KEY, MKTXPConfigKeys.HOST_KEY, MKTXPConfigKeys.PORT_KEY,  |     MKTXPEntry = namedtuple('MKTXPEntry', [MKTXPConfigKeys.ENABLED_KEY, MKTXPConfigKeys.HOST_KEY, MKTXPConfigKeys.PORT_KEY,  | ||||||
|                          MKTXPConfigKeys.USER_KEY, MKTXPConfigKeys.PASSWD_KEY,  |                          MKTXPConfigKeys.USER_KEY, MKTXPConfigKeys.PASSWD_KEY,  | ||||||
|                          MKTXPConfigKeys.SSL_KEY, MKTXPConfigKeys.SSL_CERTIFICATE,  |                          MKTXPConfigKeys.SSL_KEY, MKTXPConfigKeys.NO_SSL_CERTIFICATE, MKTXPConfigKeys.SSL_CERTIFICATE_VERIFY, | ||||||
|                           |                           | ||||||
|                          MKTXPConfigKeys.FE_DHCP_KEY, MKTXPConfigKeys.FE_DHCP_LEASE_KEY, MKTXPConfigKeys.FE_DHCP_POOL_KEY, MKTXPConfigKeys.FE_INTERFACE_KEY,  |                          MKTXPConfigKeys.FE_DHCP_KEY, MKTXPConfigKeys.FE_DHCP_LEASE_KEY, MKTXPConfigKeys.FE_DHCP_POOL_KEY, MKTXPConfigKeys.FE_INTERFACE_KEY,  | ||||||
|                          MKTXPConfigKeys.FE_MONITOR_KEY, MKTXPConfigKeys.FE_ROUTE_KEY, MKTXPConfigKeys.FE_WIRELESS_KEY, MKTXPConfigKeys.FE_WIRELESS_CLIENTS_KEY, |                          MKTXPConfigKeys.FE_MONITOR_KEY, MKTXPConfigKeys.FE_ROUTE_KEY, MKTXPConfigKeys.FE_WIRELESS_KEY, MKTXPConfigKeys.FE_WIRELESS_CLIENTS_KEY, | ||||||
|                          MKTXPConfigKeys.FE_CAPSMAN_KEY, MKTXPConfigKeys.FE_CAPSMAN_CLIENTS_KEY |                          MKTXPConfigKeys.FE_CAPSMAN_KEY, MKTXPConfigKeys.FE_CAPSMAN_CLIENTS_KEY | ||||||
|                          ]) |                          ]) | ||||||
|  |     _MKTXPEntry = namedtuple('_MKTXPEntry', [MKTXPConfigKeys.PORT_KEY, MKTXPConfigKeys.MKTXP_SOCKET_TIMEOUT,  | ||||||
|  |                                             MKTXPConfigKeys.MKTXP_INITIAL_DELAY, MKTXPConfigKeys.MKTXP_MAX_DELAY, MKTXPConfigKeys.MKTXP_INC_DIV]) | ||||||
|  |  | ||||||
|  |  | ||||||
| class OSConfig(metaclass = ABCMeta): | class OSConfig(metaclass = ABCMeta): | ||||||
|     ''' OS-related config |     ''' OS-related config | ||||||
| @@ -139,7 +155,7 @@ class MKTXPConfigHandler: | |||||||
|         ''' (Force-)Read conf data from disk |         ''' (Force-)Read conf data from disk | ||||||
|         ''' |         ''' | ||||||
|         self.config = ConfigObj(self.usr_conf_data_path) |         self.config = ConfigObj(self.usr_conf_data_path) | ||||||
|         self.mktxp_config = ConfigObj(self.mktxp_conf_path) |         self._config = ConfigObj(self.mktxp_conf_path) | ||||||
|  |  | ||||||
|     def _create_os_path(self, os_path, resource_path): |     def _create_os_path(self, os_path, resource_path): | ||||||
|         if not os.path.exists(os_path): |         if not os.path.exists(os_path): | ||||||
| @@ -190,37 +206,55 @@ class MKTXPConfigHandler: | |||||||
|     def entry(self, entry_name): |     def entry(self, entry_name): | ||||||
|         ''' Given an entry name, reads and returns the entry info |         ''' Given an entry name, reads and returns the entry info | ||||||
|         ''' |         ''' | ||||||
|         entry_reader = self._entry_reader(entry_name) |         entry_reader = self.entry_reader(entry_name) | ||||||
|         return ConfigEntry.MKTXPEntry(**entry_reader) |         return ConfigEntry.MKTXPEntry(**entry_reader) | ||||||
|  |  | ||||||
|     def mktxp_port(self): |     def _entry(self): | ||||||
|         if self.mktxp_config.get(MKTXPConfigKeys.MKTXP_CONFIG_ENTRY_NAME) and \ |         ''' MKTXP internal config entry | ||||||
|                 self.mktxp_config[MKTXPConfigKeys.MKTXP_CONFIG_ENTRY_NAME].get(MKTXPConfigKeys.PORT_KEY): |         ''' | ||||||
|                 return self.mktxp_config[MKTXPConfigKeys.MKTXP_CONFIG_ENTRY_NAME].as_int(MKTXPConfigKeys.PORT_KEY)         |         _entry_reader = self._entry_reader() | ||||||
|         return MKTXPConfigKeys.DEFAULT_MKTXP_PORT |         return ConfigEntry._MKTXPEntry(**_entry_reader) | ||||||
|  |  | ||||||
|  |  | ||||||
|     # Helpers |     # Helpers | ||||||
|     def _entry_reader(self, entry_name): |     def entry_reader(self, entry_name): | ||||||
|         entry = {} |         entry_reader = {} | ||||||
|         for key in MKTXPConfigKeys.BOOLEAN_KEYS: |         for key in MKTXPConfigKeys.BOOLEAN_KEYS: | ||||||
|             if self.config[entry_name].get(key): |             if self.config[entry_name].get(key): | ||||||
|                 entry[key] = self.config[entry_name].as_bool(key) |                 entry_reader[key] = self.config[entry_name].as_bool(key) | ||||||
|             else: |             else: | ||||||
|                 entry[key] = False |                 entry_reader[key] = False | ||||||
|  |  | ||||||
|         for key in MKTXPConfigKeys.STR_KEYS: |         for key in MKTXPConfigKeys.STR_KEYS: | ||||||
|             entry[key] = self.config[entry_name][key] |             entry_reader[key] = self.config[entry_name][key] | ||||||
|  |  | ||||||
|         # port |         # port | ||||||
|         if self.config[entry_name].get(MKTXPConfigKeys.PORT_KEY): |         if self.config[entry_name].get(MKTXPConfigKeys.PORT_KEY): | ||||||
|             entry[MKTXPConfigKeys.PORT_KEY] = self.config[entry_name].as_int(MKTXPConfigKeys.PORT_KEY) |             entry_reader[MKTXPConfigKeys.PORT_KEY] = self.config[entry_name].as_int(MKTXPConfigKeys.PORT_KEY) | ||||||
|         else: |         else: | ||||||
|             if entry[MKTXPConfigKeys.SSL_KEY]: |             entry_reader[MKTXPConfigKeys.PORT_KEY] = self._default_value_for_key(MKTXPConfigKeys.SSL_KEY, entry_reader[MKTXPConfigKeys.SSL_KEY]) | ||||||
|                 entry[MKTXPConfigKeys.PORT_KEY] = MKTXPConfigKeys.DEFAULT_API_SSL_PORT |  | ||||||
|             else: |  | ||||||
|                 entry[MKTXPConfigKeys.PORT_KEY] = MKTXPConfigKeys.DEFAULT_API_PORT |  | ||||||
|  |  | ||||||
|         return entry |         return entry_reader | ||||||
|  |  | ||||||
|  |     def _entry_reader(self): | ||||||
|  |         _entry_reader = {} | ||||||
|  |         entry_name = MKTXPConfigKeys.MKTXP_CONFIG_ENTRY_NAME | ||||||
|  |         for key in MKTXPConfigKeys.INT_KEYS: | ||||||
|  |             if self._config[entry_name].get(key): | ||||||
|  |                 _entry_reader[key] = self._config[entry_name].as_int(key) | ||||||
|  |             else: | ||||||
|  |                 _entry_reader[key] = self._default_value_for_key(key) | ||||||
|  |         return _entry_reader | ||||||
|  |  | ||||||
|  |     def _default_value_for_key(self, key, value = None): | ||||||
|  |         return { | ||||||
|  |                 MKTXPConfigKeys.SSL_KEY: lambda value: MKTXPConfigKeys.DEFAULT_API_SSL_PORT if value else MKTXPConfigKeys.DEFAULT_API_PORT, | ||||||
|  |                 MKTXPConfigKeys.PORT_KEY: lambda value: MKTXPConfigKeys.DEFAULT_MKTXP_PORT, | ||||||
|  |                 MKTXPConfigKeys.MKTXP_SOCKET_TIMEOUT: lambda value: MKTXPConfigKeys.DEFAULT_MKTXP_SOCKET_TIMEOUT, | ||||||
|  |                 MKTXPConfigKeys.MKTXP_INITIAL_DELAY: lambda value: MKTXPConfigKeys.DEFAULT_MKTXP_INITIAL_DELAY, | ||||||
|  |                 MKTXPConfigKeys.MKTXP_MAX_DELAY: lambda value: MKTXPConfigKeys.DEFAULT_MKTXP_MAX_DELAY, | ||||||
|  |                 MKTXPConfigKeys.MKTXP_INC_DIV: lambda value: MKTXPConfigKeys.DEFAULT_MKTXP_INC_DIV | ||||||
|  |                 }[key](value) | ||||||
|  |  | ||||||
|  |  | ||||||
| # Simplest possible Singleton impl | # Simplest possible Singleton impl | ||||||
|   | |||||||
| @@ -11,17 +11,18 @@ | |||||||
| ## GNU General Public License for more details. | ## GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |  | ||||||
| [SampleRouter] | [Sample-Router] | ||||||
|     enabled = False |     enabled = False         # turns metrics collection for this RouterOS device on / off | ||||||
|      |      | ||||||
|     hostname = localhost |     hostname = localhost    # RouterOS IP address | ||||||
|     port = 8728 |     port = 8728             # RouterOS IP Port | ||||||
|      |      | ||||||
|     username = user |     username = username     # RouterOS user, needs to have 'read' and 'api' permissions | ||||||
|     password = password |     password = password | ||||||
|      |      | ||||||
|     use_ssl = False |     use_ssl = False                 # enables connection via API-SSL servis | ||||||
|     ssl_certificate = False |     no_ssl_certificate = False      # enables API_SSL connect without router SSL certificate | ||||||
|  |     ssl_certificate_verify = False  # turns SSL certificate verification on / off | ||||||
|      |      | ||||||
|     dhcp = True |     dhcp = True | ||||||
|     dhcp_lease = True |     dhcp_lease = True | ||||||
| @@ -33,3 +34,5 @@ | |||||||
|     wireless_clients = True |     wireless_clients = True | ||||||
|     capsman = True |     capsman = True | ||||||
|     capsman_clients = True |     capsman_clients = True | ||||||
|  |  | ||||||
|  |      | ||||||
| @@ -72,8 +72,10 @@ class MKTXPDispatcher: | |||||||
|  |  | ||||||
|  |  | ||||||
|     def show_entries(self, args): |     def show_entries(self, args): | ||||||
|         if args['configpath']: |         if args['config']: | ||||||
|             print(f'MKTX config path: {config_handler.usr_conf_data_path}') |             print(f'MKTXP data config: {config_handler.usr_conf_data_path}') | ||||||
|  |             print(f'MKTXP internal config: {config_handler.mktxp_conf_path}') | ||||||
|  |  | ||||||
|         else: |         else: | ||||||
|             for entryname in config_handler.registered_entries(): |             for entryname in config_handler.registered_entries(): | ||||||
|                 if args['entry_name'] and entryname != args['entry_name']: |                 if args['entry_name'] and entryname != args['entry_name']: | ||||||
|   | |||||||
| @@ -101,8 +101,8 @@ class MKTXPOptionsParser: | |||||||
|                                         description = 'Displays MKTXP config router entries', |                                         description = 'Displays MKTXP config router entries', | ||||||
|                                         formatter_class=MKTXPHelpFormatter) |                                         formatter_class=MKTXPHelpFormatter) | ||||||
|         self._add_entry_name(show_parser, registered_only = True, required = False, help = "Config entry name") |         self._add_entry_name(show_parser, registered_only = True, required = False, help = "Config entry name") | ||||||
|         show_parser.add_argument('-cp', '--configpath', dest='configpath', |         show_parser.add_argument('-cfg', '--config', dest='config', | ||||||
|                                         help = "Shows MKTXP config file path", |                                         help = "Shows MKTXP config files paths", | ||||||
|                                         action = 'store_true') |                                         action = 'store_true') | ||||||
|  |  | ||||||
|         # Add command |         # Add command | ||||||
| @@ -137,7 +137,7 @@ class MKTXPOptionsParser: | |||||||
|         optional_args_group.add_argument('-ssl', '--use-ssl', dest='use_ssl', |         optional_args_group.add_argument('-ssl', '--use-ssl', dest='use_ssl', | ||||||
|                 help = "Connect via RouterOS api-ssl service", |                 help = "Connect via RouterOS api-ssl service", | ||||||
|                 action = 'store_true') |                 action = 'store_true') | ||||||
|         optional_args_group.add_argument('-ssl-cert', '--use-ssl-certificate', dest='ssl_certificate', |         optional_args_group.add_argument('-no-ssl-cert', '--no-ssl-certificate', dest='no_ssl_certificate', | ||||||
|                 help = "Connect with configured RouterOS SSL ceritficate", |                 help = "Connect with configured RouterOS SSL ceritficate", | ||||||
|                 action = 'store_true') |                 action = 'store_true') | ||||||
|  |  | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ class CapsmanCollector(BaseCollector): | |||||||
|         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 = router_metric.capsman_remote_caps_records(remote_caps_labels) | ||||||
|         if not remote_caps_records: |         if not remote_caps_records: | ||||||
|             return |             return range(0) | ||||||
|  |  | ||||||
|         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 | ||||||
| @@ -33,7 +33,7 @@ class CapsmanCollector(BaseCollector): | |||||||
|         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 = router_metric.capsman_registration_table_records(registration_labels) | ||||||
|         if not registration_records: |         if not registration_records: | ||||||
|             return |             return range(0) | ||||||
|  |  | ||||||
|         # calculate number of registrations per interface |         # calculate number of registrations per interface | ||||||
|         registration_per_interface = {} |         registration_per_interface = {} | ||||||
| @@ -53,40 +53,28 @@ class CapsmanCollector(BaseCollector): | |||||||
|             dhcp_lease_labels = ['mac_address', 'host_name', 'comment'] |             dhcp_lease_labels = ['mac_address', 'host_name', 'comment'] | ||||||
|             dhcp_lease_records = router_metric.dhcp_lease_records(dhcp_lease_labels) |             dhcp_lease_records = router_metric.dhcp_lease_records(dhcp_lease_labels) | ||||||
|             for registration_record in registration_records: |             for registration_record in registration_records: | ||||||
|  |                 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'])) | ||||||
|                 if dhcp_lease_record: |  | ||||||
|                     registration_record['name'] = dhcp_lease_record.get('comment', dhcp_lease_record.get('host_name', dhcp_lease_record.get('mac_address')))                    |                     registration_record['name'] = dhcp_lease_record.get('comment', dhcp_lease_record.get('host_name', dhcp_lease_record.get('mac_address')))                    | ||||||
|                 else: |                 except StopIteration: | ||||||
|                     registration_record['name'] = registration_record['mac_address']             |                     registration_record['name'] = f"{registration_record['mac_address']}: No DHCP registration"              | ||||||
|                  |                  | ||||||
|                 # split out tx/rx bytes |                 # split out tx/rx bytes | ||||||
|                 registration_record['tx_bytes'] = registration_record['bytes'].split(',')[0] |                 registration_record['tx_bytes'] = registration_record['bytes'].split(',')[0] | ||||||
|                 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'] | ||||||
|  |  | ||||||
|             tx_byte_metrics = BaseCollector.counter_collector('capsman_traffic_tx_bytes', 'Number of sent packet bytes', registration_records, 'tx_bytes', ['name']) |             tx_byte_metrics = BaseCollector.counter_collector('capsman_clients_tx_bytes', 'Number of sent packet bytes', registration_records, 'tx_bytes', ['name']) | ||||||
|             yield tx_byte_metrics |             yield tx_byte_metrics | ||||||
|  |  | ||||||
|             rx_byte_metrics = BaseCollector.counter_collector('capsman_traffic_rx_bytes', 'Number of received packet bytes', registration_records, 'rx_bytes', ['name']) |             rx_byte_metrics = BaseCollector.counter_collector('capsman_clients_rx_bytes', 'Number of received packet bytes', registration_records, 'rx_bytes', ['name']) | ||||||
|             yield rx_byte_metrics |             yield rx_byte_metrics | ||||||
|  |  | ||||||
|             signal_strength_metrics = BaseCollector.gauge_collector('capsman_registered_signal_strength', 'Registered devices signal strength', registration_records, 'rx_signal', ['name']) |             signal_strength_metrics = BaseCollector.gauge_collector('capsman_clients_signal_strength', 'Client devices signal strength', registration_records, 'rx_signal', ['name']) | ||||||
|             yield signal_strength_metrics |             yield signal_strength_metrics | ||||||
|  |  | ||||||
|             registration_metrics = BaseCollector.info_collector('capsman_registered_devices', 'Registered devices info',  |             registration_metrics = BaseCollector.info_collector('capsman_clients_devices', 'Registered client devices info',  | ||||||
|                                     registration_records, ['name', 'rx_signal', 'ssid', 'tx_rate', 'rx_rate', 'interface', 'mac_address', 'uptime']) |                                     registration_records, ['name', 'rx_signal', 'ssid', 'tx_rate', 'rx_rate', 'interface', 'mac_address', 'uptime']) | ||||||
|             yield registration_metrics |             yield registration_metrics | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ class DHCPCollector(BaseCollector): | |||||||
|         dhcp_lease_labels = ['active_address', 'mac_address', 'host_name', 'comment', 'server', 'expires_after'] |         dhcp_lease_labels = ['active_address', 'mac_address', 'host_name', 'comment', 'server', 'expires_after'] | ||||||
|         dhcp_lease_records = router_metric.dhcp_lease_records(dhcp_lease_labels) |         dhcp_lease_records = router_metric.dhcp_lease_records(dhcp_lease_labels) | ||||||
|         if not dhcp_lease_records: |         if not dhcp_lease_records: | ||||||
|             return |             return range(0) | ||||||
|  |  | ||||||
|         # calculate number of leases per DHCP server |         # calculate number of leases per DHCP server | ||||||
|         dhcp_lease_servers = {} |         dhcp_lease_servers = {} | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ class HealthCollector(BaseCollector): | |||||||
|         health_labels = ['voltage', 'temperature'] |         health_labels = ['voltage', 'temperature'] | ||||||
|         health_records = router_metric.health_records(health_labels) |         health_records = router_metric.health_records(health_labels) | ||||||
|         if not health_records: |         if not health_records: | ||||||
|             return |             return range(0) | ||||||
|  |  | ||||||
|         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 | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ class IdentityCollector(BaseCollector): | |||||||
|         identity_labels = ['name'] |         identity_labels = ['name'] | ||||||
|         identity_records = router_metric.identity_records(identity_labels) |         identity_records = router_metric.identity_records(identity_labels) | ||||||
|         if not identity_records: |         if not identity_records: | ||||||
|             return |             return range(0) | ||||||
|  |  | ||||||
|         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 | ||||||
|   | |||||||
| @@ -23,7 +23,11 @@ class InterfaceCollector(BaseCollector): | |||||||
|         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 = router_metric.interface_traffic_records(interface_traffic_labels) | ||||||
|         if not interface_traffic_records: |         if not interface_traffic_records: | ||||||
|             return |             return range(0) | ||||||
|  |  | ||||||
|  |         for interface_traffic_record in interface_traffic_records: | ||||||
|  |             if interface_traffic_record.get('comment'): | ||||||
|  |                 interface_traffic_record['name'] = 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']) | ||||||
|         yield rx_byte_metric |         yield rx_byte_metric | ||||||
|   | |||||||
| @@ -21,10 +21,10 @@ class MonitorCollector(BaseCollector): | |||||||
|     '''     |     '''     | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def collect(router_metric): |     def collect(router_metric): | ||||||
|         monitor_labels = ['status', 'rate', 'full_duplex', 'name'] |         monitor_labels = ('status', 'rate', 'full_duplex', 'name') | ||||||
|         monitor_records = router_metric.interface_monitor_records(monitor_labels) |         monitor_records = router_metric.interface_monitor_records(monitor_labels, include_comments = True) | ||||||
|         if not monitor_records: |         if not monitor_records: | ||||||
|             return |             return range(0) | ||||||
|  |  | ||||||
|         # translate records to appropriate values |         # translate records to appropriate values | ||||||
|         for monitor_record in monitor_records: |         for monitor_record in monitor_records: | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ class PoolCollector(BaseCollector): | |||||||
|         # 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 = router_metric.pool_records(['name']) | ||||||
|         if not pool_records: |         if not pool_records: | ||||||
|             return |             return range(0) | ||||||
|  |  | ||||||
|         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} | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ class SystemResourceCollector(BaseCollector): | |||||||
|                            'architecture_name', 'board_name'] |                            'architecture_name', 'board_name'] | ||||||
|         resource_records = router_metric.system_resource_records(resource_labels) |         resource_records = router_metric.system_resource_records(resource_labels) | ||||||
|         if not resource_records: |         if not resource_records: | ||||||
|             return |             return range(0) | ||||||
|  |  | ||||||
|         # translate records to appropriate values |         # translate records to appropriate values | ||||||
|         translated_fields = ['uptime']         |         translated_fields = ['uptime']         | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ class RouteCollector(BaseCollector): | |||||||
|         route_labels = ['connect', 'dynamic', 'static', 'bgp', 'ospf'] |         route_labels = ['connect', 'dynamic', 'static', 'bgp', 'ospf'] | ||||||
|         route_records = router_metric.route_records(route_labels) |         route_records = router_metric.route_records(route_labels) | ||||||
|         if not route_records: |         if not route_records: | ||||||
|             return |             return range(0) | ||||||
|          |          | ||||||
|         # compile total routes records |         # compile total routes records | ||||||
|         total_routes = len(route_records) |         total_routes = len(route_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 re | ||||||
| from mktxp.collectors.base_collector import BaseCollector | from mktxp.collectors.base_collector import BaseCollector | ||||||
| from mktxp.router_metric import RouterMetric | from mktxp.router_metric import RouterMetric | ||||||
|  |  | ||||||
| @@ -20,14 +21,15 @@ class WLANCollector(BaseCollector): | |||||||
|     '''     |     '''     | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def collect(router_metric): |     def collect(router_metric): | ||||||
|         monitor_labels = ['channel', 'noise_floor', 'overall_tx_ccq'] |         monitor_labels = ['channel', 'noise_floor', 'overall_tx_ccq', 'registered_clients'] | ||||||
|         monitor_records = router_metric.interface_monitor_records(monitor_labels, 'wireless') |         monitor_records = router_metric.interface_monitor_records(monitor_labels, 'wireless') | ||||||
|         if not monitor_records: |         if not monitor_records: | ||||||
|             return |             return range(0) | ||||||
|  |  | ||||||
|         # 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')] | ||||||
|         tx_ccq_records = [monitor_record for monitor_record in monitor_records if monitor_record.get('overall_tx_ccq')] |         tx_ccq_records = [monitor_record for monitor_record in monitor_records if monitor_record.get('overall_tx_ccq')] | ||||||
|  |         registered_clients_records  = [monitor_record for monitor_record in monitor_records if monitor_record.get('registered_clients')] | ||||||
|  |  | ||||||
|         if noise_floor_records: |         if noise_floor_records: | ||||||
|             noise_floor_metrics = BaseCollector.gauge_collector('wlan_noise_floor', 'Noise floor threshold', noise_floor_records, 'noise_floor', ['channel']) |             noise_floor_metrics = BaseCollector.gauge_collector('wlan_noise_floor', 'Noise floor threshold', noise_floor_records, 'noise_floor', ['channel']) | ||||||
| @@ -37,8 +39,58 @@ class WLANCollector(BaseCollector): | |||||||
|             overall_tx_ccq_metrics = BaseCollector.gauge_collector('wlan_overall_tx_ccq', 'Client Connection Quality for transmitting', tx_ccq_records, 'overall_tx_ccq', ['channel']) |             overall_tx_ccq_metrics = BaseCollector.gauge_collector('wlan_overall_tx_ccq', 'Client Connection Quality for transmitting', tx_ccq_records, 'overall_tx_ccq', ['channel']) | ||||||
|             yield overall_tx_ccq_metrics |             yield overall_tx_ccq_metrics | ||||||
|  |  | ||||||
|  |         if registered_clients_records: | ||||||
|  |             registered_clients_metrics = BaseCollector.gauge_collector('wlan_registered_clients', 'Number of registered clients', registered_clients_records, 'registered_clients', ['channel']) | ||||||
|  |             yield registered_clients_metrics | ||||||
|  |  | ||||||
|  |  | ||||||
|         # the client info metrics |         # the client info metrics | ||||||
|         if router_metric.router_entry.wireless_clients: |         if router_metric.router_entry.wireless_clients: | ||||||
|             # TBD |             registration_labels = ['interface', 'ssid', 'mac_address', 'tx_rate', 'rx_rate', 'uptime', 'bytes', 'signal_to_noise', 'tx_ccq', 'signal_strength'] | ||||||
|             pass |             registration_records = router_metric.wireless_registration_table_records(registration_labels) | ||||||
|  |             if not registration_records: | ||||||
|  |                 return range(0) | ||||||
|  |  | ||||||
|  |             dhcp_lease_labels = ['mac_address', 'host_name', 'comment'] | ||||||
|  |             dhcp_lease_records = router_metric.dhcp_lease_records(dhcp_lease_labels) | ||||||
|  |    | ||||||
|  |             for registration_record in registration_records: | ||||||
|  |                 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'])) | ||||||
|  |                     registration_record['name'] = dhcp_lease_record.get('comment', dhcp_lease_record.get('host_name', dhcp_lease_record.get('mac_address'))) | ||||||
|  |                 except StopIteration: | ||||||
|  |                     registration_record['name'] = registration_record['mac_address']             | ||||||
|  |  | ||||||
|  |                 # split out tx/rx bytes | ||||||
|  |                 registration_record['tx_bytes'] = registration_record['bytes'].split(',')[0] | ||||||
|  |                 registration_record['rx_bytes'] = registration_record['bytes'].split(',')[1] | ||||||
|  |  | ||||||
|  |                 # average signal strength | ||||||
|  |                 registration_record['signal_strength'] = re.search(r'-\d+', registration_record['signal_strength']).group() | ||||||
|  |  | ||||||
|  |                 del registration_record['bytes'] | ||||||
|  |  | ||||||
|  |             tx_byte_metrics = BaseCollector.counter_collector('wlan_clients_tx_bytes', 'Number of sent packet bytes', registration_records, 'tx_bytes', ['name']) | ||||||
|  |             yield tx_byte_metrics | ||||||
|  |  | ||||||
|  |             rx_byte_metrics = BaseCollector.counter_collector('wlan_clients_rx_bytes', 'Number of received packet bytes', registration_records, 'rx_bytes', ['name']) | ||||||
|  |             yield rx_byte_metrics | ||||||
|  |  | ||||||
|  |             signal_strength_metrics = BaseCollector.gauge_collector('wlan_clients_signal_strength', 'Average strength of the client signal recevied by AP', registration_records, 'signal_strength', ['name']) | ||||||
|  |             yield signal_strength_metrics | ||||||
|  |  | ||||||
|  |             signal_to_noise_metrics = BaseCollector.gauge_collector('wlan_clients_signal_to_noise', 'Client devices signal to noise ratio', registration_records, 'signal_to_noise', ['name']) | ||||||
|  |             yield signal_to_noise_metrics | ||||||
|  |  | ||||||
|  |             tx_ccq_metrics = BaseCollector.gauge_collector('wlan_clients_tx_ccq', 'Client Connection Quality (CCQ) for transmit', registration_records, 'tx_ccq', ['name']) | ||||||
|  |             yield tx_ccq_metrics | ||||||
|  |  | ||||||
|  |             registration_metrics = BaseCollector.info_collector('wlan_clients_devices', 'Client devices info',  | ||||||
|  |                                     registration_records, ['name', 'rx_signal', 'ssid', 'tx_rate', 'rx_rate', 'interface', 'mac_address', 'uptime']) | ||||||
|  |             yield registration_metrics | ||||||
|  |  | ||||||
|  |  | ||||||
|  |             return range(0) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -30,6 +30,11 @@ class CollectorsHandler: | |||||||
|  |  | ||||||
|     def collect(self): |     def collect(self): | ||||||
|         for router_metric in self.metrics_handler.router_metrics: |         for router_metric in self.metrics_handler.router_metrics: | ||||||
|  |             if not router_metric.api_connection.is_connected(): | ||||||
|  |                 # let's pick up on things in the next run | ||||||
|  |                 router_metric.api_connection.connect() | ||||||
|  |                 continue | ||||||
|  |  | ||||||
|             yield from IdentityCollector.collect(router_metric) |             yield from IdentityCollector.collect(router_metric) | ||||||
|             yield from SystemResourceCollector.collect(router_metric) |             yield from SystemResourceCollector.collect(router_metric) | ||||||
|             yield from HealthCollector.collect(router_metric) |             yield from HealthCollector.collect(router_metric) | ||||||
| @@ -55,3 +60,4 @@ class CollectorsHandler: | |||||||
|             if router_metric.router_entry.capsman: |             if router_metric.router_entry.capsman: | ||||||
|                 yield from CapsmanCollector.collect(router_metric) |                 yield from CapsmanCollector.collect(router_metric) | ||||||
|  |  | ||||||
|  |         return range(0) | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ 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 | ||||||
|  |  | ||||||
| class RouterAPIConnectionError(Exception): | class RouterAPIConnectionError(Exception): | ||||||
|     pass |     pass | ||||||
| @@ -27,9 +27,10 @@ class RouterAPIConnection: | |||||||
|     def __init__(self, router_name, router_entry): |     def __init__(self, router_name, router_entry): | ||||||
|         self.router_name = router_name |         self.router_name = router_name | ||||||
|         self.router_entry = router_entry |         self.router_entry = router_entry | ||||||
|  |         self.last_failure_timestamp = self.successive_failure_count = 0 | ||||||
|          |          | ||||||
|         ctx = None |         ctx = None | ||||||
|         if self.router_entry.use_ssl and not self.router_entry.ssl_certificate: |         if self.router_entry.use_ssl and self.router_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')        | ||||||
|  |  | ||||||
| @@ -40,9 +41,10 @@ class RouterAPIConnection: | |||||||
|                 port = self.router_entry.port, |                 port = self.router_entry.port, | ||||||
|                 plaintext_login = True, |                 plaintext_login = True, | ||||||
|                 use_ssl = self.router_entry.use_ssl, |                 use_ssl = self.router_entry.use_ssl, | ||||||
|  |                 ssl_verify = self.router_entry.ssl_certificate_verify, | ||||||
|                 ssl_context = ctx) |                 ssl_context = ctx) | ||||||
|          |          | ||||||
|         self.connection.socket_timeout = 2 |         self.connection.socket_timeout = config_handler._entry().socket_timeout | ||||||
|         self.api = None |         self.api = None | ||||||
|  |  | ||||||
|     def is_connected(self): |     def is_connected(self): | ||||||
| @@ -51,24 +53,63 @@ class RouterAPIConnection: | |||||||
|         try: |         try: | ||||||
|             self.api.get_resource('/system/identity').get() |             self.api.get_resource('/system/identity').get() | ||||||
|             return True |             return True | ||||||
|         except (socket.error, socket.timeout, Exception) as ex: |         except (socket.error, socket.timeout, Exception) as exc: | ||||||
|             print(f'Connection to router {self.router_name}@{self.router_entry.hostname} has been lost: {ex}') |             self._set_connect_state(success = False, exc = exc) | ||||||
|             self.api = None |  | ||||||
|             return False |             return False | ||||||
|  |  | ||||||
|     def connect(self): |     def connect(self): | ||||||
|         if self.is_connected(): |         connect_time = datetime.now() | ||||||
|  |         if self.is_connected() or self._in_connect_timeout(connect_time.timestamp()): | ||||||
|             return |             return | ||||||
|         current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") |  | ||||||
|         try: |         try: | ||||||
|             print(f'Connecting to router {self.router_name}@{self.router_entry.hostname}') |             print(f'Connecting to router {self.router_name}@{self.router_entry.hostname}') | ||||||
|             self.api = self.connection.get_api() |             self.api = self.connection.get_api() | ||||||
|             print(f'{current_time} Connection to router {self.router_name}@{self.router_entry.hostname} has been established') |             self._set_connect_state(success = True, connect_time = connect_time) | ||||||
|         except (socket.error, socket.timeout, Exception) as ex: |         except (socket.error, socket.timeout, Exception) as exc: | ||||||
|             print(f'{current_time} Connection to router {self.router_name}@{self.router_entry.hostname} has failed: {ex}') |             self._set_connect_state(success = False, connect_time = connect_time, exc = exc) | ||||||
|             raise  |             #raise RouterAPIConnectionError | ||||||
|  |  | ||||||
|     def router_api(self): |     def router_api(self): | ||||||
|         if not self.is_connected(): |         if not self.is_connected(): | ||||||
|             self.connect() |             self.connect() | ||||||
|         return self.api |         return self.api | ||||||
|  |  | ||||||
|  |     def _in_connect_timeout(self, connect_timestamp, quiet = True): | ||||||
|  |         connect_delay = self._connect_delay() | ||||||
|  |         if (connect_timestamp - self.last_failure_timestamp) < connect_delay: | ||||||
|  |             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'Successive failure count: {self.successive_failure_count}') | ||||||
|  |             return True | ||||||
|  |         if not quiet:  | ||||||
|  |             print(f'{self.router_name}@{self.router_entry.hostname}: OK to connect') | ||||||
|  |             if self.last_failure_timestamp > 0: | ||||||
|  |                 print(f'Seconds since last failure: {connect_timestamp - self.last_failure_timestamp}') | ||||||
|  |                 print(f'Prior successive failure count: {self.successive_failure_count}') | ||||||
|  |         return False | ||||||
|  |  | ||||||
|  |     def _connect_delay(self): | ||||||
|  |         mktxp_entry = config_handler._entry() | ||||||
|  |         connect_delay = (1 + self.successive_failure_count / mktxp_entry.delay_inc_div) * mktxp_entry.initial_delay_on_failure | ||||||
|  |         return connect_delay if connect_delay < mktxp_entry.max_delay_on_failure else mktxp_entry.max_delay_on_failure | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def _set_connect_state(self, success = False, connect_time = datetime.now(), exc = None): | ||||||
|  |         if success: | ||||||
|  |             self.last_failure_timestamp = 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') | ||||||
|  |         else: | ||||||
|  |             self.api = None | ||||||
|  |             self.successive_failure_count += 1 | ||||||
|  |             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}') | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -76,13 +76,20 @@ class RouterMetric: | |||||||
|             print(f'Error getting interface traffic info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |             print(f'Error getting interface traffic info from router{self.router_name}@{self.router_entry.hostname}: {exc}') | ||||||
|             return None |             return None | ||||||
|  |  | ||||||
|     def interface_monitor_records(self, interface_monitor_labels = [], kind = 'ethernet'): |     def interface_monitor_records(self, interface_monitor_labels = [], kind = 'ethernet', include_comments = False): | ||||||
|         try: |         try: | ||||||
|             interfaces = self.api_connection.router_api().get_resource(f'/interface/{kind}').get() |             interfaces = self.api_connection.router_api().get_resource(f'/interface/{kind}').get() | ||||||
|             interface_names = [interface['name'] for interface in interfaces] |             interface_names = [(interface['name'], interface.get('comment')) 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 = 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))] |             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'] = f"{interface_monitor_record['name']} ({interface_name[1]})" | ||||||
|             return self._trimmed_records(interface_monitor_records, interface_monitor_labels) |             return self._trimmed_records(interface_monitor_records, interface_monitor_labels) | ||||||
|         except Exception as exc: |         except Exception as exc: | ||||||
|             print(f'Error getting {kind} interface monitor info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |             print(f'Error getting {kind} interface monitor info from router{self.router_name}@{self.router_entry.hostname}: {exc}') | ||||||
| @@ -109,7 +116,7 @@ class RouterMetric: | |||||||
|             route_records = self.api_connection.router_api().get_resource('/ip/route').get(active='yes') |             route_records = self.api_connection.router_api().get_resource('/ip/route').get(active='yes') | ||||||
|             return self._trimmed_records(route_records, route_labels) |             return self._trimmed_records(route_records, route_labels) | ||||||
|         except Exception as exc: |         except Exception as exc: | ||||||
|             print(f'Error getting pool active routes info from router{self.router_name}@{self.router_entry.hostname}: {exc}') |             print(f'Error getting routes info from router{self.router_name}@{self.router_entry.hostname}: {exc}') | ||||||
|             return None |             return None | ||||||
|              |              | ||||||
|     def wireless_registration_table_records(self, registration_table_labels = []): |     def wireless_registration_table_records(self, registration_table_labels = []): | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user