Ejemplo n.º 1
0
 def test_add_dev(self):
     rb = ring.RingBuilder(8, 3, 1)
     dev = {
         'id': 0,
         'region': 0,
         'zone': 0,
         'weight': 1,
         'ip': '127.0.0.1',
         'port': 10000
     }
     dev_id = rb.add_dev(dev)
     self.assertRaises(exceptions.DuplicateDeviceError, rb.add_dev, dev)
     self.assertEqual(dev_id, 0)
     rb = ring.RingBuilder(8, 3, 1)
     #test add new dev with no id
     dev_id = rb.add_dev({
         'zone': 0,
         'region': 1,
         'weight': 1,
         'ip': '127.0.0.1',
         'port': 6000
     })
     self.assertEquals(rb.devs[0]['id'], 0)
     self.assertEqual(dev_id, 0)
     #test add another dev with no id
     dev_id = rb.add_dev({
         'zone': 3,
         'region': 2,
         'weight': 1,
         'ip': '127.0.0.1',
         'port': 6000
     })
     self.assertEquals(rb.devs[1]['id'], 1)
     self.assertEqual(dev_id, 1)
Ejemplo n.º 2
0
    def test_initial_balance(self):
        # 2 boxes, 2 drives each in zone 1
        # 1 box, 2 drives in zone 2
        #
        # This is balanceable, but there used to be some nondeterminism in
        # rebalance() that would sometimes give you an imbalanced ring.
        rb = ring.RingBuilder(8, 3, 1)
        rb.add_dev({'region': 1, 'zone': 1, 'weight': 4000.0,
                    'ip': '10.1.1.1', 'port': 10000, 'device': 'sda'})
        rb.add_dev({'region': 1, 'zone': 1, 'weight': 4000.0,
                    'ip': '10.1.1.1', 'port': 10000, 'device': 'sdb'})

        rb.add_dev({'region': 1, 'zone': 1, 'weight': 4000.0,
                    'ip': '10.1.1.2', 'port': 10000, 'device': 'sda'})
        rb.add_dev({'region': 1, 'zone': 1, 'weight': 4000.0,
                    'ip': '10.1.1.2', 'port': 10000, 'device': 'sdb'})

        rb.add_dev({'region': 1, 'zone': 2, 'weight': 4000.0,
                    'ip': '10.1.1.3', 'port': 10000, 'device': 'sda'})
        rb.add_dev({'region': 1, 'zone': 2, 'weight': 4000.0,
                    'ip': '10.1.1.3', 'port': 10000, 'device': 'sdb'})

        _, balance = rb.rebalance(seed=2)

        # maybe not *perfect*, but should be close
        self.assert_(balance <= 1)
Ejemplo n.º 3
0
    def test_rebalance_part_on_deleted_other_part_on_drained(self):
        rb = ring.RingBuilder(8, 3, 1)
        rb.add_dev({'id': 0, 'region': 1, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sda1'})
        rb.add_dev({'id': 1, 'region': 1, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10001, 'device': 'sda1'})
        rb.add_dev({'id': 2, 'region': 1, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10002, 'device': 'sda1'})
        rb.add_dev({'id': 3, 'region': 1, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10003, 'device': 'sda1'})
        rb.add_dev({'id': 4, 'region': 1, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10004, 'device': 'sda1'})
        rb.add_dev({'id': 5, 'region': 1, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10005, 'device': 'sda1'})

        rb.rebalance(seed=1)
        # We want a partition where 1 replica is on a removed device, 1
        # replica is on a 0-weight device, and 1 on a normal device. To
        # guarantee we have one, we see where partition 123 is, then
        # manipulate its devices accordingly.
        zero_weight_dev_id = rb._replica2part2dev[1][123]
        delete_dev_id = rb._replica2part2dev[2][123]

        rb.set_dev_weight(zero_weight_dev_id, 0.0)
        rb.remove_dev(delete_dev_id)
        rb.rebalance()
Ejemplo n.º 4
0
    def test_rebalance_with_seed(self):
        devs = [(0, 10000), (1, 10001), (2, 10002), (1, 10003)]
        ring_builders = []
        for n in range(3):
            rb = ring.RingBuilder(8, 3, 1)
            for idx, (zone, port) in enumerate(devs):
                rb.add_dev({'id': idx, 'region': 0, 'zone': zone, 'weight': 1,
                            'ip': '127.0.0.1', 'port': port, 'device': 'sda1'})
            ring_builders.append(rb)

        rb0 = ring_builders[0]
        rb1 = ring_builders[1]
        rb2 = ring_builders[2]

        r0 = rb0.get_ring()
        self.assertTrue(rb0.get_ring() is r0)


        rb0.rebalance()  # NO SEED
        rb1.rebalance(seed=10)
        rb2.rebalance(seed=10)

        r1 = rb1.get_ring()
        r2 = rb2.get_ring()

        self.assertFalse(rb0.get_ring() is r0)
        self.assertNotEquals(r0.to_dict(), r1.to_dict())
        self.assertEquals(r1.to_dict(), r2.to_dict())
Ejemplo n.º 5
0
    def test_region_fullness_with_balanceable_ring(self):
        rb = ring.RingBuilder(8, 3, 1)
        rb.add_dev({'id': 0, 'region': 0, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sda1'})
        rb.add_dev({'id': 1, 'region': 0, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10001, 'device': 'sda1'})

        rb.add_dev({'id': 2, 'region': 1, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10003, 'device': 'sda1'})
        rb.add_dev({'id': 3, 'region': 1, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10004, 'device': 'sda1'})

        rb.add_dev({'id': 4, 'region': 2, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10005, 'device': 'sda1'})
        rb.add_dev({'id': 5, 'region': 2, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10006, 'device': 'sda1'})

        rb.add_dev({'id': 6, 'region': 3, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10007, 'device': 'sda1'})
        rb.add_dev({'id': 7, 'region': 3, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10008, 'device': 'sda1'})
        rb.rebalance(seed=2)

        population_by_region = self._get_population_by_region(rb)
        self.assertEquals(population_by_region,
                          {0: 192, 1: 192, 2: 192, 3: 192})
Ejemplo n.º 6
0
 def test_rerebalance(self):
     rb = ring.RingBuilder(8, 3, 1)
     rb.add_dev({'id': 0, 'region': 0, 'zone': 0, 'weight': 1,
                 'ip': '127.0.0.1', 'port': 10000, 'device': 'sda1'})
     rb.add_dev({'id': 1, 'region': 0, 'zone': 1, 'weight': 1,
                 'ip': '127.0.0.1', 'port': 10001, 'device': 'sda1'})
     rb.add_dev({'id': 2, 'region': 0, 'zone': 2, 'weight': 1,
                 'ip': '127.0.0.1', 'port': 10002, 'device': 'sda1'})
     rb.rebalance()
     r = rb.get_ring()
     counts = {}
     for part2dev_id in r._replica2part2dev_id:
         for dev_id in part2dev_id:
             counts[dev_id] = counts.get(dev_id, 0) + 1
     self.assertEquals(counts, {0: 256, 1: 256, 2: 256})
     rb.add_dev({'id': 3, 'region': 0, 'zone': 3, 'weight': 1,
                 'ip': '127.0.0.1', 'port': 10003, 'device': 'sda1'})
     rb.pretend_min_part_hours_passed()
     rb.rebalance()
     r = rb.get_ring()
     counts = {}
     for part2dev_id in r._replica2part2dev_id:
         for dev_id in part2dev_id:
             counts[dev_id] = counts.get(dev_id, 0) + 1
     self.assertEquals(counts, {0: 192, 1: 192, 2: 192, 3: 192})
     rb.set_dev_weight(3, 100)
     rb.rebalance()
     r = rb.get_ring()
     counts = {}
     for part2dev_id in r._replica2part2dev_id:
         for dev_id in part2dev_id:
             counts[dev_id] = counts.get(dev_id, 0) + 1
     self.assertEquals(counts[3], 256)
Ejemplo n.º 7
0
    def test_multitier_expansion_more_devices(self):
        rb = ring.RingBuilder(8, 6, 1)
        rb.add_dev({'id': 0, 'region': 0, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sda'})
        rb.add_dev({'id': 1, 'region': 0, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdb'})
        rb.add_dev({'id': 2, 'region': 0, 'zone': 2, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdc'})

        rb.rebalance()
        rb.validate()

        rb.add_dev({'id': 3, 'region': 0, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdd'})
        rb.add_dev({'id': 4, 'region': 0, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sde'})
        rb.add_dev({'id': 5, 'region': 0, 'zone': 2, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdf'})

        for _ in xrange(5):
            rb.pretend_min_part_hours_passed()
            rb.rebalance()
        rb.validate()

        for part in xrange(rb.parts):
            counts = dict(zone=defaultdict(int),
                          dev_id=defaultdict(int))
            for replica in xrange(rb.replicas):
                dev = rb.devs[rb._replica2part2dev[replica][part]]
                counts['zone'][dev['zone']] += 1
                counts['dev_id'][dev['id']] += 1

            self.assertEquals({0: 2, 1: 2, 2: 2}, dict(counts['zone']))
            self.assertEquals({0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1},
                              dict(counts['dev_id']))
Ejemplo n.º 8
0
 def _shuffled_gather_helper(self):
     rb = ring.RingBuilder(8, 3, 1)
     rb.add_dev({'id': 0, 'region': 0, 'zone': 0, 'weight': 1,
                 'ip': '127.0.0.1', 'port': 10000, 'device': 'sda1'})
     rb.add_dev({'id': 1, 'region': 0, 'zone': 1, 'weight': 1,
                 'ip': '127.0.0.1', 'port': 10001, 'device': 'sda1'})
     rb.add_dev({'id': 2, 'region': 0, 'zone': 2, 'weight': 1,
                 'ip': '127.0.0.1', 'port': 10002, 'device': 'sda1'})
     rb.rebalance()
     rb.add_dev({'id': 3, 'region': 0, 'zone': 3, 'weight': 1,
                 'ip': '127.0.0.1', 'port': 10003, 'device': 'sda1'})
     rb.pretend_min_part_hours_passed()
     parts = rb._gather_reassign_parts()
     max_run = 0
     run = 0
     last_part = 0
     for part, _ in parts:
         if part > last_part:
             run += 1
         else:
             if run > max_run:
                 max_run = run
             run = 0
         last_part = part
     if run > max_run:
         max_run = run
     return max_run > len(parts) / 2
Ejemplo n.º 9
0
    def setUp(self):
        skip_if_no_xattrs()
        self.logger = FakeLogger()
        self.testdir = tempfile.mkdtemp()
        self.devices = os.path.join(self.testdir, 'node')
        shutil.rmtree(self.testdir, ignore_errors=True)
        os.mkdir(self.testdir)
        os.mkdir(self.devices)

        self.rb = ring.RingBuilder(PART_POWER, 6.0, 1)

        for i in range(6):
            ip = "127.0.0.%s" % i
            self.rb.add_dev({
                'id': i,
                'region': 0,
                'zone': 0,
                'weight': 1,
                'ip': ip,
                'port': 10000,
                'device': 'sda1'
            })
        self.rb.rebalance(seed=1)

        self.existing_device = 'sda1'
        os.mkdir(os.path.join(self.devices, self.existing_device))
        self.objects = os.path.join(self.devices, self.existing_device,
                                    'objects')
        self._setup_object()
Ejemplo n.º 10
0
    def test_remove_a_lot(self):
        rb = ring.RingBuilder(3, 3, 1)
        rb.add_dev({'id': 0, 'device': 'd0', 'ip': '10.0.0.1',
                    'port': 6002, 'weight': 1000.0, 'region': 0, 'zone': 1})
        rb.add_dev({'id': 1, 'device': 'd1', 'ip': '10.0.0.2',
                    'port': 6002, 'weight': 1000.0, 'region': 0, 'zone': 2})
        rb.add_dev({'id': 2, 'device': 'd2', 'ip': '10.0.0.3',
                    'port': 6002, 'weight': 1000.0, 'region': 0, 'zone': 3})
        rb.add_dev({'id': 3, 'device': 'd3', 'ip': '10.0.0.1',
                    'port': 6002, 'weight': 1000.0, 'region': 0, 'zone': 1})
        rb.add_dev({'id': 4, 'device': 'd4', 'ip': '10.0.0.2',
                    'port': 6002, 'weight': 1000.0, 'region': 0, 'zone': 2})
        rb.add_dev({'id': 5, 'device': 'd5', 'ip': '10.0.0.3',
                    'port': 6002, 'weight': 1000.0, 'region': 0, 'zone': 3})
        rb.rebalance()
        rb.validate()

        # this has to put more than 1/3 of the partitions in the
        # cluster on removed devices in order to ensure that at least
        # one partition has multiple replicas that need to move.
        #
        # (for an N-replica ring, it's more than 1/N of the
        # partitions, of course)
        rb.remove_dev(3)
        rb.remove_dev(4)
        rb.remove_dev(5)

        rb.rebalance()
        rb.validate()
Ejemplo n.º 11
0
    def test_get_part_devices_partial_replicas(self):
        rb = ring.RingBuilder(8, 2.5, 1)
        rb.add_dev({
            'id': 0,
            'region': 0,
            'zone': 0,
            'weight': 1,
            'ip': '127.0.0.1',
            'port': 10000,
            'device': 'sda1'
        })
        rb.add_dev({
            'id': 1,
            'region': 0,
            'zone': 1,
            'weight': 1,
            'ip': '127.0.0.1',
            'port': 10001,
            'device': 'sda1'
        })
        rb.rebalance()

        # note: partition 255 will only have 2 replicas
        part_devs = sorted(rb.get_part_devices(255),
                           key=operator.itemgetter('id'))
        self.assertEqual(part_devs, [rb.devs[0], rb.devs[1]])
Ejemplo n.º 12
0
    def test_multitier_dont_move_too_many_replicas(self):
        rb = ring.RingBuilder(8, 3, 0)
        # there'll be at least one replica in z0 and z1
        rb.add_dev({'id': 0, 'region': 0, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sda1'})
        rb.add_dev({'id': 1, 'region': 0, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdb1'})
        rb.rebalance()
        rb.validate()

        # only 1 replica should move
        rb.add_dev({'id': 2, 'region': 0, 'zone': 2, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdd1'})
        rb.add_dev({'id': 3, 'region': 0, 'zone': 3, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sde1'})
        rb.add_dev({'id': 4, 'region': 0, 'zone': 4, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdf1'})
        rb.rebalance()
        rb.validate()

        for part in xrange(rb.parts):
            zones = set()
            for replica in xrange(rb.replicas):
                zones.add(rb.devs[rb._replica2part2dev[replica][part]]['zone'])

            if len(zones) != 3:
                raise AssertionError(
                    "Partition %d not in 3 zones (got %r)" % (part, zones))
            if 0 not in zones or 1 not in zones:
                raise AssertionError(
                    "Partition %d not in zones 0 and 1 (got %r)" %
                    (part, zones))
Ejemplo n.º 13
0
    def test_add_rebalance_add_rebalance_delete_rebalance(self):
        """ Test for https://bugs.launchpad.net/swift/+bug/845952 """
        # min_part of 0 to allow for rapid rebalancing
        rb = ring.RingBuilder(8, 3, 0)
        rb.add_dev({'id': 0, 'region': 0, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sda1'})
        rb.add_dev({'id': 1, 'region': 0, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10001, 'device': 'sda1'})
        rb.add_dev({'id': 2, 'region': 0, 'zone': 2, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10002, 'device': 'sda1'})

        rb.rebalance()

        rb.add_dev({'id': 3, 'region': 0, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10003, 'device': 'sda1'})
        rb.add_dev({'id': 4, 'region': 0, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10004, 'device': 'sda1'})
        rb.add_dev({'id': 5, 'region': 0, 'zone': 2, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10005, 'device': 'sda1'})

        rb.rebalance()

        rb.remove_dev(1)

        rb.rebalance()
Ejemplo n.º 14
0
    def test_get_part_devices(self):
        rb = ring.RingBuilder(8, 3, 1)
        self.assertEqual(rb.get_part_devices(0), [])

        rb.add_dev({
            'id': 0,
            'region': 0,
            'zone': 0,
            'weight': 1,
            'ip': '127.0.0.1',
            'port': 10000,
            'device': 'sda1'
        })
        rb.add_dev({
            'id': 1,
            'region': 0,
            'zone': 1,
            'weight': 1,
            'ip': '127.0.0.1',
            'port': 10001,
            'device': 'sda1'
        })
        rb.rebalance()

        part_devs = sorted(rb.get_part_devices(0),
                           key=operator.itemgetter('id'))
        self.assertEqual(part_devs, [rb.devs[0], rb.devs[1]])
Ejemplo n.º 15
0
 def test_fractional_replicas_rebalance(self):
     rb = ring.RingBuilder(8, 2.5, 0)
     rb.add_dev({
         'id': 0,
         'region': 0,
         'region': 0,
         'zone': 0,
         'weight': 1,
         'ip': '127.0.0.1',
         'port': 10000,
         'device': 'sda1'
     })
     rb.add_dev({
         'id': 1,
         'region': 0,
         'region': 0,
         'zone': 1,
         'weight': 1,
         'ip': '127.0.0.1',
         'port': 10001,
         'device': 'sda1'
     })
     rb.rebalance()  # passes by not crashing
     rb.validate()  # also passes by not crashing
     self.assertEqual([len(p2d) for p2d in rb._replica2part2dev],
                      [256, 256, 128])
Ejemplo n.º 16
0
    def test_set_replicas_increase(self):
        rb = ring.RingBuilder(8, 2, 0)
        rb.add_dev({
            'id': 0,
            'region': 0,
            'zone': 0,
            'weight': 1,
            'ip': '127.0.0.1',
            'port': 10000,
            'device': 'sda1'
        })
        rb.add_dev({
            'id': 1,
            'region': 0,
            'zone': 1,
            'weight': 1,
            'ip': '127.0.0.1',
            'port': 10001,
            'device': 'sda1'
        })
        rb.rebalance()
        rb.validate()

        rb.replicas = 2.1
        rb.rebalance()
        rb.validate()

        self.assertEqual([len(p2d) for p2d in rb._replica2part2dev],
                         [256, 256, 25])

        rb.replicas = 2.2
        rb.rebalance()
        rb.validate()
        self.assertEqual([len(p2d) for p2d in rb._replica2part2dev],
                         [256, 256, 51])
Ejemplo n.º 17
0
 def test_save_load(self):
     rb = ring.RingBuilder(8, 3, 1)
     devs = [{'id': 0, 'region': 0, 'zone': 0, 'weight': 1,
              'ip': '127.0.0.0', 'port': 10000,
              'replication_ip': '127.0.0.0', 'replication_port': 10000,
              'device': 'sda1', 'meta': 'meta0'},
             {'id': 1, 'region': 0, 'zone': 1, 'weight': 1,
              'ip': '127.0.0.1', 'port': 10001,
              'replication_ip': '127.0.0.1', 'replication_port': 10001,
              'device': 'sdb1', 'meta': 'meta1'},
             {'id': 2, 'region': 0, 'zone': 2, 'weight': 2,
              'ip': '127.0.0.2', 'port': 10002,
              'replication_ip': '127.0.0.2', 'replication_port': 10002,
              'device': 'sdc1', 'meta': 'meta2'},
             {'id': 3, 'region': 0, 'zone': 3, 'weight': 2,
              'ip': '127.0.0.3', 'port': 10003,
              'replication_ip': '127.0.0.3', 'replication_port': 10003,
              'device': 'sdd1', 'meta': ''}]
     for d in devs:
         rb.add_dev(d)
     rb.rebalance()
     builder_file = os.path.join(self.testdir, 'test_save.builder')
     rb.save(builder_file)
     loaded_rb = ring.RingBuilder.load(builder_file)
     self.maxDiff = None
     self.assertEquals(loaded_rb.to_dict(), rb.to_dict())
Ejemplo n.º 18
0
    def test_multitier_part_moves_with_positive_min_part_hours(self):
        rb = ring.RingBuilder(8, 3, 99)
        rb.add_dev({'id': 0, 'region': 0, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sda1'})
        rb.rebalance()
        rb.validate()

        # min_part_hours is >0, so we'll only be able to move 1
        # replica to a new home
        rb.add_dev({'id': 1, 'region': 0, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdb1'})
        rb.add_dev({'id': 2, 'region': 0, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdc1'})
        rb.pretend_min_part_hours_passed()
        rb.rebalance()
        rb.validate()

        for part in xrange(rb.parts):
            devs = set()
            for replica in xrange(rb.replicas):
                devs.add(rb._replica2part2dev[replica][part])

            if len(devs) != 2:
                raise AssertionError(
                    "Partition %d not on 2 devs (got %r)" % (part, devs))
Ejemplo n.º 19
0
    def test_set_replicas_decrease(self):
        rb = ring.RingBuilder(4, 5, 0)
        rb.add_dev({'id': 0, 'region': 0, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sda1'})
        rb.add_dev({'id': 1, 'region': 0, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10001, 'device': 'sda1'})
        rb.rebalance()
        rb.validate()

        rb.replicas = 4.9
        rb.rebalance()
        print repr(rb._replica2part2dev)
        print repr(rb.devs)
        rb.validate()

        self.assertEqual([len(p2d) for p2d in rb._replica2part2dev],
                         [16, 16, 16, 16, 14])

        # cross a couple of integer thresholds (4 and 3)
        rb.replicas = 2.5
        rb.rebalance()
        rb.validate()

        self.assertEqual([len(p2d) for p2d in rb._replica2part2dev],
                         [16, 16, 8])
Ejemplo n.º 20
0
 def test_init(self):
     rb = ring.RingBuilder(8, 3, 1)
     self.assertEquals(rb.part_power, 8)
     self.assertEquals(rb.replicas, 3)
     self.assertEquals(rb.min_part_hours, 1)
     self.assertEquals(rb.parts, 2 ** 8)
     self.assertEquals(rb.devs, [])
     self.assertEquals(rb.devs_changed, False)
     self.assertEquals(rb.version, 0)
Ejemplo n.º 21
0
    def test_set_replicas(self):
        rb = ring.RingBuilder(8, 3.2, 1)
        rb.devs_changed = False
        rb.set_replicas(3.25)
        self.assertTrue(rb.devs_changed)

        rb.devs_changed = False
        rb.set_replicas(3.2500001)
        self.assertFalse(rb.devs_changed)
Ejemplo n.º 22
0
    def test_add_replicas_then_rebalance_respects_weight(self):
        rb = ring.RingBuilder(8, 3, 1)
        rb.add_dev({'id': 0, 'region': 0, 'region': 0, 'zone': 0, 'weight': 3,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sda'})
        rb.add_dev({'id': 1, 'region': 0, 'region': 0, 'zone': 0, 'weight': 3,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdb'})
        rb.add_dev({'id': 2, 'region': 0, 'region': 0, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdc'})
        rb.add_dev({'id': 3, 'region': 0, 'region': 0, 'zone': 0, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdd'})

        rb.add_dev({'id': 4, 'region': 0, 'region': 0, 'zone': 1, 'weight': 3,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sde'})
        rb.add_dev({'id': 5, 'region': 0, 'region': 0, 'zone': 1, 'weight': 3,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdf'})
        rb.add_dev({'id': 6, 'region': 0, 'region': 0, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdg'})
        rb.add_dev({'id': 7, 'region': 0, 'region': 0, 'zone': 1, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdh'})

        rb.add_dev({'id': 8, 'region': 0, 'region': 0, 'zone': 2, 'weight': 3,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdi'})
        rb.add_dev({'id': 9, 'region': 0, 'region': 0, 'zone': 2, 'weight': 3,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdj'})
        rb.add_dev({'id': 10, 'region': 0, 'region': 0, 'zone': 2, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdk'})
        rb.add_dev({'id': 11, 'region': 0, 'region': 0, 'zone': 2, 'weight': 1,
                    'ip': '127.0.0.1', 'port': 10000, 'device': 'sdl'})

        rb.rebalance(seed=1)

        r = rb.get_ring()
        counts = {}
        for part2dev_id in r._replica2part2dev_id:
            for dev_id in part2dev_id:
                counts[dev_id] = counts.get(dev_id, 0) + 1
        self.assertEquals(counts, {0: 96, 1: 96,
                                   2: 32, 3: 32,
                                   4: 96, 5: 96,
                                   6: 32, 7: 32,
                                   8: 96, 9: 96,
                                   10: 32, 11: 32})

        rb.replicas *= 2
        rb.rebalance(seed=1)

        r = rb.get_ring()
        counts = {}
        for part2dev_id in r._replica2part2dev_id:
            for dev_id in part2dev_id:
                counts[dev_id] = counts.get(dev_id, 0) + 1
        self.assertEquals(counts, {0: 192, 1: 192,
                                   2: 64, 3: 64,
                                   4: 192, 5: 192,
                                   6: 64, 7: 64,
                                   8: 192, 9: 192,
                                   10: 64, 11: 64})
Ejemplo n.º 23
0
 def test_search_devs(self):
     rb = ring.RingBuilder(8, 3, 1)
     devs = [{'id': 0, 'region': 0, 'zone': 0, 'weight': 1,
              'ip': '127.0.0.0', 'port': 10000, 'device': 'sda1',
              'meta': 'meta0'},
             {'id': 1, 'region': 0, 'zone': 1, 'weight': 1,
              'ip': '127.0.0.1', 'port': 10001, 'device': 'sdb1',
              'meta': 'meta1'},
             {'id': 2, 'region': 1, 'zone': 2, 'weight': 2,
              'ip': '127.0.0.2', 'port': 10002, 'device': 'sdc1',
              'meta': 'meta2'},
             {'id': 3, 'region': 1, 'zone': 3, 'weight': 2,
              'ip': '127.0.0.3', 'port': 10003, 'device': 'sdd1',
              'meta': 'meta3'},
             {'id': 4, 'region': 2, 'zone': 4, 'weight': 1,
              'ip': '127.0.0.4', 'port': 10004, 'device': 'sde1',
              'meta': 'meta4', 'replication_ip': '127.0.0.10',
              'replication_port': 20000},
             {'id': 5, 'region': 2, 'zone': 5, 'weight': 2,
              'ip': '127.0.0.5', 'port': 10005, 'device': 'sdf1',
              'meta': 'meta5', 'replication_ip': '127.0.0.11',
              'replication_port': 20001},
             {'id': 6, 'region': 2, 'zone': 6, 'weight': 2,
              'ip': '127.0.0.6', 'port': 10006, 'device': 'sdg1',
              'meta': 'meta6', 'replication_ip': '127.0.0.12',
              'replication_port': 20002}]
     for d in devs:
         rb.add_dev(d)
     rb.rebalance()
     res = rb.search_devs({'region': 0})
     self.assertEquals(res, [devs[0], devs[1]])
     res = rb.search_devs({'region': 1})
     self.assertEquals(res, [devs[2], devs[3]])
     res = rb.search_devs({'region': 1, 'zone': 2})
     self.assertEquals(res, [devs[2]])
     res = rb.search_devs({'id': 1})
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs({'zone': 1})
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs({'ip': '127.0.0.1'})
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs({'ip': '127.0.0.1', 'port': 10001})
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs({'port': 10001})
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs({'replication_ip': '127.0.0.10'})
     self.assertEquals(res, [devs[4]])
     res = rb.search_devs({'replication_ip': '127.0.0.10',
                           'replication_port': 20000})
     self.assertEquals(res, [devs[4]])
     res = rb.search_devs({'replication_port': 20000})
     self.assertEquals(res, [devs[4]])
     res = rb.search_devs({'device': 'sdb1'})
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs({'meta': 'meta1'})
     self.assertEquals(res, [devs[1]])
Ejemplo n.º 24
0
    def test_find_parts(self):
        rb = ring.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': 1,
            'region': 1,
            'zone': 1,
            'weight': 100,
            'ip': '127.0.0.1',
            'port': 10001,
            'device': 'sda1'
        })
        rb.add_dev({
            'id': 2,
            'region': 1,
            'zone': 2,
            'weight': 100,
            'ip': '127.0.0.1',
            'port': 10002,
            'device': 'sda1'
        })
        rb.rebalance()

        rb.add_dev({
            'id': 3,
            'region': 2,
            'zone': 1,
            'weight': 10,
            'ip': '127.0.0.1',
            'port': 10004,
            'device': 'sda1'
        })
        rb.pretend_min_part_hours_passed()
        rb.rebalance()

        argv = [
            'swift-ring-builder', 'object.builder', 'list_parts', '127.0.0.1'
        ]
        sorted_partition_count = find_parts(rb, argv)

        # 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))
Ejemplo n.º 25
0
 def test_search_devs(self):
     rb = ring.RingBuilder(8, 3, 1)
     devs = [{'id': 0, 'region': 0, 'zone': 0, 'weight': 1,
              'ip': '127.0.0.0', 'port': 10000, 'device': 'sda1',
              'meta': 'meta0'},
             {'id': 1, 'region': 0, 'zone': 1, 'weight': 1,
              'ip': '127.0.0.1', 'port': 10001, 'device': 'sdb1',
              'meta': 'meta1'},
             {'id': 2, 'region': 1, 'zone': 2, 'weight': 2,
              'ip': '127.0.0.2', 'port': 10002, 'device': 'sdc1',
              'meta': 'meta2'},
             {'id': 3, 'region': 1, 'zone': 3, 'weight': 2,
              'ip': '127.0.0.3', 'port': 10003, 'device': 'sdd1',
              'meta': 'meta3'},
             {'id': 4, 'region': 2, 'zone': 4, 'weight': 1,
              'ip': '127.0.0.4', 'port': 10004, 'device': 'sde1',
              'meta': 'meta4', 'replication_ip': '127.0.0.10',
              'replication_port': 20000},
             {'id': 5, 'region': 2, 'zone': 5, 'weight': 2,
              'ip': '127.0.0.5', 'port': 10005, 'device': 'sdf1',
              'meta': 'meta5', 'replication_ip': '127.0.0.11',
              'replication_port': 20001},
             {'id': 6, 'region': 2, 'zone': 6, 'weight': 2,
              'ip': '127.0.0.6', 'port': 10006, 'device': 'sdg1',
              'meta': 'meta6', 'replication_ip': '127.0.0.12',
              'replication_port': 20002}]
     for d in devs:
         rb.add_dev(d)
     rb.rebalance()
     res = rb.search_devs('r0')
     self.assertEquals(res, [devs[0], devs[1]])
     res = rb.search_devs('r1')
     self.assertEquals(res, [devs[2], devs[3]])
     res = rb.search_devs('r1z2')
     self.assertEquals(res, [devs[2]])
     res = rb.search_devs('d1')
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs('z1')
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs('-127.0.0.1')
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs('-[127.0.0.1]:10001')
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs(':10001')
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs('R127.0.0.10')
     self.assertEquals(res, [devs[4]])
     res = rb.search_devs('R[127.0.0.10]:20000')
     self.assertEquals(res, [devs[4]])
     res = rb.search_devs('R:20000')
     self.assertEquals(res, [devs[4]])
     res = rb.search_devs('/sdb1')
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs('_meta1')
     self.assertRaises(ValueError, rb.search_devs, 'OMGPONIES')
Ejemplo n.º 26
0
 def test_search_devs(self):
     rb = ring.RingBuilder(8, 3, 1)
     devs = [{
         'id': 0,
         'zone': 0,
         'weight': 1,
         'ip': '127.0.0.0',
         'port': 10000,
         'device': 'sda1',
         'meta': 'meta0'
     }, {
         'id': 1,
         'zone': 1,
         'weight': 1,
         'ip': '127.0.0.1',
         'port': 10001,
         'device': 'sdb1',
         'meta': 'meta1'
     }, {
         'id': 2,
         'zone': 2,
         'weight': 2,
         'ip': '127.0.0.2',
         'port': 10002,
         'device': 'sdc1',
         'meta': 'meta2'
     }, {
         'id': 3,
         'zone': 3,
         'weight': 2,
         'ip': '127.0.0.3',
         'port': 10003,
         'device': 'sdd1',
         'meta': 'meta3'
     }]
     for d in devs:
         rb.add_dev(d)
     rb.rebalance()
     res = rb.search_devs('d1')
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs('z1')
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs('-127.0.0.1')
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs('-[127.0.0.1]:10001')
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs(':10001')
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs('/sdb1')
     self.assertEquals(res, [devs[1]])
     res = rb.search_devs('_meta1')
     self.assertRaises(ValueError, rb.search_devs, 'OMGPONIES')
Ejemplo n.º 27
0
    def test_load(self):
        rb = ring.RingBuilder(8, 3, 1)
        devs = [{'id': 0, 'region': 0, 'zone': 0, 'weight': 1,
                 'ip': '127.0.0.0', 'port': 10000, 'device': 'sda1',
                 'meta': 'meta0'},
                {'id': 1, 'region': 0, 'zone': 1, 'weight': 1,
                 'ip': '127.0.0.1', 'port': 10001, 'device': 'sdb1',
                 'meta': 'meta1'},
                {'id': 2, 'region': 0, 'zone': 2, 'weight': 2,
                 'ip': '127.0.0.2', 'port': 10002, 'device': 'sdc1',
                 'meta': 'meta2'},
                {'id': 3, 'region': 0, 'zone': 3, 'weight': 2,
                 'ip': '127.0.0.3', 'port': 10003, 'device': 'sdd1'}]
        for d in devs:
            rb.add_dev(d)
        rb.rebalance()

        real_pickle = pickle.load
        try:
            #test a legit builder
            fake_pickle = mock.Mock(return_value=rb)
            fake_open = mock.Mock(return_value=None)
            pickle.load = fake_pickle
            builder = ring.RingBuilder.load('fake.builder', open=fake_open)
            self.assertEquals(fake_pickle.call_count, 1)
            fake_open.assert_has_calls([mock.call('fake.builder', 'rb')])
            self.assertEquals(builder, rb)
            fake_pickle.reset_mock()
            fake_open.reset_mock()

            #test old style builder
            fake_pickle.return_value = rb.to_dict()
            pickle.load = fake_pickle
            builder = ring.RingBuilder.load('fake.builder', open=fake_open)
            fake_open.assert_has_calls([mock.call('fake.builder', 'rb')])
            self.assertEquals(builder.devs, rb.devs)
            fake_pickle.reset_mock()
            fake_open.reset_mock()

            #test old devs but no meta
            no_meta_builder = rb
            for dev in no_meta_builder.devs:
                del(dev['meta'])
            fake_pickle.return_value = no_meta_builder
            pickle.load = fake_pickle
            builder = ring.RingBuilder.load('fake.builder', open=fake_open)
            fake_open.assert_has_calls([mock.call('fake.builder', 'rb')])
            self.assertEquals(builder.devs, rb.devs)
            fake_pickle.reset_mock()
        finally:
            pickle.load = real_pickle
Ejemplo n.º 28
0
 def test_normalized_device_tier_names(self):
     rb = ring.RingBuilder(8, 3, 0)
     rb.add_dev({
         'region': 1,
         'zone': 1,
         'ip': '127.0.0.1',
         'port': 6011,
         'device': 'd1',
         'weight': 0.0,
     })
     dev = rb.devs[0]
     expected = 'r1z1-127.0.0.1/d1'
     self.assertEqual(expected, get_tier_name(tiers_for_dev(dev)[-1], rb))
     self.assertEqual(expected, pretty_dev(dev))
Ejemplo n.º 29
0
 def test_get_ring(self):
     rb = ring.RingBuilder(8, 3, 1)
     rb.add_dev({
         'id': 0,
         'region': 0,
         'zone': 0,
         'weight': 1,
         'ip': '127.0.0.1',
         'port': 10000,
         'device': 'sda1'
     })
     rb.add_dev({
         'id': 1,
         'region': 0,
         'zone': 1,
         'weight': 1,
         'ip': '127.0.0.1',
         'port': 10001,
         'device': 'sda1'
     })
     rb.add_dev({
         'id': 2,
         'region': 0,
         'zone': 2,
         'weight': 1,
         'ip': '127.0.0.1',
         'port': 10002,
         'device': 'sda1'
     })
     rb.add_dev({
         'id': 3,
         'region': 0,
         'zone': 1,
         'weight': 1,
         'ip': '127.0.0.1',
         'port': 10004,
         'device': 'sda1'
     })
     rb.remove_dev(1)
     rb.rebalance()
     r = rb.get_ring()
     self.assert_(isinstance(r, ring.RingData))
     r2 = rb.get_ring()
     self.assert_(r is r2)
     rb.rebalance()
     r3 = rb.get_ring()
     self.assert_(r3 is not r2)
     r4 = rb.get_ring()
     self.assert_(r3 is r4)
Ejemplo n.º 30
0
    def setUp(self):
        skip_if_no_xattrs()
        self.logger = FakeLogger()
        self.testdir = tempfile.mkdtemp()
        self.devices = os.path.join(self.testdir, 'node')
        shutil.rmtree(self.testdir, ignore_errors=1)
        os.mkdir(self.testdir)
        os.mkdir(self.devices)

        self.rb = ring.RingBuilder(8, 6.0, 1)

        for i in range(6):
            ip = "127.0.0.%s" % i
            self.rb.add_dev({
                'id': i,
                'region': 0,
                'zone': 0,
                'weight': 1,
                'ip': ip,
                'port': 10000,
                'device': 'sda1'
            })
        self.rb.rebalance(seed=1)

        self.existing_device = 'sda1'
        os.mkdir(os.path.join(self.devices, self.existing_device))
        self.objects = os.path.join(self.devices, self.existing_device,
                                    'objects')
        os.mkdir(self.objects)
        self._hash = utils.hash_path('a/c/o')
        digest = binascii.unhexlify(self._hash)
        part = struct.unpack_from('>I', digest)[0] >> 24
        self.next_part = struct.unpack_from('>I', digest)[0] >> 23
        self.objdir = os.path.join(self.objects, str(part), self._hash[-3:],
                                   self._hash)
        os.makedirs(self.objdir)
        self.object_fname = "1278553064.00000.data"
        self.objname = os.path.join(self.objdir, self.object_fname)
        with open(self.objname, "wb") as dummy:
            dummy.write(b"Hello World!")
            write_metadata(dummy, {'name': '/a/c/o', 'Content-Length': '12'})

        test_policies = [StoragePolicy(0, 'platin', True)]
        storage_policy._POLICIES = StoragePolicyCollection(test_policies)

        self.expected_dir = os.path.join(self.objects, str(self.next_part),
                                         self._hash[-3:], self._hash)
        self.expected_file = os.path.join(self.expected_dir, self.object_fname)