diff options
-rw-r--r-- | python/vyos/config.py | 3 | ||||
-rw-r--r-- | python/vyos/defaults.py | 4 | ||||
-rw-r--r-- | python/vyos/util.py | 47 | ||||
-rwxr-xr-x | src/conf_mode/dns_forwarding.py | 8 | ||||
-rwxr-xr-x | src/conf_mode/host_name.py | 14 |
5 files changed, 70 insertions, 6 deletions
diff --git a/python/vyos/config.py b/python/vyos/config.py index bcf04225b..7483e3552 100644 --- a/python/vyos/config.py +++ b/python/vyos/config.py @@ -383,7 +383,8 @@ class Config(object): else: try: out = self._run(self._make_command('returnEffectiveValues', full_path)) - return out + values = re.findall(r"\'(.*?)\'", out) + return values except VyOSError: return(default) diff --git a/python/vyos/defaults.py b/python/vyos/defaults.py index 36185f16a..c46723626 100644 --- a/python/vyos/defaults.py +++ b/python/vyos/defaults.py @@ -19,3 +19,7 @@ directories = { } cfg_group = 'vyattacfg' + +cfg_vintage = 'vyatta' + +commit_lock = '/opt/vyatta/config/.lock' diff --git a/python/vyos/util.py b/python/vyos/util.py index 8b5342575..6ab606983 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -1,4 +1,4 @@ -# Copyright 2018 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright 2019 VyOS maintainers and contributors <maintainers@vyos.io> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -16,6 +16,9 @@ import os import re import grp +import time +import subprocess + import psutil import vyos.defaults @@ -131,3 +134,45 @@ def file_is_persistent(path): return (False, warning) else: return (True, None) + +def commit_in_progress(): + """ Not to be used in normal op mode scripts! """ + + # The CStore backend locks the config by opening a file + # The file is not removed after commit, so just checking + # if it exists is insufficient, we need to know if it's open by anyone + + # There are two ways to check if any other process keeps a file open. + # The first one is to try opening it and see if the OS objects. + # That's faster but prone to race conditions and can be intrusive. + # The other one is to actually check if any process keeps it open. + # It's non-intrusive but needs root permissions, else you can't check + # processes of other users. + # + # Since this will be used in scripts that modify the config outside of the CLI + # framework, those knowingly have root permissions. + # For everything else, we add a safeguard. + id = subprocess.check_output(['/usr/bin/id', '-u']).decode().strip() + if id != '0': + raise OSError("This functions needs root permissions to return correct results") + + for proc in psutil.process_iter(): + try: + files = proc.open_files() + if files: + for f in files: + if f.path == vyos.defaults.commit_lock: + return True + except psutil.NoSuchProcess as err: + # Process died before we could examine it + pass + # Default case + return False + +def wait_for_commit_lock(): + """ Not to be used in normal op mode scripts! """ + + # Very synchronous approach to multiprocessing + while commit_in_progress(): + time.sleep(1) + diff --git a/src/conf_mode/dns_forwarding.py b/src/conf_mode/dns_forwarding.py index c7e362d07..aab389074 100755 --- a/src/conf_mode/dns_forwarding.py +++ b/src/conf_mode/dns_forwarding.py @@ -23,6 +23,8 @@ import argparse import jinja2 import netifaces +import vyos.util + from vyos.config import Config from vyos import ConfigError @@ -265,6 +267,12 @@ def apply(dns): if __name__ == '__main__': args = parser.parse_args() + + if args.dhclient: + # There's a big chance it was triggered by a commit still in progress + # so we need to wait until the new values are in the running config + vyos.util.wait_for_commit_lock() + try: c = get_config(args) verify(c) diff --git a/src/conf_mode/host_name.py b/src/conf_mode/host_name.py index c5268df2a..5055faa65 100755 --- a/src/conf_mode/host_name.py +++ b/src/conf_mode/host_name.py @@ -28,6 +28,8 @@ import glob import argparse import jinja2 +import vyos.util + from vyos.config import Config from vyos import ConfigError @@ -117,10 +119,7 @@ def get_config(arguments): hosts['domain_search'].append(search) if conf.exists("system name-server"): - if not isinstance(conf.return_values("system name-server"), list): - hosts['nameserver'] = conf.return_values("system name-server").replace("'", "").split() - else: - hosts['nameserver'] = conf.return_values("system name-server") + hosts['nameserver'] = conf.return_values("system name-server") hosts['no_dhcp_ns'] = conf.exists('system disable-dhcp-nameservers') @@ -213,6 +212,13 @@ def apply(config): if __name__ == '__main__': args = parser.parse_args() + + if args.dhclient: + # There's a big chance it was triggered by a commit still in progress + # so we need to wait until the new values are in the running config + vyos.util.wait_for_commit_lock() + + try: c = get_config(args) verify(c) |