blob: e49d33fa65c0ac3c0001b7a53eb0b7b876dde77c [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#pragma once
#include <memory>
#include <string>
#include <unordered_set>
#include <vector>
#include "kudu/client/shared_ptr.h" // IWYU pragma: keep
#include "kudu/integration-tests/cluster_itest_util.h"
#include "kudu/integration-tests/mini_cluster_fs_inspector.h"
#include "kudu/mini-cluster/external_mini_cluster.h"
#include "kudu/tserver/tablet_server-test-base.h"
#include "kudu/util/random.h"
#include "kudu/util/status.h"
namespace kudu {
class MonoDelta;
namespace client {
class KuduClient;
class KuduTable;
} // namespace client
namespace tserver {
// A base for tablet server integration tests.
class TabletServerIntegrationTestBase : public TabletServerTestBase {
public:
TabletServerIntegrationTestBase();
void SetUp() override;
void AddExtraFlags(const std::string& flags_str,
std::vector<std::string>* flags);
void CreateCluster(const std::string& data_root_path,
std::vector<std::string> non_default_ts_flags = {},
std::vector<std::string> non_default_master_flags = {},
cluster::LocationInfo location_info = {});
// Creates TSServerDetails instance for each TabletServer and stores them
// in 'tablet_servers_'.
void CreateTSProxies();
// Waits that all replicas for a all tablets of 'table_id' table are online
// and creates the tablet_replicas_ map.
void WaitForReplicasAndUpdateLocations(const std::string& table_id = kTableId);
// Returns the last committed leader of the consensus configuration. Tries to get it from master
// but then actually tries to the get the committed consensus configuration to make sure.
itest::TServerDetails* GetLeaderReplicaOrNull(const std::string& tablet_id);
// For the last committed consensus configuration, return the last committed
// leader of the consensus configuration and its followers.
Status GetTabletLeaderAndFollowers(const std::string& tablet_id,
itest::TServerDetails** leader,
std::vector<itest::TServerDetails*>* followers);
Status GetLeaderReplicaWithRetries(const std::string& tablet_id,
itest::TServerDetails** leader,
int max_attempts = 100);
Status GetTabletLeaderUUIDFromMaster(const std::string& tablet_id,
std::string* leader_uuid);
itest::TServerDetails* GetReplicaWithUuidOrNull(const std::string& tablet_id,
const std::string& uuid);
// Wait for tablet servers to start up.
void WaitForTabletServers();
// Wait for tablet servers to start and all replicas are available for all
// the test table's tablets.
void WaitForTSAndReplicas(const std::string& table_id = kTableId);
// Removes a set of servers from the replicas_ list.
// Handy for controlling who to validate against after killing servers.
void PruneFromReplicas(const std::unordered_set<std::string>& uuids);
void GetOnlyLiveFollowerReplicas(const std::string& tablet_id,
std::vector<itest::TServerDetails*>* followers);
Status ShutdownServerWithUUID(const std::string& uuid);
Status RestartServerWithUUID(const std::string& uuid);
// Since we're fault-tolerant we might mask when a tablet server is
// dead. This returns Status::IllegalState() if fewer than 'num_tablet_servers'
// are alive.
Status CheckTabletServersAreAlive(int num_tablet_servers);
void TearDown() override;
void CreateClient(client::sp::shared_ptr<client::KuduClient>* client);
// Create a table with a single tablet, with 'num_replicas'.
void CreateTable(const std::string& table_id = kTableId);
// Starts an external cluster with a single tablet and a number of replicas
// equal to 'FLAGS_num_replicas'. The caller can pass 'ts_flags' and
// 'master_flags' to specify non-default flags to pass to the tablet servers
// and masters respectively. For location-aware tests scenarios, location
// mapping rules can be passed using the 'location_info' parameter.
void BuildAndStart(std::vector<std::string> ts_flags = {},
std::vector<std::string> master_flags = {},
cluster::LocationInfo location_info = {},
bool create_table = true);
void AssertAllReplicasAgree(int expected_result_count);
// Check for and restart any TS that have crashed.
// Returns the number of servers restarted.
int RestartAnyCrashedTabletServers();
// Assert that no tablet servers have crashed.
// Tablet servers that have been manually Shutdown() are allowed.
void AssertNoTabletServersCrashed();
// Find the tablet leader replica and wait for at least one operation
// committed in current term. This is useful when finding a leader replica
// to commence a Raft configuration change. Otherwise, any Raft configuration
// change attempt ends up with error:
// 'Illegal state: Leader has not yet committed an operation in its own term'.
Status WaitForLeaderWithCommittedOp(const std::string& tablet_id,
const MonoDelta& timeout,
itest::TServerDetails** leader);
// Get UUIDs of tablet servers that have a replica of the tablet identified
// by the 'tablet_id' parameter. The result is sorted in ascending order.
std::vector<std::string> GetServersWithReplica(const std::string& tablet_id) const;
// Get UUIDs of tablet servers that do not have replicas of the tablet
// identified by the 'tablet_id' parameter. The result is sorted in ascending order.
std::vector<std::string> GetServersWithoutReplica(const std::string& tablet_id) const;
protected:
std::unique_ptr<cluster::ExternalMiniCluster> cluster_;
std::unique_ptr<itest::MiniClusterFsInspector> inspect_;
// Maps server uuid to TServerDetails
itest::TabletServerMap tablet_servers_;
// Maps tablet to all replicas.
itest::TabletReplicaMap tablet_replicas_;
client::sp::shared_ptr<client::KuduClient> client_;
client::sp::shared_ptr<client::KuduTable> table_;
std::string tablet_id_;
ThreadSafeRandom random_;
};
} // namespace tserver
} // namespace kudu