diff --git a/swift/cli/ringbuilder.py b/swift/cli/ringbuilder.py index 983dbfde6c..eaaeaa6d9f 100755 --- a/swift/cli/ringbuilder.py +++ b/swift/cli/ringbuilder.py @@ -1005,6 +1005,8 @@ swift-ring-builder write_builder [min_part_hours] min_part_hours = 24 ring = Ring(ring_file) for dev in ring.devs: + if dev is None: + continue dev.update({ 'parts': 0, 'parts_wanted': 0, diff --git a/test/unit/cli/test_ringbuilder.py b/test/unit/cli/test_ringbuilder.py index e1fd35ca0e..1d7ef27340 100644 --- a/test/unit/cli/test_ringbuilder.py +++ b/test/unit/cli/test_ringbuilder.py @@ -1717,6 +1717,30 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin): err = e self.assertEqual(err.code, 2) + def test_write_builder_after_device_removal(self): + # Test regenerating builder file after having removed a device + # and lost the builder file + self.create_sample_ring() + + argv = ["", self.tmpfile, "add", "r1z1-127.0.0.1:6000/sdb" "1.0"] + self.assertRaises(SystemExit, ringbuilder.main, argv) + argv = ["", self.tmpfile, "add", "r1z1-127.0.0.1:6000/sdc" "1.0"] + self.assertRaises(SystemExit, ringbuilder.main, argv) + argv = ["", self.tmpfile, "rebalance"] + self.assertRaises(SystemExit, ringbuilder.main, argv) + + argv = ["", self.tmpfile, "remove", "--id", "0"] + self.assertRaises(SystemExit, ringbuilder.main, argv) + argv = ["", self.tmpfile, "rebalance"] + self.assertRaises(SystemExit, ringbuilder.main, argv) + + backup_file = os.path.join(os.path.dirname(self.tmpfile), + os.path.basename(self.tmpfile) + ".ring.gz") + os.remove(self.tmpfile) # loses file... + + argv = ["", backup_file, "write_builder"] + self.assertEqual(ringbuilder.main(argv), None) + def test_warn_at_risk(self): # when the number of total part replicas (3 * 2 ** 4 = 48 in # this ring) is less than the total units of weight (310 in this