From c1fdee12f94dcf4395992152358d03cb8c74f155 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Wed, 3 Jul 2019 03:35:31 +0200 Subject: T1503: add functions for commit lock checking and waiting. --- python/vyos/defaults.py | 2 ++ python/vyos/util.py | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/python/vyos/defaults.py b/python/vyos/defaults.py index f23e15631..524b80424 100644 --- a/python/vyos/defaults.py +++ b/python/vyos/defaults.py @@ -25,3 +25,5 @@ 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 +# Copyright 2019 VyOS maintainers and contributors # # 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) + -- cgit v1.2.3