blob: 7e2f26187d931d0f4e48ded3e957cca0a7446c31 [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.
#include "kudu/tools/tool_action.h"
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <boost/algorithm/string/predicate.hpp>
#include <gflags/gflags_declare.h>
#include "kudu/common/common.pb.h"
#include "kudu/common/wire_protocol.h"
#include "kudu/common/wire_protocol.pb.h"
#include "kudu/gutil/map-util.h"
#include "kudu/gutil/strings/join.h"
#include "kudu/gutil/strings/split.h"
#include "kudu/gutil/strings/stringpiece.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/master/master.pb.h"
#include "kudu/master/master.proxy.h"
#include "kudu/tools/tool_action_common.h"
#include "kudu/tserver/tablet_server.h"
#include "kudu/util/status.h"
DECLARE_string(columns);
using std::cout;
using std::string;
using std::unique_ptr;
using std::vector;
namespace kudu {
using master::ListTabletServersRequestPB;
using master::ListTabletServersResponsePB;
using master::MasterServiceProxy;
namespace tools {
namespace {
const char* const kTServerAddressArg = "tserver_address";
const char* const kTServerAddressDesc = "Address of a Kudu Tablet Server of "
"form 'hostname:port'. Port may be omitted if the Tablet Server is bound "
"to the default port.";
const char* const kFlagArg = "flag";
const char* const kValueArg = "value";
Status TServerGetFlags(const RunnerContext& context) {
const string& address = FindOrDie(context.required_args, kTServerAddressArg);
return PrintServerFlags(address, tserver::TabletServer::kDefaultPort);
}
Status TServerSetFlag(const RunnerContext& context) {
const string& address = FindOrDie(context.required_args, kTServerAddressArg);
const string& flag = FindOrDie(context.required_args, kFlagArg);
const string& value = FindOrDie(context.required_args, kValueArg);
return SetServerFlag(address, tserver::TabletServer::kDefaultPort,
flag, value);
}
Status TServerStatus(const RunnerContext& context) {
const string& address = FindOrDie(context.required_args, kTServerAddressArg);
return PrintServerStatus(address, tserver::TabletServer::kDefaultPort);
}
Status TServerTimestamp(const RunnerContext& context) {
const string& address = FindOrDie(context.required_args, kTServerAddressArg);
return PrintServerTimestamp(address, tserver::TabletServer::kDefaultPort);
}
Status ListTServers(const RunnerContext& context) {
LeaderMasterProxy proxy;
RETURN_NOT_OK(proxy.Init(context));
ListTabletServersRequestPB req;
ListTabletServersResponsePB resp;
proxy.SyncRpc<ListTabletServersRequestPB, ListTabletServersResponsePB>(
req, &resp, "ListTabletServers", &MasterServiceProxy::ListTabletServers);
if (resp.has_error()) {
return StatusFromPB(resp.error().status());
}
DataTable table({});
const auto& servers = resp.servers();
auto hostport_to_string = [](const HostPortPB& hostport) {
return strings::Substitute("$0:$1", hostport.host(), hostport.port());
};
for (const auto& column : strings::Split(FLAGS_columns, ",", strings::SkipEmpty())) {
vector<string> values;
if (boost::iequals(column, "uuid")) {
for (const auto& server : servers) {
values.emplace_back(server.instance_id().permanent_uuid());
}
} else if (boost::iequals(column, "seqno")) {
for (const auto& server : servers) {
values.emplace_back(std::to_string(server.instance_id().instance_seqno()));
}
} else if (boost::iequals(column, "rpc-addresses") ||
boost::iequals(column, "rpc_addresses")) {
for (const auto& server : servers) {
values.emplace_back(JoinMapped(server.registration().rpc_addresses(),
hostport_to_string, ","));
}
} else if (boost::iequals(column, "http-addresses") ||
boost::iequals(column, "http_addresses")) {
for (const auto& server : servers) {
values.emplace_back(JoinMapped(server.registration().http_addresses(),
hostport_to_string, ","));
}
} else if (boost::iequals(column, "version")) {
for (const auto& server : servers) {
values.emplace_back(server.registration().software_version());
}
} else if (boost::iequals(column, "heartbeat")) {
for (const auto& server : servers) {
values.emplace_back(strings::Substitute("$0ms", server.millis_since_heartbeat()));
}
} else if (boost::iequals(column, "location")) {
for (const auto& server : servers) {
string loc = server.location();
values.emplace_back(loc.empty() ? "<none>" : std::move(loc));
}
} else {
return Status::InvalidArgument("unknown column (--columns)", column);
}
table.AddColumn(column.ToString(), std::move(values));
}
RETURN_NOT_OK(table.PrintTo(cout));
return Status::OK();
}
} // anonymous namespace
unique_ptr<Mode> BuildTServerMode() {
unique_ptr<Action> get_flags =
ActionBuilder("get_flags", &TServerGetFlags)
.Description("Get the gflags for a Kudu Tablet Server")
.AddRequiredParameter({ kTServerAddressArg, kTServerAddressDesc })
.AddOptionalParameter("all_flags")
.AddOptionalParameter("flag_tags")
.Build();
unique_ptr<Action> set_flag =
ActionBuilder("set_flag", &TServerSetFlag)
.Description("Change a gflag value on a Kudu Tablet Server")
.AddRequiredParameter({ kTServerAddressArg, kTServerAddressDesc })
.AddRequiredParameter({ kFlagArg, "Name of the gflag" })
.AddRequiredParameter({ kValueArg, "New value for the gflag" })
.AddOptionalParameter("force")
.Build();
unique_ptr<Action> status =
ActionBuilder("status", &TServerStatus)
.Description("Get the status of a Kudu Tablet Server")
.AddRequiredParameter({ kTServerAddressArg, kTServerAddressDesc })
.Build();
unique_ptr<Action> timestamp =
ActionBuilder("timestamp", &TServerTimestamp)
.Description("Get the current timestamp of a Kudu Tablet Server")
.AddRequiredParameter({ kTServerAddressArg, kTServerAddressDesc })
.Build();
unique_ptr<Action> list_tservers =
ActionBuilder("list", &ListTServers)
.Description("List tablet servers in a Kudu cluster")
.AddRequiredParameter({ kMasterAddressesArg, kMasterAddressesArgDesc })
.AddOptionalParameter("columns", string("uuid,rpc-addresses"),
string("Comma-separated list of tserver info fields to "
"include in output.\nPossible values: uuid, "
"rpc-addresses, http-addresses, version, seqno, "
"and heartbeat"))
.AddOptionalParameter("format")
.AddOptionalParameter("timeout_ms")
.Build();
return ModeBuilder("tserver")
.Description("Operate on a Kudu Tablet Server")
.AddAction(std::move(get_flags))
.AddAction(std::move(set_flag))
.AddAction(std::move(status))
.AddAction(std::move(timestamp))
.AddAction(std::move(list_tservers))
.Build();
}
} // namespace tools
} // namespace kudu