2015-07-09 02:50:16 +03:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#
|
2015-07-10 08:26:30 +03:00
|
|
|
# Copyright 2015, Google Inc. All rights reserved.
|
2015-07-09 02:50:16 +03:00
|
|
|
# Use of this source code is governed by a BSD-style license that can
|
|
|
|
# be found in the LICENSE file.
|
2015-07-31 03:58:40 +03:00
|
|
|
"""End-to-end test for horizontal resharding automation."""
|
2015-07-09 02:50:16 +03:00
|
|
|
|
|
|
|
import environment
|
|
|
|
import utils
|
2015-07-10 08:26:30 +03:00
|
|
|
import worker
|
2015-07-09 02:50:16 +03:00
|
|
|
|
2015-07-31 03:58:40 +03:00
|
|
|
|
2015-07-09 02:50:16 +03:00
|
|
|
def setUpModule():
|
2015-07-10 08:26:30 +03:00
|
|
|
worker.setUpModule()
|
|
|
|
utils.Vtctld().start()
|
2015-07-09 02:50:16 +03:00
|
|
|
|
2015-08-31 08:03:22 +03:00
|
|
|
|
2015-07-09 02:50:16 +03:00
|
|
|
def tearDownModule():
|
2015-07-10 08:26:30 +03:00
|
|
|
worker.tearDownModule()
|
2015-07-09 02:50:16 +03:00
|
|
|
|
2015-07-31 03:58:40 +03:00
|
|
|
|
2015-07-10 20:51:14 +03:00
|
|
|
class TestAutomationHorizontalResharding(worker.TestBaseSplitClone):
|
2015-07-10 08:26:30 +03:00
|
|
|
"""This test reuses worker.py because worker.py also covers the happy path
|
|
|
|
of the horizontal resharding code. Instead of running the different resharding
|
|
|
|
steps "manually" as part of the test, they will be run by the automation
|
|
|
|
cluster operation.
|
|
|
|
"""
|
2015-07-09 02:50:16 +03:00
|
|
|
|
2015-08-26 03:42:03 +03:00
|
|
|
KEYSPACE = 'test_keyspace'
|
2015-08-26 02:32:09 +03:00
|
|
|
|
2015-07-10 08:26:30 +03:00
|
|
|
def test_regular_operation(self):
|
|
|
|
# Use a dedicated worker to run all vtworker commands.
|
|
|
|
worker_proc, _, worker_rpc_port = utils.run_vtworker_bg(
|
|
|
|
['--cell', 'test_nj'],
|
|
|
|
auto_log=True)
|
2015-08-26 04:54:04 +03:00
|
|
|
vtworker_endpoint = 'localhost:' + str(worker_rpc_port)
|
2015-07-10 08:26:30 +03:00
|
|
|
|
2015-08-26 08:45:44 +03:00
|
|
|
automation_server_proc, automation_server_port = (
|
|
|
|
utils.run_automation_server())
|
2015-07-10 08:26:30 +03:00
|
|
|
|
2015-07-31 03:58:40 +03:00
|
|
|
source_shard_list = '0'
|
|
|
|
dest_shard_list = '-80,80-'
|
|
|
|
_, vtctld_endpoint = utils.vtctld.rpc_endpoint()
|
2015-08-30 19:32:00 +03:00
|
|
|
utils.run(
|
|
|
|
environment.binary_argstr('automation_client') +
|
|
|
|
' --server localhost:' + str(automation_server_port) +
|
|
|
|
' --task HorizontalReshardingTask' +
|
|
|
|
' --param keyspace=' + self.KEYSPACE +
|
|
|
|
' --param source_shard_list=' + source_shard_list +
|
|
|
|
' --param dest_shard_list=' + dest_shard_list +
|
|
|
|
' --param vtctld_endpoint=' + vtctld_endpoint +
|
|
|
|
' --param vtworker_endpoint=' + vtworker_endpoint)
|
2015-07-14 22:23:24 +03:00
|
|
|
|
2015-08-26 02:32:09 +03:00
|
|
|
self.verify()
|
|
|
|
|
|
|
|
utils.kill_sub_process(automation_server_proc, soft=True)
|
|
|
|
utils.kill_sub_process(worker_proc, soft=True)
|
2015-08-30 19:32:00 +03:00
|
|
|
|
2015-08-26 02:32:09 +03:00
|
|
|
def verify(self):
|
2015-07-31 03:58:40 +03:00
|
|
|
self.assert_shard_data_equal(0, worker.shard_master,
|
|
|
|
worker.shard_0_tablets.replica)
|
|
|
|
self.assert_shard_data_equal(1, worker.shard_master,
|
|
|
|
worker.shard_1_tablets.replica)
|
2015-08-30 19:32:00 +03:00
|
|
|
|
2015-08-26 02:32:09 +03:00
|
|
|
# Verify effect of MigrateServedTypes. Dest shards are serving now.
|
2015-08-26 03:42:03 +03:00
|
|
|
utils.check_srv_keyspace('test_nj', self.KEYSPACE,
|
2015-08-26 02:32:09 +03:00
|
|
|
'Partitions(master): -80 80-\n' +
|
|
|
|
'Partitions(rdonly): -80 80-\n' +
|
|
|
|
'Partitions(replica): -80 80-\n')
|
2015-08-30 19:32:00 +03:00
|
|
|
|
2015-08-26 02:32:09 +03:00
|
|
|
# Check that query service is disabled (source shard) or enabled (dest).
|
2015-08-30 19:32:00 +03:00
|
|
|
|
2015-08-26 02:32:09 +03:00
|
|
|
# The 'rdonly' tablet requires an explicit healthcheck first because
|
|
|
|
# the following sequence of events is happening in this test:
|
|
|
|
# - SplitDiff returns 'rdonly' as 'spare' tablet (NOT_SERVING)
|
|
|
|
# - MigrateServedTypes runs and does not refresh then 'spare' tablet
|
|
|
|
# (still NOT_SERVING)
|
|
|
|
# Shard_TabletControl.DisableQueryService=true will be set in the topology
|
|
|
|
# - explicit or periodic healthcheck runs:
|
|
|
|
# a) tablet seen as caught up, change type from 'spare' to 'rdonly'
|
|
|
|
# (change to SERVING)
|
|
|
|
# b) post-action callback agent.refreshTablet() reads the topology
|
|
|
|
# and finds out that DisableQueryService=true is set.
|
|
|
|
# (change to NOT_SERVING)
|
|
|
|
#
|
|
|
|
# We must run an explicit healthcheck or we can see one of the two states:
|
|
|
|
# - NOT_SERVING, DisableQueryService=false, tablet type 'spare'
|
|
|
|
# (immediately after SplitDiff returned)
|
|
|
|
# - SERVING, DisableQueryService=false, tablet type 'rdonly'
|
|
|
|
# (during healthcheck before post-action callback is called)
|
|
|
|
utils.run_vtctl(['RunHealthCheck', worker.shard_rdonly1.tablet_alias,
|
|
|
|
'rdonly'],
|
|
|
|
auto_log=True)
|
2015-08-30 19:32:00 +03:00
|
|
|
|
2015-08-26 02:32:09 +03:00
|
|
|
# source shard: query service must be disabled after MigrateServedTypes.
|
2015-08-30 19:32:00 +03:00
|
|
|
utils.check_tablet_query_service(
|
|
|
|
self, worker.shard_rdonly1,
|
2015-08-26 02:32:09 +03:00
|
|
|
serving=False, tablet_control_disabled=True)
|
2015-08-30 19:32:00 +03:00
|
|
|
utils.check_tablet_query_service(
|
|
|
|
self, worker.shard_replica,
|
2015-08-26 02:32:09 +03:00
|
|
|
serving=False, tablet_control_disabled=True)
|
2015-08-30 19:32:00 +03:00
|
|
|
utils.check_tablet_query_service(
|
|
|
|
self, worker.shard_master,
|
2015-08-26 02:32:09 +03:00
|
|
|
serving=False, tablet_control_disabled=True)
|
2015-08-30 19:32:00 +03:00
|
|
|
|
2015-08-26 02:32:09 +03:00
|
|
|
# dest shard -80: query service must be disabled after MigrateServedTypes.
|
|
|
|
# Run explicit healthcheck because 'rdonly' tablet may still be 'spare'.
|
|
|
|
utils.run_vtctl(['RunHealthCheck', worker.shard_0_rdonly1.tablet_alias,
|
|
|
|
'rdonly'],
|
|
|
|
auto_log=True)
|
2015-08-30 19:32:00 +03:00
|
|
|
utils.check_tablet_query_service(
|
|
|
|
self, worker.shard_0_rdonly1,
|
2015-08-26 02:32:09 +03:00
|
|
|
serving=True, tablet_control_disabled=False)
|
2015-08-30 19:32:00 +03:00
|
|
|
utils.check_tablet_query_service(
|
|
|
|
self, worker.shard_0_replica,
|
2015-08-26 02:32:09 +03:00
|
|
|
serving=True, tablet_control_disabled=False)
|
2015-08-30 19:32:00 +03:00
|
|
|
utils.check_tablet_query_service(
|
|
|
|
self, worker.shard_0_master,
|
2015-08-26 02:32:09 +03:00
|
|
|
serving=True, tablet_control_disabled=False)
|
2015-07-14 22:23:24 +03:00
|
|
|
|
2015-08-26 02:32:09 +03:00
|
|
|
# dest shard 80-: query service must be disabled after MigrateServedTypes.
|
|
|
|
# Run explicit healthcheck because 'rdonly' tablet is still 'spare'.
|
|
|
|
utils.run_vtctl(['RunHealthCheck', worker.shard_1_rdonly1.tablet_alias,
|
|
|
|
'rdonly'],
|
|
|
|
auto_log=True)
|
2015-08-30 19:32:00 +03:00
|
|
|
utils.check_tablet_query_service(
|
|
|
|
self, worker.shard_1_rdonly1,
|
2015-08-26 02:32:09 +03:00
|
|
|
serving=True, tablet_control_disabled=False)
|
2015-08-30 19:32:00 +03:00
|
|
|
utils.check_tablet_query_service(
|
|
|
|
self, worker.shard_1_replica,
|
2015-08-26 02:32:09 +03:00
|
|
|
serving=True, tablet_control_disabled=False)
|
2015-08-30 19:32:00 +03:00
|
|
|
utils.check_tablet_query_service(
|
|
|
|
self, worker.shard_1_master,
|
2015-08-26 02:32:09 +03:00
|
|
|
serving=True, tablet_control_disabled=False)
|
2015-07-09 02:50:16 +03:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2015-07-10 08:26:30 +03:00
|
|
|
utils.main(test_options=worker.add_test_options)
|