Added optional parameters for services that allow all servers to be used when building the list of users.

This commit is contained in:
Markus Makela
2015-02-09 06:20:39 +02:00
parent 7cf65adc6e
commit 46ec9abe29
5 changed files with 384 additions and 342 deletions

View File

@ -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. 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. 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.

View File

@ -279,6 +279,7 @@ int error_count = 0;
char *user; char *user;
char *auth; char *auth;
char *enable_root_user; char *enable_root_user;
char *auth_all_servers;
char *weightby; char *weightby;
char *version_string; char *version_string;
bool is_rwsplit = false; bool is_rwsplit = false;
@ -291,6 +292,9 @@ int error_count = 0;
enable_root_user = config_get_value( enable_root_user = config_get_value(
obj->parameters, obj->parameters,
"enable_root_user"); "enable_root_user");
auth_all_servers = config_get_value(
obj->parameters,
"auth_all_servers");
allow_localhost_match_wildcard_host = allow_localhost_match_wildcard_host =
config_get_value(obj->parameters, config_get_value(obj->parameters,
"localhost_match_wildcard_host"); "localhost_match_wildcard_host");
@ -353,6 +357,9 @@ int error_count = 0;
serviceEnableRootUser( serviceEnableRootUser(
obj->element, obj->element,
config_truth_value(enable_root_user)); config_truth_value(enable_root_user));
if(auth_all_servers)
serviceAuthAllServers(obj->element,
config_truth_value(auth_all_servers));
if (weightby) if (weightby)
serviceWeightBy(obj->element, weightby); serviceWeightBy(obj->element, weightby);
@ -1352,6 +1359,7 @@ SERVER *server;
char *user; char *user;
char *auth; char *auth;
char *enable_root_user; char *enable_root_user;
char* auth_all_servers;
char* max_slave_conn_str; char* max_slave_conn_str;
char* max_slave_rlag_str; char* max_slave_rlag_str;
char *version_string; char *version_string;
@ -1363,7 +1371,9 @@ SERVER *server;
"user"); "user");
auth = config_get_value(obj->parameters, auth = config_get_value(obj->parameters,
"passwd"); "passwd");
auth_all_servers = config_get_value(obj->parameters, "auth_all_servers");
version_string = config_get_value(obj->parameters, "version_string"); version_string = config_get_value(obj->parameters, "version_string");
allow_localhost_match_wildcard_host = allow_localhost_match_wildcard_host =
@ -1385,7 +1395,8 @@ SERVER *server;
auth); auth);
if (enable_root_user) if (enable_root_user)
serviceEnableRootUser(service, atoi(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) if (allow_localhost_match_wildcard_host)
serviceEnableLocalhostMatchWildcardHost( serviceEnableLocalhostMatchWildcardHost(
service, service,
@ -1494,7 +1505,8 @@ SERVER *server;
char *auth; char *auth;
char *enable_root_user; char *enable_root_user;
char *allow_localhost_match_wildcard_host; char *allow_localhost_match_wildcard_host;
char *auth_all_servers;
enable_root_user = enable_root_user =
config_get_value(obj->parameters, config_get_value(obj->parameters,
"enable_root_user"); "enable_root_user");
@ -1517,7 +1529,9 @@ SERVER *server;
if (enable_root_user) if (enable_root_user)
serviceEnableRootUser(obj->element, serviceEnableRootUser(obj->element,
atoi(enable_root_user)); atoi(enable_root_user));
if(auth_all_servers)
serviceAuthAllServers(obj->element, atoi(auth_all_servers));
if (allow_localhost_match_wildcard_host) if (allow_localhost_match_wildcard_host)
serviceEnableLocalhostMatchWildcardHost( serviceEnableLocalhostMatchWildcardHost(
obj->element, obj->element,
@ -1741,6 +1755,7 @@ static char *service_params[] =
"user", "user",
"passwd", "passwd",
"enable_root_user", "enable_root_user",
"auth_all_servers",
"localhost_match_wildcard_host", "localhost_match_wildcard_host",
"max_slave_connections", "max_slave_connections",
"max_slave_replication_lag", "max_slave_replication_lag",

View File

@ -449,13 +449,14 @@ getUsers(SERVICE *service, USERS *users)
MYSQL_RES *result = NULL; MYSQL_RES *result = NULL;
char *service_user = NULL; char *service_user = NULL;
char *service_passwd = NULL; char *service_passwd = NULL;
char *dpwd; char *dpwd = NULL;
int total_users = 0; int total_users = 0;
SERVER_REF *server; SERVER_REF *server;
char *users_query; char *users_query, *tmp;
unsigned char hash[SHA_DIGEST_LENGTH]=""; unsigned char hash[SHA_DIGEST_LENGTH]="";
char *users_data = NULL; char *users_data = NULL;
int nusers = 0; char *final_data = NULL;
int nusers = -1;
int users_data_row_len = MYSQL_USER_MAXLEN + int users_data_row_len = MYSQL_USER_MAXLEN +
MYSQL_HOST_MAXLEN + MYSQL_HOST_MAXLEN +
MYSQL_PASSWORD_LEN + MYSQL_PASSWORD_LEN +
@ -469,408 +470,414 @@ getUsers(SERVICE *service, USERS *users)
ss_dassert(service_passwd == NULL || service_user == NULL); ss_dassert(service_passwd == NULL || service_user == NULL);
return -1; return -1;
} }
con = mysql_init(NULL);
if (service->svc_do_shutdown)
if (con == NULL) {
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : mysql_init: %s",
mysql_error(con))));
return -1;
}
/** Set read, write and connect timeout values */
if (gw_mysql_set_timeouts(con,
DEFAULT_READ_TIMEOUT,
DEFAULT_WRITE_TIMEOUT,
DEFAULT_CONNECT_TIMEOUT))
{ {
LOGIF(LE, (skygw_log_write_flush( return -1;
LOGFILE_ERROR, }
"Error : failed to set timeout values for backend "
"connection."))); dpwd = decryptPassword(service_passwd);
mysql_close(con); final_data = (char*) malloc(sizeof(char));
return -1; *final_data = '\0';
}
/**
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 * Attempt to connect to one of the databases database or until we run
* out of databases * out of databases
* to try * to try
*/ */
server = service->dbref; server = service->dbref;
dpwd = decryptPassword(service_passwd);
if(server == NULL)
{
goto cleanup;
}
/* Select a server with Master bit, if available */ /* Select a server with Master bit, if available */
while (server != NULL && !(server->server->status & SERVER_MASTER)) { while (server != NULL && !(server->server->status & SERVER_MASTER)) {
server = server->next; server = server->next;
} }
if (service->svc_do_shutdown) if(server == NULL)
{ {
free(dpwd); /* If no master is found take the first available server */
mysql_close(con); server = service->dbref;
return -1; }
}
while(server != NULL)
/* Try loading data from master server */ {
if (server != NULL &&
(mysql_real_connect(con, con = mysql_init(NULL);
server->server->name, service_user,
dpwd, if (con == NULL)
NULL, {
server->server->port, LOGIF(LE, (skygw_log_write_flush(
NULL, 0) != NULL)) LOGFILE_ERROR,
{ "Error : mysql_init: %s",
LOGIF(LD, (skygw_log_write_flush( mysql_error(con))));
LOGFILE_DEBUG, goto cleanup;
"Dbusers : Loading data from backend database with " }
"Master role [%s:%i] for service [%s]",
server->server->name, /** Set read, write and connect timeout values */
server->server->port, if (gw_mysql_set_timeouts(con,
service->name))); DEFAULT_READ_TIMEOUT,
} else { DEFAULT_WRITE_TIMEOUT,
/* load data from other servers via loop */ DEFAULT_CONNECT_TIMEOUT))
server = service->dbref; {
while (!service->svc_do_shutdown &&
server != NULL &&
(mysql_real_connect(con,
server->server->name,
service_user,
dpwd,
NULL,
server->server->port,
NULL,
0) == NULL))
{
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)
{
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Error : Unable to get user data from backend database " "Error : failed to set timeout values for backend "
"connection.")));
mysql_close(con);
goto cleanup;
}
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);
goto cleanup;
}
while(!service->svc_do_shutdown &&
server != NULL &&
(mysql_real_connect(con,
server->server->name,
service_user,
dpwd,
NULL,
server->server->port,
NULL,
0) == NULL))
{
server = server->next;
}
if (server == NULL)
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Unable to get user data from backend database "
"for service [%s]. Missing server information.", "for service [%s]. Missing server information.",
service->name))); service->name)));
mysql_close(con); mysql_close(con);
return -1; goto cleanup;
} }
/** Count users. Start with users and db grants for users */ /** Count users. Start with users and db grants for users */
if (mysql_query(con, MYSQL_USERS_WITH_DB_COUNT)) { if (mysql_query(con, MYSQL_USERS_WITH_DB_COUNT)) {
if (mysql_errno(con) != ER_TABLEACCESS_DENIED_ERROR) { if (mysql_errno(con) != ER_TABLEACCESS_DENIED_ERROR) {
/* This is an error we cannot handle, return */ /* This is an error we cannot handle, return */
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Error : Loading users for service [%s] encountered " "Error : Loading users for service [%s] encountered "
"error: [%s].", "error: [%s].",
service->name, service->name,
mysql_error(con)))); mysql_error(con))));
mysql_close(con); mysql_close(con);
return -1; goto cleanup;
} else { } else {
/* /*
* We have got ER_TABLEACCESS_DENIED_ERROR * We have got ER_TABLEACCESS_DENIED_ERROR
* try counting users from mysql.user without DB names. * try counting users from mysql.user without DB names.
*/ */
if (mysql_query(con, MYSQL_USERS_COUNT)) { if (mysql_query(con, MYSQL_USERS_COUNT)) {
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Error : Loading users for service [%s] encountered " "Error : Loading users for service [%s] encountered "
"error: [%s].", "error: [%s].",
service->name, service->name,
mysql_error(con)))); mysql_error(con))));
mysql_close(con); mysql_close(con);
return -1; goto cleanup;
} }
} }
} }
result = mysql_store_result(con); result = mysql_store_result(con);
if (result == NULL) { if (result == NULL) {
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Error : Loading users for service [%s] encountered " "Error : Loading users for service [%s] encountered "
"error: [%s].", "error: [%s].",
service->name, service->name,
mysql_error(con)))); mysql_error(con))));
mysql_close(con); mysql_close(con);
return -1; goto cleanup;
} }
row = mysql_fetch_row(result); row = mysql_fetch_row(result);
nusers = atoi(row[0]); nusers = atoi(row[0]);
mysql_free_result(result); mysql_free_result(result);
if (!nusers) { if (!nusers) {
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Error : Counting users for service %s returned 0", "Error : Counting users for service %s returned 0",
service->name))); service->name)));
mysql_close(con); mysql_close(con);
return -1; goto cleanup;
} }
if(service->enable_root) { if(service->enable_root) {
/* enable_root for MySQL protocol module means load the root user credentials from backend databases */ /* enable_root for MySQL protocol module means load the root user credentials from backend databases */
users_query = LOAD_MYSQL_USERS_WITH_DB_QUERY; users_query = LOAD_MYSQL_USERS_WITH_DB_QUERY;
} else { } else {
users_query = LOAD_MYSQL_USERS_WITH_DB_QUERY_NO_ROOT; users_query = LOAD_MYSQL_USERS_WITH_DB_QUERY_NO_ROOT;
} }
/* send first the query that fetches users and db grants */ /* send first the query that fetches users and db grants */
if (mysql_query(con, users_query)) { if (mysql_query(con, users_query)) {
/* /*
* An error occurred executing the query * An error occurred executing the query
* *
* Check mysql_errno() against ER_TABLEACCESS_DENIED_ERROR) * Check mysql_errno() against ER_TABLEACCESS_DENIED_ERROR)
*/ */
if (1142 != mysql_errno(con)) { if (1142 != mysql_errno(con)) {
/* This is an error we cannot handle, return */ /* This is an error we cannot handle, return */
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Error : Loading users with dbnames for service [%s] encountered " "Error : Loading users with dbnames for service [%s] encountered "
"error: [%s], MySQL errno %i", "error: [%s], MySQL errno %i",
service->name, service->name,
mysql_error(con), mysql_error(con),
mysql_errno(con)))); mysql_errno(con))));
mysql_close(con); mysql_close(con);
return -1; goto cleanup;
} else { } else {
/* /*
* We have got ER_TABLEACCESS_DENIED_ERROR * We have got ER_TABLEACCESS_DENIED_ERROR
* try loading users from mysql.user without DB names. * try loading users from mysql.user without DB names.
*/ */
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"%s: Unable to load database grant information, MaxScale " "%s: Unable to load database grant information, MaxScale "
"authentication will proceed without including database " "authentication will proceed without including database "
"permissions. To correct this GRANT select permission " "permissions. To correct this GRANT select permission "
"on msql.db to the user %s.", "on msql.db to the user %s.",
service->name, service_user))); service->name, service_user)));
/* check for root user select */ /* check for root user select */
if(service->enable_root) { if(service->enable_root) {
users_query = LOAD_MYSQL_USERS_QUERY " ORDER BY HOST DESC"; users_query = LOAD_MYSQL_USERS_QUERY " ORDER BY HOST DESC";
} else { } else {
users_query = LOAD_MYSQL_USERS_QUERY USERS_QUERY_NO_ROOT " ORDER BY HOST DESC"; users_query = LOAD_MYSQL_USERS_QUERY USERS_QUERY_NO_ROOT " ORDER BY HOST DESC";
} }
if (mysql_query(con, users_query)) { if (mysql_query(con, users_query)) {
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Error : Loading users for service [%s] encountered " "Error : Loading users for service [%s] encountered "
"error: [%s], code %i", "error: [%s], code %i",
service->name, service->name,
mysql_error(con), mysql_error(con),
mysql_errno(con)))); mysql_errno(con))));
mysql_close(con); mysql_close(con);
return -1; goto cleanup;
} }
/* users successfully loaded but without db grants */ /* users successfully loaded but without db grants */
LOGIF(LM, (skygw_log_write_flush( LOGIF(LM, (skygw_log_write_flush(
LOGFILE_MESSAGE, LOGFILE_MESSAGE,
"Loading users from [mysql.user] without access to [mysql.db] for " "Loading users from [mysql.user] without access to [mysql.db] for "
"service [%s]. MaxScale Authentication with DBname on connect " "service [%s]. MaxScale Authentication with DBname on connect "
"will not consider database grants.", "will not consider database grants.",
service->name))); service->name)));
} }
} else { } else {
/* /*
* users successfully loaded with db grants. * users successfully loaded with db grants.
*/ */
db_grants = 1; db_grants = 1;
} }
result = mysql_store_result(con); result = mysql_store_result(con);
if (result == NULL) { if (result == NULL) {
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Error : Loading users for service %s encountered " "Error : Loading users for service %s encountered "
"error: %s.", "error: %s.",
service->name, service->name,
mysql_error(con)))); mysql_error(con))));
mysql_free_result(result); mysql_free_result(result);
mysql_close(con); mysql_close(con);
return -1; goto cleanup;
} }
users_data = (char *)calloc(nusers, (users_data_row_len * sizeof(char)) + 1); users_data = (char *)calloc(nusers, (users_data_row_len * sizeof(char)) + 1);
if (users_data == NULL) { if (users_data == NULL) {
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Error : Memory allocation for user data failed due to " "Error : Memory allocation for user data failed due to "
"%d, %s.", "%d, %s.",
errno, errno,
strerror(errno)))); strerror(errno))));
mysql_free_result(result); mysql_free_result(result);
mysql_close(con); mysql_close(con);
return -1; goto cleanup;
} }
if (db_grants) { if (db_grants) {
/* load all mysql database names */ /* load all mysql database names */
dbnames = getDatabases(service, con); dbnames = getDatabases(service, con);
LOGIF(LD, (skygw_log_write( LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG, LOGFILE_DEBUG,
"Loaded %d MySQL Database Names for service [%s]", "Loaded %d MySQL Database Names for service [%s]",
dbnames, dbnames,
service->name))); service->name)));
} else { } else {
service->resources = NULL; service->resources = NULL;
} }
while ((row = mysql_fetch_row(result))) { while ((row = mysql_fetch_row(result))) {
/** /**
* Up to six fields could be returned. * Up to six fields could be returned.
* user,host,passwd,concat(),anydb,db * user,host,passwd,concat(),anydb,db
* passwd+1 (escaping the first byte that is '*') * passwd+1 (escaping the first byte that is '*')
*/ */
int rc = 0; int rc = 0;
char *password = NULL; char *password = NULL;
if (row[2] != NULL) { if (row[2] != NULL) {
/* detect mysql_old_password (pre 4.1 protocol) */ /* detect mysql_old_password (pre 4.1 protocol) */
if (strlen(row[2]) == 16) { if (strlen(row[2]) == 16) {
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"%s: The user %s@%s has on old password in the " "%s: The user %s@%s has on old password in the "
"backend database. MaxScale does not support these " "backend database. MaxScale does not support these "
"old passwords. This user will not be able to connect " "old passwords. This user will not be able to connect "
"via MaxScale. Update the users password to correct " "via MaxScale. Update the users password to correct "
"this.", "this.",
service->name, service->name,
row[0], row[0],
row[1]))); row[1])));
continue; continue;
} }
if (strlen(row[2]) > 1) if (strlen(row[2]) > 1)
password = row[2] +1; password = row[2] +1;
else else
password = row[2]; password = row[2];
} }
/* /*
* add user@host and DB global priv and specificsa grant (if possible) * add user@host and DB global priv and specificsa grant (if possible)
*/ */
if (db_grants) { if (db_grants) {
/* we have dbgrants, store them */ /* we have dbgrants, store them */
rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], password, row[4], row[5]); rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], password, row[4], row[5]);
} else { } else {
/* we don't have dbgrants, simply set ANY DB for the user */ /* we don't have dbgrants, simply set ANY DB for the user */
rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], password, "Y", NULL); rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], password, "Y", NULL);
} }
if (rc == 1) { if (rc == 1) {
if (db_grants) { if (db_grants) {
char dbgrant[MYSQL_DATABASE_MAXLEN + 1]=""; char dbgrant[MYSQL_DATABASE_MAXLEN + 1]="";
if (row[4] != NULL) { if (row[4] != NULL) {
if (strcmp(row[4], "Y")) if (strcmp(row[4], "Y"))
strcpy(dbgrant, "ANY"); strcpy(dbgrant, "ANY");
else { else {
if (row[5]) if (row[5])
strncpy(dbgrant, row[5], MYSQL_DATABASE_MAXLEN); strncpy(dbgrant, row[5], MYSQL_DATABASE_MAXLEN);
} }
} }
if (!strlen(dbgrant)) if (!strlen(dbgrant))
strcpy(dbgrant, "no db"); strcpy(dbgrant, "no db");
/* Log the user being added with its db grants */ /* Log the user being added with its db grants */
LOGIF(LD, (skygw_log_write_flush( LOGIF(LD, (skygw_log_write_flush(
LOGFILE_DEBUG, LOGFILE_DEBUG,
"%s: User %s@%s for database %s added to " "%s: User %s@%s for database %s added to "
"service user table.", "service user table.",
service->name, service->name,
row[0], row[0],
row[1], row[1],
dbgrant))); dbgrant)));
} else { } else {
/* Log the user being added (without db grants) */ /* Log the user being added (without db grants) */
LOGIF(LD, (skygw_log_write_flush( LOGIF(LD, (skygw_log_write_flush(
LOGFILE_DEBUG, LOGFILE_DEBUG,
"%s: User %s@%s added to service user table.", "%s: User %s@%s added to service user table.",
service->name, service->name,
row[0], row[0],
row[1]))); row[1])));
} }
/* Append data in the memory area for SHA1 digest */ /* Append data in the memory area for SHA1 digest */
strncat(users_data, row[3], users_data_row_len); strncat(users_data, row[3], users_data_row_len);
total_users++; total_users++;
} else { } else {
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"Warning: Failed to add user %s@%s for service [%s]. " "Warning: Failed to add user %s@%s for service [%s]. "
"This user will be unavailable via MaxScale.", "This user will be unavailable via MaxScale.",
row[0], row[0],
row[1], row[1],
service->name))); service->name)));
} }
} }
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 */ /* 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); memcpy(users->cksum, hash, SHA_DIGEST_LENGTH);
free(users_data); cleanup:
mysql_free_result(result);
mysql_close(con); free(dpwd);
free(final_data);
return total_users; return total_users;
} }

View File

@ -779,6 +779,25 @@ serviceEnableRootUser(SERVICE *service, int action)
return 1; 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 * Trim whitespace from the from an rear of a string
* *

View File

@ -136,6 +136,7 @@ typedef struct service {
svc_config_param; /*< list of config params and values */ svc_config_param; /*< list of config params and values */
int svc_config_version; /*< Version number of configuration */ int svc_config_version; /*< Version number of configuration */
bool svc_do_shutdown; /*< tells the service to exit loops etc. */ 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 SPINLOCK
users_table_spin; /**< The spinlock for users data refresh */ users_table_spin; /**< The spinlock for users data refresh */
SERVICE_REFRESH_RATE SERVICE_REFRESH_RATE