diff --git a/api/api-doc/error_injection.json b/api/api-doc/error_injection.json index 261acb4500..b01b1b828a 100644 --- a/api/api-doc/error_injection.json +++ b/api/api-doc/error_injection.json @@ -90,6 +90,30 @@ } ] }, + { + "path":"/v2/error_injection/disconnect/{ip}", + "operations":[ + { + "method":"POST", + "summary":"Drop connection to a given IP", + "type":"void", + "nickname":"inject_disconnect", + "produces":[ + "application/json" + ], + "parameters":[ + { + "name":"ip", + "description":"IP address to disconnect from", + "required":true, + "allowMultiple":false, + "type":"string", + "paramType":"path" + } + ] + } + ] + }, { "path":"/v2/error_injection/injection", "operations":[ diff --git a/api/messaging_service.cc b/api/messaging_service.cc index 9d23107122..7ed0ca594f 100644 --- a/api/messaging_service.cc +++ b/api/messaging_service.cc @@ -10,6 +10,7 @@ #include "message/messaging_service.hh" #include #include "api/api-doc/messaging_service.json.hh" +#include "api/api-doc/error_injection.json.hh" #include #include @@ -19,6 +20,8 @@ using namespace netw; namespace api { +namespace hf = httpd::error_injection_json; + using shard_info = messaging_service::shard_info; using msg_addr = messaging_service::msg_addr; @@ -142,6 +145,14 @@ void set_messaging_service(http_context& ctx, routes& r, sharded(res); }); }); + + hf::inject_disconnect.set(r, [&ms] (std::unique_ptr req) -> future { + auto ip = msg_addr(req->param["ip"]); + co_await ms.invoke_on_all([ip] (netw::messaging_service& ms) { + ms.remove_rpc_client(ip); + }); + co_return json::json_void(); + }); } void unset_messaging_service(http_context& ctx, routes& r) { @@ -155,6 +166,7 @@ void unset_messaging_service(http_context& ctx, routes& r) { get_respond_completed_messages.unset(r); get_version.unset(r); get_dropped_messages_by_ver.unset(r); + hf::inject_disconnect.unset(r); } } diff --git a/test/pylib/rest_client.py b/test/pylib/rest_client.py index df3547cc69..b237eda12d 100644 --- a/test/pylib/rest_client.py +++ b/test/pylib/rest_client.py @@ -238,6 +238,9 @@ class ScyllaRESTAPIClient(): async def message_injection(self, node_ip: str, injection: str) -> None: await self.client.post(f"/v2/error_injection/injection/{injection}/message", host=node_ip) + async def inject_disconnect(self, node_ip: str, ip_to_disconnect_from: str) -> None: + await self.client.post(f"/v2/error_injection/disconnect/{ip_to_disconnect_from}", host=node_ip) + async def get_logger_level(self, node_ip: str, logger: str) -> str: """Get logger level""" return await self.client.get_text(f"/system/logger/{logger}", host=node_ip)