MXS-2606: Sort servers before loading users
By sorting the servers in descending order based on their role we make sure that the users are loaded from a master if one is available.
This commit is contained in:
parent
f139991a2c
commit
f8ee11cf55
@ -21,6 +21,9 @@
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <maxscale/alloc.h>
|
||||
#include <maxscale/dcb.h>
|
||||
#include <maxscale/log.h>
|
||||
@ -1025,17 +1028,17 @@ bool query_and_process_users(const char* query, MYSQL* con, sqlite3* handle, SER
|
||||
return rval;
|
||||
}
|
||||
|
||||
int get_users_from_server(MYSQL* con, SERVER_REF* server_ref, SERVICE* service, SERV_LISTENER* listener)
|
||||
int get_users_from_server(MYSQL* con, SERVER* server, SERVICE* service, SERV_LISTENER* listener)
|
||||
{
|
||||
if (server_ref->server->version_string[0] == 0)
|
||||
if (server->version_string[0] == 0)
|
||||
{
|
||||
mxs_mysql_update_server_version(con, server_ref->server);
|
||||
mxs_mysql_update_server_version(con, server);
|
||||
}
|
||||
|
||||
char* query = get_users_query(server_ref->server->version_string,
|
||||
server_ref->server->version,
|
||||
char* query = get_users_query(server->version_string,
|
||||
server->version,
|
||||
service->enable_root,
|
||||
roles_are_available(con, service, server_ref->server));
|
||||
roles_are_available(con, service, server));
|
||||
|
||||
MYSQL_AUTH* instance = (MYSQL_AUTH*)listener->auth_instance;
|
||||
sqlite3* handle = get_handle(instance);
|
||||
@ -1043,20 +1046,20 @@ int get_users_from_server(MYSQL* con, SERVER_REF* server_ref, SERVICE* service,
|
||||
|
||||
bool rv = query_and_process_users(query, con, handle, service, &users);
|
||||
|
||||
if (!rv && have_mdev13453_problem(con, server_ref->server))
|
||||
if (!rv && have_mdev13453_problem(con, server))
|
||||
{
|
||||
/**
|
||||
* Try to work around MDEV-13453 by using a query without CTEs. Masquerading as
|
||||
* a 10.1.10 server makes sure CTEs aren't used.
|
||||
*/
|
||||
MXS_FREE(query);
|
||||
query = get_users_query(server_ref->server->version_string, 100110, service->enable_root, true);
|
||||
query = get_users_query(server->version_string, 100110, service->enable_root, true);
|
||||
rv = query_and_process_users(query, con, handle, service, &users);
|
||||
}
|
||||
|
||||
if (!rv)
|
||||
{
|
||||
MXS_ERROR("Failed to load users from server '%s': %s", server_ref->server->name, mysql_error(con));
|
||||
MXS_ERROR("Failed to load users from server '%s': %s", server->name, mysql_error(con));
|
||||
}
|
||||
|
||||
MXS_FREE(query);
|
||||
@ -1084,6 +1087,28 @@ int get_users_from_server(MYSQL* con, SERVER_REF* server_ref, SERVICE* service,
|
||||
return users;
|
||||
}
|
||||
|
||||
// Sorts candidates servers so that masters are before slaves which are before only running servers
|
||||
static std::vector<SERVER*> get_candidates(SERVICE* service, bool skip_local)
|
||||
{
|
||||
std::vector<SERVER*> candidates;
|
||||
|
||||
for (auto server = service->dbref; server; server = server->next)
|
||||
{
|
||||
if (SERVER_REF_IS_ACTIVE(server) && server_is_running(server->server)
|
||||
&& (!skip_local || !server_is_mxs_service(server->server)))
|
||||
{
|
||||
candidates.push_back(server->server);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(candidates.begin(), candidates.end(), [](SERVER* a, SERVER* b) {
|
||||
return (server_is_master(a) && !server_is_master(b))
|
||||
|| (server_is_slave(a) && !server_is_slave(b) && !server_is_master(b));
|
||||
});
|
||||
|
||||
return candidates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the user/passwd form mysql.user table into the service users' hashtable
|
||||
* environment.
|
||||
@ -1112,33 +1137,18 @@ static int get_users(SERV_LISTENER* listener, bool skip_local, SERVER** srv)
|
||||
sqlite3* handle = get_handle(instance);
|
||||
delete_mysql_users(handle);
|
||||
|
||||
SERVER_REF* server = service->dbref;
|
||||
int total_users = -1;
|
||||
bool no_active_servers = true;
|
||||
auto candidates = get_candidates(service, skip_local);
|
||||
|
||||
for (server = service->dbref; !maxscale_is_shutting_down() && server; server = server->next)
|
||||
for (auto server : candidates)
|
||||
{
|
||||
if (!SERVER_REF_IS_ACTIVE(server) || !server_is_active(server->server)
|
||||
|| (skip_local && server_is_mxs_service(server->server))
|
||||
|| !server_is_running(server->server))
|
||||
if (MYSQL* con = gw_mysql_init())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
no_active_servers = false;
|
||||
|
||||
MYSQL* con = gw_mysql_init();
|
||||
if (con)
|
||||
{
|
||||
if (mxs_mysql_real_connect(con, server->server, service_user, dpwd) == NULL)
|
||||
if (mxs_mysql_real_connect(con, server, service_user, dpwd) == NULL)
|
||||
{
|
||||
MXS_ERROR("Failure loading users data from backend "
|
||||
"[%s:%i] for service [%s]. MySQL error %i, %s",
|
||||
server->server->address,
|
||||
server->server->port,
|
||||
service->name,
|
||||
mysql_errno(con),
|
||||
mysql_error(con));
|
||||
MXS_ERROR("Failure loading users data from backend [%s:%i] for service [%s]. "
|
||||
"MySQL error %i, %s", server->address, server->port, service->name,
|
||||
mysql_errno(con), mysql_error(con));
|
||||
mysql_close(con);
|
||||
}
|
||||
else
|
||||
@ -1148,7 +1158,7 @@ static int get_users(SERV_LISTENER* listener, bool skip_local, SERVER** srv)
|
||||
|
||||
if (users > total_users)
|
||||
{
|
||||
*srv = server->server;
|
||||
*srv = server;
|
||||
total_users = users;
|
||||
}
|
||||
|
||||
@ -1164,12 +1174,12 @@ static int get_users(SERV_LISTENER* listener, bool skip_local, SERVER** srv)
|
||||
|
||||
MXS_FREE(dpwd);
|
||||
|
||||
if (no_active_servers)
|
||||
if (candidates.empty())
|
||||
{
|
||||
// This service has no servers or all servers are local MaxScale services
|
||||
total_users = 0;
|
||||
}
|
||||
else if (server == NULL && total_users == -1)
|
||||
else if (*srv == nullptr && total_users == -1)
|
||||
{
|
||||
MXS_ERROR("Unable to get user data from backend database for service [%s]."
|
||||
" Failed to connect to any of the backend databases.",
|
||||
|
Loading…
x
Reference in New Issue
Block a user