From b2208fcfcef596c11247ef8475f0993122be377e Mon Sep 17 00:00:00 2001 From: Shannon Mitchell Date: Sun, 17 Feb 2019 16:59:29 -0600 Subject: [PATCH] Dynamic inventory backup corruption fix When multiple users and process are accessing the dynamic inventory the inventory backup and json can get corrupted. This change checks for inventory modifictions and only saves if needed. The backup is also moved to right before the actual save. Change-Id: Ifd348ddd9c21526f5b523963dd1fd247edd6b109 Closes-Bug: #1750233 --- osa_toolkit/filesystem.py | 5 ++++- osa_toolkit/generate.py | 10 ++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/osa_toolkit/filesystem.py b/osa_toolkit/filesystem.py index 099e57d2b2..ed7228377b 100644 --- a/osa_toolkit/filesystem.py +++ b/osa_toolkit/filesystem.py @@ -244,7 +244,6 @@ def load_inventory(preferred_path=None, default_inv=None, filename=None): if inventory is not False: logger.debug("Loaded existing inventory from {}".format(file_loaded)) - _make_backup(load_path, file_loaded) else: logger.debug("No existing inventory, created fresh skeleton.") inventory = copy.deepcopy(default_inv) @@ -263,6 +262,10 @@ def save_inventory(inventory_json, save_path): inventory_file = file_find(save_path) else: inventory_file = os.path.join(save_path, INVENTORY_FILENAME) + + if os.path.isfile(inventory_file): + _make_backup(save_path, inventory_file) + with open(inventory_file, 'wb') as f: f.write(inventory_json.encode('ascii')) logger.info("Inventory written") diff --git a/osa_toolkit/generate.py b/osa_toolkit/generate.py index 3211e38d02..18d7b4d542 100755 --- a/osa_toolkit/generate.py +++ b/osa_toolkit/generate.py @@ -15,6 +15,7 @@ # # (c) 2014, Kevin Carter +import copy import json import logging import netaddr @@ -1078,6 +1079,9 @@ def main(config=None, check=False, debug=False, environment=None, **kwargs): # Load existing inventory file if found inventory, inv_path = filesys.load_inventory(config, INVENTORY_SKEL) + # Make a deep copy for change comparison + orig_inventory = copy.deepcopy(inventory) + # Save the users container cidr as a group variable cidr_networks = user_defined_config.get('cidr_networks') if not cidr_networks: @@ -1168,7 +1172,9 @@ def main(config=None, check=False, debug=False, environment=None, **kwargs): num_hosts = len(inventory['_meta']['hostvars']) logger.debug("%d hosts found.", num_hosts) - # Save new dynamic inventory - filesys.save_inventory(inventory_json, inv_path) + # Save new dynamic inventory only if modified + if orig_inventory != inventory: + logger.debug("Saving modified inventory") + filesys.save_inventory(inventory_json, inv_path) return inventory_json