There's a bunch of moving pieces here:
- Add a new RingWriter class.
  Stick it in a new swift.common.ring.io module. You *can* use it like
  the old gzip file, but you can also define named sections which can
  be referenced later on read. Section names may be arbitrary strings,
  but the "swift/" prefix is reserved for upstream use. Sections must
  contain a single length-value encoded BLOB. If sections are used, an
  additional BLOB is written at the end containing a JSON section-index,
  followed by an uncompressed offset for the index.
  Move RingReader to ring/io.py, too.
- Clean up some ring metadata handling:
  - Drop MD5 tracking in RingReader. It was brittle at best anyway, and
    nothing uses it. YAGNI
  - Fix size/raw_size attributes when loading only metadata.
- Add the ability to seek within RingReaders, though you need to know
  what you're doing and only seek to flush points.
- Let RingBuilder objects change how wide their replica2part2dev_id
  arrays are. Add a dev_id_bytes key to serialized ring metadata.
  dev_id_bytes may be either 2 or 4, but 4 requires v2 rings. We
  considered allowing dev_id_bytes of 1, but dropped it as unnecessary
  complexity for a niche use case.
- swift-ring-builder version subcommand added, which takes a ring. This
  lets operators see the serialization format of a ring on disk:
  $ swift-ring-builder object.ring.gz version
  object.ring.gz: Serialization version: 2 (2-byte IDs), build version: 54
Signed-off-by: Tim Burke <tim.burke@gmail.com>
Change-Id: Ia0ac4ea2006d8965d7fdb6659d355c77386adb70
		
	
		
			
				
	
	
		
			3089 lines
		
	
	
		
			123 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			3089 lines
		
	
	
		
			123 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Copyright (c) 2014 Christian Schwede <christian.schwede@enovance.com>
 | 
						|
#
 | 
						|
# Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
# you may not use this file except in compliance with the License.
 | 
						|
# You may obtain a copy of the License at
 | 
						|
#
 | 
						|
#    http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
#
 | 
						|
# Unless required by applicable law or agreed to in writing, software
 | 
						|
# distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
						|
# implied.
 | 
						|
# See the License for the specific language governing permissions and
 | 
						|
# limitations under the License.
 | 
						|
 | 
						|
import errno
 | 
						|
import itertools
 | 
						|
import logging
 | 
						|
from unittest import mock
 | 
						|
import os
 | 
						|
import re
 | 
						|
import io
 | 
						|
import tempfile
 | 
						|
import unittest
 | 
						|
import uuid
 | 
						|
import shlex
 | 
						|
import shutil
 | 
						|
import time
 | 
						|
 | 
						|
from swift.cli import ringbuilder
 | 
						|
from swift.cli.ringbuilder import EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR
 | 
						|
from swift.common import exceptions
 | 
						|
from swift.common.ring import RingBuilder
 | 
						|
from swift.common.ring.io import RingReader
 | 
						|
from swift.common.ring.composite_builder import CompositeRingBuilder
 | 
						|
 | 
						|
from test.unit import Timeout, write_stub_builder
 | 
						|
 | 
						|
try:
 | 
						|
    from itertools import zip_longest
 | 
						|
except ImportError:
 | 
						|
    from itertools import izip_longest as zip_longest
 | 
						|
 | 
						|
 | 
						|
class RunSwiftRingBuilderMixin(object):
 | 
						|
 | 
						|
    def run_srb(self, *argv, **kwargs):
 | 
						|
        if len(argv) == 1 and isinstance(argv[0], str):
 | 
						|
            # convert a single string to a list
 | 
						|
            argv = shlex.split(argv[0])
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        mock_stderr = io.StringIO()
 | 
						|
 | 
						|
        if 'exp_results' in kwargs:
 | 
						|
            exp_results = kwargs['exp_results']
 | 
						|
        else:
 | 
						|
            exp_results = None
 | 
						|
 | 
						|
        srb_args = ["", self.tempfile] + [str(s) for s in argv]
 | 
						|
 | 
						|
        try:
 | 
						|
            with mock.patch("sys.stdout", mock_stdout):
 | 
						|
                with mock.patch("sys.stderr", mock_stderr):
 | 
						|
                    ringbuilder.main(srb_args)
 | 
						|
        except SystemExit as err:
 | 
						|
            valid_exit_codes = None
 | 
						|
            if exp_results is not None and 'valid_exit_codes' in exp_results:
 | 
						|
                valid_exit_codes = exp_results['valid_exit_codes']
 | 
						|
            else:
 | 
						|
                valid_exit_codes = (0, 1)  # (success, warning)
 | 
						|
 | 
						|
            if err.code not in valid_exit_codes:
 | 
						|
                msg = 'Unexpected exit status %s\n' % err.code
 | 
						|
                msg += 'STDOUT:\n%s\nSTDERR:\n%s\n' % (
 | 
						|
                    mock_stdout.getvalue(), mock_stderr.getvalue())
 | 
						|
                self.fail(msg)
 | 
						|
        return (mock_stdout.getvalue(), mock_stderr.getvalue())
 | 
						|
 | 
						|
 | 
						|
class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
 | 
						|
 | 
						|
    def __init__(self, *args, **kwargs):
 | 
						|
        super(TestCommands, self).__init__(*args, **kwargs)
 | 
						|
 | 
						|
        # List of search values for various actions
 | 
						|
        # These should all match the first device in the sample ring
 | 
						|
        # (see below) but not the second device
 | 
						|
        self.search_values = ["d0", "/sda1", "r0", "z0", "z0-127.0.0.1",
 | 
						|
                              "127.0.0.1", "z0:6200", ":6200", "R127.0.0.1",
 | 
						|
                              "127.0.0.1R127.0.0.1", "R:6200",
 | 
						|
                              "_some meta data"]
 | 
						|
 | 
						|
    def setUp(self):
 | 
						|
        self.tmpdir = tempfile.mkdtemp()
 | 
						|
        tmpf = tempfile.NamedTemporaryFile(dir=self.tmpdir)
 | 
						|
        self.tempfile = self.tmpfile = tmpf.name
 | 
						|
 | 
						|
    def tearDown(self):
 | 
						|
        try:
 | 
						|
            shutil.rmtree(self.tmpdir, True)
 | 
						|
        except OSError:
 | 
						|
            pass
 | 
						|
 | 
						|
    def assertOutputStub(self, output, ext='stub',
 | 
						|
                         builder_id='(not assigned)'):
 | 
						|
        """
 | 
						|
        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__')
 | 
						|
        stub = stub.replace('__BUILDER_ID__', builder_id)
 | 
						|
        for i, (value, expected) in enumerate(
 | 
						|
                zip_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, replicas=3, overload=None,
 | 
						|
                           empty=False):
 | 
						|
        """
 | 
						|
        Create a sample ring with four devices
 | 
						|
 | 
						|
        At least four devices are needed to test removing
 | 
						|
        a device, since having less devices than replicas
 | 
						|
        is not allowed.
 | 
						|
        """
 | 
						|
 | 
						|
        # Ensure there is no existing test builder file because
 | 
						|
        # create_sample_ring() might be used more than once in a single test
 | 
						|
        try:
 | 
						|
            os.remove(self.tmpfile)
 | 
						|
        except OSError:
 | 
						|
            pass
 | 
						|
 | 
						|
        ring = RingBuilder(part_power, replicas, 1)
 | 
						|
        if overload is not None:
 | 
						|
            ring.set_overload(overload)
 | 
						|
        if not empty:
 | 
						|
            ring.add_dev({'weight': 100.0,
 | 
						|
                          'region': 0,
 | 
						|
                          'zone': 0,
 | 
						|
                          'ip': '127.0.0.1',
 | 
						|
                          'port': 6200,
 | 
						|
                          'device': 'sda1',
 | 
						|
                          'meta': 'some meta data',
 | 
						|
                          })
 | 
						|
            ring.add_dev({'weight': 100.0,
 | 
						|
                          'region': 1,
 | 
						|
                          'zone': 1,
 | 
						|
                          'ip': '127.0.0.2',
 | 
						|
                          'port': 6201,
 | 
						|
                          'device': 'sda2'
 | 
						|
                          })
 | 
						|
            ring.add_dev({'weight': 100.0,
 | 
						|
                          'region': 2,
 | 
						|
                          'zone': 2,
 | 
						|
                          'ip': '127.0.0.3',
 | 
						|
                          'port': 6202,
 | 
						|
                          'device': 'sdc3'
 | 
						|
                          })
 | 
						|
            ring.add_dev({'weight': 100.0,
 | 
						|
                          'region': 3,
 | 
						|
                          'zone': 3,
 | 
						|
                          'ip': '127.0.0.4',
 | 
						|
                          'port': 6203,
 | 
						|
                          'device': 'sdd4'
 | 
						|
                          })
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
        return ring
 | 
						|
 | 
						|
    def assertSystemExit(self, return_code, func, *argv):
 | 
						|
        with self.assertRaises(SystemExit) as cm:
 | 
						|
            func(*argv)
 | 
						|
        self.assertEqual(return_code, cm.exception.code)
 | 
						|
 | 
						|
    def test_parse_search_values_old_format(self):
 | 
						|
        # Test old format
 | 
						|
        argv = ["d0r0z0-127.0.0.1:6200R127.0.0.1:6200/sda1_some meta data"]
 | 
						|
        search_values = ringbuilder._parse_search_values(argv)
 | 
						|
        self.assertEqual(search_values['id'], 0)
 | 
						|
        self.assertEqual(search_values['region'], 0)
 | 
						|
        self.assertEqual(search_values['zone'], 0)
 | 
						|
        self.assertEqual(search_values['ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(search_values['port'], 6200)
 | 
						|
        self.assertEqual(search_values['replication_ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(search_values['replication_port'], 6200)
 | 
						|
        self.assertEqual(search_values['device'], 'sda1')
 | 
						|
        self.assertEqual(search_values['meta'], 'some meta data')
 | 
						|
 | 
						|
    def test_parse_search_values_new_format(self):
 | 
						|
        # Test new format
 | 
						|
        argv = ["--id", "0", "--region", "0", "--zone", "0",
 | 
						|
                "--ip", "127.0.0.1",
 | 
						|
                "--port", "6200",
 | 
						|
                "--replication-ip", "127.0.0.1",
 | 
						|
                "--replication-port", "6200",
 | 
						|
                "--device", "sda1", "--meta", "some meta data",
 | 
						|
                "--weight", "100"]
 | 
						|
        search_values = ringbuilder._parse_search_values(argv)
 | 
						|
        self.assertEqual(search_values['id'], 0)
 | 
						|
        self.assertEqual(search_values['region'], 0)
 | 
						|
        self.assertEqual(search_values['zone'], 0)
 | 
						|
        self.assertEqual(search_values['ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(search_values['port'], 6200)
 | 
						|
        self.assertEqual(search_values['replication_ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(search_values['replication_port'], 6200)
 | 
						|
        self.assertEqual(search_values['device'], 'sda1')
 | 
						|
        self.assertEqual(search_values['meta'], 'some meta data')
 | 
						|
        self.assertEqual(search_values['weight'], 100)
 | 
						|
 | 
						|
    def test_parse_search_values_number_of_arguments(self):
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["--region", "2", "test"]
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._parse_search_values, argv)
 | 
						|
 | 
						|
    def test_find_parts(self):
 | 
						|
        rb = RingBuilder(8, 3, 0)
 | 
						|
        rb.add_dev({'id': 0, 'region': 1, 'zone': 0, 'weight': 100,
 | 
						|
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sda1'})
 | 
						|
        rb.add_dev({'id': 3, 'region': 1, 'zone': 0, 'weight': 100,
 | 
						|
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdb1'})
 | 
						|
        rb.add_dev({'id': 1, 'region': 1, 'zone': 1, 'weight': 100,
 | 
						|
                    'ip': '127.0.0.1', 'port': 10001, 'device': 'sda1'})
 | 
						|
        rb.add_dev({'id': 4, 'region': 1, 'zone': 1, 'weight': 100,
 | 
						|
                    'ip': '127.0.0.1', 'port': 10001, 'device': 'sdb1'})
 | 
						|
        rb.add_dev({'id': 2, 'region': 1, 'zone': 2, 'weight': 100,
 | 
						|
                    'ip': '127.0.0.1', 'port': 10002, 'device': 'sda1'})
 | 
						|
        rb.add_dev({'id': 5, 'region': 1, 'zone': 2, 'weight': 100,
 | 
						|
                    'ip': '127.0.0.1', 'port': 10002, 'device': 'sdb1'})
 | 
						|
        rb.rebalance()
 | 
						|
 | 
						|
        rb.add_dev({'id': 6, 'region': 2, 'zone': 1, 'weight': 10,
 | 
						|
                    'ip': '127.0.0.1', 'port': 10004, 'device': 'sda1'})
 | 
						|
        rb.pretend_min_part_hours_passed()
 | 
						|
        rb.rebalance()
 | 
						|
 | 
						|
        ringbuilder.builder = rb
 | 
						|
        sorted_partition_count = ringbuilder._find_parts(
 | 
						|
            rb.search_devs({'ip': '127.0.0.1'}))
 | 
						|
 | 
						|
        # Expect 256 partitions in the output
 | 
						|
        self.assertEqual(256, len(sorted_partition_count))
 | 
						|
 | 
						|
        # Each partitions should have 3 replicas
 | 
						|
        for partition, count in sorted_partition_count:
 | 
						|
            self.assertEqual(
 | 
						|
                3, count, "Partition %d has only %d replicas" %
 | 
						|
                (partition, count))
 | 
						|
 | 
						|
    def test_parse_list_parts_values_number_of_arguments(self):
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["--region", "2", "test"]
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._parse_list_parts_values, argv)
 | 
						|
 | 
						|
    def test_parse_add_values_number_of_arguments(self):
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["--region", "2", "test"]
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._parse_add_values, argv)
 | 
						|
 | 
						|
    def test_set_weight_values_no_devices(self):
 | 
						|
        # Test no devices
 | 
						|
        # _set_weight_values doesn't take argv-like arguments
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._set_weight_values, [], 100, {})
 | 
						|
 | 
						|
    def test_parse_set_weight_values_number_of_arguments(self):
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["r1", "100", "r2"]
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._parse_set_weight_values, argv)
 | 
						|
 | 
						|
        argv = ["--region", "2"]
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._parse_set_weight_values, argv)
 | 
						|
 | 
						|
    def test_set_region_values_no_devices(self):
 | 
						|
        # Test no devices
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._set_region_values, [], 100, {})
 | 
						|
 | 
						|
    def test_parse_set_region_values_number_of_arguments(self):
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["r1", "100", "r2"]
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._parse_set_region_values, argv)
 | 
						|
 | 
						|
        argv = ["--region", "2"]
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._parse_set_region_values, argv)
 | 
						|
 | 
						|
    def test_set_zone_values_no_devices(self):
 | 
						|
        # Test no devices
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._set_zone_values, [], 100, {})
 | 
						|
 | 
						|
    def test_parse_set_zone_values_number_of_arguments(self):
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["r1", "100", "r2"]
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._parse_set_zone_values, argv)
 | 
						|
 | 
						|
        argv = ["--region", "2"]
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._parse_set_zone_values, argv)
 | 
						|
 | 
						|
    def test_set_info_values_no_devices(self):
 | 
						|
        # Test no devices
 | 
						|
        # _set_info_values doesn't take argv-like arguments
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._set_info_values, [], 100, {})
 | 
						|
 | 
						|
    def test_parse_set_info_values_number_of_arguments(self):
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["r1", "127.0.0.1", "r2"]
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._parse_set_info_values, argv)
 | 
						|
 | 
						|
    def test_parse_remove_values_number_of_arguments(self):
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["--region", "2", "test"]
 | 
						|
        self.assertSystemExit(
 | 
						|
            EXIT_ERROR, ringbuilder._parse_remove_values, argv)
 | 
						|
 | 
						|
    def test_create_ring(self):
 | 
						|
        argv = ["", self.tmpfile, "create", "6", "3.14159265359", "1"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertEqual(ring.part_power, 6)
 | 
						|
        self.assertEqual(ring.replicas, 3.14159265359)
 | 
						|
        self.assertEqual(ring.min_part_hours, 1)
 | 
						|
 | 
						|
    def test_create_ring_number_of_arguments(self):
 | 
						|
        # Test missing arguments
 | 
						|
        argv = ["", self.tmpfile, "create"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_add_device_ipv4_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv4(old format)
 | 
						|
        argv = ["", self.tmpfile, "add",
 | 
						|
                "r2z3-127.0.0.1:6200/sda3_some meta data", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Check that device was created with given data
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertEqual(dev['region'], 2)
 | 
						|
        self.assertEqual(dev['zone'], 3)
 | 
						|
        self.assertEqual(dev['ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(dev['port'], 6200)
 | 
						|
        self.assertEqual(dev['device'], 'sda3')
 | 
						|
        self.assertEqual(dev['weight'], 3.14159265359)
 | 
						|
        self.assertEqual(dev['replication_ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(dev['replication_port'], 6200)
 | 
						|
        self.assertEqual(dev['meta'], 'some meta data')
 | 
						|
 | 
						|
    def test_add_duplicate_devices(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test adding duplicate devices
 | 
						|
        argv = ["", self.tmpfile, "add",
 | 
						|
                "r1z1-127.0.0.1:6200/sda9", "3.14159265359",
 | 
						|
                "r1z1-127.0.0.1:6200/sda9", "2"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_add_device_ipv6_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv6(old format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "r2z3-2001:0000:1234:0000:0000:C1C0:ABCD:0876:6200"
 | 
						|
             "R2::10:7000/sda3_some meta data",
 | 
						|
             "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Check that device was created with given data
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertEqual(dev['region'], 2)
 | 
						|
        self.assertEqual(dev['zone'], 3)
 | 
						|
        self.assertEqual(dev['ip'], '2001:0:1234::c1c0:abcd:876')
 | 
						|
        self.assertEqual(dev['port'], 6200)
 | 
						|
        self.assertEqual(dev['device'], 'sda3')
 | 
						|
        self.assertEqual(dev['weight'], 3.14159265359)
 | 
						|
        self.assertEqual(dev['replication_ip'], '2::10')
 | 
						|
        self.assertEqual(dev['replication_port'], 7000)
 | 
						|
        self.assertEqual(dev['meta'], 'some meta data')
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_add_device_ipv4_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv4(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "127.0.0.2",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "127.0.0.2",
 | 
						|
             "--replication-port", "6200",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Check that device was created with given data
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertEqual(dev['region'], 2)
 | 
						|
        self.assertEqual(dev['zone'], 3)
 | 
						|
        self.assertEqual(dev['ip'], '127.0.0.2')
 | 
						|
        self.assertEqual(dev['port'], 6200)
 | 
						|
        self.assertEqual(dev['device'], 'sda3')
 | 
						|
        self.assertEqual(dev['weight'], 3.14159265359)
 | 
						|
        self.assertEqual(dev['replication_ip'], '127.0.0.2')
 | 
						|
        self.assertEqual(dev['replication_port'], 6200)
 | 
						|
        self.assertEqual(dev['meta'], 'some meta data')
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_add_device_ipv6_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv6(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[3001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "[3::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Check that device was created with given data
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertEqual(dev['region'], 2)
 | 
						|
        self.assertEqual(dev['zone'], 3)
 | 
						|
        self.assertEqual(dev['ip'], '3001:0:1234::c1c0:abcd:876')
 | 
						|
        self.assertEqual(dev['port'], 6200)
 | 
						|
        self.assertEqual(dev['device'], 'sda3')
 | 
						|
        self.assertEqual(dev['weight'], 3.14159265359)
 | 
						|
        self.assertEqual(dev['replication_ip'], '3::10')
 | 
						|
        self.assertEqual(dev['replication_port'], 7000)
 | 
						|
        self.assertEqual(dev['meta'], 'some meta data')
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_add_device_domain_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Check that device was created with given data
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertEqual(dev['region'], 2)
 | 
						|
        self.assertEqual(dev['zone'], 3)
 | 
						|
        self.assertEqual(dev['ip'], 'test.test.com')
 | 
						|
        self.assertEqual(dev['port'], 6200)
 | 
						|
        self.assertEqual(dev['device'], 'sda3')
 | 
						|
        self.assertEqual(dev['weight'], 3.14159265359)
 | 
						|
        self.assertEqual(dev['replication_ip'], 'r.test.com')
 | 
						|
        self.assertEqual(dev['replication_port'], 7000)
 | 
						|
        self.assertEqual(dev['meta'], 'some meta data')
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_add_device_number_of_arguments(self):
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["", self.tmpfile, "add"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_add_device_already_exists(self):
 | 
						|
        # Test Add a device that already exists
 | 
						|
        argv = ["", self.tmpfile, "add",
 | 
						|
                "r0z0-127.0.0.1:6200/sda1_some meta data", "100"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_add_device_old_missing_region(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test add device without specifying a region
 | 
						|
        argv = ["", self.tmpfile, "add",
 | 
						|
                "z3-127.0.0.1:6200/sde3_some meta data", "3.14159265359"]
 | 
						|
        exp_results = {'valid_exit_codes': [2]}
 | 
						|
        self.run_srb(*argv, exp_results=exp_results)
 | 
						|
        # Check that ring was created with sane value for region
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertGreater(dev['region'], 0)
 | 
						|
 | 
						|
    def test_add_device_part_power_increase(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.next_part_power = 1
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
 | 
						|
        argv = ["", self.tmpfile, "add",
 | 
						|
                "r0z0-127.0.1.1:6200/sda1_some meta data", "100"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_remove_device(self):
 | 
						|
        for search_value in self.search_values:
 | 
						|
            self.create_sample_ring()
 | 
						|
            argv = ["", self.tmpfile, "remove", search_value]
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
            ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
            # Check that weight was set to 0
 | 
						|
            dev = ring.devs[0]
 | 
						|
            self.assertEqual(dev['weight'], 0)
 | 
						|
 | 
						|
            # Check that device is in list of devices to be removed
 | 
						|
            self.assertEqual(dev['region'], 0)
 | 
						|
            self.assertEqual(dev['zone'], 0)
 | 
						|
            self.assertEqual(dev['ip'], '127.0.0.1')
 | 
						|
            self.assertEqual(dev['port'], 6200)
 | 
						|
            self.assertEqual(dev['device'], 'sda1')
 | 
						|
            self.assertEqual(dev['weight'], 0)
 | 
						|
            self.assertEqual(dev['replication_ip'], '127.0.0.1')
 | 
						|
            self.assertEqual(dev['replication_port'], 6200)
 | 
						|
            self.assertEqual(dev['meta'], 'some meta data')
 | 
						|
 | 
						|
            # Check that second device in ring is not affected
 | 
						|
            dev = ring.devs[1]
 | 
						|
            self.assertEqual(dev['weight'], 100)
 | 
						|
            self.assertFalse([d for d in ring._remove_devs if d['id'] == 1])
 | 
						|
 | 
						|
            # Final check, rebalance and check ring is ok
 | 
						|
            ring.rebalance()
 | 
						|
            self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_remove_device_ipv4_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv4(old format)
 | 
						|
        argv = ["", self.tmpfile, "remove",
 | 
						|
                "d0r0z0-127.0.0.1:6200R127.0.0.1:6200/sda1_some meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        # Check that weight was set to 0
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['weight'], 0)
 | 
						|
 | 
						|
        # Check that device is in list of devices to be removed
 | 
						|
        self.assertEqual(dev['region'], 0)
 | 
						|
        self.assertEqual(dev['zone'], 0)
 | 
						|
        self.assertEqual(dev['ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(dev['port'], 6200)
 | 
						|
        self.assertEqual(dev['device'], 'sda1')
 | 
						|
        self.assertEqual(dev['weight'], 0)
 | 
						|
        self.assertEqual(dev['replication_ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(dev['replication_port'], 6200)
 | 
						|
        self.assertEqual(dev['meta'], 'some meta data')
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
        self.assertFalse([d for d in ring._remove_devs if d['id'] == 1])
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_remove_device_ipv6_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add IPV6
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test ipv6(old format)
 | 
						|
        argv = ["", self.tmpfile, "remove",
 | 
						|
                "d4r2z3-[2001:0000:1234:0000:0000:C1C0:ABCD:0876]:6200"
 | 
						|
                "R[2::10]:7000/sda3_some meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
        self.assertFalse([d for d in ring._remove_devs if d['id'] == 0])
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
        self.assertFalse([d for d in ring._remove_devs if d['id'] == 1])
 | 
						|
 | 
						|
        # Check that weight was set to 0
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertEqual(dev['weight'], 0)
 | 
						|
 | 
						|
        # Check that device is in list of devices to be removed
 | 
						|
        self.assertEqual(dev['region'], 2)
 | 
						|
        self.assertEqual(dev['zone'], 3)
 | 
						|
        self.assertEqual(dev['ip'], '2001:0:1234::c1c0:abcd:876')
 | 
						|
        self.assertEqual(dev['port'], 6200)
 | 
						|
        self.assertEqual(dev['device'], 'sda3')
 | 
						|
        self.assertEqual(dev['weight'], 0)
 | 
						|
        self.assertEqual(dev['replication_ip'], '2::10')
 | 
						|
        self.assertEqual(dev['replication_port'], 7000)
 | 
						|
        self.assertEqual(dev['meta'], 'some meta data')
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_remove_device_ipv4_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv4(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "remove",
 | 
						|
             "--id", "0", "--region", "0", "--zone", "0",
 | 
						|
             "--ip", "127.0.0.1",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "127.0.0.1",
 | 
						|
             "--replication-port", "6200",
 | 
						|
             "--device", "sda1", "--meta", "some meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        # Check that weight was set to 0
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['weight'], 0)
 | 
						|
 | 
						|
        # Check that device is in list of devices to be removed
 | 
						|
        self.assertEqual(dev['region'], 0)
 | 
						|
        self.assertEqual(dev['zone'], 0)
 | 
						|
        self.assertEqual(dev['ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(dev['port'], 6200)
 | 
						|
        self.assertEqual(dev['device'], 'sda1')
 | 
						|
        self.assertEqual(dev['weight'], 0)
 | 
						|
        self.assertEqual(dev['replication_ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(dev['replication_port'], 6200)
 | 
						|
        self.assertEqual(dev['meta'], 'some meta data')
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
        self.assertFalse([d for d in ring._remove_devs if d['id'] == 1])
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_remove_device_ipv6_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[3001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "8000",
 | 
						|
             "--replication-ip", "[3::10]",
 | 
						|
             "--replication-port", "9000",
 | 
						|
             "--device", "sda30", "--meta", "other meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test ipv6(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "remove",
 | 
						|
             "--id", "4", "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[3001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "8000",
 | 
						|
             "--replication-ip", "[3::10]",
 | 
						|
             "--replication-port", "9000",
 | 
						|
             "--device", "sda30", "--meta", "other meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
        self.assertFalse([d for d in ring._remove_devs if d['id'] == 0])
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
        self.assertFalse([d for d in ring._remove_devs if d['id'] == 1])
 | 
						|
 | 
						|
        # Check that weight was set to 0
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertEqual(dev['weight'], 0)
 | 
						|
 | 
						|
        # Check that device is in list of devices to be removed
 | 
						|
        self.assertEqual(dev['region'], 2)
 | 
						|
        self.assertEqual(dev['zone'], 3)
 | 
						|
        self.assertEqual(dev['ip'], '3001:0:1234::c1c0:abcd:876')
 | 
						|
        self.assertEqual(dev['port'], 8000)
 | 
						|
        self.assertEqual(dev['device'], 'sda30')
 | 
						|
        self.assertEqual(dev['weight'], 0)
 | 
						|
        self.assertEqual(dev['replication_ip'], '3::10')
 | 
						|
        self.assertEqual(dev['replication_port'], 9000)
 | 
						|
        self.assertEqual(dev['meta'], 'other meta data')
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_remove_device_domain_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "remove",
 | 
						|
             "--id", "4", "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
        self.assertFalse([d for d in ring._remove_devs if d['id'] == 0])
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
        self.assertFalse([d for d in ring._remove_devs if d['id'] == 1])
 | 
						|
 | 
						|
        # Check that weight was set to 0
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertEqual(dev['weight'], 0)
 | 
						|
 | 
						|
        # Check that device is in list of devices to be removed
 | 
						|
        self.assertEqual(dev['region'], 2)
 | 
						|
        self.assertEqual(dev['zone'], 3)
 | 
						|
        self.assertEqual(dev['ip'], 'test.test.com')
 | 
						|
        self.assertEqual(dev['port'], 6200)
 | 
						|
        self.assertEqual(dev['device'], 'sda3')
 | 
						|
        self.assertEqual(dev['weight'], 0)
 | 
						|
        self.assertEqual(dev['replication_ip'], 'r.test.com')
 | 
						|
        self.assertEqual(dev['replication_port'], 7000)
 | 
						|
        self.assertEqual(dev['meta'], 'some meta data')
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_remove_device_number_of_arguments(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["", self.tmpfile, "remove"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_remove_device_no_matching(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test No matching devices
 | 
						|
        argv = ["", self.tmpfile, "remove",
 | 
						|
                "--ip", "unknown"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_remove_device_part_power_increase(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.next_part_power = 1
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
 | 
						|
        argv = ["", self.tmpfile, "remove", "d0"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_set_weight(self):
 | 
						|
        for search_value in self.search_values:
 | 
						|
            self.create_sample_ring()
 | 
						|
 | 
						|
            argv = ["", self.tmpfile, "set_weight",
 | 
						|
                    search_value, "3.14159265359"]
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
            ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
            # Check that weight was changed
 | 
						|
            dev = ring.devs[0]
 | 
						|
            self.assertEqual(dev['weight'], 3.14159265359)
 | 
						|
 | 
						|
            # Check that second device in ring is not affected
 | 
						|
            dev = ring.devs[1]
 | 
						|
            self.assertEqual(dev['weight'], 100)
 | 
						|
 | 
						|
            # Final check, rebalance and check ring is ok
 | 
						|
            ring.rebalance()
 | 
						|
            self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_set_weight_old_format_two_devices(self):
 | 
						|
        # Would block without the 'yes' argument
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["", self.tmpfile, "set_weight",
 | 
						|
                "d2", "3.14", "d1", "6.28", "--yes"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        # Check that weight was changed
 | 
						|
        self.assertEqual(ring.devs[2]['weight'], 3.14)
 | 
						|
        self.assertEqual(ring.devs[1]['weight'], 6.28)
 | 
						|
        # Check that other devices in ring are not affected
 | 
						|
        self.assertEqual(ring.devs[0]['weight'], 100)
 | 
						|
        self.assertEqual(ring.devs[3]['weight'], 100)
 | 
						|
 | 
						|
    def test_set_weight_ipv4_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv4(old format)
 | 
						|
        argv = ["", self.tmpfile, "set_weight",
 | 
						|
                "d0r0z0-127.0.0.1:6200R127.0.0.1:6200/sda1_some meta data",
 | 
						|
                "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        # Check that weight was changed
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['weight'], 3.14159265359)
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_set_weight_ipv6_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add IPV6
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "100"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test ipv6(old format)
 | 
						|
        argv = ["", self.tmpfile, "set_weight",
 | 
						|
                "d4r2z3-[2001:0000:1234:0000:0000:C1C0:ABCD:0876]:6200"
 | 
						|
                "R[2::10]:7000/sda3_some meta data", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
 | 
						|
        # Check that weight was changed
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertEqual(dev['weight'], 3.14159265359)
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_set_weight_ipv4_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv4(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "set_weight",
 | 
						|
             "--id", "0", "--region", "0", "--zone", "0",
 | 
						|
             "--ip", "127.0.0.1",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "127.0.0.1",
 | 
						|
             "--replication-port", "6200",
 | 
						|
             "--device", "sda1", "--meta", "some meta data", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        # Check that weight was changed
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['weight'], 3.14159265359)
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_set_weight_ipv6_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add IPV6
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "100"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test ipv6(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "set_weight",
 | 
						|
             "--id", "4", "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
 | 
						|
        # Check that weight was changed
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertEqual(dev['weight'], 3.14159265359)
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_set_weight_domain_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "100"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "set_weight",
 | 
						|
             "--id", "4", "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['weight'], 100)
 | 
						|
 | 
						|
        # Check that weight was changed
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertEqual(dev['weight'], 3.14159265359)
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_set_weight_number_of_arguments(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["", self.tmpfile, "set_weight"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_set_weight_no_matching(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test No matching devices
 | 
						|
        argv = ["", self.tmpfile, "set_weight",
 | 
						|
                "--ip", "unknown"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def _check_region(self, ring, dev_id, expected_region):
 | 
						|
        for dev in ring.devs:
 | 
						|
            if dev['id'] != dev_id:
 | 
						|
                self.assertNotEqual(dev['region'], expected_region)
 | 
						|
            else:
 | 
						|
                self.assertEqual(dev['region'], expected_region)
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_set_region(self):
 | 
						|
        for search_value in self.search_values:
 | 
						|
            self.create_sample_ring()
 | 
						|
 | 
						|
            argv = ["", self.tmpfile, "set_region",
 | 
						|
                    search_value, "314"]
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
            ring = RingBuilder.load(self.tmpfile)
 | 
						|
            self._check_region(ring, 0, 314)
 | 
						|
 | 
						|
    def test_set_region_ipv4_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv4(old format)
 | 
						|
        argv = ["", self.tmpfile, "set_region",
 | 
						|
                "d0r0z0-127.0.0.1:6200R127.0.0.1:6200/sda1_some meta data",
 | 
						|
                "314"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        self._check_region(ring, 0, 314)
 | 
						|
 | 
						|
    def test_set_region_ipv6_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add IPV6
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6000",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "100"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test ipv6(old format)
 | 
						|
        argv = ["", self.tmpfile, "set_region",
 | 
						|
                "d4r2z3-[2001:0000:1234:0000:0000:C1C0:ABCD:0876]:6000"
 | 
						|
                "R[2::10]:7000/sda3_some meta data", "314"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        self._check_region(ring, 4, 314)
 | 
						|
 | 
						|
    def test_set_region_ipv4_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv4(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "set_region",
 | 
						|
             "--id", "0", "--region", "0", "--zone", "0",
 | 
						|
             "--ip", "127.0.0.1",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "127.0.0.1",
 | 
						|
             "--replication-port", "6200",
 | 
						|
             "--device", "sda1", "--meta", "some meta data", "314"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        self._check_region(ring, 0, 314)
 | 
						|
 | 
						|
    def test_set_region_ipv6_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add IPV6
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6000",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "100"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test ipv6(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "set_region",
 | 
						|
             "--id", "4", "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6000",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data", "314"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        self._check_region(ring, 4, 314)
 | 
						|
 | 
						|
    def test_set_region_domain_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6000",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "100"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "set_region",
 | 
						|
             "--id", "4", "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6000",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data", "314"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        self._check_region(ring, 4, 314)
 | 
						|
 | 
						|
    def test_set_region_number_of_arguments(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["", self.tmpfile, "set_region"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_set_region_no_matching(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test No matching devices
 | 
						|
        argv = ["", self.tmpfile, "set_region",
 | 
						|
                "--ip", "unknown"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_set_zone(self):
 | 
						|
        for search_value in self.search_values:
 | 
						|
            self.create_sample_ring()
 | 
						|
 | 
						|
            argv = ["", self.tmpfile, "set_zone",
 | 
						|
                    search_value, "314"]
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
            ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
            self._check_zone(ring, 0, 314)
 | 
						|
 | 
						|
    def test_set_zone_ipv4_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv4(old format)
 | 
						|
        argv = ["", self.tmpfile, "set_zone",
 | 
						|
                "d0r0z0-127.0.0.1:6200R127.0.0.1:6200/sda1_some meta data",
 | 
						|
                "314"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        self._check_zone(ring, 0, 314)
 | 
						|
 | 
						|
    def _check_zone(self, ring, dev_id, expected_zone):
 | 
						|
        for dev in ring.devs:
 | 
						|
            if dev['id'] != dev_id:
 | 
						|
                self.assertFalse(dev['zone'] == expected_zone)
 | 
						|
            else:
 | 
						|
                self.assertEqual(dev['zone'], expected_zone)
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_set_zone_ipv6_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add IPV6
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6000",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "100"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test ipv6(old format)
 | 
						|
        argv = ["", self.tmpfile, "set_zone",
 | 
						|
                "d4r2z3-[2001:0000:1234:0000:0000:C1C0:ABCD:0876]:6000"
 | 
						|
                "R[2::10]:7000/sda3_some meta data", "314"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        self._check_zone(ring, 4, 314)
 | 
						|
 | 
						|
    def test_set_zone_ipv4_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv4(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "set_zone",
 | 
						|
             "--id", "0", "--region", "0", "--zone", "0",
 | 
						|
             "--ip", "127.0.0.1",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "127.0.0.1",
 | 
						|
             "--replication-port", "6200",
 | 
						|
             "--device", "sda1", "--meta", "some meta data", "314"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        self._check_zone(ring, 0, 314)
 | 
						|
 | 
						|
    def test_set_zone_ipv6_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add IPV6
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6000",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "100"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test ipv6(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "set_zone",
 | 
						|
             "--id", "4", "--region", "2",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6000",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data", "314"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        self._check_zone(ring, 4, 314)
 | 
						|
 | 
						|
    def test_set_zone_domain_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6000",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "100"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "set_zone",
 | 
						|
             "--id", "4", "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6000",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data", "314"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        self._check_zone(ring, 4, 314)
 | 
						|
 | 
						|
    def test_set_zone_number_of_arguments(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["", self.tmpfile, "set_zone"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_set_zone_no_matching(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test No matching devices
 | 
						|
        argv = ["", self.tmpfile, "set_zone",
 | 
						|
                "--ip", "unknown"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_set_info(self):
 | 
						|
        for search_value in self.search_values:
 | 
						|
 | 
						|
            self.create_sample_ring()
 | 
						|
            argv = ["", self.tmpfile, "set_info", search_value,
 | 
						|
                    "127.0.1.1:8000/sda1_other meta data"]
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
            # Check that device was created with given data
 | 
						|
            ring = RingBuilder.load(self.tmpfile)
 | 
						|
            dev = ring.devs[0]
 | 
						|
            self.assertEqual(dev['ip'], '127.0.1.1')
 | 
						|
            self.assertEqual(dev['port'], 8000)
 | 
						|
            self.assertEqual(dev['device'], 'sda1')
 | 
						|
            self.assertEqual(dev['meta'], 'other meta data')
 | 
						|
 | 
						|
            # Check that second device in ring is not affected
 | 
						|
            dev = ring.devs[1]
 | 
						|
            self.assertEqual(dev['ip'], '127.0.0.2')
 | 
						|
            self.assertEqual(dev['port'], 6201)
 | 
						|
            self.assertEqual(dev['device'], 'sda2')
 | 
						|
            self.assertEqual(dev['meta'], '')
 | 
						|
 | 
						|
            # Final check, rebalance and check ring is ok
 | 
						|
            ring.rebalance()
 | 
						|
            self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_set_info_ipv4_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv4(old format)
 | 
						|
        argv = ["", self.tmpfile, "set_info",
 | 
						|
                "d0r0z0-127.0.0.1:6200R127.0.0.1:6200/sda1_some meta data",
 | 
						|
                "127.0.1.1:8000R127.0.1.1:8000/sda10_other meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Check that device was created with given data
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['ip'], '127.0.1.1')
 | 
						|
        self.assertEqual(dev['port'], 8000)
 | 
						|
        self.assertEqual(dev['replication_ip'], '127.0.1.1')
 | 
						|
        self.assertEqual(dev['replication_port'], 8000)
 | 
						|
        self.assertEqual(dev['device'], 'sda10')
 | 
						|
        self.assertEqual(dev['meta'], 'other meta data')
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['ip'], '127.0.0.2')
 | 
						|
        self.assertEqual(dev['port'], 6201)
 | 
						|
        self.assertEqual(dev['device'], 'sda2')
 | 
						|
        self.assertEqual(dev['meta'], '')
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_set_info_ipv6_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add IPV6
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test ipv6(old format)
 | 
						|
        argv = ["", self.tmpfile, "set_info",
 | 
						|
                "d4r2z3-[2001:0000:1234:0000:0000:C1C0:ABCD:0876]:6200"
 | 
						|
                "R[2::10]:7000/sda3_some meta data",
 | 
						|
                "[3001:0000:1234:0000:0000:C1C0:ABCD:0876]:8000"
 | 
						|
                "R[3::10]:8000/sda30_other meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(dev['port'], 6200)
 | 
						|
        self.assertEqual(dev['replication_ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(dev['replication_port'], 6200)
 | 
						|
        self.assertEqual(dev['device'], 'sda1')
 | 
						|
        self.assertEqual(dev['meta'], 'some meta data')
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['ip'], '127.0.0.2')
 | 
						|
        self.assertEqual(dev['port'], 6201)
 | 
						|
        self.assertEqual(dev['device'], 'sda2')
 | 
						|
        self.assertEqual(dev['meta'], '')
 | 
						|
 | 
						|
        # Check that device was created with given data
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertEqual(dev['ip'], '3001:0:1234::c1c0:abcd:876')
 | 
						|
        self.assertEqual(dev['port'], 8000)
 | 
						|
        self.assertEqual(dev['replication_ip'], '3::10')
 | 
						|
        self.assertEqual(dev['replication_port'], 8000)
 | 
						|
        self.assertEqual(dev['device'], 'sda30')
 | 
						|
        self.assertEqual(dev['meta'], 'other meta data')
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_set_info_ipv4_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv4(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "set_info",
 | 
						|
             "--id", "0", "--region", "0", "--zone", "0",
 | 
						|
             "--ip", "127.0.0.1",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "127.0.0.1",
 | 
						|
             "--replication-port", "6200",
 | 
						|
             "--device", "sda1", "--meta", "some meta data",
 | 
						|
             "--change-ip", "127.0.2.1",
 | 
						|
             "--change-port", "9000",
 | 
						|
             "--change-replication-ip", "127.0.2.1",
 | 
						|
             "--change-replication-port", "9000",
 | 
						|
             "--change-device", "sda100", "--change-meta", "other meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Check that device was created with given data
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['ip'], '127.0.2.1')
 | 
						|
        self.assertEqual(dev['port'], 9000)
 | 
						|
        self.assertEqual(dev['replication_ip'], '127.0.2.1')
 | 
						|
        self.assertEqual(dev['replication_port'], 9000)
 | 
						|
        self.assertEqual(dev['device'], 'sda100')
 | 
						|
        self.assertEqual(dev['meta'], 'other meta data')
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['ip'], '127.0.0.2')
 | 
						|
        self.assertEqual(dev['port'], 6201)
 | 
						|
        self.assertEqual(dev['device'], 'sda2')
 | 
						|
        self.assertEqual(dev['meta'], '')
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_set_info_ipv6_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add IPV6
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test ipv6(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "set_info",
 | 
						|
             "--id", "4", "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--change-ip", "[4001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--change-port", "9000",
 | 
						|
             "--change-replication-ip", "[4::10]",
 | 
						|
             "--change-replication-port", "9000",
 | 
						|
             "--change-device", "sda300", "--change-meta", "other meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(dev['port'], 6200)
 | 
						|
        self.assertEqual(dev['replication_ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(dev['replication_port'], 6200)
 | 
						|
        self.assertEqual(dev['device'], 'sda1')
 | 
						|
        self.assertEqual(dev['meta'], 'some meta data')
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['ip'], '127.0.0.2')
 | 
						|
        self.assertEqual(dev['port'], 6201)
 | 
						|
        self.assertEqual(dev['device'], 'sda2')
 | 
						|
        self.assertEqual(dev['meta'], '')
 | 
						|
 | 
						|
        # Check that device was created with given data
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertEqual(dev['ip'], '4001:0:1234::c1c0:abcd:876')
 | 
						|
        self.assertEqual(dev['port'], 9000)
 | 
						|
        self.assertEqual(dev['replication_ip'], '4::10')
 | 
						|
        self.assertEqual(dev['replication_port'], 9000)
 | 
						|
        self.assertEqual(dev['device'], 'sda300')
 | 
						|
        self.assertEqual(dev['meta'], 'other meta data')
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_set_info_domain_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "set_info",
 | 
						|
             "--id", "4", "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--change-ip", "test.test2.com",
 | 
						|
             "--change-port", "9000",
 | 
						|
             "--change-replication-ip", "r.test2.com",
 | 
						|
             "--change-replication-port", "9000",
 | 
						|
             "--change-device", "sda300", "--change-meta", "other meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[0]
 | 
						|
        self.assertEqual(dev['ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(dev['port'], 6200)
 | 
						|
        self.assertEqual(dev['replication_ip'], '127.0.0.1')
 | 
						|
        self.assertEqual(dev['replication_port'], 6200)
 | 
						|
        self.assertEqual(dev['device'], 'sda1')
 | 
						|
        self.assertEqual(dev['meta'], 'some meta data')
 | 
						|
 | 
						|
        # Check that second device in ring is not affected
 | 
						|
        dev = ring.devs[1]
 | 
						|
        self.assertEqual(dev['ip'], '127.0.0.2')
 | 
						|
        self.assertEqual(dev['port'], 6201)
 | 
						|
        self.assertEqual(dev['device'], 'sda2')
 | 
						|
        self.assertEqual(dev['meta'], '')
 | 
						|
 | 
						|
        # Check that device was created with given data
 | 
						|
        dev = ring.devs[-1]
 | 
						|
        self.assertEqual(dev['ip'], 'test.test2.com')
 | 
						|
        self.assertEqual(dev['port'], 9000)
 | 
						|
        self.assertEqual(dev['replication_ip'], 'r.test2.com')
 | 
						|
        self.assertEqual(dev['replication_port'], 9000)
 | 
						|
        self.assertEqual(dev['device'], 'sda300')
 | 
						|
        self.assertEqual(dev['meta'], 'other meta data')
 | 
						|
 | 
						|
        # Final check, rebalance and check ring is ok
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_set_info_number_of_arguments(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["", self.tmpfile, "set_info"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_set_info_no_matching(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test No matching devices
 | 
						|
        argv = ["", self.tmpfile, "set_info",
 | 
						|
                "--ip", "unknown"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_set_info_already_exists(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test Set a device that already exists
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "set_info",
 | 
						|
             "--id", "0", "--region", "0", "--zone", "0",
 | 
						|
             "--ip", "127.0.0.1",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "127.0.0.1",
 | 
						|
             "--replication-port", "6200",
 | 
						|
             "--device", "sda1", "--meta", "some meta data",
 | 
						|
             "--change-ip", "127.0.0.2",
 | 
						|
             "--change-port", "6201",
 | 
						|
             "--change-replication-ip", "127.0.0.2",
 | 
						|
             "--change-replication-port", "6201",
 | 
						|
             "--change-device", "sda2", "--change-meta", ""]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_set_min_part_hours(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["", self.tmpfile, "set_min_part_hours", "24"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertEqual(ring.min_part_hours, 24)
 | 
						|
 | 
						|
    def test_set_min_part_hours_number_of_arguments(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["", self.tmpfile, "set_min_part_hours"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_set_replicas(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["", self.tmpfile, "set_replicas", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertEqual(ring.replicas, 3.14159265359)
 | 
						|
 | 
						|
    def test_set_overload(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["", self.tmpfile, "set_overload", "0.19878"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertEqual(ring.overload, 0.19878)
 | 
						|
 | 
						|
    def test_set_overload_negative(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["", self.tmpfile, "set_overload", "-0.19878"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertEqual(ring.overload, 0.0)
 | 
						|
 | 
						|
    def test_set_overload_non_numeric(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["", self.tmpfile, "set_overload", "swedish fish"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertEqual(ring.overload, 0.0)
 | 
						|
 | 
						|
    def test_set_overload_percent(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = "set_overload 10%".split()
 | 
						|
        out, err = self.run_srb(*argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertEqual(ring.overload, 0.1)
 | 
						|
        self.assertIn('10.00%', out)
 | 
						|
        self.assertIn('0.100000', out)
 | 
						|
 | 
						|
    def test_set_overload_percent_strange_input(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = "set_overload 26%%%%".split()
 | 
						|
        out, err = self.run_srb(*argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertEqual(ring.overload, 0.26)
 | 
						|
        self.assertIn('26.00%', out)
 | 
						|
        self.assertIn('0.260000', out)
 | 
						|
 | 
						|
    def test_server_overload_crazy_high(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = "set_overload 10".split()
 | 
						|
        out, err = self.run_srb(*argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertEqual(ring.overload, 10.0)
 | 
						|
        self.assertIn('Warning overload is greater than 100%', out)
 | 
						|
        self.assertIn('1000.00%', out)
 | 
						|
        self.assertIn('10.000000', out)
 | 
						|
        # but it's cool if you do it on purpose
 | 
						|
        argv[-1] = '1000%'
 | 
						|
        out, err = self.run_srb(*argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertEqual(ring.overload, 10.0)
 | 
						|
        self.assertNotIn('Warning overload is greater than 100%', out)
 | 
						|
        self.assertIn('1000.00%', out)
 | 
						|
        self.assertIn('10.000000', out)
 | 
						|
 | 
						|
    def test_set_overload_number_of_arguments(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test missing arguments
 | 
						|
        argv = ["", self.tmpfile, "set_overload"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_set_replicas_number_of_arguments(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["", self.tmpfile, "set_replicas"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_set_replicas_invalid_value(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test not a valid number
 | 
						|
        argv = ["", self.tmpfile, "set_replicas", "test"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Test new replicas is 0
 | 
						|
        argv = ["", self.tmpfile, "set_replicas", "0"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_validate(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.rebalance()
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
        argv = ["", self.tmpfile, "validate"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_validate_composite_builder_file(self):
 | 
						|
        b1, b1_file = write_stub_builder(self.tmpdir, 1)
 | 
						|
        b2, b2_file = write_stub_builder(self.tmpdir, 2)
 | 
						|
        cb = CompositeRingBuilder([b1_file, b2_file])
 | 
						|
        cb.compose()
 | 
						|
        cb_file = os.path.join(self.tmpdir, 'composite.builder')
 | 
						|
        cb.save(cb_file)
 | 
						|
        argv = ["", cb_file, "validate"]
 | 
						|
        with mock.patch("sys.stdout", io.StringIO()) as mock_stdout:
 | 
						|
            self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
        lines = mock_stdout.getvalue().strip().split('\n')
 | 
						|
        self.assertIn("Ring Builder file is invalid", lines[0])
 | 
						|
        self.assertIn("appears to be a composite ring builder file", lines[0])
 | 
						|
        self.assertFalse(lines[1:])
 | 
						|
 | 
						|
    def test_validate_empty_file(self):
 | 
						|
        open(self.tmpfile, 'a').close
 | 
						|
        argv = ["", self.tmpfile, "validate"]
 | 
						|
        with mock.patch("sys.stdout", io.StringIO()) as mock_stdout:
 | 
						|
            self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
        lines = mock_stdout.getvalue().strip().split('\n')
 | 
						|
        self.assertIn("Ring Builder file is invalid", lines[0])
 | 
						|
        self.assertNotIn("appears to be a composite ring builder file",
 | 
						|
                         lines[0])
 | 
						|
        self.assertFalse(lines[1:])
 | 
						|
 | 
						|
    def test_validate_corrupted_file(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.rebalance()
 | 
						|
        self.assertTrue(ring.validate())  # ring is valid until now
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
        argv = ["", self.tmpfile, "validate"]
 | 
						|
 | 
						|
        # corrupt the file
 | 
						|
        with open(self.tmpfile, 'wb') as f:
 | 
						|
            f.write(os.urandom(1024))
 | 
						|
        with mock.patch("sys.stdout", io.StringIO()) as mock_stdout:
 | 
						|
            self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
        lines = mock_stdout.getvalue().strip().split('\n')
 | 
						|
        self.assertIn("Ring Builder file is invalid", lines[0])
 | 
						|
        self.assertNotIn("appears to be a composite ring builder file",
 | 
						|
                         lines[0])
 | 
						|
        self.assertFalse(lines[1:])
 | 
						|
 | 
						|
    def test_validate_non_existent_file(self):
 | 
						|
        rand_file = '%s/%s' % (tempfile.gettempdir(), str(uuid.uuid4()))
 | 
						|
        argv = ["", rand_file, "validate"]
 | 
						|
        with mock.patch("sys.stdout", io.StringIO()) as mock_stdout:
 | 
						|
            self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
        lines = mock_stdout.getvalue().strip().split('\n')
 | 
						|
        self.assertIn("Ring Builder file does not exist", lines[0])
 | 
						|
        self.assertNotIn("appears to be a composite ring builder file",
 | 
						|
                         lines[0])
 | 
						|
        self.assertFalse(lines[1:])
 | 
						|
 | 
						|
    def test_validate_non_accessible_file(self):
 | 
						|
        with mock.patch.object(
 | 
						|
                RingBuilder, 'load',
 | 
						|
                mock.Mock(side_effect=exceptions.PermissionError("boom"))):
 | 
						|
            argv = ["", self.tmpfile, "validate"]
 | 
						|
            with mock.patch("sys.stdout", io.StringIO()) as mock_stdout:
 | 
						|
                self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
        lines = mock_stdout.getvalue().strip().split('\n')
 | 
						|
        self.assertIn("boom", lines[0])
 | 
						|
        self.assertFalse(lines[1:])
 | 
						|
 | 
						|
    def test_validate_generic_error(self):
 | 
						|
        with mock.patch.object(
 | 
						|
                RingBuilder, 'load', mock.Mock(
 | 
						|
                    side_effect=IOError('Generic error occurred'))):
 | 
						|
            argv = ["", self.tmpfile, "validate"]
 | 
						|
            self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_search_device_ipv4_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv4(old format)
 | 
						|
        argv = ["", self.tmpfile, "search",
 | 
						|
                "d0r0z0-127.0.0.1:6200R127.0.0.1:6200/sda1_some meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_search_device_ipv6_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add IPV6
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # write ring file
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.rebalance()
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
 | 
						|
        # Test ipv6(old format)
 | 
						|
        argv = ["", self.tmpfile, "search",
 | 
						|
                "d4r2z3-[2001:0000:1234:0000:0000:C1C0:ABCD:0876]:6200"
 | 
						|
                "R[2::10]:7000/sda3_some meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_search_device_ipv4_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test ipv4(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "search",
 | 
						|
             "--id", "0", "--region", "0", "--zone", "0",
 | 
						|
             "--ip", "127.0.0.1",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "127.0.0.1",
 | 
						|
             "--replication-port", "6200",
 | 
						|
             "--device", "sda1", "--meta", "some meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_search_device_ipv6_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add IPV6
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # write ring file
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.rebalance()
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
 | 
						|
        # Test ipv6(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "search",
 | 
						|
             "--id", "4", "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_search_device_domain_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        # write ring file
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.rebalance()
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
 | 
						|
        # Test domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "search",
 | 
						|
             "--id", "4", "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_search_device_number_of_arguments(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["", self.tmpfile, "search"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_search_device_no_matching(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test No matching devices
 | 
						|
        argv = ["", self.tmpfile, "search",
 | 
						|
                "--ip", "unknown"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_list_parts_ipv4_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.rebalance()
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
        # Test ipv4(old format)
 | 
						|
        argv = ["", self.tmpfile, "list_parts",
 | 
						|
                "d0r0z0-127.0.0.1:6200R127.0.0.1:6200/sda1_some meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_list_parts_ipv6_old_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add IPV6
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # write ring file
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.rebalance()
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
 | 
						|
        # Test ipv6(old format)
 | 
						|
        argv = ["", self.tmpfile, "list_parts",
 | 
						|
                "d4r2z3-[2001:0000:1234:0000:0000:C1C0:ABCD:0876]:6200"
 | 
						|
                "R[2::10]:7000/sda3_some meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_list_parts_ipv4_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.rebalance()
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
        # Test ipv4(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "list_parts",
 | 
						|
             "--id", "0", "--region", "0", "--zone", "0",
 | 
						|
             "--ip", "127.0.0.1",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "127.0.0.1",
 | 
						|
             "--replication-port", "6200",
 | 
						|
             "--device", "sda1", "--meta", "some meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_list_parts_ipv6_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add IPV6
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # write ring file
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.rebalance()
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
 | 
						|
        # Test ipv6(new format)
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "list_parts",
 | 
						|
             "--id", "4", "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "[2001:0000:1234:0000:0000:C1C0:ABCD:0876]",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "[2::10]",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_list_parts_domain_new_format(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # add domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "add",
 | 
						|
             "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data",
 | 
						|
             "--weight", "3.14159265359"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # write ring file
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.rebalance()
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
 | 
						|
        # Test domain name
 | 
						|
        argv = \
 | 
						|
            ["", self.tmpfile, "list_parts",
 | 
						|
             "--id", "4", "--region", "2", "--zone", "3",
 | 
						|
             "--ip", "test.test.com",
 | 
						|
             "--port", "6200",
 | 
						|
             "--replication-ip", "r.test.com",
 | 
						|
             "--replication-port", "7000",
 | 
						|
             "--device", "sda3", "--meta", "some meta data"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_list_parts_number_of_arguments(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test Number of arguments abnormal
 | 
						|
        argv = ["", self.tmpfile, "list_parts"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_list_parts_no_matching(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test No matching devices
 | 
						|
        argv = ["", self.tmpfile, "list_parts",
 | 
						|
                "--ip", "unknown"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_unknown(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["", self.tmpfile, "unknown"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_default(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["", self.tmpfile]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_default_output(self):
 | 
						|
        with mock.patch('uuid.uuid4', return_value=mock.Mock(hex=None)):
 | 
						|
            self.create_sample_ring()
 | 
						|
        out, err = self.run_srb('')
 | 
						|
        self.assertOutputStub(out)
 | 
						|
 | 
						|
    def test_default_output_id_assigned(self):
 | 
						|
        ring = self.create_sample_ring()
 | 
						|
        out, err = self.run_srb('')
 | 
						|
        self.assertOutputStub(out, builder_id=ring.id)
 | 
						|
 | 
						|
    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': 10000.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, builder_id=ring.id)
 | 
						|
 | 
						|
    def test_default_show_removed(self):
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        mock_stderr = io.StringIO()
 | 
						|
 | 
						|
        ring = self.create_sample_ring()
 | 
						|
 | 
						|
        # Note: it also sets device's weight to zero.
 | 
						|
        argv = ["", self.tmpfile, "remove", "--id", "1"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Setting another device's weight to zero to be sure we distinguish
 | 
						|
        # real removed device and device with zero weight.
 | 
						|
        argv = ["", self.tmpfile, "set_weight", "0", "--id", "3"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        argv = ["", self.tmpfile]
 | 
						|
        with mock.patch("sys.stdout", mock_stdout):
 | 
						|
            with mock.patch("sys.stderr", mock_stderr):
 | 
						|
                self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        expected = "%s, build version 6, id %s\n" \
 | 
						|
            "64 partitions, 3.000000 replicas, 4 regions, 4 zones, " \
 | 
						|
            "4 devices, 2-byte IDs, 100.00 balance, 0.00 dispersion\n" \
 | 
						|
            "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:port  name weight " \
 | 
						|
            "partitions balance flags meta\n" \
 | 
						|
            "            0      0    0  127.0.0.1:6200 " \
 | 
						|
            "     127.0.0.1:6200  sda1 100.00" \
 | 
						|
            "          0 -100.00       some meta data\n" \
 | 
						|
            "            1      1    1  127.0.0.2:6201 " \
 | 
						|
            "     127.0.0.2:6201  sda2   0.00" \
 | 
						|
            "          0    0.00   DEL \n" \
 | 
						|
            "            2      2    2  127.0.0.3:6202 " \
 | 
						|
            "     127.0.0.3:6202  sdc3 100.00" \
 | 
						|
            "          0 -100.00       \n" \
 | 
						|
            "            3      3    3  127.0.0.4:6203 " \
 | 
						|
            "     127.0.0.4:6203  sdd4   0.00" \
 | 
						|
            "          0    0.00       \n" %\
 | 
						|
                   (self.tmpfile, ring.id, self.tmpfile)
 | 
						|
        self.assertEqual(expected, mock_stdout.getvalue())
 | 
						|
 | 
						|
    def test_default_sorted_output(self):
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        mock_stderr = io.StringIO()
 | 
						|
 | 
						|
        # Create a sample ring and remove/add some devices.
 | 
						|
        now = time.time()
 | 
						|
        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.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        argv = ["", self.tmpfile, "remove", "--id", "0"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        argv = ["", self.tmpfile, "remove", "--id", "3"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        argv = ["", self.tmpfile, "rebalance"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, 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.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # Check the order of the devices listed the output.
 | 
						|
        argv = ["", self.tmpfile]
 | 
						|
        with mock.patch("sys.stdout", mock_stdout), mock.patch(
 | 
						|
                "sys.stderr", mock_stderr), mock.patch(
 | 
						|
                    'swift.common.ring.builder.time', return_value=now):
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        self.assertOutputStub(mock_stdout.getvalue(), builder_id=ring.id)
 | 
						|
 | 
						|
    def test_default_ringfile_check(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
 | 
						|
        # ring file not created
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        mock_stderr = io.StringIO()
 | 
						|
        argv = ["", self.tmpfile]
 | 
						|
        with mock.patch("sys.stdout", mock_stdout):
 | 
						|
            with mock.patch("sys.stderr", mock_stderr):
 | 
						|
                self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring_not_found_re = re.compile(r"Ring file .*\.ring\.gz not found")
 | 
						|
        self.assertTrue(ring_not_found_re.findall(mock_stdout.getvalue()))
 | 
						|
 | 
						|
        # write ring file
 | 
						|
        argv = ["", self.tmpfile, "rebalance"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        # ring file is up-to-date
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        argv = ["", self.tmpfile]
 | 
						|
        with mock.patch("sys.stdout", mock_stdout):
 | 
						|
            with mock.patch("sys.stderr", mock_stderr):
 | 
						|
                self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring_up_to_date_re = re.compile(
 | 
						|
            r"Ring file .*\.ring\.gz is up-to-date"
 | 
						|
        )
 | 
						|
        self.assertTrue(ring_up_to_date_re.findall(mock_stdout.getvalue()))
 | 
						|
 | 
						|
        # change builder (set weight)
 | 
						|
        argv = ["", self.tmpfile, "set_weight", "0", "--id", "3"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        # ring file is obsolete after set_weight
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        argv = ["", self.tmpfile]
 | 
						|
        with mock.patch("sys.stdout", mock_stdout):
 | 
						|
            with mock.patch("sys.stderr", mock_stderr):
 | 
						|
                self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring_obsolete_re = re.compile(r"Ring file .*\.ring\.gz is obsolete")
 | 
						|
        self.assertTrue(ring_obsolete_re.findall(mock_stdout.getvalue()))
 | 
						|
 | 
						|
        # write ring file
 | 
						|
        argv = ["", self.tmpfile, "write_ring"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        # ring file up-to-date again
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        argv = ["", self.tmpfile]
 | 
						|
        with mock.patch("sys.stdout", mock_stdout):
 | 
						|
            with mock.patch("sys.stderr", mock_stderr):
 | 
						|
                self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        self.assertTrue(ring_up_to_date_re.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 = io.StringIO()
 | 
						|
        argv = ["", self.tmpfile]
 | 
						|
        with mock.patch("sys.stdout", mock_stdout):
 | 
						|
            with mock.patch("sys.stderr", mock_stderr):
 | 
						|
                self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring_invalid_re = re.compile(r"Ring file .*\.ring\.gz is invalid")
 | 
						|
        self.assertTrue(ring_invalid_re.findall(mock_stdout.getvalue()))
 | 
						|
 | 
						|
    def test_default_no_device_ring_without_exception(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
 | 
						|
        # remove devices from ring file
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        mock_stderr = io.StringIO()
 | 
						|
        for device in ["d0", "d1", "d2", "d3"]:
 | 
						|
            argv = ["", self.tmpfile, "remove", device]
 | 
						|
            with mock.patch("sys.stdout", mock_stdout):
 | 
						|
                with mock.patch("sys.stderr", mock_stderr):
 | 
						|
                    self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        # default ring file without exception
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        mock_stderr = io.StringIO()
 | 
						|
        argv = ["", self.tmpfile, "default"]
 | 
						|
        with mock.patch("sys.stdout", mock_stdout):
 | 
						|
            with mock.patch("sys.stderr", mock_stderr):
 | 
						|
                self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        deleted_dev_list = (
 | 
						|
            "            0      0    0  127.0.0.1:6200      127.0.0.1:6200  "
 | 
						|
            "sda1   0.00          0    0.00   DEL some meta data\n"
 | 
						|
            "            1      1    1  127.0.0.2:6201      127.0.0.2:6201  "
 | 
						|
            "sda2   0.00          0    0.00   DEL \n"
 | 
						|
            "            2      2    2  127.0.0.3:6202      127.0.0.3:6202  "
 | 
						|
            "sdc3   0.00          0    0.00   DEL \n"
 | 
						|
            "            3      3    3  127.0.0.4:6203      127.0.0.4:6203  "
 | 
						|
            "sdd4   0.00          0    0.00   DEL \n")
 | 
						|
 | 
						|
        output = mock_stdout.getvalue()
 | 
						|
        self.assertIn("64 partitions", output)
 | 
						|
        self.assertIn("all devices have been deleted", output)
 | 
						|
        self.assertIn("all devices have been deleted", output)
 | 
						|
        self.assertIn(deleted_dev_list, output)
 | 
						|
 | 
						|
    def test_empty_ring(self):
 | 
						|
        self.create_sample_ring(empty=True)
 | 
						|
 | 
						|
        # default ring file without exception
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        mock_stderr = io.StringIO()
 | 
						|
        argv = ["", self.tmpfile, "default"]
 | 
						|
        with mock.patch("sys.stdout", mock_stdout):
 | 
						|
            with mock.patch("sys.stderr", mock_stderr):
 | 
						|
                self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        output = mock_stdout.getvalue()
 | 
						|
        self.assertIn("64 partitions", output)
 | 
						|
        self.assertIn("There are no devices in this ring", output)
 | 
						|
 | 
						|
    def test_pretend_min_part_hours_passed(self):
 | 
						|
        self.run_srb("create", 8, 3, 1)
 | 
						|
        argv_pretend = ["", self.tmpfile, "pretend_min_part_hours_passed"]
 | 
						|
        # pretend_min_part_hours_passed should success, even not rebalanced
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv_pretend)
 | 
						|
        self.run_srb("add",
 | 
						|
                     "r1z1-10.1.1.1:2345/sda", 100.0,
 | 
						|
                     "r1z1-10.1.1.1:2345/sdb", 100.0,
 | 
						|
                     "r1z1-10.1.1.1:2345/sdc", 100.0)
 | 
						|
        argv_rebalance = ["", self.tmpfile, "rebalance"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv_rebalance)
 | 
						|
        self.run_srb("add", "r1z1-10.1.1.1:2345/sdd", 100.0)
 | 
						|
        # rebalance fail without pretend_min_part_hours_passed
 | 
						|
        self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv_rebalance)
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv_pretend)
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv_rebalance)
 | 
						|
 | 
						|
    def test_rebalance(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["", self.tmpfile, "rebalance", "3"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
 | 
						|
    def test_rebalance_no_device_change(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.rebalance()
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
        # Test No change to the device
 | 
						|
        argv = ["", self.tmpfile, "rebalance", "3"]
 | 
						|
        with mock.patch('swift.common.ring.RingBuilder.save') as mock_save:
 | 
						|
            self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)
 | 
						|
        self.assertEqual(len(mock_save.calls), 0)
 | 
						|
 | 
						|
    def test_rebalance_saves_dispersion_improvement(self):
 | 
						|
        # We set up a situation where dispersion improves but balance
 | 
						|
        # doesn't. We construct a ring with one zone, then add a second zone
 | 
						|
        # concurrently with a new device in the first zone. That first
 | 
						|
        # device won't acquire any partitions, so the ring's balance won't
 | 
						|
        # change. However, dispersion will improve.
 | 
						|
 | 
						|
        ring = RingBuilder(6, 6, 1)
 | 
						|
        devs = ('d%s' % i for i in itertools.count())
 | 
						|
        for i in range(6):
 | 
						|
            ring.add_dev({
 | 
						|
                'region': 1, 'zone': 1,
 | 
						|
                'ip': '10.0.0.1', 'port': 20001, 'weight': 1000,
 | 
						|
                'device': next(devs)})
 | 
						|
        ring.rebalance()
 | 
						|
 | 
						|
        # The last guy in zone 1
 | 
						|
        ring.add_dev({
 | 
						|
            'region': 1, 'zone': 1,
 | 
						|
            'ip': '10.0.0.1', 'port': 20001, 'weight': 1000,
 | 
						|
            'device': next(devs)})
 | 
						|
 | 
						|
        # Add zone 2 (same total weight as zone 1)
 | 
						|
        for i in range(7):
 | 
						|
            ring.add_dev({
 | 
						|
                'region': 1, 'zone': 2,
 | 
						|
                'ip': '10.0.0.2', 'port': 20001, 'weight': 1000,
 | 
						|
                'device': next(devs)})
 | 
						|
        ring.pretend_min_part_hours_passed()
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
        del ring
 | 
						|
 | 
						|
        # Rebalance once: this gets 1/6th replica into zone 2; the ring is
 | 
						|
        # saved because devices changed.
 | 
						|
        argv = ["", self.tmpfile, "rebalance", "5759339"]
 | 
						|
        self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)
 | 
						|
        rb = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertEqual(rb.dispersion, 33.333333333333336)
 | 
						|
        self.assertEqual(rb.get_balance(), 100)
 | 
						|
        self.run_srb('pretend_min_part_hours_passed')
 | 
						|
 | 
						|
        # Rebalance again: this gets 2/6th replica into zone 2, but no devices
 | 
						|
        # changed and the balance stays the same. The only improvement is
 | 
						|
        # dispersion.
 | 
						|
 | 
						|
        captured = {}
 | 
						|
 | 
						|
        def capture_save(rb, path):
 | 
						|
            captured['dispersion'] = rb.dispersion
 | 
						|
            captured['balance'] = rb.get_balance()
 | 
						|
        # The warning is benign; it's just telling the user to keep on
 | 
						|
        # rebalancing. The important assertion is that the builder was
 | 
						|
        # saved.
 | 
						|
        with mock.patch('swift.common.ring.RingBuilder.save', capture_save):
 | 
						|
            self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)
 | 
						|
        self.assertEqual(captured, {
 | 
						|
            'dispersion': 16.666666666666668,
 | 
						|
            'balance': 100,
 | 
						|
        })
 | 
						|
 | 
						|
    def test_rebalance_no_devices(self):
 | 
						|
        # Test no devices
 | 
						|
        argv = ["", self.tmpfile, "create", "6", "3.14159265359", "1"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        argv = ["", self.tmpfile, "rebalance"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_rebalance_remove_zero_weighted_device(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.set_dev_weight(2, 0.0)
 | 
						|
        ring.rebalance()
 | 
						|
        ring.pretend_min_part_hours_passed()
 | 
						|
        ring.remove_dev(2)
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
 | 
						|
        # Test rebalance after remove 0 weighted device
 | 
						|
        argv = ["", self.tmpfile, "rebalance", "3"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
        self.assertEqual(len(ring.devs), 4)
 | 
						|
        self.assertIsNone(ring.devs[2])
 | 
						|
 | 
						|
    def test_rebalance_remove_off_end_trims_dev_list(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.set_dev_weight(3, 0.0)
 | 
						|
        ring.rebalance()
 | 
						|
        ring.pretend_min_part_hours_passed()
 | 
						|
        ring.remove_dev(3)
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
 | 
						|
        # Test rebalance after remove 0 weighted device
 | 
						|
        argv = ["", self.tmpfile, "rebalance", "3"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertTrue(ring.validate())
 | 
						|
        self.assertEqual(len(ring.devs), 3)
 | 
						|
 | 
						|
    def test_rebalance_resets_time_remaining(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
 | 
						|
        time_path = 'swift.common.ring.builder.time'
 | 
						|
        argv = ["", self.tmpfile, "rebalance", "3"]
 | 
						|
        time = 0
 | 
						|
 | 
						|
        # first rebalance, should have 1 hour left before next rebalance
 | 
						|
        time += 3600
 | 
						|
        with mock.patch(time_path, return_value=time):
 | 
						|
            self.assertEqual(ring.min_part_seconds_left, 0)
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
            ring = RingBuilder.load(self.tmpfile)
 | 
						|
            self.assertEqual(ring.min_part_seconds_left, 3600)
 | 
						|
 | 
						|
        # min part hours passed, change ring and save for rebalance
 | 
						|
        ring.set_dev_weight(0, ring.devs[0]['weight'] * 2)
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
 | 
						|
        # second rebalance, should have 1 hour left
 | 
						|
        time += 3600
 | 
						|
        with mock.patch(time_path, return_value=time):
 | 
						|
            self.assertEqual(ring.min_part_seconds_left, 0)
 | 
						|
            self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)
 | 
						|
            ring = RingBuilder.load(self.tmpfile)
 | 
						|
            self.assertEqual(ring.min_part_seconds_left, 3600)
 | 
						|
 | 
						|
    def test_time_remaining(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        now = time.time()
 | 
						|
        with mock.patch('swift.common.ring.builder.time', return_value=now):
 | 
						|
            self.run_srb('rebalance')
 | 
						|
            out, err = self.run_srb('rebalance')
 | 
						|
        self.assertIn('No partitions could be reassigned', out)
 | 
						|
        self.assertIn('must be at least min_part_hours', out)
 | 
						|
        self.assertIn('1 hours (1:00:00 remaining)', out)
 | 
						|
        the_future = now + 3600
 | 
						|
        with mock.patch('swift.common.ring.builder.time',
 | 
						|
                        return_value=the_future):
 | 
						|
            out, err = self.run_srb('rebalance')
 | 
						|
        self.assertIn('No partitions could be reassigned', out)
 | 
						|
        self.assertIn('There is no need to do so at this time', out)
 | 
						|
        # or you can pretend_min_part_hours_passed
 | 
						|
        self.run_srb('pretend_min_part_hours_passed')
 | 
						|
        out, err = self.run_srb('rebalance')
 | 
						|
        self.assertIn('No partitions could be reassigned', out)
 | 
						|
        self.assertIn('There is no need to do so at this time', out)
 | 
						|
 | 
						|
    def test_rebalance_failure_does_not_reset_last_moves_epoch(self):
 | 
						|
        ring = RingBuilder(8, 3, 1)
 | 
						|
        ring.add_dev({'id': 0, 'region': 0, 'zone': 0, 'weight': 1,
 | 
						|
                      'ip': '127.0.0.1', 'port': 6010, 'device': 'sda1'})
 | 
						|
        ring.add_dev({'id': 1, 'region': 0, 'zone': 0, 'weight': 1,
 | 
						|
                      'ip': '127.0.0.1', 'port': 6020, 'device': 'sdb1'})
 | 
						|
        ring.add_dev({'id': 2, 'region': 0, 'zone': 0, 'weight': 1,
 | 
						|
                      'ip': '127.0.0.1', 'port': 6030, 'device': 'sdc1'})
 | 
						|
 | 
						|
        time_path = 'swift.common.ring.builder.time'
 | 
						|
        argv = ["", self.tmpfile, "rebalance", "3"]
 | 
						|
 | 
						|
        with mock.patch(time_path, return_value=0):
 | 
						|
            ring.rebalance()
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
 | 
						|
        # min part hours not passed
 | 
						|
        with mock.patch(time_path, return_value=(3600 * 0.6)):
 | 
						|
            self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)
 | 
						|
            ring = RingBuilder.load(self.tmpfile)
 | 
						|
            self.assertEqual(ring.min_part_seconds_left, 3600 * 0.4)
 | 
						|
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
 | 
						|
        # min part hours passed, no partitions need to be moved
 | 
						|
        with mock.patch(time_path, return_value=(3600 * 1.5)):
 | 
						|
            self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)
 | 
						|
            ring = RingBuilder.load(self.tmpfile)
 | 
						|
            self.assertEqual(ring.min_part_seconds_left, 0)
 | 
						|
 | 
						|
    def test_rebalance_with_seed(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        # Test rebalance using explicit seed parameter
 | 
						|
        argv = ["", self.tmpfile, "rebalance", "--seed", "2"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_rebalance_removed_devices(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argvs = [
 | 
						|
            ["", self.tmpfile, "rebalance", "3"],
 | 
						|
            ["", self.tmpfile, "remove", "d0"],
 | 
						|
            ["", self.tmpfile, "rebalance", "3"]]
 | 
						|
        for argv in argvs:
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_rebalance_min_part_hours_not_passed(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argvs = [
 | 
						|
            ["", self.tmpfile, "rebalance", "3"],
 | 
						|
            ["", self.tmpfile, "set_weight", "d0", "1000"]]
 | 
						|
        for argv in argvs:
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        last_replica2part2dev = ring._replica2part2dev
 | 
						|
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        argv = ["", self.tmpfile, "rebalance", "3"]
 | 
						|
        with mock.patch("sys.stdout", mock_stdout):
 | 
						|
            self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)
 | 
						|
        expected = "No partitions could be reassigned.\n" + \
 | 
						|
                   "The time between rebalances must be " + \
 | 
						|
                   "at least min_part_hours: 1 hours"
 | 
						|
        self.assertTrue(expected in mock_stdout.getvalue())
 | 
						|
 | 
						|
        # Messages can be faked, so let's assure that the partition assignment
 | 
						|
        # did not change at all, despite the warning
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        self.assertEqual(last_replica2part2dev, ring._replica2part2dev)
 | 
						|
 | 
						|
    def test_rebalance_part_power_increase(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        ring = RingBuilder.load(self.tmpfile)
 | 
						|
        ring.next_part_power = 1
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
 | 
						|
        argv = ["", self.tmpfile, "rebalance", "3"]
 | 
						|
        self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_write_ring(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["", self.tmpfile, "rebalance"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        argv = ["", self.tmpfile, "write_ring"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        for version in ("1", "2"):
 | 
						|
            argv = ["", self.tmpfile, "write_ring", "--format-version",
 | 
						|
                    version]
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
            with RingReader.open("%s.ring.gz" % self.tmpfile) as reader:
 | 
						|
                self.assertEqual(int(version), reader.version)
 | 
						|
 | 
						|
        exp_results = {'valid_exit_codes': [EXIT_ERROR]}
 | 
						|
        out, err = self.run_srb("write_ring", "--format-version", "3",
 | 
						|
                                exp_results=exp_results)
 | 
						|
        self.assertIn('invalid choice', err)
 | 
						|
 | 
						|
    def test_write_empty_ring(self):
 | 
						|
        ring = RingBuilder(6, 3, 1)
 | 
						|
        ring.save(self.tmpfile)
 | 
						|
        exp_results = {'valid_exit_codes': [EXIT_ERROR]}
 | 
						|
        out, err = self.run_srb("write_ring", exp_results=exp_results)
 | 
						|
        exp_out = 'Unable to write empty ring.\n'
 | 
						|
        self.assertEqual(exp_out, out[-len(exp_out):])
 | 
						|
        self.assertIn("Defaulting to --format-version=1", out)
 | 
						|
 | 
						|
        for version in (1, 2):
 | 
						|
            out, err = self.run_srb("write_ring",
 | 
						|
                                    "--format-version={}".format(version),
 | 
						|
                                    exp_results=exp_results)
 | 
						|
            self.assertEqual(exp_out, out)
 | 
						|
 | 
						|
    def test_write_builder(self):
 | 
						|
        # Test builder file already exists
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["", self.tmpfile, "rebalance"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        argv = ["", self.tmpfile, "write_builder"]
 | 
						|
        exp_results = {'valid_exit_codes': [2]}
 | 
						|
        self.run_srb(*argv, exp_results=exp_results)
 | 
						|
 | 
						|
    def test_write_builder_fractional_replicas(self):
 | 
						|
        # Test builder file already exists
 | 
						|
        self.create_sample_ring(replicas=1.2)
 | 
						|
        argv = ["", self.tmpfile, "rebalance"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        ring_file = os.path.join(os.path.dirname(self.tmpfile),
 | 
						|
                                 os.path.basename(self.tmpfile) + ".ring.gz")
 | 
						|
        os.remove(self.tmpfile)  # loses file...
 | 
						|
 | 
						|
        argv = ["", ring_file, "write_builder", "24"]
 | 
						|
        self.assertIsNone(ringbuilder.main(argv))
 | 
						|
 | 
						|
        # Note that we've picked up an extension
 | 
						|
        builder = RingBuilder.load(self.tmpfile + '.builder')
 | 
						|
        # Version was recorded in the .ring.gz!
 | 
						|
        self.assertEqual(builder.version, 5)
 | 
						|
        # Note that this is different from the original! But it more-closely
 | 
						|
        # reflects the reality that we have an extra replica for 12 of 64 parts
 | 
						|
        self.assertEqual(builder.replicas, 1.1875)
 | 
						|
 | 
						|
    def test_write_builder_no_version(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        rb = RingBuilder.load(self.tmpfile)
 | 
						|
        rb.rebalance()
 | 
						|
 | 
						|
        # Make sure we write down the ring in the old way, with no version
 | 
						|
        rd = rb.get_ring()
 | 
						|
        rd.version = None
 | 
						|
        rd.save(self.tmpfile + ".ring.gz")
 | 
						|
 | 
						|
        ring_file = os.path.join(os.path.dirname(self.tmpfile),
 | 
						|
                                 os.path.basename(self.tmpfile) + ".ring.gz")
 | 
						|
        os.remove(self.tmpfile)  # loses file...
 | 
						|
 | 
						|
        argv = ["", ring_file, "write_builder", "24"]
 | 
						|
        self.assertIsNone(ringbuilder.main(argv))
 | 
						|
 | 
						|
        # Note that we've picked up an extension
 | 
						|
        builder = RingBuilder.load(self.tmpfile + '.builder')
 | 
						|
        # No version in the .ring.gz; default to 0
 | 
						|
        self.assertEqual(builder.version, 0)
 | 
						|
 | 
						|
    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:6200/sdb", "1.0"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        argv = ["", self.tmpfile, "add", "r1z1-127.0.0.1:6200/sdc", "1.0"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        argv = ["", self.tmpfile, "rebalance"]
 | 
						|
        self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)
 | 
						|
 | 
						|
        argv = ["", self.tmpfile, "remove", "--id", "0"]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
        argv = ["", self.tmpfile, "rebalance"]
 | 
						|
        self.assertSystemExit(EXIT_WARNING, 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", "24"]
 | 
						|
        self.assertIsNone(ringbuilder.main(argv))
 | 
						|
 | 
						|
        rb = RingBuilder.load(self.tmpfile + '.builder')
 | 
						|
        self.assertIsNotNone(rb._last_part_moves)
 | 
						|
        rb._last_part_moves = None
 | 
						|
        rb.save(self.tmpfile)
 | 
						|
 | 
						|
        argv = ["", self.tmpfile + '.builder', "rebalance"]
 | 
						|
        self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_version_serialization_default(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        rb = RingBuilder.load(self.tmpfile)
 | 
						|
        rb.rebalance()
 | 
						|
        rd = rb.get_ring()
 | 
						|
        rd.save(self.tmpfile + ".ring.gz")
 | 
						|
 | 
						|
        ring_file = os.path.join(os.path.dirname(self.tmpfile),
 | 
						|
                                 os.path.basename(self.tmpfile) + ".ring.gz")
 | 
						|
 | 
						|
        argv = ["", ring_file, "version"]
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        with mock.patch("sys.stdout", mock_stdout):
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        expected = ("%s.ring.gz: Serialization version: 1 (2-byte IDs), "
 | 
						|
                    "build version: 5\n" % self.tmpfile)
 | 
						|
        self.assertEqual(expected, mock_stdout.getvalue())
 | 
						|
 | 
						|
    def test_version_serialization_1(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        rb = RingBuilder.load(self.tmpfile)
 | 
						|
        rb.rebalance()
 | 
						|
        rd = rb.get_ring()
 | 
						|
        rd.save(self.tmpfile + ".ring.gz", format_version=1)
 | 
						|
 | 
						|
        ring_file = os.path.join(os.path.dirname(self.tmpfile),
 | 
						|
                                 os.path.basename(self.tmpfile) + ".ring.gz")
 | 
						|
 | 
						|
        argv = ["", ring_file, "version"]
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        with mock.patch("sys.stdout", mock_stdout):
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        expected = ("%s.ring.gz: Serialization version: 1 (2-byte IDs), "
 | 
						|
                    "build version: 5\n" % self.tmpfile)
 | 
						|
        self.assertEqual(expected, mock_stdout.getvalue())
 | 
						|
 | 
						|
    def test_version_serialization_2(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        rb = RingBuilder.load(self.tmpfile)
 | 
						|
        rb.rebalance()
 | 
						|
        rd = rb.get_ring()
 | 
						|
        rd.save(self.tmpfile + ".ring.gz", format_version=2)
 | 
						|
 | 
						|
        ring_file = os.path.join(os.path.dirname(self.tmpfile),
 | 
						|
                                 os.path.basename(self.tmpfile) + ".ring.gz")
 | 
						|
 | 
						|
        argv = ["", ring_file, "version"]
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        with mock.patch("sys.stdout", mock_stdout):
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        expected = ("%s.ring.gz: Serialization version: 2 (2-byte IDs), "
 | 
						|
                    "build version: 5\n" % self.tmpfile)
 | 
						|
        self.assertEqual(expected, mock_stdout.getvalue())
 | 
						|
 | 
						|
    def test_version_from_builder_file(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        rb = RingBuilder.load(self.tmpfile)
 | 
						|
        rb.rebalance()
 | 
						|
        rd = rb.get_ring()
 | 
						|
        rd.save(self.tmpfile + ".ring.gz", format_version=2)
 | 
						|
 | 
						|
        # read version from ring when builder file given as argument
 | 
						|
        argv = ["", self.tmpfile, "version"]
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        with mock.patch("sys.stdout", mock_stdout):
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # output still reports ring file
 | 
						|
        expected = ("%s.ring.gz: Serialization version: 2 (2-byte IDs), "
 | 
						|
                    "build version: 5\n" % self.tmpfile)
 | 
						|
        self.assertEqual(expected, mock_stdout.getvalue())
 | 
						|
 | 
						|
    def test_version_with_builder_file_missing(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        rb = RingBuilder.load(self.tmpfile)
 | 
						|
        rb.rebalance()
 | 
						|
        rd = rb.get_ring()
 | 
						|
        rd.save(self.tmpfile + ".ring.gz", format_version=2)
 | 
						|
 | 
						|
        # remove the builder to hit some interesting except blocks in main
 | 
						|
        os.unlink(self.tmpfile)
 | 
						|
 | 
						|
        test_args = [
 | 
						|
            # explicit ring file version of course works when builder missing
 | 
						|
            self.tmpfile + ".ring.gz",
 | 
						|
            # even when builder file is missing you can still implicitly
 | 
						|
            # identify the ring file and read the version
 | 
						|
            self.tmpfile,
 | 
						|
        ]
 | 
						|
 | 
						|
        for path in test_args:
 | 
						|
            argv = ["", path, "version"]
 | 
						|
            mock_stdout = io.StringIO()
 | 
						|
            with mock.patch("sys.stdout", mock_stdout):
 | 
						|
                self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
            expected = ("%s.ring.gz: Serialization version: 2 (2-byte IDs), "
 | 
						|
                        "build version: 5\n" % self.tmpfile)
 | 
						|
            self.assertEqual(expected, mock_stdout.getvalue())
 | 
						|
 | 
						|
        # but of course if the path is nonsensical we get an error
 | 
						|
        argv = ["", self.tmpfile + ".nonsense", "version"]
 | 
						|
        with self.assertRaises(FileNotFoundError):
 | 
						|
            ringbuilder.main(argv)
 | 
						|
 | 
						|
    def test_version_from_builder_file_with_ring_missing(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        rb = RingBuilder.load(self.tmpfile)
 | 
						|
        rb.rebalance()
 | 
						|
        # Don't even bother to write the ring
 | 
						|
 | 
						|
        test_args = [
 | 
						|
            self.tmpfile + ".ring.gz",
 | 
						|
            # If provided with the (existing) builder, we can infer the
 | 
						|
            # (nonexisting) ring
 | 
						|
            self.tmpfile,
 | 
						|
        ]
 | 
						|
 | 
						|
        for path in test_args:
 | 
						|
            argv = ["", path, "version"]
 | 
						|
            # Gotta have a ring to get the version info
 | 
						|
            with self.assertRaises(FileNotFoundError):
 | 
						|
                ringbuilder.main(argv)
 | 
						|
 | 
						|
    def test_warn_at_risk(self):
 | 
						|
        # check that warning is generated when rebalance does not achieve
 | 
						|
        # satisfactory balance
 | 
						|
        self.create_sample_ring()
 | 
						|
        orig_rebalance = RingBuilder.rebalance
 | 
						|
        fake_balance = 6
 | 
						|
 | 
						|
        def fake_rebalance(builder_instance, *args, **kwargs):
 | 
						|
            parts, balance, removed_devs = orig_rebalance(builder_instance)
 | 
						|
            return parts, fake_balance, removed_devs
 | 
						|
 | 
						|
        argv = ["", self.tmpfile, "rebalance"]
 | 
						|
        with mock.patch("swift.common.ring.builder.RingBuilder.rebalance",
 | 
						|
                        fake_rebalance):
 | 
						|
            self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # even when some overload is allowed
 | 
						|
        self.create_sample_ring(overload=0.05)
 | 
						|
        argv = ["", self.tmpfile, "rebalance"]
 | 
						|
        with mock.patch("swift.common.ring.builder.RingBuilder.rebalance",
 | 
						|
                        fake_rebalance):
 | 
						|
            self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_no_warn_when_balanced(self):
 | 
						|
        # check that no warning is generated when satisfactory balance is
 | 
						|
        # achieved...
 | 
						|
        self.create_sample_ring()
 | 
						|
        orig_rebalance = RingBuilder.rebalance
 | 
						|
        fake_balance = 5
 | 
						|
 | 
						|
        def fake_rebalance(builder_instance, *args, **kwargs):
 | 
						|
            parts, balance, removed_devs = orig_rebalance(builder_instance)
 | 
						|
            return parts, fake_balance, removed_devs
 | 
						|
 | 
						|
        argv = ["", self.tmpfile, "rebalance"]
 | 
						|
        with mock.patch("swift.common.ring.builder.RingBuilder.rebalance",
 | 
						|
                        fake_rebalance):
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        # ...or balance is within permitted overload
 | 
						|
        self.create_sample_ring(overload=0.06)
 | 
						|
        fake_balance = 6
 | 
						|
        argv = ["", self.tmpfile, "rebalance"]
 | 
						|
        with mock.patch("swift.common.ring.builder.RingBuilder.rebalance",
 | 
						|
                        fake_rebalance):
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_invalid_device_name(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        for device_name in ["", " ", " sda1", "sda1 ", " meta "]:
 | 
						|
 | 
						|
            argv = ["",
 | 
						|
                    self.tmpfile,
 | 
						|
                    "add",
 | 
						|
                    "r1z1-127.0.0.1:6200/%s" % device_name,
 | 
						|
                    "1"]
 | 
						|
            self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
            argv = ["",
 | 
						|
                    self.tmpfile,
 | 
						|
                    "add",
 | 
						|
                    "--region", "1",
 | 
						|
                    "--zone", "1",
 | 
						|
                    "--ip", "127.0.0.1",
 | 
						|
                    "--port", "6200",
 | 
						|
                    "--device", device_name,
 | 
						|
                    "--weight", "100"]
 | 
						|
            self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_dispersion_command(self):
 | 
						|
        self.create_sample_ring()
 | 
						|
        self.run_srb('rebalance')
 | 
						|
        out, err = self.run_srb('dispersion -v')
 | 
						|
        self.assertIn('dispersion', out.lower())
 | 
						|
        self.assertFalse(err)
 | 
						|
 | 
						|
    def test_dispersion_command_recalculate(self):
 | 
						|
        rb = RingBuilder(8, 3, 0)
 | 
						|
        for i in range(3):
 | 
						|
            i += 1
 | 
						|
            rb.add_dev({'region': 1, 'zone': i, 'weight': 1.0,
 | 
						|
                        'ip': '127.0.0.%d' % i, 'port': 6000, 'device': 'sda'})
 | 
						|
        # extra device in z1
 | 
						|
        rb.add_dev({'region': 1, 'zone': 1, 'weight': 1.0,
 | 
						|
                    'ip': '127.0.0.1', 'port': 6000, 'device': 'sdb'})
 | 
						|
        rb.rebalance()
 | 
						|
        self.assertEqual(rb.dispersion, 16.666666666666668)
 | 
						|
        # simulate an out-of-date dispersion calculation
 | 
						|
        rb.dispersion = 50
 | 
						|
        rb.save(self.tempfile)
 | 
						|
        old_version = rb.version
 | 
						|
        out, err = self.run_srb('dispersion')
 | 
						|
        self.assertIn('Dispersion is 50.000000', out)
 | 
						|
        out, err = self.run_srb('dispersion --recalculate')
 | 
						|
        self.assertIn('Dispersion is 16.666667', out)
 | 
						|
        rb = RingBuilder.load(self.tempfile)
 | 
						|
        self.assertEqual(rb.version, old_version + 1)
 | 
						|
 | 
						|
    def test_use_ringfile_as_builderfile(self):
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        mock_stderr = io.StringIO()
 | 
						|
 | 
						|
        argv = ["", self.tmpfile, "rebalance", "3"],
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
        argv = ["", "%s.ring.gz" % self.tmpfile]
 | 
						|
 | 
						|
        with mock.patch("sys.stdout", mock_stdout):
 | 
						|
            with mock.patch("sys.stderr", mock_stderr):
 | 
						|
                self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
 | 
						|
        expected = "Note: using %s.builder instead of %s.ring.gz " \
 | 
						|
            "as builder file\n" \
 | 
						|
            "Ring Builder file does not exist: %s.builder\n" % (
 | 
						|
                self.tmpfile, self.tmpfile, self.tmpfile)
 | 
						|
        self.assertEqual(expected, mock_stdout.getvalue())
 | 
						|
 | 
						|
    def test_main_no_arguments(self):
 | 
						|
        # Test calling main with no arguments
 | 
						|
        argv = []
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_main_single_argument(self):
 | 
						|
        # Test calling main with single argument
 | 
						|
        argv = [""]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_main_with_safe(self):
 | 
						|
        # Test calling main with '-safe' argument
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["-safe", self.tmpfile]
 | 
						|
        self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_remove_all_devices(self):
 | 
						|
        # Would block without the 'yes' argument
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["", self.tmpfile, "remove", "--weight", "100", "--yes"]
 | 
						|
        with Timeout(5):
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_set_info_all_devices(self):
 | 
						|
        # Would block without the 'yes' argument
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["", self.tmpfile, "set_info", "--weight", "100",
 | 
						|
                "--change-meta", "something", "--yes"]
 | 
						|
        with Timeout(5):
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
    def test_set_weight_all_devices(self):
 | 
						|
        # Would block without the 'yes' argument
 | 
						|
        self.create_sample_ring()
 | 
						|
        argv = ["", self.tmpfile, "set_weight",
 | 
						|
                "--weight", "100", "200", "--yes"]
 | 
						|
        with Timeout(5):
 | 
						|
            self.assertSystemExit(EXIT_SUCCESS, ringbuilder.main, argv)
 | 
						|
 | 
						|
 | 
						|
class TestRebalanceCommand(unittest.TestCase, RunSwiftRingBuilderMixin):
 | 
						|
 | 
						|
    def __init__(self, *args, **kwargs):
 | 
						|
        super(TestRebalanceCommand, self).__init__(*args, **kwargs)
 | 
						|
 | 
						|
    def setUp(self):
 | 
						|
        self.tmpdir = tempfile.mkdtemp()
 | 
						|
        tmpf = tempfile.NamedTemporaryFile(dir=self.tmpdir)
 | 
						|
        self.tempfile = self.tmpfile = tmpf.name
 | 
						|
 | 
						|
    def tearDown(self):
 | 
						|
        try:
 | 
						|
            shutil.rmtree(self.tmpdir, True)
 | 
						|
        except OSError:
 | 
						|
            pass
 | 
						|
 | 
						|
    def run_srb(self, *argv):
 | 
						|
        mock_stdout = io.StringIO()
 | 
						|
        mock_stderr = io.StringIO()
 | 
						|
 | 
						|
        srb_args = ["", self.tempfile] + [str(s) for s in argv]
 | 
						|
 | 
						|
        try:
 | 
						|
            with mock.patch("sys.stdout", mock_stdout):
 | 
						|
                with mock.patch("sys.stderr", mock_stderr):
 | 
						|
                    ringbuilder.main(srb_args)
 | 
						|
        except SystemExit as err:
 | 
						|
            if err.code not in (0, 1):  # (success, warning)
 | 
						|
                raise
 | 
						|
        return (mock_stdout.getvalue(), mock_stderr.getvalue())
 | 
						|
 | 
						|
    def test_debug(self):
 | 
						|
        # NB: getLogger(name) always returns the same object
 | 
						|
        rb_logger = logging.getLogger("swift.ring.builder")
 | 
						|
        try:
 | 
						|
            self.assertNotEqual(rb_logger.getEffectiveLevel(), logging.DEBUG)
 | 
						|
 | 
						|
            self.run_srb("create", 8, 3, 1)
 | 
						|
            self.run_srb("add",
 | 
						|
                         "r1z1-10.1.1.1:2345/sda", 100.0,
 | 
						|
                         "r1z1-10.1.1.1:2345/sdb", 100.0,
 | 
						|
                         "r1z1-10.1.1.1:2345/sdc", 100.0,
 | 
						|
                         "r1z1-10.1.1.1:2345/sdd", 100.0)
 | 
						|
            self.run_srb("rebalance", "--debug")
 | 
						|
            self.assertEqual(rb_logger.getEffectiveLevel(), logging.DEBUG)
 | 
						|
 | 
						|
            rb_logger.setLevel(logging.INFO)
 | 
						|
            self.run_srb("rebalance", "--debug", "123")
 | 
						|
            self.assertEqual(rb_logger.getEffectiveLevel(), logging.DEBUG)
 | 
						|
 | 
						|
            rb_logger.setLevel(logging.INFO)
 | 
						|
            self.run_srb("rebalance", "123", "--debug")
 | 
						|
            self.assertEqual(rb_logger.getEffectiveLevel(), logging.DEBUG)
 | 
						|
 | 
						|
        finally:
 | 
						|
            rb_logger.setLevel(logging.INFO)  # silence other test cases
 | 
						|
 | 
						|
    def test_rebalance_warning_appears(self):
 | 
						|
        self.run_srb("create", 8, 3, 24)
 | 
						|
        # all in one machine: totally balanceable
 | 
						|
        self.run_srb("add",
 | 
						|
                     "r1z1-10.1.1.1:2345/sda", 100.0,
 | 
						|
                     "r1z1-10.1.1.1:2345/sdb", 100.0,
 | 
						|
                     "r1z1-10.1.1.1:2345/sdc", 100.0,
 | 
						|
                     "r1z1-10.1.1.1:2345/sdd", 100.0)
 | 
						|
        out, err = self.run_srb("rebalance")
 | 
						|
        self.assertNotIn("rebalance/repush", out)
 | 
						|
 | 
						|
        # 2 machines of equal size: balanceable, but not in one pass due to
 | 
						|
        # min_part_hours > 0
 | 
						|
        self.run_srb("add",
 | 
						|
                     "r1z1-10.1.1.2:2345/sda", 100.0,
 | 
						|
                     "r1z1-10.1.1.2:2345/sdb", 100.0,
 | 
						|
                     "r1z1-10.1.1.2:2345/sdc", 100.0,
 | 
						|
                     "r1z1-10.1.1.2:2345/sdd", 100.0)
 | 
						|
        self.run_srb("pretend_min_part_hours_passed")
 | 
						|
        out, err = self.run_srb("rebalance")
 | 
						|
        self.assertIn("rebalance/repush", out)
 | 
						|
 | 
						|
        # after two passes, it's all balanced out
 | 
						|
        self.run_srb("pretend_min_part_hours_passed")
 | 
						|
        out, err = self.run_srb("rebalance")
 | 
						|
        self.assertNotIn("rebalance/repush", out)
 | 
						|
 | 
						|
    def test_rebalance_warning_with_overload(self):
 | 
						|
        self.run_srb("create", 8, 3, 24)
 | 
						|
        self.run_srb("set_overload", 0.12)
 | 
						|
        # The ring's balance is at least 5, so normally we'd get a warning,
 | 
						|
        # but it's suppressed due to the overload factor.
 | 
						|
        self.run_srb("add",
 | 
						|
                     "r1z1-10.1.1.1:2345/sda", 100.0,
 | 
						|
                     "r1z1-10.1.1.1:2345/sdb", 100.0,
 | 
						|
                     "r1z1-10.1.1.1:2345/sdc", 120.0)
 | 
						|
        out, err = self.run_srb("rebalance")
 | 
						|
        self.assertNotIn("rebalance/repush", out)
 | 
						|
 | 
						|
        # Now we add in a really big device, but not enough partitions move
 | 
						|
        # to fill it in one pass, so we see the rebalance warning.
 | 
						|
        self.run_srb("add", "r1z1-10.1.1.1:2345/sdd", 99999.0)
 | 
						|
        self.run_srb("pretend_min_part_hours_passed")
 | 
						|
        out, err = self.run_srb("rebalance")
 | 
						|
        self.assertIn("rebalance/repush", out)
 | 
						|
 | 
						|
    def test_cached_dispersion_value(self):
 | 
						|
        self.run_srb("create", 8, 3, 24)
 | 
						|
        self.run_srb("add",
 | 
						|
                     "r1z1-10.1.1.1:2345/sda", 100.0,
 | 
						|
                     "r1z1-10.1.1.1:2345/sdb", 100.0,
 | 
						|
                     "r1z1-10.1.1.1:2345/sdc", 100.0,
 | 
						|
                     "r1z1-10.1.1.1:2345/sdd", 100.0)
 | 
						|
        self.run_srb('rebalance')
 | 
						|
        out, err = self.run_srb()  # list devices
 | 
						|
        self.assertIn('dispersion', out)
 | 
						|
        # remove cached dispersion value
 | 
						|
        builder = RingBuilder.load(self.tempfile)
 | 
						|
        builder.dispersion = None
 | 
						|
        builder.save(self.tempfile)
 | 
						|
        # now dispersion output is suppressed
 | 
						|
        out, err = self.run_srb()  # list devices
 | 
						|
        self.assertNotIn('dispersion', out)
 | 
						|
        # but will show up after rebalance
 | 
						|
        self.run_srb('rebalance', '-f')
 | 
						|
        out, err = self.run_srb()  # list devices
 | 
						|
        self.assertIn('dispersion', out)
 | 
						|
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    unittest.main()
 |