Example #1
0
    def test_rebalance_stability_join(self):
        num_services = 10
        num_nodes = 10000
        # Adding 1 service to a set of N should move 1/(N+1) of all nodes
        # Eg, for a cluster of 10 nodes, adding one should move 1/11, or 9%
        # We allow for 1/N to allow for rounding in tests.
        redistribution_factor = 1.0 / num_services

        nodes = [str(x) for x in range(num_nodes)]
        services = [str(x) for x in range(num_services)]
        new_services = services + ['new']
        delta = self._compare_rings(
            nodes, services, hash_ring.HashRing(services),
            new_services, hash_ring.HashRing(new_services))

        self.assertLess(len(delta), num_nodes * redistribution_factor)
Example #2
0
    def test_rebalance_stability_leave(self):
        num_services = 10
        num_nodes = 10000
        # Removing 1 service from a set of N should move 1/(N) of all nodes
        # Eg, for a cluster of 10 nodes, removing one should move 1/10, or 10%
        # We allow for 1/(N-1) to allow for rounding in tests.
        redistribution_factor = 1.0 / (num_services - 1)

        nodes = [str(x) for x in range(num_nodes)]
        services = [str(x) for x in range(num_services)]
        new_services = services[:]
        new_services.pop()
        delta = self._compare_rings(
            nodes, services, hash_ring.HashRing(services),
            new_services, hash_ring.HashRing(new_services))

        self.assertLess(len(delta), num_nodes * redistribution_factor)
Example #3
0
 def test_distribution_one_replica(self):
     hosts = ['foo', 'bar', 'baz']
     ring = hash_ring.HashRing(hosts)
     fake_1_hosts = ring.get_hosts('fake')
     fake_2_hosts = ring.get_hosts('fake-again')
     # We should have one hosts for each thing
     self.assertThat(fake_1_hosts, matchers.HasLength(1))
     self.assertThat(fake_2_hosts, matchers.HasLength(1))
     # And they must not be the same answers even on this simple data.
     self.assertNotEqual(fake_1_hosts, fake_2_hosts)
Example #4
0
    def test__hash2int_returns_int(self, mock_md5):
        r1 = 32 * 'a'
        r2 = 32 * 'b'
        # 2**PARTITION_EXPONENT calls to md5.update per host
        # PARTITION_EXPONENT is currently always 5, so 32 calls each here
        mock_md5.return_value.hexdigest.side_effect = [r1] * 32 + [r2] * 32

        hosts = ['foo', 'bar']
        ring = hash_ring.HashRing(hosts)

        self.assertIn(int(r1, 16), ring._host_hashes)
        self.assertIn(int(r2, 16), ring._host_hashes)
Example #5
0
 def test_ignore_hosts(self):
     hosts = ['foo', 'bar', 'baz']
     ring = hash_ring.HashRing(hosts)
     equals_bar_or_baz = matchers.MatchesAny(
         matchers.Equals(['bar']),
         matchers.Equals(['baz']))
     self.assertThat(
         ring.get_hosts('fake', ignore_hosts=['foo']),
         equals_bar_or_baz)
     self.assertThat(
         ring.get_hosts('fake', ignore_hosts=['foo', 'bar']),
         equals_bar_or_baz)
     self.assertEqual([], ring.get_hosts('fake', ignore_hosts=hosts))
Example #6
0
 def test_create_ring(self):
     hosts = ['foo', 'bar']
     ring = hash_ring.HashRing(hosts)
     self.assertEqual(set(hosts), ring.hosts)
     self.assertEqual(1, ring.replicas)
     self.assertEqual(2 ** 5 * 2, len(ring._partitions))
Example #7
0
 def test_get_hosts_invalid_data(self):
     hosts = ['foo', 'bar']
     ring = hash_ring.HashRing(hosts)
     self.assertRaises(exception.Invalid,
                       ring.get_hosts,
                       None)
Example #8
0
 def test_ignore_non_existent_host(self):
     hosts = ['foo', 'bar']
     ring = hash_ring.HashRing(hosts)
     self.assertEqual(['foo'], ring.get_hosts('fake',
                                              ignore_hosts=['baz']))