Files
scylladb/test/cluster/test_zero_token_nodes_topology_ops.py
Avi Kivity 0ae22a09d4 LICENSE: Update to version 1.1
Updated terms of non-commercial use (must be a never-customer).
2026-04-12 19:46:33 +03:00

113 lines
5.0 KiB
Python

#
# Copyright (C) 2024-present ScyllaDB
#
# SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.1
#
import pytest
import logging
import time
from cassandra.cluster import ConsistencyLevel
from test.pylib.manager_client import ManagerClient
from test.pylib.scylla_cluster import ReplaceConfig
from test.pylib.util import wait_for_cql_and_get_hosts
from test.cluster.util import check_node_log_for_failed_mutations, start_writes
@pytest.mark.asyncio
@pytest.mark.parametrize('tablets_enabled', [True, False])
async def test_zero_token_nodes_topology_ops(manager: ManagerClient, tablets_enabled: bool):
"""
Test that:
- adding a zero-token node in the gossip-based topology fails
- topology operations in the Raft-based topology involving zero-token nodes succeed
- client requests to normal nodes in the presence of zero-token nodes (2 normal nodes, RF=2, CL=2) succeed
"""
def get_pf(rack: str) -> dict[str, str]:
return {"dc": "dc1", "rack": rack}
normal_cfg = {'tablets_mode_for_new_keyspaces': 'enabled' if tablets_enabled else 'disabled'}
zero_token_cfg = {'tablets_mode_for_new_keyspaces': 'enabled' if tablets_enabled else 'disabled', 'join_ring': False}
logging.info('Adding the first server')
server_a = await manager.server_add(config=normal_cfg, property_file=get_pf("r1"))
logging.info('Adding the second server as zero-token')
server_b = await manager.server_add(config=zero_token_cfg, property_file=get_pf("rz"))
logging.info('Adding the third server')
server_c = await manager.server_add(config=normal_cfg, property_file=get_pf("r2"))
await wait_for_cql_and_get_hosts(manager.cql, [server_a, server_c], time.time() + 60)
finish_writes = await start_writes(manager.cql, 2, ConsistencyLevel.TWO)
logging.info('Adding the fourth server as zero-token')
await manager.server_add(config=zero_token_cfg, property_file=get_pf("rz")) # Necessary to preserve the Raft majority.
logging.info(f'Restarting {server_b}')
await manager.server_stop_gracefully(server_b.server_id)
await manager.server_start(server_b.server_id)
logging.info(f'Stopping {server_b}')
await manager.server_stop_gracefully(server_b.server_id)
replace_cfg_b = ReplaceConfig(replaced_id=server_b.server_id, reuse_ip_addr=False, use_host_id=False)
logging.info(f'Trying to replace {server_b} with a token-owing server')
await manager.server_add(replace_cfg_b, config=normal_cfg, property_file=server_b.property_file(),
expected_error='Cannot replace the zero-token node')
logging.info(f'Replacing {server_b}')
server_b = await manager.server_add(replace_cfg_b, config=zero_token_cfg, property_file=server_b.property_file())
logging.info(f'Stopping {server_b}')
await manager.server_stop_gracefully(server_b.server_id)
replace_cfg_b = ReplaceConfig(replaced_id=server_b.server_id, reuse_ip_addr=True, use_host_id=False)
logging.info(f'Replacing {server_b} with the same IP')
server_b = await manager.server_add(replace_cfg_b, config=zero_token_cfg, property_file=server_b.property_file())
logging.info(f'Decommissioning {server_b}')
await manager.decommission_node(server_b.server_id)
logging.info('Adding two zero-token servers')
[server_b, server_d] = await manager.servers_add(2, config=zero_token_cfg, property_file=get_pf("rz"))
logging.info(f'Rebuilding {server_b}')
await manager.rebuild_node(server_b.server_id)
logging.info(f'Stopping {server_b}')
await manager.server_stop_gracefully(server_b.server_id)
logging.info(f'Stopping {server_d}')
await manager.server_stop_gracefully(server_d.server_id)
server_d_id = await manager.get_host_id(server_d.server_id)
logging.info(f'Initiating removenode of {server_b} by {server_a}, ignore_dead={[server_d_id]}')
await manager.remove_node(server_a.server_id, server_b.server_id, [server_d_id])
logging.info(f'Initiating removenode of {server_d} by {server_a}')
await manager.remove_node(server_a.server_id, server_d.server_id)
logging.info('Adding a zero-token server')
await manager.server_add(config=zero_token_cfg, property_file=get_pf("rz"))
# FIXME: Finish writes after the last server_add call once scylladb/scylladb#19737 is fixed.
logging.info('Checking results of the background writes')
await finish_writes()
logging.info('Adding a normal server')
server_e = await manager.server_add(config=normal_cfg, property_file=get_pf("r1"))
logging.info(f'Stopping {server_e}')
await manager.server_stop_gracefully(server_e.server_id)
replace_cfg_e = ReplaceConfig(replaced_id=server_e.server_id, reuse_ip_addr=False, use_host_id=False)
logging.info(f'Trying to replace {server_e} with a zero-token server')
await manager.server_add(replace_cfg_e, config=zero_token_cfg, property_file=server_e.property_file(),
expected_error='Cannot replace the token-owning node')
await check_node_log_for_failed_mutations(manager, server_a)
await check_node_log_for_failed_mutations(manager, server_c)