Skip to content

Commit

Permalink
op-mode: T6577: create generic service restart helper to work with th…
Browse files Browse the repository at this point in the history
…e 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 c74ae85)

# Conflicts:
#	op-mode-definitions/suricata.xml.in
  • Loading branch information
c-po authored and mergify[bot] committed Jul 17, 2024
1 parent 95d345c commit 18b67dc
Show file tree
Hide file tree
Showing 14 changed files with 163 additions and 13 deletions.
4 changes: 2 additions & 2 deletions op-mode-definitions/dhcp.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@
<properties>
<help>Restart DHCP server</help>
</properties>
<command>if cli-shell-api existsActive service dhcp-server; then sudo systemctl restart kea-dhcp4-server.service; else echo "DHCP server not configured"; fi</command>
<command>sudo ${vyos_op_scripts_dir}/restart.py restart_service --name dhcp</command>
</node>
<node name="relay-agent">
<properties>
Expand All @@ -264,7 +264,7 @@
<properties>
<help>Restart DHCPv6 server</help>
</properties>
<command>if cli-shell-api existsActive service dhcpv6-server; then sudo systemctl restart kea-dhcp6-server.service; else echo "DHCPv6 server not configured"; fi</command>
<command>sudo ${vyos_op_scripts_dir}/restart.py restart_service --name dhcpv6</command>
</node>
<node name="relay-agent">
<properties>
Expand Down
2 changes: 1 addition & 1 deletion op-mode-definitions/dns-dynamic.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
<properties>
<help>Restart Dynamic DNS service</help>
</properties>
<command>if cli-shell-api existsActive service dns dynamic; then sudo systemctl restart ddclient.service; else echo "Dynamic DNS not configured"; fi</command>
<command>sudo ${vyos_op_scripts_dir}/restart.py restart_service --name dns_dynamic</command>
</node>
</children>
</node>
Expand Down
2 changes: 1 addition & 1 deletion op-mode-definitions/dns-forwarding.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
<properties>
<help>Restart DNS Forwarding service</help>
</properties>
<command>if cli-shell-api existsActive service dns forwarding; then sudo systemctl restart pdns-recursor.service; else echo "DNS forwarding not configured"; fi</command>
<command>sudo ${vyos_op_scripts_dir}/restart.py restart_service --name dns_forwarding</command>
</leafNode>
</children>
</node>
Expand Down
2 changes: 1 addition & 1 deletion op-mode-definitions/igmp-proxy.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<properties>
<help>Restart the IGMP proxy process</help>
</properties>
<command>sudo systemctl restart igmpproxy.service</command>
<command>sudo ${vyos_op_scripts_dir}/restart.py restart_service --name igmp_proxy</command>
</node>
</children>
</node>
Expand Down
2 changes: 1 addition & 1 deletion op-mode-definitions/mdns-reflector.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
<properties>
<help>Restart mDNS repeater service</help>
</properties>
<command>sudo systemctl restart avahi-daemon.service</command>
<command>sudo ${vyos_op_scripts_dir}/restart.py restart_service --name mdns_repeater</command>
</node>
</children>
</node>
Expand Down
2 changes: 1 addition & 1 deletion op-mode-definitions/restart-router-advert.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<properties>
<help>Restart IPv6 Router Advertisement service</help>
</properties>
<command>if cli-shell-api existsActive service router-advert; then sudo systemctl restart radvd.service; else echo "IPv6 Router Advertisement service not configured"; fi</command>
<command>sudo ${vyos_op_scripts_dir}/restart.py restart_service --name router_advert</command>
</node>
</children>
</node>
Expand Down
2 changes: 1 addition & 1 deletion op-mode-definitions/restart-snmp.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<properties>
<help>Restart SNMP service</help>
</properties>
<command>if cli-shell-api existsActive service snmp; then sudo systemctl restart snmpd.service; else echo "Service SNMP not configured"; fi</command>
<command>sudo ${vyos_op_scripts_dir}/restart.py restart_service --name snmp</command>
</node>
</children>
</node>
Expand Down
2 changes: 1 addition & 1 deletion op-mode-definitions/restart-ssh.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<properties>
<help>Restart SSH service</help>
</properties>
<command>if cli-shell-api existsActive service ssh; then sudo systemctl restart "ssh@*.service"; else echo "Service SSH not configured"; fi</command>
<command>sudo ${vyos_op_scripts_dir}/restart.py restart_service --name ssh --vrf "*"</command>
</node>
</children>
</node>
Expand Down
2 changes: 1 addition & 1 deletion op-mode-definitions/reverse-proxy.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<properties>
<help>Restart reverse-proxy service</help>
</properties>
<command>if cli-shell-api existsActive load-balancing reverse-proxy; then sudo systemctl restart haproxy.service; else echo "Reverse-Proxy not configured"; fi</command>
<command>sudo ${vyos_op_scripts_dir}/restart.py restart_service --name reverse_proxy</command>
</node>
</children>
</node>
Expand Down
23 changes: 23 additions & 0 deletions op-mode-definitions/suricata.xml.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="update">
<children>
<node name="suricata">
<properties>
<help>Update Suricata</help>
</properties>
<command>if test -f /run/suricata/suricata.yaml; then sudo suricata-update --suricata-conf /run/suricata/suricata.yaml; sudo systemctl restart suricata; else echo "Service Suricata not configured"; fi </command>
</node>
</children>
</node>
<node name="restart">
<children>
<node name="suricata">
<properties>
<help>Restart Suricata service</help>
</properties>
<command>sudo ${vyos_op_scripts_dir}/restart.py restart_service --name suricata</command>
</node>
</children>
</node>
</interfaceDefinition>
2 changes: 1 addition & 1 deletion op-mode-definitions/vpn-ipsec.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
<properties>
<help>Restart the IPsec VPN process</help>
</properties>
<command>if systemctl is-active --quiet strongswan; then sudo systemctl restart strongswan ; echo "IPsec process restarted"; else echo "IPsec process not running" ; fi</command>
<command>sudo ${vyos_op_scripts_dir}/restart.py restart_service --name ipsec</command>
</node>
</children>
</node>
Expand Down
2 changes: 1 addition & 1 deletion op-mode-definitions/vrrp.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<properties>
<help>Restart VRRP (Virtual Router Redundancy Protocol) process</help>
</properties>
<command>sudo systemctl restart keepalived.service</command>
<command>sudo ${vyos_op_scripts_dir}/restart.py restart_service --name vrrp</command>
</node>
</children>
</node>
Expand Down
2 changes: 1 addition & 1 deletion op-mode-definitions/webproxy.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<properties>
<help>Restart WebProxy service</help>
</properties>
<command>if cli-shell-api existsActive service webproxy; then sudo systemctl restart squid.service; else echo "Service WebProxy not configured"; fi</command>
<command>sudo ${vyos_op_scripts_dir}/restart.py restart_service --name webproxy</command>
</node>
</children>
</node>
Expand Down
127 changes: 127 additions & 0 deletions src/op_mode/restart.py
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

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)

0 comments on commit 18b67dc

Please sign in to comment.