From b741e5ffdfceb532c1166e778a072de8d4d1e6ea Mon Sep 17 00:00:00 2001 From: Arne Juul Date: Thu, 27 May 2021 13:52:08 +0000 Subject: prepare for "check connectivity" api * Cmd now has more generic "name" property and optional "portNumber" * add CmdType CHECK_CONNECTIVITY * add a simple one-shot PeerCheck utility * add CheckCompletionHandler that handles a Cmd with type CHECK_CONNECTIVITY * dummy in handleCmd for now --- configd/src/apps/sentinel/CMakeLists.txt | 3 ++ .../src/apps/sentinel/check-completion-handler.cpp | 31 +++++++++++++ .../src/apps/sentinel/check-completion-handler.h | 27 ++++++++++++ configd/src/apps/sentinel/cmdq.h | 14 +++--- configd/src/apps/sentinel/manager.cpp | 10 +++-- configd/src/apps/sentinel/peer-check.cpp | 51 ++++++++++++++++++++++ configd/src/apps/sentinel/peer-check.h | 37 ++++++++++++++++ configd/src/apps/sentinel/status-callback.cpp | 8 ++++ configd/src/apps/sentinel/status-callback.h | 13 ++++++ 9 files changed, 186 insertions(+), 8 deletions(-) create mode 100644 configd/src/apps/sentinel/check-completion-handler.cpp create mode 100644 configd/src/apps/sentinel/check-completion-handler.h create mode 100644 configd/src/apps/sentinel/peer-check.cpp create mode 100644 configd/src/apps/sentinel/peer-check.h create mode 100644 configd/src/apps/sentinel/status-callback.cpp create mode 100644 configd/src/apps/sentinel/status-callback.h (limited to 'configd/src') diff --git a/configd/src/apps/sentinel/CMakeLists.txt b/configd/src/apps/sentinel/CMakeLists.txt index f6b4c3a2184..d67a41f2a75 100644 --- a/configd/src/apps/sentinel/CMakeLists.txt +++ b/configd/src/apps/sentinel/CMakeLists.txt @@ -1,6 +1,7 @@ # Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. vespa_add_executable(configd_config-sentinel_app SOURCES + check-completion-handler.cpp cmdq.cpp config-owner.cpp env.cpp @@ -8,11 +9,13 @@ vespa_add_executable(configd_config-sentinel_app manager.cpp metrics.cpp output-connection.cpp + peer-check.cpp rpchooks.cpp rpcserver.cpp sentinel.cpp service.cpp state-api.cpp + status-callback.cpp OUTPUT_NAME vespa-config-sentinel INSTALL sbin DEPENDS diff --git a/configd/src/apps/sentinel/check-completion-handler.cpp b/configd/src/apps/sentinel/check-completion-handler.cpp new file mode 100644 index 00000000000..f854a85d297 --- /dev/null +++ b/configd/src/apps/sentinel/check-completion-handler.cpp @@ -0,0 +1,31 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "check-completion-handler.h" +#include +LOG_SETUP(".check-completion-handler"); + +namespace config::sentinel { + +void CheckCompletionHandler::create(Cmd::UP request, FRT_Supervisor &orb) { + LOG_ASSERT(request->type() == Cmd::CHECK_CONNECTIVITY); + // will delete itself on completion: + new CheckCompletionHandler(std::move(request), orb); +} + +CheckCompletionHandler::CheckCompletionHandler(Cmd::UP request, FRT_Supervisor &orb) + : _parentRequest(std::move(request)) +{ + const std::string & host = _parentRequest->name(); + int port = _parentRequest->portNumber(); + _peerCheck = std::make_unique(*this, host, port, orb); + +} + +CheckCompletionHandler::~CheckCompletionHandler() = default; + +void CheckCompletionHandler::returnStatus(bool ok) { + _parentRequest->retValue(ok ? "ok" : "bad"); + delete this; +} + +} diff --git a/configd/src/apps/sentinel/check-completion-handler.h b/configd/src/apps/sentinel/check-completion-handler.h new file mode 100644 index 00000000000..ae43799dd54 --- /dev/null +++ b/configd/src/apps/sentinel/check-completion-handler.h @@ -0,0 +1,27 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include "status-callback.h" +#include "peer-check.h" +#include "cmdq.h" + +namespace config::sentinel { + +/** + * Handles a checkConnectivity request by making an outgoing + * ping request. When the ping finishes, fills an answer + * into the parent request and deletes itself. + **/ +class CheckCompletionHandler : public StatusCallback { +public: + static void create(Cmd::UP request, FRT_Supervisor &orb); + virtual ~CheckCompletionHandler(); + void returnStatus(bool ok) override; +private: + CheckCompletionHandler(Cmd::UP request, FRT_Supervisor &orb); + Cmd::UP _parentRequest; + std::unique_ptr _peerCheck; +}; + +} diff --git a/configd/src/apps/sentinel/cmdq.h b/configd/src/apps/sentinel/cmdq.h index 105d5f29b60..38c95967d70 100644 --- a/configd/src/apps/sentinel/cmdq.h +++ b/configd/src/apps/sentinel/cmdq.h @@ -5,6 +5,7 @@ #include #include #include +#include class FRT_RPCRequest; @@ -13,14 +14,16 @@ namespace config::sentinel { class Cmd { public: using UP = std::unique_ptr; - enum CmdType { LIST, RESTART, START, STOP }; + enum CmdType { LIST, RESTART, START, STOP, CHECK_CONNECTIVITY }; - Cmd(FRT_RPCRequest *req, CmdType cmdType, const char *service = "") - : _req(req), _cmdType(cmdType), _serviceName(service) + Cmd(FRT_RPCRequest *req, CmdType cmdType, std::string name = "", int portnum = 0) + : _req(req), _cmdType(cmdType), _name(name), _port(portnum) {} CmdType type() const { return _cmdType; } - const char *serviceName() const { return _serviceName; } + // the service name or host name: + const std::string & name() const { return _name; } + int portNumber() const { return _port; } void retError(const char *errorString) const; void retValue(const char *valueString) const; @@ -29,7 +32,8 @@ public: private: FRT_RPCRequest *_req; CmdType _cmdType; - const char *_serviceName; + std::string _name; + int _port; }; class CommandQueue diff --git a/configd/src/apps/sentinel/manager.cpp b/configd/src/apps/sentinel/manager.cpp index 80dd2a3fda8..6f8bf69cb83 100644 --- a/configd/src/apps/sentinel/manager.cpp +++ b/configd/src/apps/sentinel/manager.cpp @@ -271,7 +271,7 @@ Manager::handleCmd(const Cmd& cmd) break; case Cmd::RESTART: { - Service *service = serviceByName(cmd.serviceName()); + Service *service = serviceByName(cmd.name()); if (service == nullptr) { cmd.retError("Cannot find named service"); return; @@ -287,7 +287,7 @@ Manager::handleCmd(const Cmd& cmd) break; case Cmd::START: { - Service *service = serviceByName(cmd.serviceName()); + Service *service = serviceByName(cmd.name()); if (service == nullptr) { cmd.retError("Cannot find named service"); return; @@ -301,7 +301,7 @@ Manager::handleCmd(const Cmd& cmd) break; case Cmd::STOP: { - Service *service = serviceByName(cmd.serviceName()); + Service *service = serviceByName(cmd.name()); if (service == nullptr) { cmd.retError("Cannot find named service"); return; @@ -312,6 +312,10 @@ Manager::handleCmd(const Cmd& cmd) } } break; + case Cmd::CHECK_CONNECTIVITY: + // XXX placeholder: + cmd.retValue("unknown"); + break; } } diff --git a/configd/src/apps/sentinel/peer-check.cpp b/configd/src/apps/sentinel/peer-check.cpp new file mode 100644 index 00000000000..6aef1443ef2 --- /dev/null +++ b/configd/src/apps/sentinel/peer-check.cpp @@ -0,0 +1,51 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "peer-check.h" +#include +#include + +LOG_SETUP(".peer-check"); + +using vespalib::make_string_short::fmt; + +namespace config::sentinel { + +PeerCheck::PeerCheck(StatusCallback &callback, const std::string &host, int port, FRT_Supervisor &orb) + : _callback(callback), + _hostname(host), + _portnum(port), + _target(nullptr), + _req(nullptr) +{ + auto spec = fmt("tcp/%s:%d", _hostname.c_str(), _portnum); + _target = orb.GetTarget(spec.c_str()); + _req = orb.AllocRPCRequest(); + _req->SetMethodName("frt.rpc.ping"); + _target->InvokeAsync(_req, 0.500, this); +} + +PeerCheck::~PeerCheck() { + if (_req != nullptr) { + _req->Abort(); + } +} + +void PeerCheck::RequestDone(FRT_RPCRequest *req) { + LOG_ASSERT(req == _req); + bool statusOk = false; + if (req->IsError()) { + LOG(warning, "error on ping to %s [port %d]: %s (%d)", _hostname.c_str(), _portnum, + req->GetErrorMessage(), req->GetErrorCode()); + } else { + LOG(info, "OK ping to %s [port %d]", _hostname.c_str(), _portnum); + statusOk = true; + } + _req->SubRef(); + _req = nullptr; + _target->SubRef(); + _target = nullptr; + // Note: will delete this object, so must be called as final step: + _callback.returnStatus(statusOk); +} + +} diff --git a/configd/src/apps/sentinel/peer-check.h b/configd/src/apps/sentinel/peer-check.h new file mode 100644 index 00000000000..658375a8d7b --- /dev/null +++ b/configd/src/apps/sentinel/peer-check.h @@ -0,0 +1,37 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include "status-callback.h" +#include +#include +#include +#include +#include +#include + +namespace config::sentinel { + +class PeerCheck : public FRT_IRequestWait +{ +public: + PeerCheck(StatusCallback &callback, const std::string &host, int portnum, FRT_Supervisor &orb); + ~PeerCheck(); + + PeerCheck(const PeerCheck &) = delete; + PeerCheck(PeerCheck &&) = delete; + PeerCheck& operator= (const PeerCheck &) = delete; + PeerCheck& operator= (PeerCheck &&) = delete; + + /** from FRT_IRequestWait **/ + void RequestDone(FRT_RPCRequest *req) override; + +private: + StatusCallback &_callback; + std::string _hostname; + int _portnum; + FRT_Target *_target; + FRT_RPCRequest *_req; +}; + +} diff --git a/configd/src/apps/sentinel/status-callback.cpp b/configd/src/apps/sentinel/status-callback.cpp new file mode 100644 index 00000000000..9bd820c9f39 --- /dev/null +++ b/configd/src/apps/sentinel/status-callback.cpp @@ -0,0 +1,8 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "status-callback.h" +namespace config::sentinel { + +StatusCallback::~StatusCallback() = default; + +} diff --git a/configd/src/apps/sentinel/status-callback.h b/configd/src/apps/sentinel/status-callback.h new file mode 100644 index 00000000000..53a3185623b --- /dev/null +++ b/configd/src/apps/sentinel/status-callback.h @@ -0,0 +1,13 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +namespace config::sentinel { + +/** very simple callback API with "ok" or "not ok" status only */ +struct StatusCallback { + virtual void returnStatus(bool ok) = 0; + virtual ~StatusCallback(); +}; + +} -- cgit v1.2.3