From eeb0fa40a19917e6548f95f0bd3c08736928449b Mon Sep 17 00:00:00 2001 From: Christian Schwede <cschwede@redhat.com> Date: Thu, 6 Aug 2015 07:21:15 +0000 Subject: [PATCH] Make swift-ring-builder filename usage more consistent Sometimes the given argument is internally altered and another filename is used without a note to the operator. Even worse, a given .ring.gz filename is sometimes written out as builder file, without updating the corresponding .builder file. There is already a method to parse the given argv and return the name of the builder and ring file. However, it's rarely used and no warning is given to the user if it is altered. This patch uses the already parsed builder and ring file name instead of argv[1], and also adds a note to the user if the used filename is differently to the one given as argument. Closes-Bug: 1482096 Change-Id: I2f8ef23aeab8b07caaa799f7dcd57e684b4b2ad2 --- swift/cli/ringbuilder.py | 42 +++++++++++++++++-------------- test/unit/cli/test_ringbuilder.py | 17 +++++++++++++ 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/swift/cli/ringbuilder.py b/swift/cli/ringbuilder.py index 25440530b1..c020df6c67 100755 --- a/swift/cli/ringbuilder.py +++ b/swift/cli/ringbuilder.py @@ -403,14 +403,15 @@ swift-ring-builder <builder_file> create <part_power> <replicas> print(Commands.create.__doc__.strip()) exit(EXIT_ERROR) builder = RingBuilder(int(argv[3]), float(argv[4]), int(argv[5])) - backup_dir = pathjoin(dirname(argv[1]), 'backups') + backup_dir = pathjoin(dirname(builder_file), 'backups') try: mkdir(backup_dir) except OSError as err: if err.errno != EEXIST: raise - builder.save(pathjoin(backup_dir, '%d.' % time() + basename(argv[1]))) - builder.save(argv[1]) + builder.save(pathjoin(backup_dir, + '%d.' % time() + basename(builder_file))) + builder.save(builder_file) exit(EXIT_SUCCESS) def default(): @@ -418,7 +419,7 @@ swift-ring-builder <builder_file> create <part_power> <replicas> swift-ring-builder <builder_file> Shows information about the ring and the devices within. """ - print('%s, build version %d' % (argv[1], builder.version)) + print('%s, build version %d' % (builder_file, builder.version)) regions = 0 zones = 0 balance = 0 @@ -546,7 +547,7 @@ swift-ring-builder <builder_file> list_parts if not builder._replica2part2dev: print('Specified builder file \"%s\" is not rebalanced yet. ' - 'Please rebalance first.' % argv[1]) + 'Please rebalance first.' % builder_file) exit(EXIT_ERROR) devs = _parse_list_parts_values(argv[3:]) @@ -612,7 +613,7 @@ swift-ring-builder <builder_file> add print('The on-disk ring builder is unchanged.') exit(EXIT_ERROR) - builder.save(argv[1]) + builder.save(builder_file) exit(EXIT_SUCCESS) def set_weight(): @@ -644,7 +645,7 @@ swift-ring-builder <builder_file> set_weight _parse_set_weight_values(argv[3:]) - builder.save(argv[1]) + builder.save(builder_file) exit(EXIT_SUCCESS) def set_info(): @@ -689,7 +690,7 @@ swift-ring-builder <builder_file> set_info print(err) exit(EXIT_ERROR) - builder.save(argv[1]) + builder.save(builder_file) exit(EXIT_SUCCESS) def remove(): @@ -754,7 +755,7 @@ swift-ring-builder <builder_file> search print('%s marked for removal and will ' 'be removed next rebalance.' % format_device(dev)) - builder.save(argv[1]) + builder.save(builder_file) exit(EXIT_SUCCESS) def rebalance(): @@ -856,9 +857,9 @@ swift-ring-builder <builder_file> rebalance [options] ts = time() builder.get_ring().save( pathjoin(backup_dir, '%d.' % ts + basename(ring_file))) - builder.save(pathjoin(backup_dir, '%d.' % ts + basename(argv[1]))) + builder.save(pathjoin(backup_dir, '%d.' % ts + basename(builder_file))) builder.get_ring().save(ring_file) - builder.save(argv[1]) + builder.save(builder_file) exit(status) def dispersion(): @@ -893,7 +894,7 @@ swift-ring-builder <builder_file> dispersion <search_filter> [options] status = EXIT_SUCCESS if not builder._replica2part2dev: print('Specified builder file \"%s\" is not rebalanced yet. ' - 'Please rebalance first.' % argv[1]) + 'Please rebalance first.' % builder_file) exit(EXIT_ERROR) usage = Commands.dispersion.__doc__.strip() parser = optparse.OptionParser(usage) @@ -1015,7 +1016,7 @@ swift-ring-builder <ring_file> write_builder [min_part_hours] def pretend_min_part_hours_passed(): builder.pretend_min_part_hours_passed() - builder.save(argv[1]) + builder.save(builder_file) exit(EXIT_SUCCESS) def set_min_part_hours(): @@ -1031,7 +1032,7 @@ swift-ring-builder <builder_file> set_min_part_hours <hours> builder.change_min_part_hours(int(argv[3])) print('The minimum number of hours before a partition can be ' 'reassigned is now set to %s' % argv[3]) - builder.save(argv[1]) + builder.save(builder_file) exit(EXIT_SUCCESS) def set_replicas(): @@ -1063,7 +1064,7 @@ swift-ring-builder <builder_file> set_replicas <replicas> builder.set_replicas(new_replicas) print('The replica count is now %.6f.' % builder.replicas) print('The change will take effect after the next rebalance.') - builder.save(argv[1]) + builder.save(builder_file) exit(EXIT_SUCCESS) def set_overload(): @@ -1106,7 +1107,7 @@ swift-ring-builder <builder_file> set_overload <overload>[%] print('The overload factor is now %0.2f%% (%.6f)' % ( builder.overload * 100, builder.overload)) print('The change will take effect after the next rebalance.') - builder.save(argv[1]) + builder.save(builder_file) exit(status) @@ -1139,6 +1140,9 @@ def main(arguments=None): exit(EXIT_SUCCESS) builder_file, ring_file = parse_builder_ring_filename_args(argv) + if builder_file != argv[1]: + print('Note: using %s instead of %s as builder file' % ( + builder_file, argv[1])) try: builder = RingBuilder.load(builder_file) @@ -1151,10 +1155,10 @@ def main(arguments=None): exit(EXIT_ERROR) except Exception as e: print('Problem occurred while reading builder file: %s. %s' % - (argv[1], e)) + (builder_file, e)) exit(EXIT_ERROR) - backup_dir = pathjoin(dirname(argv[1]), 'backups') + backup_dir = pathjoin(dirname(builder_file), 'backups') try: mkdir(backup_dir) except OSError as err: @@ -1167,7 +1171,7 @@ def main(arguments=None): command = argv[2] if argv[0].endswith('-safe'): try: - with lock_parent_directory(abspath(argv[1]), 15): + with lock_parent_directory(abspath(builder_file), 15): Commands.__dict__.get(command, Commands.unknown.im_func)() except exceptions.LockTimeout: print("Ring/builder dir currently locked.") diff --git a/test/unit/cli/test_ringbuilder.py b/test/unit/cli/test_ringbuilder.py index ec51d13f06..cf9efe59b0 100644 --- a/test/unit/cli/test_ringbuilder.py +++ b/test/unit/cli/test_ringbuilder.py @@ -1741,6 +1741,23 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin): err = exc self.assertEquals(err.code, 2) + def test_use_ringfile_as_builderfile(self): + mock_stdout = six.StringIO() + mock_stderr = six.StringIO() + + argv = ["", "object.ring.gz"] + + try: + with mock.patch("sys.stdout", mock_stdout): + with mock.patch("sys.stderr", mock_stderr): + ringbuilder.main(argv) + except SystemExit: + pass + expected = "Note: using object.builder instead of object.ring.gz " \ + "as builder file\n" \ + "Ring Builder file does not exist: object.builder\n" + self.assertEqual(expected, mock_stdout.getvalue()) + class TestRebalanceCommand(unittest.TestCase, RunSwiftRingBuilderMixin):