diff options
author | Indrajit Raychaudhuri <irc@indrajit.com> | 2023-09-13 01:02:12 -0500 |
---|---|---|
committer | Indrajit Raychaudhuri <irc@indrajit.com> | 2023-09-30 01:51:10 -0500 |
commit | 6aee08497522990b19291de42f9d445679eaae27 (patch) | |
tree | a8aa00e4790f759e55f3b8a8e6cfa3b137ee9fd0 | |
parent | 179703886441ef5508a63ba6d9d4c11b050d3ff8 (diff) | |
download | vyos-1x-6aee08497522990b19291de42f9d445679eaae27.tar.gz vyos-1x-6aee08497522990b19291de42f9d445679eaae27.zip |
ddclient: T5574: Support per-service cache management for services
Add support for per-service cache management for ddclient providers
via `wait-time` and `expiry-time` options. This allows for finer-grained
control over how often a service is updated and how long the hostname
will be cached before being marked expired in ddclient's cache.
More specifically, `wait-time` controls how often ddclient will attempt
to check for a change in the hostname's IP address, and `expiry-time`
controls how often ddclient to a forced update of the hostname's IP
address.
These options intentionally don't have any default values because they
are provider-specific. They get treated similar to the other provider-
specific options in that they are only used if defined.
-rw-r--r-- | data/templates/dns-dynamic/ddclient.conf.j2 | 11 | ||||
-rw-r--r-- | interface-definitions/dns-dynamic.xml.in | 2 | ||||
-rw-r--r-- | interface-definitions/include/dns/dynamic-service-wait-expiry-time.xml.i | 28 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_service_dns_dynamic.py | 12 | ||||
-rwxr-xr-x | src/conf_mode/dns_dynamic.py | 3 |
5 files changed, 49 insertions, 7 deletions
diff --git a/data/templates/dns-dynamic/ddclient.conf.j2 b/data/templates/dns-dynamic/ddclient.conf.j2 index 5905b19ea..6e77abdb5 100644 --- a/data/templates/dns-dynamic/ddclient.conf.j2 +++ b/data/templates/dns-dynamic/ddclient.conf.j2 @@ -14,10 +14,8 @@ if{{ ipv }}={{ address }}, \ {% endif %} {% endfor %} {# Other service options #} -{% for k,v in kwargs.items() %} -{% if v is vyos_defined %} -{{ k }}={{ v }}{{ ',' if not loop.last }} \ -{% endif %} +{% for k,v in kwargs.items() if v is vyos_defined %} +{{ k | replace('_', '-') }}={{ v }}{{ ',' if not loop.last }} \ {% endfor %} {# Actual hostname for the service #} {{ host }} @@ -49,7 +47,6 @@ use=no {{ render_config(host, address, service_cfg.web_options, protocol='nsupdate', server=config.server, zone=config.zone, password=config.key, ttl=config.ttl) }} - {% endfor %} {% endfor %} {% endif %} @@ -66,8 +63,8 @@ use=no # Web service dynamic DNS configuration for {{ name }}: [{{ config.protocol }}, {{ host }}] {{ render_config(host, address, service_cfg.web_options, ip_suffixes, protocol=config.protocol, server=config.server, zone=config.zone, - login=config.username, password=config.password, ttl=config.ttl) }} - + login=config.username, password=config.password, ttl=config.ttl, + min_interval=config.wait_time, max_interval=config.expiry_time) }} {% endfor %} {% endfor %} {% endif %} diff --git a/interface-definitions/dns-dynamic.xml.in b/interface-definitions/dns-dynamic.xml.in index ba7f426c1..723223f1c 100644 --- a/interface-definitions/dns-dynamic.xml.in +++ b/interface-definitions/dns-dynamic.xml.in @@ -61,6 +61,7 @@ <children> #include <include/generic-description.xml.i> #include <include/dns/dynamic-service-host-name-server.xml.i> + #include <include/dns/dynamic-service-wait-expiry-time.xml.i> <leafNode name="key"> <properties> <help>File containing the TSIG secret key shared with remote DNS server</help> @@ -88,6 +89,7 @@ <children> #include <include/generic-description.xml.i> #include <include/dns/dynamic-service-host-name-server.xml.i> + #include <include/dns/dynamic-service-wait-expiry-time.xml.i> #include <include/generic-username.xml.i> #include <include/generic-password.xml.i> #include <include/dns/time-to-live.xml.i> diff --git a/interface-definitions/include/dns/dynamic-service-wait-expiry-time.xml.i b/interface-definitions/include/dns/dynamic-service-wait-expiry-time.xml.i new file mode 100644 index 000000000..866690cbe --- /dev/null +++ b/interface-definitions/include/dns/dynamic-service-wait-expiry-time.xml.i @@ -0,0 +1,28 @@ +<!-- include start from dns/dynamic-service-wait-expiry-time.xml.i --> +<leafNode name="wait-time"> + <properties> + <help>Time in seconds to wait between update attempts</help> + <valueHelp> + <format>u32:60-86400</format> + <description>Time in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 60-86400"/> + </constraint> + <constraintErrorMessage>Wait time must be between 60 and 86400 seconds</constraintErrorMessage> + </properties> +</leafNode> +<leafNode name="expiry-time"> + <properties> + <help>Time in seconds for the hostname to be marked expired in cache</help> + <valueHelp> + <format>u32:300-2160000</format> + <description>Time in seconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 300-2160000"/> + </constraint> + <constraintErrorMessage>Expiry time must be between 300 and 2160000 seconds</constraintErrorMessage> + </properties> +</leafNode> +<!-- include end --> diff --git a/smoketest/scripts/cli/test_service_dns_dynamic.py b/smoketest/scripts/cli/test_service_dns_dynamic.py index 66dcde434..acabc0070 100755 --- a/smoketest/scripts/cli/test_service_dns_dynamic.py +++ b/smoketest/scripts/cli/test_service_dns_dynamic.py @@ -116,6 +116,9 @@ class TestServiceDDNS(VyOSUnitTestSHIM.TestCase): svc_path = ['address', interface, 'service', 'dynv6'] proto = 'dyndns2' ip_version = 'ipv6' + wait_time = '600' + expiry_time_good = '3600' + expiry_time_bad = '360' self.cli_set(base_path + ['timeout', timeout]) self.cli_set(base_path + svc_path + ['ip-version', ip_version]) @@ -124,6 +127,13 @@ class TestServiceDDNS(VyOSUnitTestSHIM.TestCase): self.cli_set(base_path + svc_path + ['username', username]) self.cli_set(base_path + svc_path + ['password', password]) self.cli_set(base_path + svc_path + ['host-name', hostname]) + self.cli_set(base_path + svc_path + ['wait-time', wait_time]) + + # expiry-time must be greater than wait-time, exception is raised otherwise + self.cli_set(base_path + svc_path + ['expiry-time', expiry_time_bad]) + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_set(base_path + svc_path + ['expiry-time', expiry_time_good]) # commit changes self.cli_commit() @@ -137,6 +147,8 @@ class TestServiceDDNS(VyOSUnitTestSHIM.TestCase): self.assertIn(f'server={server}', ddclient_conf) self.assertIn(f'login={username}', ddclient_conf) self.assertIn(f'password={password}', ddclient_conf) + self.assertIn(f'min-interval={wait_time}', ddclient_conf) + self.assertIn(f'max-interval={expiry_time_good}', ddclient_conf) # IPv4+IPv6 dual DDNS service configuration def test_03_dyndns_service_dual_stack(self): diff --git a/src/conf_mode/dns_dynamic.py b/src/conf_mode/dns_dynamic.py index 8a438cf6f..874c4b689 100755 --- a/src/conf_mode/dns_dynamic.py +++ b/src/conf_mode/dns_dynamic.py @@ -111,6 +111,9 @@ def verify(dyndns): raise ConfigError(f'"{config["protocol"]}" does not support ' f'both IPv4 and IPv6 at the same time for "{config["server"]}"') + if {'wait_time', 'expiry_time'} <= config.keys() and int(config['expiry_time']) < int(config['wait_time']): + raise ConfigError(f'"expiry-time" must be greater than "wait-time"') + return None def generate(dyndns): |