summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/prometheus/blackbox_exporter.service.j221
-rw-r--r--data/templates/prometheus/blackbox_exporter.yml.j223
-rw-r--r--debian/control3
-rw-r--r--interface-definitions/include/monitoring/blackbox-exporter-module-commons.xml.i39
-rw-r--r--interface-definitions/service_monitoring_prometheus.xml.in76
-rwxr-xr-xsmoketest/scripts/cli/test_service_monitoring_prometheus.py74
-rwxr-xr-xsrc/conf_mode/service_monitoring_prometheus.py54
7 files changed, 290 insertions, 0 deletions
diff --git a/data/templates/prometheus/blackbox_exporter.service.j2 b/data/templates/prometheus/blackbox_exporter.service.j2
new file mode 100644
index 000000000..e93030246
--- /dev/null
+++ b/data/templates/prometheus/blackbox_exporter.service.j2
@@ -0,0 +1,21 @@
+{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' runuser -u node_exporter -- ' if vrf is vyos_defined else '' %}
+[Unit]
+Description=Blackbox Exporter
+Documentation=https://github.com/prometheus/blackbox_exporter
+After=network.target
+
+[Service]
+{% if vrf is not vyos_defined %}
+User=node_exporter
+{% endif %}
+ExecStart={{ vrf_command }}/usr/sbin/blackbox_exporter \
+{% if listen_address is vyos_defined %}
+{% for address in listen_address %}
+ --web.listen-address={{ address }}:{{ port }} \
+{% endfor %}
+{% else %}
+ --web.listen-address=:{{ port }} \
+{% endif %}
+ --config.file=/run/blackbox_exporter/config.yml
+[Install]
+WantedBy=multi-user.target
diff --git a/data/templates/prometheus/blackbox_exporter.yml.j2 b/data/templates/prometheus/blackbox_exporter.yml.j2
new file mode 100644
index 000000000..ba2eecd77
--- /dev/null
+++ b/data/templates/prometheus/blackbox_exporter.yml.j2
@@ -0,0 +1,23 @@
+modules:
+{% if modules is defined and modules.dns is defined and modules.dns.name is defined %}
+{% for module_name, module_config in modules.dns.name.items() %}
+ {{ module_name }}:
+ prober: dns
+ timeout: {{ module_config.timeout }}s
+ dns:
+ query_name: "{{ module_config.query_name }}"
+ query_type: "{{ module_config.query_type }}"
+ preferred_ip_protocol: "{{ module_config.preferred_ip_protocol | replace('v', '') }}"
+ ip_protocol_fallback: {{ 'true' if module_config.ip_protocol_fallback is vyos_defined else 'false' }}
+{% endfor %}
+{% endif %}
+{% if modules is defined and modules.icmp is vyos_defined and modules.icmp.name is vyos_defined %}
+{% for module_name, module_config in modules.icmp.name.items() %}
+ {{ module_name }}:
+ prober: icmp
+ timeout: {{ module_config.timeout }}s
+ icmp:
+ preferred_ip_protocol: "{{ module_config.preferred_ip_protocol | replace('v', '') }}"
+ ip_protocol_fallback: {{ 'true' if module_config.ip_protocol_fallback is vyos_defined else 'false' }}
+{% endfor %}
+{% endif %} \ No newline at end of file
diff --git a/debian/control b/debian/control
index 08b86356a..b1cb5c4ef 100644
--- a/debian/control
+++ b/debian/control
@@ -241,6 +241,9 @@ Depends:
# For "service monitoring prometheus frr-exporter"
frr-exporter,
# End "service monitoring prometheus frr-exporter"
+# For "service monitoring prometheus blackbox-exporter"
+ blackbox-exporter,
+# End "service monitoring prometheus blackbox-exporter"
# For "service monitoring telegraf"
telegraf (>= 1.20),
# End "service monitoring telegraf"
diff --git a/interface-definitions/include/monitoring/blackbox-exporter-module-commons.xml.i b/interface-definitions/include/monitoring/blackbox-exporter-module-commons.xml.i
new file mode 100644
index 000000000..a97eb5232
--- /dev/null
+++ b/interface-definitions/include/monitoring/blackbox-exporter-module-commons.xml.i
@@ -0,0 +1,39 @@
+<!-- include start from monitoring/blackbox-module-commons.xml.i -->
+<leafNode name="timeout">
+ <properties>
+ <help>Timeout in seconds for the probe request</help>
+ <valueHelp>
+ <format>u32:1-60</format>
+ <description>Timeout in seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-60"/>
+ </constraint>
+ <constraintErrorMessage>Timeout must be between 1 and 60 seconds</constraintErrorMessage>
+ </properties>
+ <defaultValue>5</defaultValue>
+</leafNode>
+<leafNode name="preferred-ip-protocol">
+ <properties>
+ <help>Preferred IP protocol for this module</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>Prefer IPv4</description>
+ </valueHelp>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>Prefer IPv6</description>
+ </valueHelp>
+ <constraint>
+ <regex>(ipv4|ipv6)</regex>
+ </constraint>
+ </properties>
+ <defaultValue>ip6</defaultValue>
+</leafNode>
+<leafNode name="ip-protocol-fallback">
+ <properties>
+ <help>Allow fallback to other IP protocol if necessary</help>
+ <valueless/>
+ </properties>
+</leafNode>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/service_monitoring_prometheus.xml.in b/interface-definitions/service_monitoring_prometheus.xml.in
index 24f31e15c..740900f1f 100644
--- a/interface-definitions/service_monitoring_prometheus.xml.in
+++ b/interface-definitions/service_monitoring_prometheus.xml.in
@@ -36,6 +36,82 @@
#include <include/interface/vrf.xml.i>
</children>
</node>
+ <node name="blackbox-exporter">
+ <properties>
+ <help>Prometheus exporter for probing endpoints</help>
+ </properties>
+ <children>
+ #include <include/listen-address.xml.i>
+ #include <include/port-number.xml.i>
+ <leafNode name="port">
+ <defaultValue>9115</defaultValue>
+ </leafNode>
+ #include <include/interface/vrf.xml.i>
+ <node name="modules">
+ <properties>
+ <help>Configure blackbox exporter modules</help>
+ </properties>
+ <children>
+ <node name="dns">
+ <properties>
+ <help>Configure dns module</help>
+ </properties>
+ <children>
+ <tagNode name="name">
+ <properties>
+ <help>Name of the dns module</help>
+ </properties>
+ <children>
+ <leafNode name="query-name">
+ <properties>
+ <help>Name to be queried</help>
+ <constraint>
+ <validator name="fqdn"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="query-type">
+ <properties>
+ <help>DNS query type</help>
+ <valueHelp>
+ <format>ANY</format>
+ <description>Query any DNS record</description>
+ </valueHelp>
+ <valueHelp>
+ <format>A</format>
+ <description>Query IPv4 address record</description>
+ </valueHelp>
+ <valueHelp>
+ <format>AAAA</format>
+ <description>Query IPv6 address record</description>
+ </valueHelp>
+ </properties>
+ <defaultValue>ANY</defaultValue>
+ </leafNode>
+ #include <include/monitoring/blackbox-exporter-module-commons.xml.i>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ <node name="icmp">
+ <properties>
+ <help>Configure icmp module</help>
+ </properties>
+ <children>
+ <tagNode name="name">
+ <properties>
+ <help>Name of the icmp module</help>
+ </properties>
+ <children>
+ #include <include/monitoring/blackbox-exporter-module-commons.xml.i>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
</children>
</node>
</children>
diff --git a/smoketest/scripts/cli/test_service_monitoring_prometheus.py b/smoketest/scripts/cli/test_service_monitoring_prometheus.py
index dae103e4b..df737f840 100755
--- a/smoketest/scripts/cli/test_service_monitoring_prometheus.py
+++ b/smoketest/scripts/cli/test_service_monitoring_prometheus.py
@@ -22,12 +22,14 @@ from vyos.utils.file import read_file
NODE_EXPORTER_PROCESS_NAME = 'node_exporter'
FRR_EXPORTER_PROCESS_NAME = 'frr_exporter'
+BLACKBOX_EXPORTER_PROCESS_NAME = 'blackbox_exporter'
base_path = ['service', 'monitoring', 'prometheus']
listen_if = 'dum3421'
listen_ip = '192.0.2.1'
node_exporter_service_file = '/etc/systemd/system/node_exporter.service'
frr_exporter_service_file = '/etc/systemd/system/frr_exporter.service'
+blackbox_exporter_service_file = '/etc/systemd/system/blackbox_exporter.service'
class TestMonitoringPrometheus(VyOSUnitTestSHIM.TestCase):
@@ -75,6 +77,78 @@ class TestMonitoringPrometheus(VyOSUnitTestSHIM.TestCase):
# Check for running process
self.assertTrue(process_named_running(FRR_EXPORTER_PROCESS_NAME))
+ def test_03_blackbox_exporter(self):
+ self.cli_set(base_path + ['blackbox-exporter', 'listen-address', listen_ip])
+
+ # commit changes
+ self.cli_commit()
+
+ file_content = read_file(blackbox_exporter_service_file)
+ self.assertIn(f'{listen_ip}:9115', file_content)
+
+ # Check for running process
+ self.assertTrue(process_named_running(BLACKBOX_EXPORTER_PROCESS_NAME))
+
+ def test_04_blackbox_exporter_with_config(self):
+ self.cli_set(base_path + ['blackbox-exporter', 'listen-address', listen_ip])
+ self.cli_set(
+ base_path
+ + [
+ 'blackbox-exporter',
+ 'modules',
+ 'dns',
+ 'name',
+ 'dns_ip4',
+ 'preferred-ip-protocol',
+ 'ipv4',
+ ]
+ )
+ self.cli_set(
+ base_path
+ + [
+ 'blackbox-exporter',
+ 'modules',
+ 'dns',
+ 'name',
+ 'dns_ip4',
+ 'query-name',
+ 'vyos.io',
+ ]
+ )
+ self.cli_set(
+ base_path
+ + [
+ 'blackbox-exporter',
+ 'modules',
+ 'dns',
+ 'name',
+ 'dns_ip4',
+ 'query-type',
+ 'A',
+ ]
+ )
+ self.cli_set(
+ base_path
+ + [
+ 'blackbox-exporter',
+ 'modules',
+ 'icmp',
+ 'name',
+ 'icmp_ip6',
+ 'preferred-ip-protocol',
+ 'ipv6',
+ ]
+ )
+
+ # commit changes
+ self.cli_commit()
+
+ file_content = read_file(blackbox_exporter_service_file)
+ self.assertIn(f'{listen_ip}:9115', file_content)
+
+ # Check for running process
+ self.assertTrue(process_named_running(BLACKBOX_EXPORTER_PROCESS_NAME))
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/src/conf_mode/service_monitoring_prometheus.py b/src/conf_mode/service_monitoring_prometheus.py
index e0a9fc4ef..42628b05c 100755
--- a/src/conf_mode/service_monitoring_prometheus.py
+++ b/src/conf_mode/service_monitoring_prometheus.py
@@ -35,6 +35,9 @@ node_exporter_systemd_service = 'node_exporter.service'
frr_exporter_service_file = '/etc/systemd/system/frr_exporter.service'
frr_exporter_systemd_service = 'frr_exporter.service'
+blackbox_exporter_service_file = '/etc/systemd/system/blackbox_exporter.service'
+blackbox_exporter_systemd_service = 'blackbox_exporter.service'
+
def get_config(config=None):
if config:
@@ -57,6 +60,12 @@ def get_config(config=None):
if tmp:
monitoring.update({'frr_exporter_restart_required': {}})
+ tmp = False
+ for node in ['vrf', 'config-file']:
+ tmp = tmp or is_node_changed(conf, base + ['blackbox-exporter', node])
+ if tmp:
+ monitoring.update({'blackbox_exporter_restart_required': {}})
+
return monitoring
@@ -70,6 +79,22 @@ def verify(monitoring):
if 'frr_exporter' in monitoring:
verify_vrf(monitoring['frr_exporter'])
+ if 'blackbox_exporter' in monitoring:
+ verify_vrf(monitoring['blackbox_exporter'])
+
+ if (
+ 'modules' in monitoring['blackbox_exporter']
+ and 'dns' in monitoring['blackbox_exporter']['modules']
+ and 'name' in monitoring['blackbox_exporter']['modules']['dns']
+ ):
+ for mod_name, mod_config in monitoring['blackbox_exporter']['modules'][
+ 'dns'
+ ]['name'].items():
+ if 'query_name' not in mod_config:
+ raise ConfigError(
+ f'query name not specified in dns module {mod_name}'
+ )
+
return None
@@ -84,6 +109,11 @@ def generate(monitoring):
if os.path.isfile(frr_exporter_service_file):
os.unlink(frr_exporter_service_file)
+ if not monitoring or 'blackbox_exporter' not in monitoring:
+ # Delete systemd files
+ if os.path.isfile(blackbox_exporter_service_file):
+ os.unlink(blackbox_exporter_service_file)
+
if not monitoring:
return None
@@ -103,6 +133,20 @@ def generate(monitoring):
monitoring['frr_exporter'],
)
+ if 'blackbox_exporter' in monitoring:
+ # Render blackbox_exporter service_file
+ render(
+ blackbox_exporter_service_file,
+ 'prometheus/blackbox_exporter.service.j2',
+ monitoring['blackbox_exporter'],
+ )
+ # Render blackbox_exporter config file
+ render(
+ '/run/blackbox_exporter/config.yml',
+ 'prometheus/blackbox_exporter.yml.j2',
+ monitoring['blackbox_exporter'],
+ )
+
return None
@@ -113,6 +157,8 @@ def apply(monitoring):
call(f'systemctl stop {node_exporter_systemd_service}')
if not monitoring or 'frr_exporter' not in monitoring:
call(f'systemctl stop {frr_exporter_systemd_service}')
+ if not monitoring or 'blackbox_exporter' not in monitoring:
+ call(f'systemctl stop {blackbox_exporter_systemd_service}')
if not monitoring:
return
@@ -133,6 +179,14 @@ def apply(monitoring):
call(f'systemctl {systemd_action} {frr_exporter_systemd_service}')
+ if 'blackbox_exporter' in monitoring:
+ # we need to restart the service if e.g. the VRF name changed
+ systemd_action = 'reload-or-restart'
+ if 'blackbox_exporter_restart_required' in monitoring:
+ systemd_action = 'restart'
+
+ call(f'systemctl {systemd_action} {blackbox_exporter_systemd_service}')
+
if __name__ == '__main__':
try: