Add info about state of ring file to default command.

Try to find ring file, load and compare it with builder file, then show result state.
Examples:
Ring file object.ring.gz not found, probably it hasn't been written yet
Ring file object.ring.gz is up-to-date
Ring file object.ring.gz is obsolete
Ring file object.ring.gz is invalid: ValueError('string length not a multiple of item size',)

Change-Id: I4d769aa5fe1c2b1167ec088aa372874f7d13ae48
This commit is contained in:
Peter Lisák 2015-12-03 16:48:18 +01:00 committed by Ondřej Nový
parent 6a473e3d7b
commit f56f29ef7a
2 changed files with 81 additions and 2 deletions

View File

@ -33,7 +33,7 @@ from six.moves import zip as izip
from six.moves import input
from swift.common import exceptions
from swift.common.ring import RingBuilder, Ring
from swift.common.ring import RingBuilder, Ring, RingData
from swift.common.ring.builder import MAX_BALANCE
from swift.common.ring.utils import validate_args, \
validate_and_normalize_ip, build_dev_from_opts, \
@ -450,6 +450,23 @@ swift-ring-builder <builder_file>
timedelta(seconds=builder.min_part_seconds_left)))
print('The overload factor is %0.2f%% (%.6f)' % (
builder.overload * 100, builder.overload))
# compare ring file against builder file
if not exists(ring_file):
print('Ring file %s not found, '
'probably it hasn\'t been written yet' % ring_file)
else:
builder_dict = builder.get_ring().to_dict()
try:
ring_dict = RingData.load(ring_file).to_dict()
except Exception as exc:
print('Ring file %s is invalid: %r' % (ring_file, exc))
else:
if builder_dict == ring_dict:
print('Ring file %s is up-to-date' % ring_file)
else:
print('Ring file %s is obsolete' % ring_file)
if builder.devs:
balance_per_dev = builder._build_balance_per_dev()
print('Devices: id region zone ip address port '

View File

@ -16,6 +16,7 @@
import logging
import mock
import os
import re
import six
import tempfile
import unittest
@ -1741,6 +1742,8 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
"The minimum number of hours before a partition can be " \
"reassigned is 1 (0:00:00 remaining)\n" \
"The overload factor is 0.00%% (0.000000)\n" \
"Ring file %s.ring.gz not found, probably " \
"it hasn't been written yet\n" \
"Devices: id region zone ip address port " \
"replication ip replication port name weight " \
"partitions balance flags meta\n" \
@ -1755,9 +1758,68 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
" 0 -100.00 \n" \
" 3 3 3 127.0.0.4 6003 " \
"127.0.0.4 6003 sdd4 0.00" \
" 0 0.00 \n" % self.tmpfile
" 0 0.00 \n" % (self.tmpfile, self.tmpfile)
self.assertEqual(expected, mock_stdout.getvalue())
def test_default_ringfile_check(self):
self.create_sample_ring()
# ring file not created
mock_stdout = six.StringIO()
mock_stderr = six.StringIO()
argv = ["", self.tmpfile]
with mock.patch("sys.stdout", mock_stdout):
with mock.patch("sys.stderr", mock_stderr):
self.assertRaises(SystemExit, ringbuilder.main, argv)
rnf = re.compile("Ring file .*\.ring\.gz not found")
self.assertTrue(rnf.findall(mock_stdout.getvalue()))
# write ring file
argv = ["", self.tmpfile, "rebalance"]
self.assertRaises(SystemExit, ringbuilder.main, argv)
# ring file is up-to-date
mock_stdout = six.StringIO()
argv = ["", self.tmpfile]
with mock.patch("sys.stdout", mock_stdout):
with mock.patch("sys.stderr", mock_stderr):
self.assertRaises(SystemExit, ringbuilder.main, argv)
rutd = re.compile("Ring file .*\.ring\.gz is up-to-date")
self.assertTrue(rutd.findall(mock_stdout.getvalue()))
# change builder (set weight)
argv = ["", self.tmpfile, "set_weight", "0", "--id", "3"]
self.assertRaises(SystemExit, ringbuilder.main, argv)
# ring file is obsolete after set_weight
mock_stdout = six.StringIO()
argv = ["", self.tmpfile]
with mock.patch("sys.stdout", mock_stdout):
with mock.patch("sys.stderr", mock_stderr):
self.assertRaises(SystemExit, ringbuilder.main, argv)
ro = re.compile("Ring file .*\.ring\.gz is obsolete")
self.assertTrue(ro.findall(mock_stdout.getvalue()))
# write ring file
argv = ["", self.tmpfile, "write_ring"]
self.assertRaises(SystemExit, ringbuilder.main, argv)
# ring file up-to-date again
mock_stdout = six.StringIO()
argv = ["", self.tmpfile]
with mock.patch("sys.stdout", mock_stdout):
with mock.patch("sys.stderr", mock_stderr):
self.assertRaises(SystemExit, ringbuilder.main, argv)
self.assertTrue(rutd.findall(mock_stdout.getvalue()))
# Break ring file e.g. just make it empty
open('%s.ring.gz' % self.tmpfile, 'w').close()
# ring file is invalid
mock_stdout = six.StringIO()
argv = ["", self.tmpfile]
with mock.patch("sys.stdout", mock_stdout):
with mock.patch("sys.stderr", mock_stderr):
self.assertRaises(SystemExit, ringbuilder.main, argv)
ro = re.compile("Ring file .*\.ring\.gz is invalid")
self.assertTrue(ro.findall(mock_stdout.getvalue()))
def test_rebalance(self):
self.create_sample_ring()
argv = ["", self.tmpfile, "rebalance", "3"]