From 9495ac100114b932569592ee5ea2d4c0bba0a2a3 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Wed, 10 May 2023 02:41:15 +0100 Subject: vyos.utils: T5195: add vyos.utils.dict.check_mutually_exclusive_options --- python/vyos/utils/dict.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) 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}") -- cgit v1.2.3 From 8dc6b0aa8d7bbecfc5087a7406725812779eaaf6 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Wed, 10 May 2023 02:42:38 +0100 Subject: vrrp: T5215: Add built-in ping check for VRRP groups --- data/templates/high-availability/keepalived.conf.j2 | 8 ++++++-- interface-definitions/high-availability.xml.in | 19 ++++++++++++++++++- src/conf_mode/high-availability.py | 7 +++++++ 3 files changed, 31 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 - Health check script + Health check @@ -117,6 +117,23 @@ 60 + + + ICMP ping health check + + ipv4 + IPv4 ping target address + + + ipv6 + IPv6 ping target address + + + + + + + Health check script file 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. -- cgit v1.2.3