From a1134e4aa2cd40a95b9cda713dcc5ef5ffcc7e41 Mon Sep 17 00:00:00 2001
From: Mingyu Li
Date: Wed, 10 Feb 2016 00:19:17 +0800
Subject: [PATCH] Order devices in the output of swift-ring-builder
After the change to reuse device id's [1], the order of devices in the
output of swift-ring-builder is confusing. This patch list the devices
in order of (region, zone, ip, device).
The effect of this patch is as illustrated in [2].
This patch also partially fix Bug 1545016.
1. https://review.openstack.org/#/c/265461/
2. https://github.com/MicrowiseOnGitHub/tempfiles/blob/master/reorder_ring_output
Change-Id: I564ed1b8d0cd4a6250649689b1bce7ad3574fe57
Partial-Bug: 1545016
Closes-Bug: 1536743
---
swift/cli/ringbuilder.py | 5 ++-
test/unit/cli/test_default_sorted_output.stub | 10 ++++++
test/unit/cli/test_ringbuilder.py | 35 +++++++++++++++++++
3 files changed, 49 insertions(+), 1 deletion(-)
create mode 100644 test/unit/cli/test_default_sorted_output.stub
diff --git a/swift/cli/ringbuilder.py b/swift/cli/ringbuilder.py
index 1e1f2d97a4..087d677540 100644
--- a/swift/cli/ringbuilder.py
+++ b/swift/cli/ringbuilder.py
@@ -517,7 +517,10 @@ swift-ring-builder
balance_per_dev = builder._build_balance_per_dev()
header_line, print_dev_f = _make_display_device_table(builder)
print(header_line)
- for dev in builder._iter_devs():
+ for dev in sorted(
+ builder._iter_devs(),
+ key=lambda x: (x['region'], x['zone'], x['ip'], x['device'])
+ ):
flags = 'DEL' if dev in builder._remove_devs else ''
print_dev_f(dev, balance_per_dev[dev['id']], flags)
exit(EXIT_SUCCESS)
diff --git a/test/unit/cli/test_default_sorted_output.stub b/test/unit/cli/test_default_sorted_output.stub
new file mode 100644
index 0000000000..ab510fd3d3
--- /dev/null
+++ b/test/unit/cli/test_default_sorted_output.stub
@@ -0,0 +1,10 @@
+__RINGFILE__, build version 9, id __BUILDER_ID__
+64 partitions, 3.000000 replicas, 2 regions, 4 zones, 4 devices, 100.00 balance, 0.00 dispersion
+The minimum number of hours before a partition can be reassigned is 1 (1:00:00 remaining)
+The overload factor is 0.00% (0.000000)
+Ring file __RINGFILE__.ring.gz is obsolete
+Devices: id region zone ip address:port replication ip:port name weight partitions balance flags meta
+ 1 1 1 127.0.0.2:6201 127.0.0.2:6201 sda2 100.00 64 33.33
+ 4 1 2 127.0.0.5:6004 127.0.0.5:6004 sda5 100.00 64 33.33
+ 0 2 1 127.0.0.6:6005 127.0.0.6:6005 sdb6 100.00 0 -100.00
+ 2 2 2 127.0.0.3:6202 127.0.0.3:6202 sdc3 100.00 64 33.33
diff --git a/test/unit/cli/test_ringbuilder.py b/test/unit/cli/test_ringbuilder.py
index 568286c019..96eded2fac 100644
--- a/test/unit/cli/test_ringbuilder.py
+++ b/test/unit/cli/test_ringbuilder.py
@@ -1754,6 +1754,41 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
(self.tmpfile, ring.id, self.tmpfile)
self.assertEqual(expected, mock_stdout.getvalue())
+ def test_default_sorted_output(self):
+ mock_stdout = six.StringIO()
+ mock_stderr = six.StringIO()
+
+ # Create a sample ring and remove/add some devices.
+ ring = self.create_sample_ring()
+ argv = ["", self.tmpfile, "add",
+ "--region", "1", "--zone", "2",
+ "--ip", "127.0.0.5", "--port", "6004",
+ "--replication-ip", "127.0.0.5",
+ "--replication-port", "6004",
+ "--device", "sda5", "--weight", "100.0"]
+ self.assertRaises(SystemExit, ringbuilder.main, argv)
+ argv = ["", self.tmpfile, "remove", "--id", "0"]
+ self.assertRaises(SystemExit, ringbuilder.main, argv)
+ argv = ["", self.tmpfile, "remove", "--id", "3"]
+ self.assertRaises(SystemExit, ringbuilder.main, argv)
+ argv = ["", self.tmpfile, "rebalance"]
+ self.assertRaises(SystemExit, ringbuilder.main, argv)
+ argv = \
+ ["", self.tmpfile, "add",
+ "--region", "2", "--zone", "1",
+ "--ip", "127.0.0.6", "--port", "6005",
+ "--replication-ip", "127.0.0.6",
+ "--replication-port", "6005",
+ "--device", "sdb6", "--weight", "100.0"]
+ self.assertRaises(SystemExit, ringbuilder.main, argv)
+
+ # Check the order of the devices listed the output.
+ argv = ["", self.tmpfile]
+ with mock.patch("sys.stdout", mock_stdout):
+ with mock.patch("sys.stderr", mock_stderr):
+ self.assertRaises(SystemExit, ringbuilder.main, argv)
+ self.assertOutputStub(mock_stdout.getvalue(), builder_id=ring.id)
+
def test_default_ringfile_check(self):
self.create_sample_ring()