diff options
author | Viacheslav <v.gletenko@vyos.io> | 2021-12-27 07:58:30 +0000 |
---|---|---|
committer | Viacheslav <v.gletenko@vyos.io> | 2022-01-04 09:40:09 +0000 |
commit | 3628121505658fd4c588960136d5645afc791c59 (patch) | |
tree | 71094a599ddea9e66d1d7762f72154fc20da5787 /src/conf_mode/vrrp.py | |
parent | acefbacf7966b6a44dbdc3dfff49294ae59e70f6 (diff) | |
download | vyos-1x-3628121505658fd4c588960136d5645afc791c59.tar.gz vyos-1x-3628121505658fd4c588960136d5645afc791c59.zip |
keepalived: T4109: Add high-availability virtual-server
Add new feature, high-availability virtual-server
Change XML, python and templates
Move vrrp to root node 'high-availability' as all logic are
handler by root node 'high-availability'
Diffstat (limited to 'src/conf_mode/vrrp.py')
-rwxr-xr-x | src/conf_mode/vrrp.py | 159 |
1 files changed, 0 insertions, 159 deletions
diff --git a/src/conf_mode/vrrp.py b/src/conf_mode/vrrp.py deleted file mode 100755 index c72efc61f..000000000 --- a/src/conf_mode/vrrp.py +++ /dev/null @@ -1,159 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2018-2021 VyOS maintainers and contributors -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 or later as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -import os - -from sys import exit -from ipaddress import ip_interface -from ipaddress import IPv4Interface -from ipaddress import IPv6Interface - -from vyos.config import Config -from vyos.configdict import dict_merge -from vyos.ifconfig.vrrp import VRRP -from vyos.template import render -from vyos.template import is_ipv4 -from vyos.template import is_ipv6 -from vyos.util import call -from vyos.util import is_systemd_service_running -from vyos.xml import defaults -from vyos import ConfigError -from vyos import airbag -airbag.enable() - -def get_config(config=None): - if config: - conf = config - else: - conf = Config() - - base = ['high-availability', 'vrrp'] - if not conf.exists(base): - return None - - vrrp = conf.get_config_dict(base, key_mangling=('-', '_'), - get_first_key=True, no_tag_node_value_mangle=True) - # We have gathered the dict representation of the CLI, but there are default - # options which we need to update into the dictionary retrived. - if 'group' in vrrp: - default_values = defaults(base + ['group']) - for group in vrrp['group']: - vrrp['group'][group] = dict_merge(default_values, vrrp['group'][group]) - - ## Get the sync group used for conntrack-sync - conntrack_path = ['service', 'conntrack-sync', 'failover-mechanism', 'vrrp', 'sync-group'] - if conf.exists(conntrack_path): - vrrp['conntrack_sync_group'] = conf.return_value(conntrack_path) - - return vrrp - -def verify(vrrp): - if not vrrp: - return None - - used_vrid_if = [] - if 'group' in vrrp: - for group, group_config in vrrp['group'].items(): - # Check required fields - if 'vrid' not in group_config: - raise ConfigError(f'VRID is required but not set in VRRP group "{group}"') - - if 'interface' not in group_config: - raise ConfigError(f'Interface is required but not set in VRRP group "{group}"') - - if 'address' not in group_config: - raise ConfigError(f'Virtual IP address is required but not set in VRRP group "{group}"') - - if 'authentication' in group_config: - if not {'password', 'type'} <= set(group_config['authentication']): - raise ConfigError(f'Authentication requires both type and passwortd to be set in VRRP group "{group}"') - - # We can not use a VRID once per interface - interface = group_config['interface'] - vrid = group_config['vrid'] - tmp = {'interface': interface, 'vrid': vrid} - if tmp in used_vrid_if: - raise ConfigError(f'VRID "{vrid}" can only be used once on interface "{interface}"!') - used_vrid_if.append(tmp) - - # Keepalived doesn't allow mixing IPv4 and IPv6 in one group, so we mirror that restriction - - # XXX: filter on map object is destructive, so we force it to list. - # Additionally, filter objects always evaluate to True, empty or not, - # so we force them to lists as well. - vaddrs = list(map(lambda i: ip_interface(i), group_config['address'])) - vaddrs4 = list(filter(lambda x: isinstance(x, IPv4Interface), vaddrs)) - vaddrs6 = list(filter(lambda x: isinstance(x, IPv6Interface), vaddrs)) - - if vaddrs4 and vaddrs6: - raise ConfigError(f'VRRP group "{group}" mixes IPv4 and IPv6 virtual addresses, this is not allowed.\n' \ - 'Create individual groups for IPv4 and IPv6!') - if vaddrs4: - if 'hello_source_address' in group_config: - if is_ipv6(group_config['hello_source_address']): - raise ConfigError(f'VRRP group "{group}" uses IPv4 but hello-source-address is IPv6!') - - if 'peer_address' in group_config: - if is_ipv6(group_config['peer_address']): - raise ConfigError(f'VRRP group "{group}" uses IPv4 but peer-address is IPv6!') - - if vaddrs6: - if 'hello_source_address' in group_config: - if is_ipv4(group_config['hello_source_address']): - raise ConfigError(f'VRRP group "{group}" uses IPv6 but hello-source-address is IPv4!') - - if 'peer_address' in group_config: - if is_ipv4(group_config['peer_address']): - raise ConfigError(f'VRRP group "{group}" uses IPv6 but peer-address is IPv4!') - # Check sync groups - if 'sync_group' in vrrp: - for sync_group, sync_config in vrrp['sync_group'].items(): - if 'member' in sync_config: - for member in sync_config['member']: - if member not in vrrp['group']: - raise ConfigError(f'VRRP sync-group "{sync_group}" refers to VRRP group "{member}", '\ - 'but it does not exist!') - -def generate(vrrp): - if not vrrp: - return None - - render(VRRP.location['config'], 'vrrp/keepalived.conf.tmpl', vrrp) - return None - -def apply(vrrp): - service_name = 'keepalived.service' - if not vrrp: - call(f'systemctl stop {service_name}') - return None - - # XXX: T3944 - reload keepalived configuration if service is already running - # to not cause any service disruption when applying changes. - if is_systemd_service_running(service_name): - call(f'systemctl reload {service_name}') - else: - call(f'systemctl restart {service_name}') - return None - -if __name__ == '__main__': - try: - c = get_config() - verify(c) - generate(c) - apply(c) - except ConfigError as e: - print(e) - exit(1) |