summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2018-05-13 15:48:08 +0200
committerChristian Poessinger <christian@poessinger.com>2018-05-13 15:48:08 +0200
commit00f4d8ad780001b9a3f534c32d485676bc97993a (patch)
tree2436992c98ad4daa2adb21df3ae54133c80811a4 /src
parentb1741fa54f711cb60f16c7f909bed50cd45be38c (diff)
downloadvyos-1x-00f4d8ad780001b9a3f534c32d485676bc97993a.tar.gz
vyos-1x-00f4d8ad780001b9a3f534c32d485676bc97993a.zip
T623: refactor NTP script and switch to jinja2
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf-mode/vyos-config-ntp.py153
1 files changed, 93 insertions, 60 deletions
diff --git a/src/conf-mode/vyos-config-ntp.py b/src/conf-mode/vyos-config-ntp.py
index b9328f3e0..061e8760e 100755
--- a/src/conf-mode/vyos-config-ntp.py
+++ b/src/conf-mode/vyos-config-ntp.py
@@ -18,7 +18,8 @@
import sys
import os
-import time
+
+import jinja2
import ipaddress
from vyos.config import Config
@@ -26,95 +27,127 @@ from vyos.util import ConfigError
config_file = r'/etc/ntp.conf'
+# Please be careful if you edit the template.
+config_tmpl = """
+### Autogenerated by vyos-config-ntp.py ###
+
+#
+# Non-configurable defaults
+#
+driftfile /var/lib/ntp/ntp.drift
+# By default, only allow ntpd to query time sources, ignore any incoming requests
+restrict default ignore
+# Local users have unrestricted access, allowing reconfiguration via ntpdc
+restrict 127.0.0.1
+restrict -6 ::1
+
+
+#
+# Configurable section
+#
+
+{% if servers -%}
+{% for s in servers -%}
+# Server configuration for: {{ s.name }}
+server {{ s.name }} iburst {{ s.options | join(" ") }}
+
+{% endfor -%}
+{% endif %}
+
+{% if allowed_networks -%}
+{% for n in allowed_networks -%}
+# Client configuration for network: {{ n.network }}
+restrict {{ n.address }} mask {{ n.netmask }} nomodify notrap nopeer
+
+{% endfor -%}
+{% endif %}
+
+"""
+
+default_config_data = {
+ 'servers': [],
+ 'allowed_networks': []
+}
+
def get_config():
- ntp = {}
+ ntp = default_config_data
conf = Config()
- conf.set_level('system ntp')
- if not conf.exists(''):
- return ntp
+ if not conf.exists('system ntp'):
+ return None
+ else:
+ conf.set_level('system ntp')
if conf.exists('allow-clients address'):
- ntp.setdefault('allow-networks', [])
- networks = []
networks = conf.return_values('allow-clients address')
- for network in networks:
- ntp['allow-networks'].append(network)
+ for n in networks:
+ addr = ipaddress.ip_network(n)
+ net = {
+ "network" : n,
+ "address" : addr.network_address,
+ "netmask" : addr.netmask
+ }
+
+ ntp['allowed_networks'].append(net)
if conf.exists('server'):
- ntp.setdefault('servers', [])
for node in conf.list_nodes('server'):
+ options = []
server = {
"name": node,
- "dynamic": False,
- "noselect": False,
- "preempt": False,
- "prefer": False,
+ "options": []
}
if conf.exists('server {0} dynamic'.format(node)):
- server['dynamic'] = True
+ options.append('dynamic')
if conf.exists('server {0} noselect'.format(node)):
- server['noselect'] = True
+ options.append('noselect')
if conf.exists('server {0} preempt'.format(node)):
- server['preempt'] = True
+ options.append('preempt')
if conf.exists('server {0} prefer'.format(node)):
- server['prefer'] = True
+ options.append('prefer')
+ server['options'] = options
ntp['servers'].append(server)
return ntp
def verify(ntp):
- if 'allow-networks' in ntp.keys():
- for network in ntp['allow-networks']:
- try:
- addr = ipaddress.ip_network(network)
- except ValueError:
- raise ConfigError("{0} does not appear to be a valid IPv4 or IPv6 network, check host bits.".format(network))
+ # bail out early - looks like removal from running config
+ if ntp is None:
+ return None
+
+ # Configuring allowed clients without a server makes no sense
+ if len(ntp['allowed_networks']) and not len(ntp['servers']):
+ raise ConfigError('NTP server not configured')
+
+ for n in ntp['allowed_networks']:
+ try:
+ addr = ipaddress.ip_network( n['network'] )
+ break
+ except ValueError:
+ raise ConfigError("{0} does not appear to be a valid IPv4 or IPv6 network, check host bits!".format(n['network']))
return None
def generate(ntp):
- config_header = '### Autogenerated by vyos-config-ntp.py on {tm} ###\n'.format(tm=time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime()))
-
- # write new configuration file
- f = open(config_file, 'w')
- f.write(config_header)
- f.write('\n')
- f.write('driftfile /var/lib/ntp/ntp.drift\n')
- f.write('\n')
- f.write('# By default, only allow ntpd to query time sources, ignore any incoming requests\n')
- f.write('restrict default ignore\n')
- f.write('\n')
- f.write('# Local users have unrestricted access, allowing reconfiguration via ntpdc\n')
- f.write('restrict 127.0.0.1\n')
- f.write('restrict -6 ::1\n')
- f.write('\n')
-
- if 'servers' in ntp.keys():
- for server in ntp['servers']:
- opt = ['dynamic', 'noselect', 'preempt', 'prefer']
- f.write('# Server configuration for: {0}\n'.format(server['name']))
- f.write('server {0} iburst {1}\n'.format(server['name'], '{0}'.format(' '.join(str(o) for o in opt if server[o]))))
- f.write('restrict {0} nomodify notrap nopeer noquery\n'.format(server['name']))
- f.write('\n')
-
- if 'allow-networks' in ntp.keys():
- for network in ntp['allow-networks']:
- addr = ipaddress.ip_network(network)
- f.write('# Client configuration for network: {0}\n'.format(network))
- f.write('restrict {0} mask {1} nomodify notrap nopeer\n'.format(addr.network_address, addr.netmask))
- f.write('\n')
-
- f.close()
+ # bail out early - looks like removal from running config
+ if ntp is None:
+ return None
+
+ tmpl = jinja2.Template(config_tmpl)
+ config_text = tmpl.render(ntp)
+ with open(config_file, 'w') as f:
+ f.write(config_text)
+
return None
def apply(ntp):
- if len(ntp) == 0:
- cmd = "sudo /usr/sbin/invoke-rc.d ntp stop"
+ if ntp is not None:
+ os.system('sudo /usr/sbin/invoke-rc.d ntp force-reload')
else:
- cmd = "sudo /usr/sbin/invoke-rc.d ntp force-reload"
+ # NTP suuport is removed in the commit
+ os.system('sudo /usr/sbin/invoke-rc.d ntp stop')
+ os.unlink(config_file)
- os.system(cmd)
return None
if __name__ == '__main__':