From 00dbad0825f2653d2a1c3020f7278ed5ffdc2fe4 Mon Sep 17 00:00:00 2001 From: Florian Hines Date: Fri, 25 Jan 2013 08:00:33 -0800 Subject: [PATCH] Add optional locking to swift-ring-builder If invoked as 'swift-ring-builder-safe' the directory containing the builder file provided will be locked (via lock_parent_directory()). This provides a small safe guard against multiple instances of the swift-ring-builder (or other utilities that observe this lock) from attempting to write to or read the builder/ring files while operations are in progress. This is particularly useful in environments where ring management has been automated (via Chef or custom solutions) but the operator still occasionally needs to manually interact with the ring. DocImpact Change-Id: Ia362744a8151a91bfb586d01da582906726852e6 --- bin/swift-ring-builder | 14 +++++++++++--- doc/manpages/swift-ring-builder.1 | 8 ++++++++ doc/source/admin_guide.rst | 8 ++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/bin/swift-ring-builder b/bin/swift-ring-builder index a31021e3c0..4349c43893 100755 --- a/bin/swift-ring-builder +++ b/bin/swift-ring-builder @@ -19,14 +19,14 @@ from array import array from errno import EEXIST from itertools import islice, izip from os import mkdir -from os.path import basename, dirname, exists, join as pathjoin +from os.path import basename, abspath, dirname, exists, join as pathjoin from sys import argv, exit from textwrap import wrap from time import time from swift.common import exceptions from swift.common.ring import RingBuilder - +from swift.common.utils import lock_parent_directory MAJOR_VERSION = 1 MINOR_VERSION = 3 @@ -625,4 +625,12 @@ if __name__ == '__main__': command = "default" else: command = argv[2] - Commands.__dict__.get(command, Commands.unknown)() + if argv[0].endswith('-safe'): + try: + with lock_parent_directory(abspath(argv[1]), 15): + Commands.__dict__.get(command, Commands.unknown)() + except exceptions.LockTimeout: + print "Ring/builder dir currently locked." + exit(2) + else: + Commands.__dict__.get(command, Commands.unknown)() diff --git a/doc/manpages/swift-ring-builder.1 b/doc/manpages/swift-ring-builder.1 index c8433e8ddf..59f7736e72 100644 --- a/doc/manpages/swift-ring-builder.1 +++ b/doc/manpages/swift-ring-builder.1 @@ -48,6 +48,14 @@ partitions will end up assigned to different devices, and therefore nearly all data stored will have to be replicated to new locations. So, recovery from a builder file loss is possible, but data will definitely be unreachable for an extended time. +.PP +If invoked as 'swift-ring-builder-safe' the directory containing the builder +file provided will be locked (via a .lock file in the files parent directory). +This provides a basic safe guard against multiple instances of the swift-ring-builder +(or other utilities that observe this lock) from attempting to write to or read +the builder/ring files while operations are in progress. This can be useful in +environments where ring management has been automated but the operator still +needs to interact with the rings manually. .SH SEARCH diff --git a/doc/source/admin_guide.rst b/doc/source/admin_guide.rst index b1d00fa364..bb080a136e 100644 --- a/doc/source/admin_guide.rst +++ b/doc/source/admin_guide.rst @@ -53,6 +53,14 @@ Once you are done with all changes to the ring, the changes need to be Once the new rings are built, they should be pushed out to all the servers in the cluster. +Optionally, if invoked as 'swift-ring-builder-safe' the directory containing +the specified builder file will be locked (via a .lock file in the parent +directory). This provides a basic safe guard against multiple instances +of the swift-ring-builder (or other utilities that observe this lock) from +attempting to write to or read the builder/ring files while operations are in +progress. This can be useful in environments where ring management has been +automated but the operator still needs to interact with the rings manually. + ----------------------- Scripting Ring Creation -----------------------