summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2023-05-10 21:13:08 +0200
committerGitHub <noreply@github.com>2023-05-10 21:13:08 +0200
commit6eaa327c2a3bca3924e72cf7c5736489bb76f784 (patch)
tree3dcd4adf7692682026b3290b36c96de91d46c580
parent96d9bf0a88fc822b8edd78db293b7f17ae8766cf (diff)
parent8dc6b0aa8d7bbecfc5087a7406725812779eaaf6 (diff)
downloadvyos-1x-6eaa327c2a3bca3924e72cf7c5736489bb76f784.tar.gz
vyos-1x-6eaa327c2a3bca3924e72cf7c5736489bb76f784.zip
Merge pull request #1987 from dmbaturin/T5251-vrrp-group-ping
T5215: add a built-in ping check for VRRP groups
-rw-r--r--data/templates/high-availability/keepalived.conf.j28
-rw-r--r--interface-definitions/high-availability.xml.in19
-rw-r--r--python/vyos/utils/dict.py21
-rwxr-xr-xsrc/conf_mode/high-availability.py7
4 files changed, 52 insertions, 3 deletions
diff --git a/data/templates/high-availability/keepalived.conf.j2 b/data/templates/high-availability/keepalived.conf.j2
index 6ea5f91d0..85b89c70c 100644
--- a/data/templates/high-availability/keepalived.conf.j2
+++ b/data/templates/high-availability/keepalived.conf.j2
@@ -32,9 +32,13 @@ global_defs {
{% if vrrp.group is vyos_defined %}
{% for name, group_config in vrrp.group.items() if group_config.disable is not vyos_defined %}
-{% if group_config.health_check.script is vyos_defined %}
+{% if group_config.health_check is vyos_defined %}
vrrp_script healthcheck_{{ name }} {
+{% if group_config.health_check.script is vyos_defined %}
script "{{ group_config.health_check.script }}"
+{% elif group_config.health_check.ping is vyos_defined %}
+ script "/usr/bin/ping -c1 {{ group_config.health_check.ping }}"
+{% endif %}
interval {{ group_config.health_check.interval }}
fall {{ group_config.health_check.failure_count }}
rise 1
@@ -121,7 +125,7 @@ vrrp_instance {{ name }} {
{% endfor %}
}
{% endif %}
-{% if group_config.health_check.script is vyos_defined %}
+{% if group_config.health_check is vyos_defined %}
track_script {
healthcheck_{{ name }}
}
diff --git a/interface-definitions/high-availability.xml.in b/interface-definitions/high-availability.xml.in
index 9b52fe82e..94253def3 100644
--- a/interface-definitions/high-availability.xml.in
+++ b/interface-definitions/high-availability.xml.in
@@ -96,7 +96,7 @@
#include <include/generic-disable-node.xml.i>
<node name="health-check">
<properties>
- <help>Health check script</help>
+ <help>Health check</help>
</properties>
<children>
<leafNode name="failure-count">
@@ -117,6 +117,23 @@
</properties>
<defaultValue>60</defaultValue>
</leafNode>
+ <leafNode name="ping">
+ <properties>
+ <help>ICMP ping health check</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>IPv4 ping target address</description>
+ </valueHelp>
+ <valueHelp>
+ <format>ipv6</format>
+ <description>IPv6 ping target address</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-address"/>
+ <validator name="ipv6-address"/>
+ </constraint>
+ </properties>
+ </leafNode>
<leafNode name="script">
<properties>
<help>Health check script file</help>
diff --git a/python/vyos/utils/dict.py b/python/vyos/utils/dict.py
index 66b40d92b..4afc9f54e 100644
--- a/python/vyos/utils/dict.py
+++ b/python/vyos/utils/dict.py
@@ -233,3 +233,24 @@ def dict_to_list(d, save_key_to=None):
collect.append(item)
return collect
+
+def check_mutually_exclusive_options(d, keys, required=False):
+ """ Checks if a dict has at most one or only one of
+ mutually exclusive keys.
+ """
+ present_keys = []
+
+ for k in d:
+ if k in keys:
+ present_keys.append(k)
+
+ # Un-mangle the keys to make them match CLI option syntax
+ from re import sub
+ orig_keys = list(map(lambda s: sub(r'_', '-', s), keys))
+ orig_present_keys = list(map(lambda s: sub(r'_', '-', s), present_keys))
+
+ if len(present_keys) > 1:
+ raise ValueError(f"Options {orig_keys} are mutually-exclusive but more than one of them is present: {orig_present_keys}")
+
+ if required and (len(present_keys) < 1):
+ raise ValueError(f"At least one of the following options is required: {orig_present_keys}")
diff --git a/src/conf_mode/high-availability.py b/src/conf_mode/high-availability.py
index 5e76dd9f9..7a63f5b4b 100755
--- a/src/conf_mode/high-availability.py
+++ b/src/conf_mode/high-availability.py
@@ -106,6 +106,13 @@ def verify(ha):
if not {'password', 'type'} <= set(group_config['authentication']):
raise ConfigError(f'Authentication requires both type and passwortd to be set in VRRP group "{group}"')
+ if 'health_check' in group_config:
+ from vyos.utils.dict import check_mutually_exclusive_options
+ try:
+ check_mutually_exclusive_options(group_config["health_check"], ["script", "ping"], required=True)
+ except ValueError as e:
+ raise ConfigError(f'Health check config is incorrect in VRRP group "{group}": {e}')
+
# Keepalived doesn't allow mixing IPv4 and IPv6 in one group, so we mirror that restriction
# We also need to make sure VRID is not used twice on the same interface with the
# same address family.