From f773368df7c5eb40a8c6334ebbed2de88bdb21af Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Tue, 16 Jul 2024 21:28:55 +0200 Subject: op-mode: T6577: create generic service restart helper to work with the API Right now we have multiple restart helpers (e.g. dhcp server, ssh, ntp) that all do the same (more or less): * Check if service is configured on CLI * Restart if configured * Error out if unconfigured This is not available via the op-mode API. Create a new restart.py op-mode helper that takes the service name and possible VRF as argument so it's also exposed via API. (cherry picked from commit c74ae852152b0c3c3f00a1847d081d28f500e178) --- src/op_mode/restart.py | 127 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100755 src/op_mode/restart.py (limited to 'src') diff --git a/src/op_mode/restart.py b/src/op_mode/restart.py new file mode 100755 index 000000000..813d3a2b7 --- /dev/null +++ b/src/op_mode/restart.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 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 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 . + +import sys +import typing +import vyos.opmode + +from vyos.configquery import ConfigTreeQuery +from vyos.utils.process import call +from vyos.utils.commit import commit_in_progress + +config = ConfigTreeQuery() + +service_map = { + 'dhcp' : { + 'systemd_service': 'kea-dhcp4-server', + 'path': ['service', 'dhcp-server'], + }, + 'dhcpv6' : { + 'systemd_service': 'kea-dhcp6-server', + 'path': ['service', 'dhcpv6-server'], + }, + 'dns_dynamic': { + 'systemd_service': 'ddclient', + 'path': ['service', 'dns', 'dynamic'], + }, + 'dns_forwarding': { + 'systemd_service': 'pdns-recursor', + 'path': ['service', 'dns', 'forwarding'], + }, + 'igmp_proxy': { + 'systemd_service': 'igmpproxy', + 'path': ['protocols', 'igmp-proxy'], + }, + 'ipsec': { + 'systemd_service': 'strongswan', + 'path': ['vpn', 'ipsec'], + }, + 'mdns_repeater': { + 'systemd_service': 'avahi-daemon', + 'path': ['service', 'mdns', 'repeater'], + }, + 'reverse_proxy': { + 'systemd_service': 'haproxy', + 'path': ['load-balancing', 'reverse-proxy'], + }, + 'router_advert': { + 'systemd_service': 'radvd', + 'path': ['service', 'router-advert'], + }, + 'snmp' : { + 'systemd_service': 'snmpd', + }, + 'ssh' : { + 'systemd_service': 'ssh', + }, + 'suricata' : { + 'systemd_service': 'suricata', + }, + 'vrrp' : { + 'systemd_service': 'keepalived', + 'path': ['high-availability', 'vrrp'], + }, + 'webproxy' : { + 'systemd_service': 'squid', + }, +} +services = typing.Literal['dhcp', 'dhcpv6', 'dns_dynamic', 'dns_forwarding', 'igmp_proxy', 'ipsec', 'mdns_repeater', 'reverse_proxy', 'router_advert', 'snmp', 'ssh', 'suricata' 'vrrp', 'webproxy'] + +def _verify(func): + """Decorator checks if DHCP(v6) config exists""" + from functools import wraps + + @wraps(func) + def _wrapper(*args, **kwargs): + config = ConfigTreeQuery() + name = kwargs.get('name') + human_name = name.replace('_', '-') + + if commit_in_progress(): + print(f'Cannot restart {human_name} service while a commit is in progress') + sys.exit(1) + + # Get optional CLI path from service_mapping dict + # otherwise use "service name" CLI path + path = ['service', name] + if 'path' in service_map[name]: + path = service_map[name]['path'] + + # Check if config does not exist + if not config.exists(path): + raise vyos.opmode.UnconfiguredSubsystem(f'Service {human_name} is not configured!') + if config.exists(path + ['disable']): + raise vyos.opmode.UnconfiguredSubsystem(f'Service {human_name} is disabled!') + return func(*args, **kwargs) + + return _wrapper + +@_verify +def restart_service(raw: bool, name: services, vrf: typing.Optional[str]): + systemd_service = service_map[name]['systemd_service'] + if vrf: + call(f'systemctl restart "{systemd_service}@{vrf}.service"') + else: + call(f'systemctl restart "{systemd_service}.service"') + +if __name__ == '__main__': + try: + res = vyos.opmode.run(sys.modules[__name__]) + if res: + print(res) + except (ValueError, vyos.opmode.Error) as e: + print(e) + sys.exit(1) -- cgit v1.2.3