diff --git a/api/storage_service.cc b/api/storage_service.cc index a0643ce5d3..9c9e1ed8d0 100644 --- a/api/storage_service.cc +++ b/api/storage_service.cc @@ -69,6 +69,11 @@ sstring validate_keyspace(http_context& ctx, const parameters& param) { return validate_keyspace(ctx, param["keyspace"]); } +locator::host_id validate_host_id(const sstring& param) { + auto hoep = locator::host_id_or_endpoint(param, locator::host_id_or_endpoint::param_type::host_id); + return hoep.id; +} + // splits a request parameter assumed to hold a comma-separated list of table names // verify that the tables are found, otherwise a bad_param_exception exception is thrown // containing the description of the respective no_such_column_family error. @@ -715,7 +720,7 @@ void set_storage_service(http_context& ctx, routes& r, sharded req) { - auto host_id = req->get_query_param("host_id"); + auto host_id = validate_host_id(req->get_query_param("host_id")); std::vector ignore_nodes_strs= split(req->get_query_param("ignore_nodes"), ","); auto ignore_nodes = std::list(); for (std::string n : ignore_nodes_strs) { diff --git a/locator/token_metadata.cc b/locator/token_metadata.cc index 0d743e180e..461e33978f 100644 --- a/locator/token_metadata.cc +++ b/locator/token_metadata.cc @@ -1432,4 +1432,33 @@ future<> shared_token_metadata::mutate_token_metadata(seastar::noncopyable_funct set(make_token_metadata_ptr(std::move(tm))); } +host_id_or_endpoint::host_id_or_endpoint(const sstring& s, param_type restrict) { + switch (restrict) { + case param_type::host_id: + try { + id = host_id(utils::UUID(s)); + } catch (const marshal_exception& e) { + throw std::invalid_argument(format("Invalid host_id {}: {}", s, e.what())); + } + break; + case param_type::endpoint: + try { + endpoint = gms::inet_address(s); + } catch (std::invalid_argument& e) { + throw std::invalid_argument(format("Invalid inet_address {}: {}", s, e.what())); + } + break; + case param_type::auto_detect: + try { + id = host_id(utils::UUID(s)); + } catch (const marshal_exception& e) { + try { + endpoint = gms::inet_address(s); + } catch (std::invalid_argument& e) { + throw std::invalid_argument(format("Invalid host_id or inet_address {}", s)); + } + } + } +} + } // namespace locator diff --git a/locator/token_metadata.hh b/locator/token_metadata.hh index f938952039..433b9a840b 100644 --- a/locator/token_metadata.hh +++ b/locator/token_metadata.hh @@ -133,6 +133,27 @@ private: bool _sort_by_proximity = true; }; +struct host_id_or_endpoint { + host_id id; + gms::inet_address endpoint; + + enum class param_type { + host_id, + endpoint, + auto_detect + }; + + host_id_or_endpoint(const sstring& s, param_type restrict = param_type::auto_detect); + + bool has_host_id() const noexcept { + return bool(id); + } + + bool has_endpoint() const noexcept { + return endpoint != gms::inet_address(); + } +}; + using dc_rack_fn = seastar::noncopyable_function; class token_metadata_impl; diff --git a/service/storage_service.cc b/service/storage_service.cc index 453ccbb1fe..1cc344ebf0 100644 --- a/service/storage_service.cc +++ b/service/storage_service.cc @@ -2328,12 +2328,11 @@ void storage_service::run_replace_ops(std::unordered_set& bootstrap_token } } -future<> storage_service::removenode(sstring host_id_string, std::list ignore_nodes) { - return run_with_api_lock(sstring("removenode"), [host_id_string, ignore_nodes = std::move(ignore_nodes)] (storage_service& ss) mutable { - return seastar::async([&ss, host_id_string, ignore_nodes = std::move(ignore_nodes)] { +future<> storage_service::removenode(locator::host_id host_id, std::list ignore_nodes) { + return run_with_api_lock(sstring("removenode"), [host_id, ignore_nodes = std::move(ignore_nodes)] (storage_service& ss) mutable { + return seastar::async([&ss, host_id, ignore_nodes = std::move(ignore_nodes)] { auto uuid = utils::make_random_uuid(); auto tmptr = ss.get_token_metadata_ptr(); - auto host_id = locator::host_id(utils::UUID(host_id_string)); auto endpoint_opt = tmptr->get_endpoint_for_host_id(host_id); if (!endpoint_opt) { throw std::runtime_error(format("removenode[{}]: Host ID not found in the cluster", uuid)); diff --git a/service/storage_service.hh b/service/storage_service.hh index 47e25c478b..33cfee6bc1 100644 --- a/service/storage_service.hh +++ b/service/storage_service.hh @@ -704,7 +704,7 @@ public: * * @param hostIdString token for the node */ - future<> removenode(sstring host_id_string, std::list ignore_nodes); + future<> removenode(locator::host_id host_id, std::list ignore_nodes); future node_ops_cmd_handler(gms::inet_address coordinator, node_ops_cmd_request req); void node_ops_cmd_check(gms::inet_address coordinator, const node_ops_cmd_request& req); future<> node_ops_cmd_heartbeat_updater(node_ops_cmd cmd, utils::UUID uuid, std::list nodes, lw_shared_ptr heartbeat_updater_done);