summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf_mode/interfaces_openvpn.py30
1 files changed, 29 insertions, 1 deletions
diff --git a/src/conf_mode/interfaces_openvpn.py b/src/conf_mode/interfaces_openvpn.py
index ab27fe66e..d6b63ae2a 100755
--- a/src/conf_mode/interfaces_openvpn.py
+++ b/src/conf_mode/interfaces_openvpn.py
@@ -78,6 +78,28 @@ otp_file = '/config/auth/openvpn/{ifname}-otp-secrets'
secret_chars = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
service_file = '/run/systemd/system/openvpn@{ifname}.service.d/20-override.conf'
+def _only_client_config_changed(conf, base, ifname):
+ """
+ Return True when the sole diff under this interface is a change to
+ `server.client` entries (i.e. CCD files).
+ """
+
+ iface_path = base + [ifname]
+ diff = get_config_diff(conf)
+
+ def _has_only_changes(path, node):
+ changes = diff.node_changed_children(path)
+ return len(changes) == 1 and changes[0] == node
+
+ # Something outside of 'server' also changed - not a CCD-only change
+ if _has_only_changes(iface_path, 'server'):
+ # Something outside of 'server.client' also changed - not a CCD-only change
+ if _has_only_changes(iface_path + ['server'], 'client'):
+ return True
+
+ return False
+
+
def get_config(config=None):
"""
Retrieve CLI config as dictionary. Dictionary can never be empty, as at least the
@@ -117,6 +139,12 @@ def get_config(config=None):
if is_node_changed(conf, base + [ifname, 'enable-dco']):
openvpn.update({'restart_required': {}})
+ # Detect changes that are limited to per-client CCD entries (T6478).
+ # OpenVPN reads client-config-dir files at connect time, so adding or
+ # updating them requires neither a SIGHUP nor a service restart.
+ if 'restart_required' not in openvpn and openvpn['mode'] == 'server':
+ openvpn['client_only_changed'] = _only_client_config_changed(conf, base, ifname)
+
# We have to get the dict using 'get_config_dict' instead of 'get_interface_dict'
# as 'get_interface_dict' merges the defaults in, so we can not check for defaults in there.
tmp = conf.get_config_dict(base + [openvpn['ifname']], get_first_key=True)
@@ -818,7 +846,7 @@ def apply(openvpn):
# No matching OpenVPN process running - maybe it got killed or none
# existed - nevertheless, spawn new OpenVPN process
- if not openvpn.get('no_restart_crl'):
+ if not openvpn.get('no_restart_crl') and not openvpn.get('client_only_changed'):
action = 'reload-or-restart'
if 'restart_required' in openvpn:
action = 'restart'