summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniil Baturin <daniil@baturin.org>2019-03-31 17:25:31 +0200
committerDaniil Baturin <daniil@baturin.org>2019-03-31 17:25:31 +0200
commit588dee1177c5f9c3341ce6b948045e65f7bd93bf (patch)
tree89685426534a443332c97e0ec5cc1d3bcb34757c
parentab0b68f0242fb39baa64022f3366df891e96f222 (diff)
downloadvyos-1x-588dee1177c5f9c3341ce6b948045e65f7bd93bf.tar.gz
vyos-1x-588dee1177c5f9c3341ce6b948045e65f7bd93bf.zip
Revert "Fixes: T1262 - dhcp requested WAN ip address doesn't get search parameter in /etc/resolv.conf"
This reverts commit 1a384ed21f1777faaef653f9d1e3d9c05542fdc8.
-rwxr-xr-xsrc/conf_mode/host_name.py266
1 files changed, 64 insertions, 202 deletions
diff --git a/src/conf_mode/host_name.py b/src/conf_mode/host_name.py
index 27e2d9170..030735215 100755
--- a/src/conf_mode/host_name.py
+++ b/src/conf_mode/host_name.py
@@ -24,236 +24,98 @@ import os
import re
import sys
import subprocess
-import copy
-import jinja2
-import glob
from vyos.config import Config
from vyos import ConfigError
-config_file_hosts = '/etc/hosts'
-config_file_resolv = '/etc/resolv.conf'
-config_tmpl_hosts = """
-### Autogenerated by host_name.py ###
-127.0.0.1 localhost {{ hostname }}{% if domain_name %}.{{ domain_name }}{% endif %}
+hosts_file = '/etc/hosts'
+hostname_regex = re.compile("^[A-Za-z0-9][-.A-Za-z0-9]*[A-Za-z0-9]$")
+local_addr = '127.0.1.1' # NOSONAR
-# The following lines are desirable for IPv6 capable hosts
-::1 localhost ip6-localhost ip6-loopback
-fe00::0 ip6-localnet
-ff00::0 ip6-mcastprefix
-ff02::1 ip6-allnodes
-ff02::2 ip6-allrouters
-
-# static hostname mappings
-{%- if static_host_mapping['hostnames'] %}
-{% for hn in static_host_mapping['hostnames'] -%}
-{{static_host_mapping['hostnames'][hn]['ipaddr']}}\t{{static_host_mapping['hostnames'][hn]['alias']}}\t{{hn}}
-{% endfor -%}
-{%- endif %}
-
-### modifications from other scripts should be added below
-
-"""
-
-config_tmpl_resolv = """
-### Autogenerated by host_name.py ###
-{% for ns in nameserver -%}
-nameserver {{ ns }}
-{% endfor -%}
-
-{%- if domain_name %}
-domain {{ domain_name }}
-{%- endif %}
-
-{%- if domain_search %}
-search {{ domain_search | join(" ") }}
-{%- endif %}
-
-"""
-
-# borrowed from: https://github.com/donjajo/py-world/blob/master/resolvconfReader.py, THX!
-def get_resolvers(file):
- resolvers = []
- try:
- with open(file, 'r') as resolvconf:
- for line in resolvconf.readlines():
- line = line.split('#',1)[0];
- line = line.rstrip();
- if 'nameserver' in line:
- resolvers.append(line.split()[1])
- return resolvers
- except IOError:
- return []
-
-def get_dhcp_search_doms(file):
- search_doms = []
- try:
- with open(file, 'r') as resolvconf:
- for line in resolvconf.readlines():
- line = line.split('#',1)[0];
- line = line.rstrip();
- if 'search' in line:
- return re.sub('^search','',line).lstrip().split()
- except IOError:
- return []
-
-default_config_data = {
- 'hostname': 'vyos',
- 'domain_name': '',
- 'domain_search': [],
- 'nameserver': [],
- 'no_dhcp_ns': False
-}
def get_config():
- conf = Config()
- hosts = copy.deepcopy(default_config_data)
+ """Get configuration"""
+ conf = Config()
- hosts['hostname'] = conf.return_value("system host-name")
- hosts['domain_name'] = conf.return_value("system domain-name")
+ hostname = conf.return_value("system host-name")
+ domain = conf.return_value("system domain-name")
- if hosts['domain_name']:
- hosts['domain_search'].append(hosts['domain_name'])
+ # No one likes fixups, but we really don't want VyOS fail to boot
+ # if hostname is not in the config
+ if not hostname:
+ hostname = "vyos"
- for search in conf.return_values("system domain-search domain"):
- hosts['domain_search'].append(search)
+ if domain:
+ fqdn = "{0}.{1}".format(hostname, domain)
+ else:
+ fqdn = hostname
- hosts['nameserver'] = conf.return_values("system name-server")
- hosts['no_dhcp_ns'] = conf.exists('system disable-dhcp-nameservers')
+ return {"hostname": hostname, "domain": domain, "fqdn": fqdn}
- ## system static-host-mapping
- hosts['static_host_mapping'] = { 'hostnames' : {}}
-
- if conf.exists('system static-host-mapping host-name'):
- for hn in conf.list_nodes('system static-host-mapping host-name'):
- hosts['static_host_mapping']['hostnames'][hn] = {
- 'ipaddr' : conf.return_value('system static-host-mapping host-name ' + hn + ' inet'),
- 'alias' : ''
- }
-
- if conf.exists('system static-host-mapping host-name ' + hn + ' alias'):
- a = conf.return_values('system static-host-mapping host-name ' + hn + ' alias')
- hosts['static_host_mapping']['hostnames'][hn]['alias'] = " ".join( conf.return_values('system static-host-mapping host-name ' + hn + ' alias') )
-
- return hosts
def verify(config):
- if config is None:
- return None
+ """Verify configuration"""
+ # check for invalid host
- # pattern $VAR(@) "^[[:alnum:]][-.[:alnum:]]*[[:alnum:]]$" ; "invalid host name $VAR(@)"
- hostname_regex = re.compile("^[A-Za-z0-9][-.A-Za-z0-9]*[A-Za-z0-9]$")
- if not hostname_regex.match(config['hostname']):
- raise ConfigError('Invalid host name ' + config["hostname"])
+ # pattern $VAR(@) "^[[:alnum:]][-.[:alnum:]]*[[:alnum:]]$" ; "invalid host name $VAR(@)"
+ if not hostname_regex.match(config["hostname"]):
+ raise ConfigError('Invalid host name ' + config["hostname"])
- # pattern $VAR(@) "^.{1,63}$" ; "invalid host-name length"
- length = len(config['hostname'])
- if length < 1 or length > 63:
- raise ConfigError('Invalid host-name length, must be less than 63 characters')
+ # pattern $VAR(@) "^.{1,63}$" ; "invalid host-name length"
+ length = len(config["hostname"])
+ if length < 1 or length > 63:
+ raise ConfigError(
+ 'Invalid host-name length, must be less than 63 characters')
- # The search list is currently limited to six domains with a total of 256 characters.
- # https://linux.die.net/man/5/resolv.conf
- if len(config['domain_search']) > 6:
- raise ConfigError('The search list is currently limited to six domains')
-
- tmp = ' '.join(config['domain_search'])
- if len(tmp) > 256:
- raise ConfigError('The search list is currently limited to 256 characters')
-
- # static mappings alias hostname
- if config['static_host_mapping']['hostnames']:
- for hn in config['static_host_mapping']['hostnames']:
- if not config['static_host_mapping']['hostnames'][hn]['ipaddr']:
- raise ConfigError('IP address required for ' + hn)
- for hn_alias in config['static_host_mapping']['hostnames'][hn]['alias'].split(' '):
- if not hostname_regex.match(hn_alias) and len (hn_alias) !=0:
- raise ConfigError('Invalid hostname alias ' + hn_alias)
-
- return None
-
-def generate(config):
- if config is None:
return None
- # If "system disable-dhcp-nameservers" is __configured__ all DNS resolvers
- # received via dhclient should not be added into the final 'resolv.conf'.
- #
- # We iterate over every resolver file and retrieve the received nameservers
- # for later adjustment of the system nameservers
- dhcp_ns = []
- for file in glob.glob('/etc/resolv.conf.dhclient-new*'):
- for r in get_resolvers(file):
- dhcp_ns.append(r)
-
- if not config['no_dhcp_ns']:
- config['nameserver'] += dhcp_ns
- for file in glob.glob('/etc/resolv.conf.dhclient-new*'):
- config['domain_search'] = get_dhcp_search_doms(file)
-
- # We have third party scripts altering /etc/hosts, too.
- # One example are the DHCP hostname update scripts thus we need to cache in
- # every modification first - so changing domain-name, domain-search or hostname
- # during runtime works
- old_hosts = ""
- with open(config_file_hosts, 'r') as f:
- # Skips text before the beginning of our marker.
- # NOTE: Marker __MUST__ match the one specified in config_tmpl_hosts
- for line in f:
- if line.strip() == '### modifications from other scripts should be added below':
- break
-
- for line in f:
- # This additional line.strip() filters empty lines
- if line.strip():
- old_hosts += line
- # Add an additional newline
- old_hosts += '\n'
-
- tmpl = jinja2.Template(config_tmpl_hosts)
- config_text = tmpl.render(config)
-
- with open(config_file_hosts, 'w') as f:
- f.write(config_text)
- f.write(old_hosts)
+def generate(config):
+ """Generate configuration files"""
+ # read the hosts file
+ with open(hosts_file, 'r') as f:
+ hosts = f.read()
+
+ # get the current hostname
+ old_hostname = subprocess.check_output(['hostname']).decode().strip()
+
+ # replace the local host line
+ vyos_host_line_re = re.compile(r"({}\s+{}.*)".format(local_addr, old_hostname))
+ vyos_host_line = "{}\t{} # VyOS entry\n".format(local_addr, config["fqdn"])
+ if re.search(vyos_host_line_re, hosts):
+ hosts = re.sub(vyos_host_line_re, vyos_host_line, hosts)
+ else:
+ # On boot (or after errors), the /etc/hosts file has no line for vyos hostname,
+ # so we have to add it
+ hosts = "{0}\n{1}".format(hosts, vyos_host_line)
+
+ with open(hosts_file, 'w') as f:
+ f.write(hosts)
- tmpl = jinja2.Template(config_tmpl_resolv)
- config_text = tmpl.render(config)
- with open(config_file_resolv, 'w') as f:
- f.write(config_text)
+ return None
- return None
def apply(config):
- if config is None:
- return None
-
- fqdn = config['hostname']
- if config['domain_name']:
- fqdn += '.' + config['domain_name']
+ """Apply configuration"""
+ os.system("hostnamectl set-hostname --static {0}".format(config["fqdn"]))
- os.system("hostnamectl set-hostname --static {0}".format(fqdn))
+ # Restart services that use the hostname
+ os.system("systemctl restart rsyslog.service")
- # Restart services that use the hostname
- os.system("systemctl restart rsyslog.service")
+ # If SNMP is running, restart it too
+ if os.system("pgrep snmpd > /dev/null") == 0:
+ os.system("systemctl restart snmpd.service")
- # If SNMP is running, restart it too
- if os.system("pgrep snmpd > /dev/null") == 0:
- os.system("systemctl restart snmpd.service")
-
- # restart pdns if it is used
- if os.system("/usr/bin/rec_control ping >/dev/null 2>&1") == 0:
- os.system("/etc/init.d/pdns-recursor restart >/dev/null")
+ return None
- return None
if __name__ == '__main__':
- try:
- c = get_config()
- verify(c)
- generate(c)
- apply(c)
- except ConfigError as e:
- print(e)
- sys.exit(1)
+ try:
+ c = get_config()
+ verify(c)
+ generate(c)
+ apply(c)
+ except ConfigError as e:
+ print(e)
+ sys.exit(1)