Ejemplo n.º 1
0
    def test_touch_nodes_from_host(self):
        nodes = self._add_nodes_and_assert_exists(count=3)

        # Add another node from a different host
        with mock.patch.object(ovn_hash_ring_db, 'CONF') as mock_conf:
            mock_conf.host = 'another-host-' + uuidutils.generate_uuid()
            another_host_node = self._add_nodes_and_assert_exists()[0]

        # Assert that updated_at isn't updated yet
        for node in nodes:
            node_db = self._get_node_row(node)
            self.assertEqual(node_db.created_at, node_db.updated_at)

        # Assert the same for the node from another host
        node_db = self._get_node_row(another_host_node)
        self.assertEqual(node_db.created_at, node_db.updated_at)

        # Touch the nodes from our host
        time.sleep(1)
        ovn_hash_ring_db.touch_nodes_from_host(self.admin_ctx,
                                               HASH_RING_TEST_GROUP)

        # Assert that updated_at is now updated
        for node in nodes:
            node_db = self._get_node_row(node)
            self.assertGreater(node_db.updated_at, node_db.created_at)

        # Assert that the node from another host hasn't been touched
        # (updated_at is not updated)
        node_db = self._get_node_row(another_host_node)
        self.assertEqual(node_db.created_at, node_db.updated_at)
Ejemplo n.º 2
0
    def test_touch_nodes_from_host_different_groups(self):
        another_group = 'another_test_group'
        group1 = self._add_nodes_and_assert_exists(count=3)
        group2 = self._add_nodes_and_assert_exists(count=2,
                                                   group_name=another_group)

        # Assert that updated_at isn't updated yet
        for node in group1 + group2:
            node_db = self._get_node_row(node)
            self.assertEqual(node_db.created_at, node_db.updated_at)

        # Touch the nodes from group1
        time.sleep(1)
        ovn_hash_ring_db.touch_nodes_from_host(self.admin_ctx,
                                               HASH_RING_TEST_GROUP)

        # Assert that updated_at was updated for group1
        for node in group1:
            node_db = self._get_node_row(node)
            self.assertGreater(node_db.updated_at, node_db.created_at)

        # Assert that updated_at wasn't updated for group2
        for node in group2:
            node_db = self._get_node_row(node)
            self.assertEqual(node_db.created_at, node_db.updated_at)
Ejemplo n.º 3
0
    def test_active_nodes(self):
        self._add_nodes_and_assert_exists(count=3)

        # Add another node from a different host
        with mock.patch.object(ovn_hash_ring_db, 'CONF') as mock_conf:
            mock_conf.host = 'another-host-' + uuidutils.generate_uuid()
            another_host_node = self._add_nodes_and_assert_exists()[0]

        # Assert all nodes are active (within 60 seconds)
        self.assertEqual(
            4,
            len(
                ovn_hash_ring_db.get_active_nodes(
                    self.admin_ctx,
                    interval=60,
                    group_name=HASH_RING_TEST_GROUP)))

        # Substract 60 seconds from utcnow() and touch the nodes from our host
        time.sleep(1)
        fake_utcnow = timeutils.utcnow() - datetime.timedelta(seconds=60)
        with mock.patch.object(timeutils, 'utcnow') as mock_utcnow:
            mock_utcnow.return_value = fake_utcnow
            ovn_hash_ring_db.touch_nodes_from_host(self.admin_ctx,
                                                   HASH_RING_TEST_GROUP)

        # Now assert that all nodes from our host are seeing as offline.
        # Only the node from another host should be active
        active_nodes = ovn_hash_ring_db.get_active_nodes(
            self.admin_ctx, interval=60, group_name=HASH_RING_TEST_GROUP)
        self.assertEqual(1, len(active_nodes))
        self.assertEqual(another_host_node, active_nodes[0].node_uuid)
Ejemplo n.º 4
0
    def test_ring_rebalance(self):
        # Use pre-defined UUIDs to make the hashes predictable
        node_1_uuid = db_hash_ring.add_node(self.admin_ctx,
                                            HASH_RING_TEST_GROUP, 'node-1')
        node_2_uuid = db_hash_ring.add_node(self.admin_ctx,
                                            HASH_RING_TEST_GROUP, 'node-2')

        # Add another node from a different host
        with mock.patch.object(db_hash_ring, 'CONF') as mock_conf:
            mock_conf.host = 'another-host-52359446-c366'
            another_host_node = db_hash_ring.add_node(self.admin_ctx,
                                                      HASH_RING_TEST_GROUP,
                                                      'another-host')

        # Assert all nodes are alive in the ring
        self.hash_ring_manager.refresh()
        self.assertEqual(3, len(self.hash_ring_manager._hash_ring.nodes))

        # Hash certain values against the nodes
        hash_dict_before = {
            node_1_uuid: 'fake-uuid',
            node_2_uuid: 'fake-uuid-0',
            another_host_node: 'fake-uuid-ABCDE'
        }
        self._verify_hashes(hash_dict_before)

        # Mock utcnow() as the HASH_RING_NODES_TIMEOUT have expired
        # already and touch the nodes from our host
        fake_utcnow = timeutils.utcnow() - datetime.timedelta(
            seconds=constants.HASH_RING_NODES_TIMEOUT)
        with mock.patch.object(timeutils, 'utcnow') as mock_utcnow:
            mock_utcnow.return_value = fake_utcnow
            db_hash_ring.touch_nodes_from_host(self.admin_ctx,
                                               HASH_RING_TEST_GROUP)

        # Now assert that the ring was re-balanced and only the node from
        # another host is marked as alive
        self.hash_ring_manager.refresh()
        self.assertEqual([another_host_node],
                         list(self.hash_ring_manager._hash_ring.nodes.keys()))

        # Now only "another_host_node" is alive, all values should hash to it
        hash_dict_after_rebalance = {
            another_host_node: 'fake-uuid',
            another_host_node: 'fake-uuid-0',
            another_host_node: 'fake-uuid-ABCDE'
        }
        self._verify_hashes(hash_dict_after_rebalance)

        # Now touch the nodes so they appear active again
        db_hash_ring.touch_nodes_from_host(self.admin_ctx,
                                           HASH_RING_TEST_GROUP)
        self.hash_ring_manager.refresh()

        # The ring should re-balance and as it was before
        self._verify_hashes(hash_dict_before)
Ejemplo n.º 5
0
    def test__wait_startup_before_caching(self):
        db_hash_ring.add_node(self.admin_ctx, HASH_RING_TEST_GROUP, 'node-1')
        db_hash_ring.add_node(self.admin_ctx, HASH_RING_TEST_GROUP, 'node-2')

        # Assert it will return True until created_at != updated_at
        self.assertTrue(self.hash_ring_manager._wait_startup_before_caching)
        self.assertTrue(self.hash_ring_manager._cache_startup_timeout)

        # Touch the nodes (== update the updated_at column)
        db_hash_ring.touch_nodes_from_host(self.admin_ctx,
                                           HASH_RING_TEST_GROUP)

        # Assert it's now False. Waiting is not needed anymore
        self.assertFalse(self.hash_ring_manager._wait_startup_before_caching)
        self.assertFalse(self.hash_ring_manager._cache_startup_timeout)

        # Now assert that since the _cache_startup_timeout has been
        # flipped, we no longer will read from the database
        with mock.patch.object(hash_ring_manager.db_hash_ring,
                               'get_active_nodes') as get_nodes_mock:
            self.assertFalse(
                self.hash_ring_manager._wait_startup_before_caching)
            self.assertFalse(get_nodes_mock.called)
Ejemplo n.º 6
0
 def touch_hash_ring_nodes(self):
     # NOTE(lucasagomes): Note that we do not rely on the OVSDB lock
     # here because we want the maintenance tasks from each instance to
     # execute this task.
     hash_ring_db.touch_nodes_from_host(self.ctx, self._group)