From 13c04324cf8528a71e086ea6eb7f11b793d26cee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Sun, 19 Aug 2018 20:35:41 +0300 Subject: [PATCH] Add master extraction via REST API The master server of a monitor can now be extracted with the mon_get_external_master function. It uses the REST API to find a master server in the set of servers monitored by a monitor. --- include/maxscale/monitor.hh | 14 ++++++++++ server/core/monitor.cc | 55 +++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/include/maxscale/monitor.hh b/include/maxscale/monitor.hh index 51e1ef4e2..30baf48ca 100644 --- a/include/maxscale/monitor.hh +++ b/include/maxscale/monitor.hh @@ -338,4 +338,18 @@ MXS_MONITOR_API MonitorApi::s_api = &MonitorApi::diagnostics_json, }; +/** + * Get the master server of the monitor pointed by @c url + * + * The URL must be in `http://hostname-of-maxscale:/v1/monitors/` + * format and must point to a single monitor resource. + * + * TODO: Move the base URL and credentials into a global parameter + * + * @param url URL to a REST API endpoint for a monitor + * + * @return The host and port of the monitor or an empty string and 0 if an error occurred + */ +std::pair mon_get_external_master(const std::string& url); + } diff --git a/server/core/monitor.cc b/server/core/monitor.cc index f26d850cf..e0c8f0471 100644 --- a/server/core/monitor.cc +++ b/server/core/monitor.cc @@ -2866,4 +2866,59 @@ void MonitorInstance::run_one_tick() store_server_journal(m_monitor, m_master); } +static bool remote_server_is_master(const std::string& url, std::string* host, int* port) +{ + bool rval = false; + auto res = mxs::http::get(url); + json_t* state = mxs_json_pointer(res.body.get(), "data/attributes/state"); + json_t* json_host = mxs_json_pointer(res.body.get(), "data/attributes/parameters/address"); + json_t* json_port = mxs_json_pointer(res.body.get(), "data/attributes/parameters/port"); + + if (json_is_string(json_host) && json_is_integer(json_port) && json_is_string(state)) + { + const std::set master_states{ "Master, Running", "Master, Synced, Running" }; + + if (master_states.count(json_string_value(state))) + { + *host = json_string_value(json_host); + *port = json_integer_value(json_port); + rval = true; + } + } + + return rval; +} + +std::pair mon_get_external_master(const std::string& url) +{ + std::string host; + int port = 0; + + auto res = mxs::http::get(url); + json_t* remote = mxs_json_pointer(res.body.get(), "data/relationships/servers/links/self"); + json_t* arr = mxs_json_pointer(res.body.get(), "data/relationships/servers/data"); + + if (json_is_string(remote) && json_is_array(arr)) + { + std::string remote_host = json_string_value(remote); + size_t i; + json_t* value; + + json_array_foreach(arr, i, value) + { + json_t* id = mxs_json_pointer(value, "id"); + + if (json_is_string(id)) + { + if (remote_server_is_master(remote_host + json_string_value(id), &host, &port)) + { + break; + } + } + } + } + + return {host, port}; +} + }