Added optional parameters for services that allow all servers to be used when building the list of users.
This commit is contained in:
@ -14,7 +14,7 @@ When MaxScale first starts, it creates all services and thus creates the router
|
||||
|
||||
When a user connects to MaxScale, a new session is created and the newSession function is called. At this point the client session connects to all the backend servers and initializes the list of databases.
|
||||
|
||||
After the session is created queries are routed to the router's routeQuery function. This is where most of the work regarding the resolution of query destinations is done. The main internal functions involved in routing the query are get_shard_route_target (detects if a query needs to be sent to all the servers or to a specific one), get_shard_target_name (parses the query and finds the name of the right server) and route_session_write (handles sending and and storing session commands). After this point the client's query has been sent to the backend server and the router waits for either an response or an error signaling that the backend server is not responding.
|
||||
After the session is created queries are routed to the router's routeQuery function. This is where most of the work regarding the resolution of query destinations is done. This router parses the incoming buffers for full SQL packets first and routes each of them individually. The main internal functions involved in routing the query are get_shard_route_target (detects if a query needs to be sent to all the servers or to a specific one), get_shard_target_name (parses the query and finds the name of the right server) and route_session_write (handles sending and and storing session commands). After this point the client's query has been sent to the backend server and the router waits for either an response or an error signaling that the backend server is not responding.
|
||||
|
||||
If a response is received the clientReply function is called and response is simply sent to the client and the router is then ready for more queries. If there is no response from the server and the connection to it is lost the handleError function is called. This function tries to find replacement servers for the failed ones and regenerates the list of databases. This also triggeres the sending of an error packet to the client that notifies that the server is not responding.
|
||||
|
||||
|
||||
@ -279,6 +279,7 @@ int error_count = 0;
|
||||
char *user;
|
||||
char *auth;
|
||||
char *enable_root_user;
|
||||
char *auth_all_servers;
|
||||
char *weightby;
|
||||
char *version_string;
|
||||
bool is_rwsplit = false;
|
||||
@ -291,6 +292,9 @@ int error_count = 0;
|
||||
enable_root_user = config_get_value(
|
||||
obj->parameters,
|
||||
"enable_root_user");
|
||||
auth_all_servers = config_get_value(
|
||||
obj->parameters,
|
||||
"auth_all_servers");
|
||||
allow_localhost_match_wildcard_host =
|
||||
config_get_value(obj->parameters,
|
||||
"localhost_match_wildcard_host");
|
||||
@ -353,6 +357,9 @@ int error_count = 0;
|
||||
serviceEnableRootUser(
|
||||
obj->element,
|
||||
config_truth_value(enable_root_user));
|
||||
if(auth_all_servers)
|
||||
serviceAuthAllServers(obj->element,
|
||||
config_truth_value(auth_all_servers));
|
||||
if (weightby)
|
||||
serviceWeightBy(obj->element, weightby);
|
||||
|
||||
@ -1352,6 +1359,7 @@ SERVER *server;
|
||||
char *user;
|
||||
char *auth;
|
||||
char *enable_root_user;
|
||||
char* auth_all_servers;
|
||||
char* max_slave_conn_str;
|
||||
char* max_slave_rlag_str;
|
||||
char *version_string;
|
||||
@ -1364,6 +1372,8 @@ SERVER *server;
|
||||
auth = config_get_value(obj->parameters,
|
||||
"passwd");
|
||||
|
||||
auth_all_servers = config_get_value(obj->parameters, "auth_all_servers");
|
||||
|
||||
version_string = config_get_value(obj->parameters, "version_string");
|
||||
|
||||
allow_localhost_match_wildcard_host =
|
||||
@ -1385,7 +1395,8 @@ SERVER *server;
|
||||
auth);
|
||||
if (enable_root_user)
|
||||
serviceEnableRootUser(service, atoi(enable_root_user));
|
||||
|
||||
if(auth_all_servers)
|
||||
serviceAuthAllServers(service, atoi(auth_all_servers));
|
||||
if (allow_localhost_match_wildcard_host)
|
||||
serviceEnableLocalhostMatchWildcardHost(
|
||||
service,
|
||||
@ -1494,6 +1505,7 @@ SERVER *server;
|
||||
char *auth;
|
||||
char *enable_root_user;
|
||||
char *allow_localhost_match_wildcard_host;
|
||||
char *auth_all_servers;
|
||||
|
||||
enable_root_user =
|
||||
config_get_value(obj->parameters,
|
||||
@ -1517,6 +1529,8 @@ SERVER *server;
|
||||
if (enable_root_user)
|
||||
serviceEnableRootUser(obj->element,
|
||||
atoi(enable_root_user));
|
||||
if(auth_all_servers)
|
||||
serviceAuthAllServers(obj->element, atoi(auth_all_servers));
|
||||
|
||||
if (allow_localhost_match_wildcard_host)
|
||||
serviceEnableLocalhostMatchWildcardHost(
|
||||
@ -1741,6 +1755,7 @@ static char *service_params[] =
|
||||
"user",
|
||||
"passwd",
|
||||
"enable_root_user",
|
||||
"auth_all_servers",
|
||||
"localhost_match_wildcard_host",
|
||||
"max_slave_connections",
|
||||
"max_slave_replication_lag",
|
||||
|
||||
@ -449,13 +449,14 @@ getUsers(SERVICE *service, USERS *users)
|
||||
MYSQL_RES *result = NULL;
|
||||
char *service_user = NULL;
|
||||
char *service_passwd = NULL;
|
||||
char *dpwd;
|
||||
char *dpwd = NULL;
|
||||
int total_users = 0;
|
||||
SERVER_REF *server;
|
||||
char *users_query;
|
||||
char *users_query, *tmp;
|
||||
unsigned char hash[SHA_DIGEST_LENGTH]="";
|
||||
char *users_data = NULL;
|
||||
int nusers = 0;
|
||||
char *final_data = NULL;
|
||||
int nusers = -1;
|
||||
int users_data_row_len = MYSQL_USER_MAXLEN +
|
||||
MYSQL_HOST_MAXLEN +
|
||||
MYSQL_PASSWORD_LEN +
|
||||
@ -469,15 +470,52 @@ getUsers(SERVICE *service, USERS *users)
|
||||
ss_dassert(service_passwd == NULL || service_user == NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (service->svc_do_shutdown)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
dpwd = decryptPassword(service_passwd);
|
||||
final_data = (char*) malloc(sizeof(char));
|
||||
*final_data = '\0';
|
||||
|
||||
/**
|
||||
* Attempt to connect to one of the databases database or until we run
|
||||
* out of databases
|
||||
* to try
|
||||
*/
|
||||
server = service->dbref;
|
||||
|
||||
if(server == NULL)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
/* Select a server with Master bit, if available */
|
||||
while (server != NULL && !(server->server->status & SERVER_MASTER)) {
|
||||
server = server->next;
|
||||
}
|
||||
|
||||
if(server == NULL)
|
||||
{
|
||||
/* If no master is found take the first available server */
|
||||
server = service->dbref;
|
||||
}
|
||||
|
||||
while(server != NULL)
|
||||
{
|
||||
|
||||
con = mysql_init(NULL);
|
||||
|
||||
if (con == NULL) {
|
||||
if (con == NULL)
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : mysql_init: %s",
|
||||
mysql_error(con))));
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/** Set read, write and connect timeout values */
|
||||
if (gw_mysql_set_timeouts(con,
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
@ -489,56 +527,19 @@ getUsers(SERVICE *service, USERS *users)
|
||||
"Error : failed to set timeout values for backend "
|
||||
"connection.")));
|
||||
mysql_close(con);
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (mysql_options(con, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL)) {
|
||||
if (mysql_options(con, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL))
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : failed to set external connection. "
|
||||
"It is needed for backend server connections.")));
|
||||
mysql_close(con);
|
||||
return -1;
|
||||
}
|
||||
/**
|
||||
* Attempt to connect to one of the databases database or until we run
|
||||
* out of databases
|
||||
* to try
|
||||
*/
|
||||
server = service->dbref;
|
||||
dpwd = decryptPassword(service_passwd);
|
||||
|
||||
/* Select a server with Master bit, if available */
|
||||
while (server != NULL && !(server->server->status & SERVER_MASTER)) {
|
||||
server = server->next;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (service->svc_do_shutdown)
|
||||
{
|
||||
free(dpwd);
|
||||
mysql_close(con);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Try loading data from master server */
|
||||
if (server != NULL &&
|
||||
(mysql_real_connect(con,
|
||||
server->server->name, service_user,
|
||||
dpwd,
|
||||
NULL,
|
||||
server->server->port,
|
||||
NULL, 0) != NULL))
|
||||
{
|
||||
LOGIF(LD, (skygw_log_write_flush(
|
||||
LOGFILE_DEBUG,
|
||||
"Dbusers : Loading data from backend database with "
|
||||
"Master role [%s:%i] for service [%s]",
|
||||
server->server->name,
|
||||
server->server->port,
|
||||
service->name)));
|
||||
} else {
|
||||
/* load data from other servers via loop */
|
||||
server = service->dbref;
|
||||
|
||||
while(!service->svc_do_shutdown &&
|
||||
server != NULL &&
|
||||
@ -554,25 +555,6 @@ getUsers(SERVICE *service, USERS *users)
|
||||
server = server->next;
|
||||
}
|
||||
|
||||
if (service->svc_do_shutdown)
|
||||
{
|
||||
free(dpwd);
|
||||
mysql_close(con);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (server != NULL) {
|
||||
LOGIF(LD, (skygw_log_write_flush(
|
||||
LOGFILE_DEBUG,
|
||||
"Dbusers : Loading data from backend database "
|
||||
"[%s:%i] for service [%s]",
|
||||
server->server->name,
|
||||
server->server->port,
|
||||
service->name)));
|
||||
}
|
||||
}
|
||||
|
||||
free(dpwd);
|
||||
|
||||
if (server == NULL)
|
||||
{
|
||||
@ -582,7 +564,7 @@ getUsers(SERVICE *service, USERS *users)
|
||||
"for service [%s]. Missing server information.",
|
||||
service->name)));
|
||||
mysql_close(con);
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/** Count users. Start with users and db grants for users */
|
||||
@ -596,7 +578,7 @@ getUsers(SERVICE *service, USERS *users)
|
||||
service->name,
|
||||
mysql_error(con))));
|
||||
mysql_close(con);
|
||||
return -1;
|
||||
goto cleanup;
|
||||
} else {
|
||||
/*
|
||||
* We have got ER_TABLEACCESS_DENIED_ERROR
|
||||
@ -610,7 +592,7 @@ getUsers(SERVICE *service, USERS *users)
|
||||
service->name,
|
||||
mysql_error(con))));
|
||||
mysql_close(con);
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -625,7 +607,7 @@ getUsers(SERVICE *service, USERS *users)
|
||||
service->name,
|
||||
mysql_error(con))));
|
||||
mysql_close(con);
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
row = mysql_fetch_row(result);
|
||||
@ -640,7 +622,7 @@ getUsers(SERVICE *service, USERS *users)
|
||||
"Error : Counting users for service %s returned 0",
|
||||
service->name)));
|
||||
mysql_close(con);
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if(service->enable_root) {
|
||||
@ -671,7 +653,7 @@ getUsers(SERVICE *service, USERS *users)
|
||||
|
||||
mysql_close(con);
|
||||
|
||||
return -1;
|
||||
goto cleanup;
|
||||
} else {
|
||||
/*
|
||||
* We have got ER_TABLEACCESS_DENIED_ERROR
|
||||
@ -704,7 +686,7 @@ getUsers(SERVICE *service, USERS *users)
|
||||
|
||||
mysql_close(con);
|
||||
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* users successfully loaded but without db grants */
|
||||
@ -737,7 +719,7 @@ getUsers(SERVICE *service, USERS *users)
|
||||
mysql_free_result(result);
|
||||
mysql_close(con);
|
||||
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
users_data = (char *)calloc(nusers, (users_data_row_len * sizeof(char)) + 1);
|
||||
@ -752,7 +734,7 @@ getUsers(SERVICE *service, USERS *users)
|
||||
mysql_free_result(result);
|
||||
mysql_close(con);
|
||||
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (db_grants) {
|
||||
@ -862,14 +844,39 @@ getUsers(SERVICE *service, USERS *users)
|
||||
}
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
mysql_close(con);
|
||||
|
||||
if((tmp = realloc(final_data, (strlen(final_data) + strlen(users_data) + 1) * sizeof(char))) == NULL)
|
||||
{
|
||||
free(users_data);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
final_data = tmp;
|
||||
|
||||
strcat(final_data,users_data);
|
||||
free(users_data);
|
||||
|
||||
if(service->users_from_all)
|
||||
{
|
||||
server = server->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
server = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* compute SHA1 digest for users' data */
|
||||
SHA1((const unsigned char *) users_data, strlen(users_data), hash);
|
||||
SHA1((const unsigned char *) final_data, strlen(final_data), hash);
|
||||
|
||||
memcpy(users->cksum, hash, SHA_DIGEST_LENGTH);
|
||||
|
||||
free(users_data);
|
||||
mysql_free_result(result);
|
||||
mysql_close(con);
|
||||
cleanup:
|
||||
|
||||
free(dpwd);
|
||||
free(final_data);
|
||||
|
||||
return total_users;
|
||||
}
|
||||
|
||||
@ -779,6 +779,25 @@ serviceEnableRootUser(SERVICE *service, int action)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable loading the user data from only one server or all of them
|
||||
*
|
||||
* @param service The service we are setting the data for
|
||||
* @param action 1 for root enable, 0 for disable access
|
||||
* @return 0 on failure
|
||||
*/
|
||||
|
||||
int
|
||||
serviceAuthAllServers(SERVICE *service, int action)
|
||||
{
|
||||
if (action != 0 && action != 1)
|
||||
return 0;
|
||||
|
||||
service->users_from_all = action;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim whitespace from the from an rear of a string
|
||||
*
|
||||
|
||||
@ -136,6 +136,7 @@ typedef struct service {
|
||||
svc_config_param; /*< list of config params and values */
|
||||
int svc_config_version; /*< Version number of configuration */
|
||||
bool svc_do_shutdown; /*< tells the service to exit loops etc. */
|
||||
bool users_from_all; /*< Load users from one server or all of them */
|
||||
SPINLOCK
|
||||
users_table_spin; /**< The spinlock for users data refresh */
|
||||
SERVICE_REFRESH_RATE
|
||||
|
||||
Reference in New Issue
Block a user