From 77a0c827cbb02c3374d72f48973ba24d6c34d50c Mon Sep 17 00:00:00 2001 From: Oliver Walsh Date: Fri, 7 Aug 2020 16:15:43 +0100 Subject: [PATCH] Ensure tripleo ansible inventory file update is atomic Multiple python-tripleoclient commands can run concurrently and all attempt to update the same inventory file in ~/tripleo-ansible-inventory.yaml. Make the update atomic to ensure the inventory file is always complete/valid. (cherry picked from commit 8e082f45ddfb8f29bd02feb1c9fd1ace4e9ec6dd) (squashing commits as the 1st patch is failing in the stein gate without the fix from the 2nd patch) Ensure atomic inventory file rename runs on the same mountpoint Linux rename system call is only supported on the same mountpoint [1]. /tmp is often a tmpfs mount, so instead generate the temp inventory file in the same directory as the target inventory file. [1] See EXDEV in https://man7.org/linux/man-pages/man2/rename.2.html Closes-bug: #1892008 Change-Id: Ifa41bfcb921496978f82aee4e67fdb419cf9ffc5 (cherry picked from commit c1af9b7ad94ee46dc280cfeb6e1b0678e70773aa) --- tripleo_common/inventory.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tripleo_common/inventory.py b/tripleo_common/inventory.py index d5b05bc6d..e21181536 100644 --- a/tripleo_common/inventory.py +++ b/tripleo_common/inventory.py @@ -16,7 +16,8 @@ # under the License. from collections import OrderedDict -import os.path +import os +import tempfile import yaml from heatclient.exc import HTTPNotFound @@ -309,5 +310,11 @@ class TripleoInventory(object): if var in inventory: inventory[var]['vars'].update(value) - with open(inventory_file_path, 'w') as inventory_file: + # Atomic update as concurrent tripleoclient commands can call this + inventory_file_dir = os.path.dirname(inventory_file_path) + with tempfile.NamedTemporaryFile( + 'w', + dir=inventory_file_dir, + delete=False) as inventory_file: yaml.dump(inventory, inventory_file, TemplateDumper) + os.rename(inventory_file.name, inventory_file_path)