waitress, IPv4/IPv6 listen list

This commit is contained in:
Arseniy Kuznetsov
2024-03-10 14:28:48 +01:00
parent f70719d46f
commit 412b6f3511
6 changed files with 36 additions and 29 deletions

View File

@@ -213,7 +213,7 @@ mktxp edit -i
``` ```
[MKTXP] [MKTXP]
port = 49090 listen = '0.0.0.0:49090' # Space separated list of socket addresses to listen to, both IPV4 and IPV6
socket_timeout = 2 socket_timeout = 2
initial_delay_on_failure = 120 initial_delay_on_failure = 120
@@ -275,7 +275,7 @@ optional arguments:
While most of the [mktxp options](https://github.com/akpw/mktxp#getting-started) are self explanatory, some might require a bit of a context. While most of the [mktxp options](https://github.com/akpw/mktxp#getting-started) are self explanatory, some might require a bit of a context.
### Remote DHCP resolution ### Remote DHCP resolution
When gathering various IP address-related metrics, MKTXP automatically resolves IP addresses whenever DHCP info is available. In many cases however, the exported devices do not have this information locally and instead rely on central DHCP servers. To improve readibility / usefulness of the exported metrics, MKTXP supports remote DHCP server calls via the following option: When gathering various IP address-related metrics, MKTXP automatically resolves IP addresses whenever DHCP info is available. In many cases however, the exported devices do not have this information locally and instead rely on central DHCP servers. To improve readability / usefulness of the exported metrics, MKTXP supports remote DHCP server calls via the following option:
``` ```
remote_dhcp_entry = None # An MKTXP entry for remote DHCP info resolution in capsman/wireless remote_dhcp_entry = None # An MKTXP entry for remote DHCP info resolution in capsman/wireless
``` ```
@@ -323,11 +323,13 @@ total_max_scrape_duration = 30 # Max overall duration of all metrics collec
To keeps things within expected boundaries, the last two parameters allows for controlling both individual and overall scrape durations To keeps things within expected boundaries, the last two parameters allows for controlling both individual and overall scrape durations
### mktxp port ### mktxp listening socket addresses
By default, mktxp runs it's HTTP metrics endpoint on port 49090. You can change it via the following [system option](https://github.com/akpw/mktxp/blob/main/README.md#mktxp-system-configuration): By default, mktxp runs it's HTTP metrics endpoint on any IPv4 address on port 49090. However, it is also able to listen on multiple socket addresses, both IPv4 and IPv6.
You can configure this behaviour via the following [system option](https://github.com/akpw/mktxp/blob/main/README.md#mktxp-system-configuration), setting ```listen``` to a space-separated list of sockets to listen to, e.g.:
``` ```
port = 49090 listen = '0.0.0.0:49090 [::1]:49090'
``` ```
A wildcard for the hostname is supported as well, and binding to both IPv4/IPv6 as available.
## Setting up MKTXP to run as a Linux Service ## Setting up MKTXP to run as a Linux Service
If you've installed MKTXP on a Linux system, you can run it with system boot via adding a service. \ If you've installed MKTXP on a Linux system, you can run it with system boot via adding a service. \

View File

@@ -24,20 +24,20 @@ def check_version():
print(\ print(\
''' '''
Mikrotik Prometheus Exporter requires Mikrotik Prometheus Exporter requires
Python version 3.6 or later. Python version 3.8 or later.
You can create an isolated Python 3.6 environment You can create an isolated Python 3.8 environment
with the virtualenv tool: with the virtualenv tool:
http://docs.python-guide.org/en/latest/dev/virtualenvs http://docs.python-guide.org/en/latest/dev/virtualenvs
''') ''')
sys.exit(0) sys.exit(0)
elif sys.version_info.major == 3 and sys.version_info.minor < 6: elif sys.version_info.major == 3 and sys.version_info.minor < 8:
print(\ print(\
''' '''
Mikrotik Prometheus Exporter requires Mikrotik Prometheus Exporter requires
Python version 3.6 or later. Python version 3.8 or later.
Please upgrade to the latest Python 3.x version. Please upgrade to the latest Python 3.x version.

View File

@@ -12,7 +12,7 @@
[MKTXP] [MKTXP]
port = 49090 listen = '0.0.0.0:49090' # Space separated list of socket addresses to listen to, both IPV4 and IPV6
socket_timeout = 2 socket_timeout = 2
initial_delay_on_failure = 120 initial_delay_on_failure = 120
@@ -20,7 +20,7 @@
delay_inc_div = 5 delay_inc_div = 5
bandwidth = False # Turns metrics bandwidth metrics collection on / off bandwidth = False # Turns metrics bandwidth metrics collection on / off
bandwidth_test_interval = 600 # Interval for colllecting bandwidth metrics bandwidth_test_interval = 600 # Interval for collecting bandwidth metrics
minimal_collect_interval = 5 # Minimal metric collection interval minimal_collect_interval = 5 # Minimal metric collection interval
verbose_mode = False # Set it on for troubleshooting verbose_mode = False # Set it on for troubleshooting

View File

@@ -57,6 +57,7 @@ class MKTXPConfigKeys:
ENABLED_KEY = 'enabled' ENABLED_KEY = 'enabled'
HOST_KEY = 'hostname' HOST_KEY = 'hostname'
PORT_KEY = 'port' PORT_KEY = 'port'
LISTEN_KEY = 'listen'
USER_KEY = 'username' USER_KEY = 'username'
PASSWD_KEY = 'password' PASSWD_KEY = 'password'
@@ -153,7 +154,7 @@ class MKTXPConfigKeys:
MKTXP_INC_DIV, MKTXP_BANDWIDTH_TEST_INTERVAL, MKTXP_MIN_COLLECT_INTERVAL, MKTXP_INC_DIV, MKTXP_BANDWIDTH_TEST_INTERVAL, MKTXP_MIN_COLLECT_INTERVAL,
MKTXP_MAX_WORKER_THREADS, MKTXP_MAX_SCRAPE_DURATION, MKTXP_TOTAL_MAX_SCRAPE_DURATION) MKTXP_MAX_WORKER_THREADS, MKTXP_MAX_SCRAPE_DURATION, MKTXP_TOTAL_MAX_SCRAPE_DURATION)
# MKTXP config entry nane # MKTXP config entry name
MKTXP_CONFIG_ENTRY_NAME = 'MKTXP' MKTXP_CONFIG_ENTRY_NAME = 'MKTXP'
@@ -167,7 +168,7 @@ class ConfigEntry:
MKTXPConfigKeys.MKTXP_USE_COMMENTS_OVER_NAMES, MKTXPConfigKeys.FE_PUBLIC_IP_KEY, MKTXPConfigKeys.FE_IPV6_FIREWALL_KEY, MKTXPConfigKeys.FE_IPV6_NEIGHBOR_KEY, MKTXPConfigKeys.MKTXP_USE_COMMENTS_OVER_NAMES, MKTXPConfigKeys.FE_PUBLIC_IP_KEY, MKTXPConfigKeys.FE_IPV6_FIREWALL_KEY, MKTXPConfigKeys.FE_IPV6_NEIGHBOR_KEY,
MKTXPConfigKeys.FE_USER_KEY, MKTXPConfigKeys.FE_QUEUE_KEY, MKTXPConfigKeys.FE_REMOTE_DHCP_ENTRY, MKTXPConfigKeys.FE_CHECK_FOR_UPDATES, MKTXPConfigKeys.FE_KID_CONTROL_DEVICE, MKTXPConfigKeys.FE_BGP_KEY, MKTXPConfigKeys.FE_USER_KEY, MKTXPConfigKeys.FE_QUEUE_KEY, MKTXPConfigKeys.FE_REMOTE_DHCP_ENTRY, MKTXPConfigKeys.FE_CHECK_FOR_UPDATES, MKTXPConfigKeys.FE_KID_CONTROL_DEVICE, MKTXPConfigKeys.FE_BGP_KEY,
]) ])
MKTXPSystemEntry = namedtuple('MKTXPSystemEntry', [MKTXPConfigKeys.PORT_KEY, MKTXPConfigKeys.MKTXP_SOCKET_TIMEOUT, MKTXPSystemEntry = namedtuple('MKTXPSystemEntry', [MKTXPConfigKeys.PORT_KEY, MKTXPConfigKeys.LISTEN_KEY, MKTXPConfigKeys.MKTXP_SOCKET_TIMEOUT,
MKTXPConfigKeys.MKTXP_INITIAL_DELAY, MKTXPConfigKeys.MKTXP_MAX_DELAY, MKTXPConfigKeys.MKTXP_INITIAL_DELAY, MKTXPConfigKeys.MKTXP_MAX_DELAY,
MKTXPConfigKeys.MKTXP_INC_DIV, MKTXPConfigKeys.MKTXP_BANDWIDTH_KEY, MKTXPConfigKeys.MKTXP_INC_DIV, MKTXPConfigKeys.MKTXP_BANDWIDTH_KEY,
MKTXPConfigKeys.MKTXP_VERBOSE_MODE, MKTXPConfigKeys.MKTXP_BANDWIDTH_TEST_INTERVAL, MKTXPConfigKeys.MKTXP_VERBOSE_MODE, MKTXPConfigKeys.MKTXP_BANDWIDTH_TEST_INTERVAL,
@@ -291,10 +292,10 @@ class MKTXPConfigHandler:
def _read_from_disk(self): def _read_from_disk(self):
''' (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, indent_type = ' ')
self.config.preserve_comments = True self.config.preserve_comments = True
self._config = ConfigObj(self.mktxp_conf_path) self._config = ConfigObj(self.mktxp_conf_path, indent_type = ' ')
self._config.preserve_comments = True self._config.preserve_comments = True
def _create_os_path(self, os_path, resource_path): def _create_os_path(self, os_path, resource_path):
@@ -363,7 +364,8 @@ class MKTXPConfigHandler:
system_entry_reader[key] = self._config[entry_name].as_int(key) system_entry_reader[key] = self._config[entry_name].as_int(key)
else: else:
system_entry_reader[key] = self._default_value_for_key(key) system_entry_reader[key] = self._default_value_for_key(key)
new_keys.append(key) # read from disk next time if key not in (MKTXPConfigKeys.PORT_KEY): # Port key has been depricated
new_keys.append(key) # read from disk next time
for key in MKTXPConfigKeys.SYSTEM_BOOLEAN_KEYS_NO.union(MKTXPConfigKeys.SYSTEM_BOOLEAN_KEYS_YES): for key in MKTXPConfigKeys.SYSTEM_BOOLEAN_KEYS_NO.union(MKTXPConfigKeys.SYSTEM_BOOLEAN_KEYS_YES):
if self._config[entry_name].get(key) is not None: if self._config[entry_name].get(key) is not None:
@@ -372,9 +374,17 @@ class MKTXPConfigHandler:
system_entry_reader[key] = True if key in MKTXPConfigKeys.SYSTEM_BOOLEAN_KEYS_YES else False system_entry_reader[key] = True if key in MKTXPConfigKeys.SYSTEM_BOOLEAN_KEYS_YES else False
new_keys.append(key) # read from disk next time new_keys.append(key) # read from disk next time
# listen
if self._config[entry_name].get(MKTXPConfigKeys.LISTEN_KEY):
system_entry_reader[MKTXPConfigKeys.LISTEN_KEY] = self._config[entry_name].get(MKTXPConfigKeys.LISTEN_KEY)
else:
system_entry_reader[MKTXPConfigKeys.LISTEN_KEY] = f'0.0.0.0:{system_entry_reader[MKTXPConfigKeys.PORT_KEY]}'
new_keys.append(MKTXPConfigKeys.LISTEN_KEY) # read from disk next time
if new_keys: if new_keys:
self._config[entry_name] = system_entry_reader self._config[entry_name] = system_entry_reader
try: try:
self._config[entry_name].pop(MKTXPConfigKeys.PORT_KEY, None) # Port key has been depricated
self._config.write() self._config.write()
if self._config[entry_name].as_bool(MKTXPConfigKeys.MKTXP_VERBOSE_MODE): if self._config[entry_name].as_bool(MKTXPConfigKeys.MKTXP_VERBOSE_MODE):
print(f'Updated system entry {entry_name} with new system keys {new_keys}') print(f'Updated system entry {entry_name} with new system keys {new_keys}')

View File

@@ -12,10 +12,9 @@
## GNU General Public License for more details. ## GNU General Public License for more details.
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 from prometheus_client import make_wsgi_app
from mktxp.cli.config.config import config_handler from mktxp.cli.config.config import config_handler
from mktxp.flow.collector_handler import CollectorHandler from mktxp.flow.collector_handler import CollectorHandler
@@ -27,6 +26,8 @@ from mktxp.cli.output.wifi_out import WirelessOutput
from mktxp.cli.output.dhcp_out import DHCPOutput from mktxp.cli.output.dhcp_out import DHCPOutput
from mktxp.cli.output.conn_stats_out import ConnectionsStatsOutput from mktxp.cli.output.conn_stats_out import ConnectionsStatsOutput
from waitress import serve
class ExportProcessor: class ExportProcessor:
''' Base Export Processing ''' Base Export Processing
@@ -34,16 +35,9 @@ class ExportProcessor:
@staticmethod @staticmethod
def start(): def start():
REGISTRY.register(CollectorHandler(RouterEntriesHandler(), CollectorRegistry())) REGISTRY.register(CollectorHandler(RouterEntriesHandler(), CollectorRegistry()))
ExportProcessor.run(port=config_handler.system_entry().port)
@staticmethod
def run(server_class=HTTPServer, handler_class=MetricsHandler, port=None):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f'{current_time} Running HTTP metrics server on port {port}') print(f'{current_time} Running HTTP metrics server on: {config_handler.system_entry().listen}')
httpd.serve_forever() serve(make_wsgi_app(), listen = config_handler.system_entry().listen)
class OutputProcessor: class OutputProcessor:
''' Base CLI Processing ''' Base CLI Processing

View File

@@ -48,7 +48,8 @@ setup(
'configobj>=5.0.6', 'configobj>=5.0.6',
'humanize>=3.2.0', 'humanize>=3.2.0',
'texttable>=1.6.3', 'texttable>=1.6.3',
'speedtest-cli>=2.1.2' 'speedtest-cli>=2.1.2',
'waitress>=3.0.0',
], ],
test_suite = 'tests.mktxp_test_suite', test_suite = 'tests.mktxp_test_suite',
@@ -63,7 +64,7 @@ setup(
'Development Status :: 4 - Beta', 'Development Status :: 4 - Beta',
'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: 3 :: Only',
'Intended Audience :: Developers', 'Intended Audience :: Developers',
'Intended Audience :: System Administrators', 'Intended Audience :: System Administrators',