import os
import sys
import time
import pytest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from helpers.cluster import ClickHouseCluster
from helpers.test_tools import TSV
cluster = ClickHouseCluster(__file__)
node = cluster.add_instance(
"node", main_configs=["configs/config.d/storage_configuration.xml"], stay_alive=True
)
@pytest.fixture(scope="module")
def started_cluster():
try:
cluster.start()
yield cluster
finally:
cluster.shutdown()
old_disk_config = """
/var/lib/clickhouse/disk0/
disk0
localhost
9000
"""
new_disk_config = """
/var/lib/clickhouse/disk0/
/var/lib/clickhouse/disk1/
disk1
disk0
localhost
9000
"""
def set_config(node, config):
node.replace_config("/etc/clickhouse-server/config.d/config.xml", config)
node.query("SYSTEM RELOAD CONFIG")
# to give ClickHouse time to refresh disks
time.sleep(1)
def test_hot_reload_policy(started_cluster):
node.query(
"CREATE TABLE t (d Int32, s String) ENGINE = MergeTree() PARTITION BY d ORDER BY tuple() SETTINGS storage_policy = 'default_policy'"
)
node.query("SYSTEM STOP MERGES t")
node.query("INSERT INTO TABLE t VALUES (1, 'foo')")
set_config(node, new_disk_config)
# After reloading new policy with new disk, merge tree tables should reinitialize the new disk (create relative path, 'detached' folder...)
# and as default policy is `least_used`, at least one insertion should come to the new disk
node.query("INSERT INTO TABLE t VALUES (1, 'foo')")
node.query("INSERT INTO TABLE t VALUES (1, 'bar')")
num_disks = int(
node.query(
"SELECT uniqExact(disk_name) FROM system.parts WHERE database = 'default' AND table = 't'"
)
)
assert (
num_disks == 2
), "Node should write data to 2 disks after reloading disks, but got {}".format(
num_disks
)
# If `detached` is not created this query will throw exception
node.query("ALTER TABLE t DETACH PARTITION 1")
node.query("DROP TABLE t")
def test_hot_reload_policy_distributed_table(started_cluster):
# Same test for distributed table, it should reinitialize the storage policy and data volume
# We check it by trying an insert and the distribution queue must be on new disk
# Restart node first
set_config(node, old_disk_config)
node.restart_clickhouse()
node.query(
"CREATE TABLE t (d Int32, s String) ENGINE = MergeTree PARTITION BY d ORDER BY tuple()"
)
node.query(
"CREATE TABLE t_d (d Int32, s String) ENGINE = Distributed('default', 'default', 't', d%20, 'default_policy')"
)
node.query("SYSTEM STOP DISTRIBUTED SENDS t_d")
node.query(
"INSERT INTO TABLE t_d SETTINGS prefer_localhost_replica = 0 VALUES (2, 'bar') (12, 'bar')"
)
# t_d should create queue on disk0
queue_path = node.query("SELECT data_path FROM system.distribution_queue")
assert (
"disk0" in queue_path
), "Distributed table should create distributed queue on disk0 (disk1), but the queue path is {}".format(
queue_path
)
node.query("SYSTEM START DISTRIBUTED SENDS t_d")
node.query("SYSTEM FLUSH DISTRIBUTED t_d")
set_config(node, new_disk_config)
node.query("SYSTEM STOP DISTRIBUTED SENDS t_d")
node.query(
"INSERT INTO TABLE t_d SETTINGS prefer_localhost_replica = 0 VALUES (2, 'bar') (12, 'bar')"
)
# t_d should create queue on disk1
queue_path = node.query("SELECT data_path FROM system.distribution_queue")
assert (
"disk1" in queue_path
), "Distributed table should be using new disk (disk1), but the queue paths are {}".format(
queue_path
)
node.query("DROP TABLE t")
node.query("DROP TABLE t_d")