diff options
-rw-r--r-- | python/vyos/util.py | 37 | ||||
-rwxr-xr-x | src/op_mode/vrrp.py | 17 |
2 files changed, 46 insertions, 8 deletions
diff --git a/python/vyos/util.py b/python/vyos/util.py index cc7ce5b40..3ffd025b9 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -136,6 +136,43 @@ def file_is_persistent(path): else: return (True, None) +def wait_for_inotify(file_path, pre_hook=None, event_type=None, timeout=None, sleep_interval=0.1): + """ Waits for an inotify event to occur """ + if not os.path.dirname(file_path): + raise ValueError( + "File path {} does not have a directory part (required for inotify watching)".format(file_path)) + if not os.path.basename(file_path): + raise ValueError( + "File path {} does not have a file part, do not know what to watch for".format(file_path)) + + from inotify.adapters import Inotify + from time import time + + time_start = time() + + i = Inotify() + i.add_watch(os.path.dirname(file_path)) + + if pre_hook: + pre_hook() + + for event in i.event_gen(yield_nones=True): + if (timeout is not None) and ((time() - time_start) > timeout): + # If the function didn't return until this point, + # the file failed to have been written to and closed within the timeout + raise OSError("Waiting for file {} to be written has failed".format(file_path)) + + if event is not None: + (_, type_names, path, filename) = event + if filename == os.path.basename(file_path): + if event_type in type_names: + return + +def wait_for_file_write_complete(file_path, pre_hook=None, timeout=None, sleep_interval=0.1): + """ Waits for a process to close a file after opening it in write mode. """ + wait_for_inotify(file_path, + event_type='IN_CLOSE_WRITE', pre_hook=pre_hook, timeout=timeout, sleep_interval=sleep_interval) + def commit_in_progress(): """ Not to be used in normal op mode scripts! """ diff --git a/src/op_mode/vrrp.py b/src/op_mode/vrrp.py index 8d1369823..7a1146b9e 100755 --- a/src/op_mode/vrrp.py +++ b/src/op_mode/vrrp.py @@ -27,10 +27,9 @@ import vyos.util def print_summary(): try: - vyos.keepalived.force_json_dump() - # Wait for keepalived to produce the data - # Replace with inotify or similar if it proves problematic - time.sleep(0.2) + json_data = vyos.util.wait_for_file_write_complete(vyos.keepalived.json_file, + pre_hook=(lambda: vyos.keepalived.force_json_dump()), + timeout=30) json_data = vyos.keepalived.get_json_data() vyos.keepalived.remove_vrrp_data("json") except: @@ -60,8 +59,9 @@ def print_summary(): def print_statistics(): try: - vyos.keepalived.force_stats_dump() - time.sleep(0.2) + json_data = vyos.util.wait_for_file_write_complete(vyos.keepalived.stats_file, + pre_hook=(lambda: vyos.keepalived.force_stats_dump()), + timeout=30) output = vyos.keepalived.get_statistics() print(output) vyos.keepalived.remove_vrrp_data("stats") @@ -71,8 +71,9 @@ def print_statistics(): def print_state_data(): try: - vyos.keepalived.force_state_data_dump() - time.sleep(0.2) + json_data = vyos.util.wait_for_file_write_complete(vyos.keepalived.state_file, + pre_hook=(lambda: vyos.keepalived.force_state_data_dump()), + timeout=30) output = vyos.keepalived.get_state_data() print(output) vyos.keepalived.remove_vrrp_data("state") |