Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion doc/appendices/command-line/traffic_ctl.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ of subcommands that control different aspects of Traffic Server:
:program:`traffic_ctl plugin`
Interact with plugins.
:program:`traffic_ctl host`
Manipulate host status. parents for now but will be expanded to origins.
Manipulate host status.
:program:`traffic_ctl hostdb`
Manipulate HostDB status.
:program:`traffic_ctl rpc`
Interact directly with the |RPC| server in |TS|

Expand Down Expand Up @@ -560,6 +562,16 @@ records may be viewed using the :program:`traffic_ctl host status` command.

.. _traffic_ctl_rpc:

traffic_ctl hostdb
------------------
.. program:: traffic_ctl hostdb

.. option:: status

:ref:`admin_lookup_records`

Get the current status of HostDB.

traffic_ctl rpc
---------------
.. program:: traffic_ctl rpc
Expand Down
9 changes: 9 additions & 0 deletions include/iocore/hostdb/HostDBProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,9 @@ class HostDBRecord : public RefCountObj
/// Get the array of info instances.
swoc::MemSpan<HostDBInfo> rr_info();

/// Get the array of info instances to read
swoc::MemSpan<const HostDBInfo> rr_info() const;

/** Find a host record by IP address.
*
* @param addr Address key.
Expand Down Expand Up @@ -802,6 +805,12 @@ HostDBRecord::rr_info()
return {this->apply_offset<HostDBInfo>(rr_offset), rr_count};
}

inline swoc::MemSpan<const HostDBInfo>
HostDBRecord::rr_info() const
{
return {this->apply_offset<const HostDBInfo>(rr_offset), rr_count};
}

inline bool
HostDBRecord::is_failed() const
{
Expand Down
28 changes: 28 additions & 0 deletions include/mgmt/rpc/handlers/hostdb/HostDB.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* @file
@section license License

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 "mgmt/rpc/jsonrpc/JsonRPCManager.h"

namespace rpc::handlers::hostdb
{
swoc::Rv<YAML::Node> get_hostdb_status(std::string_view const &id, YAML::Node const &);
} // namespace rpc::handlers::hostdb
1 change: 1 addition & 0 deletions src/mgmt/rpc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ add_library(
handlers/common/ErrorUtils.cc
handlers/common/RecordsUtils.cc
handlers/config/Configuration.cc
handlers/hostdb/HostDB.cc
handlers/records/Records.cc
handlers/storage/Storage.cc
handlers/server/Server.cc
Expand Down
175 changes: 175 additions & 0 deletions src/mgmt/rpc/handlers/hostdb/HostDB.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/**
@section license License

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 "mgmt/rpc/handlers/hostdb/HostDB.h"
#include "mgmt/rpc/handlers/common/ErrorUtils.h"

#include "iocore/hostdb/HostDBProcessor.h"
#include "../src/iocore/hostdb/P_HostDBProcessor.h"
#include "swoc/MemSpan.h"
#include "tsutil/TsSharedMutex.h"
#include "yaml-cpp/node/node.h"
#include <shared_mutex>
#include <string>

namespace
{
DbgCtl dbg_ctl_rpc_server{"rpc.server"};
DbgCtl dbg_ctl_rpc_handler_server{"rpc.handler.hostdb"};

constexpr std::string_view
str(HostDBType type)
{
// No default to find HostDBType change
switch (type) {
case HostDBType::ADDR:
return "ADDR";
case HostDBType::SRV:
return "SRV";
case HostDBType::HOST:
return "HOST";
case HostDBType::UNSPEC:
return "UNSPEC";
}

return "";
}

constexpr std::string_view
str(sa_family_t type)
{
switch (type) {
case AF_UNIX:
return "AF_UNIX";
case AF_INET:
return "AF_INET";
case AF_INET6:
return "AF_INET6";
case AF_UNSPEC:
return "UNSPEC";
default:
return "UNKNOWN";
}
}
} // end anonymous namespace

namespace YAML
{
template <> struct convert<HostDBCache> {
static Node
encode(const HostDBCache *const hostDB)
{
Node partitions;
for (size_t i = 0; i < hostDB->refcountcache->partition_count(); i++) {
auto &partition = hostDB->refcountcache->get_partition(i);
std::vector<RefCountCacheHashEntry *> partition_entries;

{
std::shared_lock<ts::shared_mutex> shared_lock{partition.lock};
partition_entries.reserve(partition.count());
partition.copy(partition_entries);
}

Node partition_node;
partition_node["id"] = i;

for (RefCountCacheHashEntry *entry : partition_entries) {
HostDBRecord *record = static_cast<HostDBRecord *>(entry->item.get());
partition_node["records"].push_back(*record);
}

partitions.push_back(partition_node);
}

auto &version = AppVersionInfo::get_version();

Node node;
node["metadata"]["timestamp"] =
std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
node["metadata"]["version"] = version.full_version();
node["partitions"] = partitions;

return node;
}
};

template <> struct convert<HostDBRecord> {
static Node
encode(const HostDBRecord &record)
{
Node metadata;
metadata["name"] = record.name();
metadata["type"] = str(record.record_type);
metadata["af_familiy"] = str(record.af_family);
metadata["failed"] = record.is_failed();
metadata["ip_timestamp"] = record.ip_timestamp.time_since_epoch().count();

Node node;
node["metadata"] = metadata;

swoc::MemSpan<const HostDBInfo> span = record.rr_info();
for (const HostDBInfo &info : span) {
YAML::Node info_node;
if (record.is_srv()) {
YAML::Node srv_node;
srv_node["weight"] = info.data.srv.srv_weight;
srv_node["priority"] = info.data.srv.srv_priority;
srv_node["port"] = info.data.srv.srv_port;
srv_node["target"] = info.srvname();

info_node["srv"] = srv_node;
} else {
char buf[INET6_ADDRSTRLEN];
info.data.ip.toString(buf, sizeof(buf));

info_node["ip"] = std::string(buf);
}

info_node["health"]["last_failure"] = info.last_failure.load().time_since_epoch().count();
info_node["health"]["fail_count"] = static_cast<int>(info.fail_count.load());

node["info"].push_back(info_node);
}

return node;
}
};
} // namespace YAML

namespace rpc::handlers::hostdb
{
namespace err = rpc::handlers::errors;

swoc::Rv<YAML::Node>
get_hostdb_status(std::string_view const & /* params ATS_UNUSED */, YAML::Node const & /* params ATS_UNUSED */)
{
swoc::Rv<YAML::Node> resp;
try {
YAML::Node data = YAML::convert<HostDBCache>::encode(hostDBProcessor.cache());

resp.result()["data"] = data;
} catch (std::exception const &ex) {
resp.errata()
.assign(std::error_code{errors::Codes::SERVER})
.note("Error found when calling get_hostdb_status API: {}", ex.what());
}
return resp;
}
} // namespace rpc::handlers::hostdb
115 changes: 115 additions & 0 deletions src/mgmt/rpc/schema/hostdb_status_schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "HostDB info definition",
"description":"This is the definition expected for a RPC hostdb status request. This should be used to obtain information of HostDB from Traffic Server Licensed under Apache V2 https://www.apache.org/licenses/LICENSE-2.0",
"type": "object",
"properties": {
"metadata": {
"type": "object",
"properties": {
"timestamp": {
"type": "integer"
},
"version": {
"type": "string"
}
}
},
"partitions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "Partition identifier"
},
"records": {
"type": "array",
"items": {
"type": "object",
"properties": {
"metadata": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["UNSPEC", "ADDR", "SRV", "HOST"]
},
"af_family": {
"type": "string",
"enum": ["UNSPEC", "UNIX", "AF_INET", "AF_INET6"]
},
"name": {
"type": "string",
"description": "Query hostname or resolved name"
},
"failed": {
"type": "boolean"
},
"ip_timestamp": {
"type": "integer"
}
}
},
"info": {
"type": "array",
"items": {
"type": "object",
"properties": {
"data": {
"oneOf": [
{
"type": "object",
"properties": {
"ip": {
"type": "string"
}
}
},
{
"type": "object",
"properties": {
"srv": {
"type": "object",
"properties": {
"weight": {
"type": "integer"
},
"priority": {
"type": "integer"
},
"port": {
"type": "integer"
},
"target": {
"type": "string"
}
}
}
}
}
]
},
"health": {
"type": "object",
"properties": {
"last_failure": {
"type": "integer"
},
"fail_count": {
"type": "integer"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
Loading