Merge "swift-ring-builder output corrected for ipv6"

This commit is contained in:
Jenkins 2016-08-11 17:35:13 +00:00 committed by Gerrit Code Review
commit 6d472f8a7a
4 changed files with 171 additions and 22 deletions

View File

@ -39,7 +39,7 @@ from swift.common.ring.utils import validate_args, \
parse_builder_ring_filename_args, parse_search_value, \ parse_builder_ring_filename_args, parse_search_value, \
parse_search_values_from_opts, parse_change_values_from_opts, \ parse_search_values_from_opts, parse_change_values_from_opts, \
dispersion_report, parse_add_value dispersion_report, parse_add_value
from swift.common.utils import lock_parent_directory from swift.common.utils import lock_parent_directory, is_valid_ipv6
MAJOR_VERSION = 1 MAJOR_VERSION = 1
MINOR_VERSION = 3 MINOR_VERSION = 3
@ -376,6 +376,58 @@ def _parse_remove_values(argvish):
exit(EXIT_ERROR) exit(EXIT_ERROR)
def _make_display_device_table(builder):
ip_width = 10
port_width = 4
rep_ip_width = 14
rep_port_width = 4
ip_ipv6 = rep_ipv6 = False
for dev in builder._iter_devs():
if is_valid_ipv6(dev['ip']):
ip_ipv6 = True
if is_valid_ipv6(dev['replication_ip']):
rep_ipv6 = True
ip_width = max(len(dev['ip']), ip_width)
rep_ip_width = max(len(dev['replication_ip']), rep_ip_width)
port_width = max(len(str(dev['port'])), port_width)
rep_port_width = max(len(str(dev['replication_port'])),
rep_port_width)
if ip_ipv6:
ip_width += 2
if rep_ipv6:
rep_ip_width += 2
header_line = ('Devices:%5s %6s %4s %' + str(ip_width)
+ 's:%-' + str(port_width) + 's %' +
str(rep_ip_width) + 's:%-' + str(rep_port_width) +
's %5s %6s %10s %7s %5s %s') % (
'id', 'region', 'zone', 'ip address',
'port', 'replication ip', 'port', 'name',
'weight', 'partitions', 'balance', 'flags',
'meta')
def print_dev_f(dev, balance_per_dev=0.00, flags=''):
def get_formated_ip(key):
value = dev[key]
if ':' in value:
value = '[%s]' % value
return value
dev_ip = get_formated_ip('ip')
dev_replication_ip = get_formated_ip('replication_ip')
format_string = ''.join(['%13d %6d %4d ',
'%', str(ip_width), 's:%-',
str(port_width), 'd ', '%',
str(rep_ip_width), 's', ':%-',
str(rep_port_width), 'd %5s %6.02f'
' %10s %7.02f %5s %s'])
args = (dev['id'], dev['region'], dev['zone'], dev_ip, dev['port'],
dev_replication_ip, dev['replication_port'], dev['device'],
dev['weight'], dev['parts'], balance_per_dev, flags,
dev['meta'])
print(format_string % args)
return header_line, print_dev_f
class Commands(object): class Commands(object):
@staticmethod @staticmethod
def unknown(): def unknown():
@ -458,18 +510,11 @@ swift-ring-builder <builder_file>
if builder.devs: if builder.devs:
balance_per_dev = builder._build_balance_per_dev() balance_per_dev = builder._build_balance_per_dev()
print('Devices: id region zone ip address port ' header_line, print_dev_f = _make_display_device_table(builder)
'replication ip replication port name ' print(header_line)
'weight partitions balance flags meta')
for dev in builder._iter_devs(): for dev in builder._iter_devs():
flags = 'DEL' if dev in builder._remove_devs else '' flags = 'DEL' if dev in builder._remove_devs else ''
print(' %5d %7d %5d %15s %5d %15s %17d %9s %6.02f ' print_dev_f(dev, balance_per_dev[dev['id']], flags)
'%10s %7.02f %5s %s' %
(dev['id'], dev['region'], dev['zone'], dev['ip'],
dev['port'], dev['replication_ip'],
dev['replication_port'], dev['device'], dev['weight'],
dev['parts'], balance_per_dev[dev['id']], flags,
dev['meta']))
exit(EXIT_SUCCESS) exit(EXIT_SUCCESS)
@staticmethod @staticmethod
@ -905,7 +950,7 @@ swift-ring-builder <builder_file> dispersion <search_filter> [options]
--verbose option will display dispersion graph broken down by tier --verbose option will display dispersion graph broken down by tier
You can filter which tiers are evaluated to drill down using a regex You can filter which tiers are evaluated to drill down using a regex
in the optional search_filter arguemnt. i.e. in the optional search_filter argument. i.e.
swift-ring-builder <builder_file> dispersion "r\d+z\d+$" -v swift-ring-builder <builder_file> dispersion "r\d+z\d+$" -v

View File

@ -0,0 +1,11 @@
__RINGFILE__, build version 4
64 partitions, 3.000000 replicas, 4 regions, 4 zones, 4 devices, 100.00 balance, 0.00 dispersion
The minimum number of hours before a partition can be reassigned is 1 (0:00:00 remaining)
The overload factor is 0.00% (0.000000)
Ring file __RINGFILE__.ring.gz not found, probably it hasn't been written yet
Devices: id region zone ip address:port replication ip:port name weight partitions balance flags meta
0 0 0 127.0.0.1:6200 127.0.0.1:6200 sda1 100.00 0 -100.00 some meta data
1 1 1 127.0.0.2:6201 127.0.0.2:6201 sda2 100.00 0 -100.00
2 2 2 127.0.0.3:6202 127.0.0.3:6202 sdc3 100.00 0 -100.00
3 3 3 127.0.0.4:6203 127.0.0.4:6203 sdd4 100.00 0 -100.00

View File

@ -0,0 +1,10 @@
__RINGFILE__, build version 4
256 partitions, 3.000000 replicas, 4 regions, 4 zones, 4 devices, 100.00 balance, 0.00 dispersion
The minimum number of hours before a partition can be reassigned is 1 (0:00:00 remaining)
The overload factor is 0.00% (0.000000)
Ring file __RINGFILE__.ring.gz not found, probably it hasn't been written yet
Devices: id region zone ip address:port replication ip:port name weight partitions balance flags meta
0 0 0 [2001:db8:85a3::8a2e:370:7334]:6200 [2001:db8:85a3::8a2e:370:7334]:6200 sda1 100.00 0 -100.00 some meta data
1 1 1 127.0.0.1:66201 127.0.0.1:66201 sda2 100.00 0 -100.00
2 2 2 [2001:db8:85a3::8a2e:370:7336]:6202 127.0.10.127:7070 sdc3 100.00 0 -100.00
3 3 3 [2001:db8:85a3::8a2e:370:7337]:6203 [7001:db8:85a3::8a2e:370:7337]:11664 sdd4 100.00 0 -100.00

View File

@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import errno
import itertools
import logging import logging
import mock import mock
import os import os
@ -92,6 +94,43 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
except OSError: except OSError:
pass pass
def assertOutputStub(self, output, ext='stub'):
"""
assert that the given output string is equal to a in-tree stub file,
if a test needs to check multiple outputs it can use custom ext's
"""
filepath = os.path.abspath(
os.path.join(os.path.dirname(__file__), self.id().split('.')[-1]))
print(filepath)
filepath = '%s.%s' % (filepath, ext)
try:
with open(filepath, 'r') as f:
stub = f.read()
except (IOError, OSError) as e:
if e.errno == errno.ENOENT:
self.fail('%r does not exist' % filepath)
else:
self.fail('%r could not be read (%s)' % (filepath, e))
output = output.replace(self.tempfile, '__RINGFILE__')
for i, (value, expected) in enumerate(
itertools.izip_longest(
output.splitlines(), stub.splitlines())):
# N.B. differences in trailing whitespace are ignored!
value = (value or '').rstrip()
expected = (expected or '').rstrip()
try:
self.assertEqual(value, expected)
except AssertionError:
msg = 'Line #%s value is not like expected:\n%r\n%r' % (
i, value, expected)
msg += '\n\nFull output was:\n'
for i, line in enumerate(output.splitlines()):
msg += '%3d: %s\n' % (i, line)
msg += '\n\nCompared to stub:\n'
for i, line in enumerate(stub.splitlines()):
msg += '%3d: %s\n' % (i, line)
self.fail(msg)
def create_sample_ring(self, part_power=6): def create_sample_ring(self, part_power=6):
""" Create a sample ring with four devices """ Create a sample ring with four devices
@ -1614,6 +1653,50 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
argv = ["", self.tmpfile] argv = ["", self.tmpfile]
self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv) self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
def test_default_output(self):
self.create_sample_ring()
out, err = self.run_srb('')
self.assertOutputStub(out)
def test_ipv6_output(self):
ring = RingBuilder(8, 3, 1)
ring.add_dev({'weight': 100.0,
'region': 0,
'zone': 0,
'ip': '2001:db8:85a3::8a2e:370:7334',
'port': 6200,
'device': 'sda1',
'meta': 'some meta data',
})
ring.add_dev({'weight': 100.0,
'region': 1,
'zone': 1,
'ip': '127.0.0.1',
'port': 66201,
'device': 'sda2',
})
ring.add_dev({'weight': 100.0,
'region': 2,
'zone': 2,
'ip': '2001:db8:85a3::8a2e:370:7336',
'port': 6202,
'device': 'sdc3',
'replication_ip': '127.0.10.127',
'replication_port': 7070,
})
ring.add_dev({'weight': 100.0,
'region': 3,
'zone': 3,
'ip': '2001:db8:85a3::8a2e:370:7337',
'port': 6203,
'device': 'sdd4',
'replication_ip': '7001:db8:85a3::8a2e:370:7337',
'replication_port': 11664,
})
ring.save(self.tmpfile)
out, err = self.run_srb('')
self.assertOutputStub(out)
def test_default_show_removed(self): def test_default_show_removed(self):
mock_stdout = six.StringIO() mock_stdout = six.StringIO()
mock_stderr = six.StringIO() mock_stderr = six.StringIO()
@ -1642,20 +1725,20 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
"The overload factor is 0.00%% (0.000000)\n" \ "The overload factor is 0.00%% (0.000000)\n" \
"Ring file %s.ring.gz not found, probably " \ "Ring file %s.ring.gz not found, probably " \
"it hasn't been written yet\n" \ "it hasn't been written yet\n" \
"Devices: id region zone ip address port " \ "Devices: id region zone ip address:port " \
"replication ip replication port name weight " \ "replication ip:port name weight " \
"partitions balance flags meta\n" \ "partitions balance flags meta\n" \
" 0 0 0 127.0.0.1 6200 " \ " 0 0 0 127.0.0.1:6200 " \
"127.0.0.1 6200 sda1 100.00" \ " 127.0.0.1:6200 sda1 100.00" \
" 0 -100.00 some meta data\n" \ " 0 -100.00 some meta data\n" \
" 1 1 1 127.0.0.2 6201 " \ " 1 1 1 127.0.0.2:6201 " \
"127.0.0.2 6201 sda2 0.00" \ " 127.0.0.2:6201 sda2 0.00" \
" 0 0.00 DEL \n" \ " 0 0.00 DEL \n" \
" 2 2 2 127.0.0.3 6202 " \ " 2 2 2 127.0.0.3:6202 " \
"127.0.0.3 6202 sdc3 100.00" \ " 127.0.0.3:6202 sdc3 100.00" \
" 0 -100.00 \n" \ " 0 -100.00 \n" \
" 3 3 3 127.0.0.4 6203 " \ " 3 3 3 127.0.0.4:6203 " \
"127.0.0.4 6203 sdd4 0.00" \ " 127.0.0.4:6203 sdd4 0.00" \
" 0 0.00 \n" % (self.tmpfile, self.tmpfile) " 0 0.00 \n" % (self.tmpfile, self.tmpfile)
self.assertEqual(expected, mock_stdout.getvalue()) self.assertEqual(expected, mock_stdout.getvalue())