Merge branch '2.1' into 2.2
This commit is contained in:
commit
bd39284f9c
@ -132,7 +132,7 @@ configure_file(${CMAKE_SOURCE_DIR}/etc/upstart/maxscale.conf.in ${CMAKE_BINARY_D
|
||||
configure_file(${CMAKE_SOURCE_DIR}/test/maxscale_test.cnf ${CMAKE_BINARY_DIR}/maxscale.cnf @ONLY)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/test/maxscale_test_secondary.cnf ${CMAKE_BINARY_DIR}/maxscale_secondary.cnf @ONLY)
|
||||
|
||||
set(FLAGS "-Wall -Wno-unused-variable -Wno-unused-function -Werror -fPIC" CACHE STRING "Compilation flags")
|
||||
set(FLAGS "-rdynamic -Wall -Wno-unused-variable -Wno-unused-function -Werror -fPIC" CACHE STRING "Compilation flags")
|
||||
set(DEBUG_FLAGS "-ggdb -pthread -pipe -Wformat -fstack-protector --param=ssp-buffer-size=4" CACHE STRING "Debug compilation flags")
|
||||
|
||||
if(CMAKE_VERSION VERSION_GREATER 2.6)
|
||||
|
@ -196,6 +196,24 @@ write or modify the data in the backend server. The default is 2 seconds.
|
||||
auth_write_timeout=10
|
||||
```
|
||||
|
||||
#### `query_retries`
|
||||
|
||||
The number of times an interrupted query will be retried. This feature was added
|
||||
in MaxScale 2.1.10 and is disabled by default.
|
||||
|
||||
An interrupted query is any query that is interrupted by a network
|
||||
error. Connection timeouts are included in network errors and thus is it
|
||||
advisable to make sure that the value of `query_retry_timeout` is set to an
|
||||
adequate value.
|
||||
|
||||
#### `query_retry_timeout`
|
||||
|
||||
The total timeout in seconds for any retried queries. The default value is 5
|
||||
seconds.
|
||||
|
||||
An interrupted query is retried for either the configured amount of attempts or
|
||||
until the configured timeout is reached.
|
||||
|
||||
#### `ms_timestamp`
|
||||
|
||||
Enable or disable the high precision timestamps in logfiles. Enabling this adds
|
||||
|
@ -22,6 +22,20 @@ release notes:
|
||||
For any problems you encounter, please consider submitting a bug report at
|
||||
[Jira](https://jira.mariadb.org).
|
||||
|
||||
## Changed Features
|
||||
|
||||
### Internal Query Retries
|
||||
|
||||
The internal SQL queries that MaxScale executes to load database users as well
|
||||
as monitor the database itself can now be automatically retried if they are
|
||||
interrupted. The new global parameter, `query_retries` controls the number of
|
||||
retry attempts each query will receive if it fails due to a network problem.
|
||||
The `query_retry_timeout` global parameter controls the total timeout for the
|
||||
retries.
|
||||
|
||||
To enable this functionality, add `query_retries=<number-of-retries>` under the
|
||||
`[maxscale]` section where _<number-of-retries>_ is a positive integer.
|
||||
|
||||
## Bug fixes
|
||||
|
||||
[Here is a list of bugs fixed in MaxScale 2.1.10.](https://jira.mariadb.org/issues/?jql=project%20%3D%20MXS%20AND%20issuetype%20%3D%20Bug%20AND%20status%20%3D%20Closed%20AND%20fixVersion%20%3D%202.1.10)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <limits.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <maxscale/modinfo.h>
|
||||
#include <maxscale/jansson.h>
|
||||
@ -132,6 +133,8 @@ extern const char CN_PORT[];
|
||||
extern const char CN_PROTOCOL[];
|
||||
extern const char CN_QUERY_CLASSIFIER[];
|
||||
extern const char CN_QUERY_CLASSIFIER_ARGS[];
|
||||
extern const char CN_QUERY_RETRIES[];
|
||||
extern const char CN_QUERY_RETRY_TIMEOUT[];
|
||||
extern const char CN_RELATIONSHIPS[];
|
||||
extern const char CN_LINKS[];
|
||||
extern const char CN_REQUIRED[];
|
||||
@ -219,6 +222,8 @@ typedef struct
|
||||
char admin_ssl_key[PATH_MAX]; /**< Admin SSL key */
|
||||
char admin_ssl_cert[PATH_MAX]; /**< Admin SSL cert */
|
||||
char admin_ssl_ca_cert[PATH_MAX]; /**< Admin SSL CA cert */
|
||||
int query_retries; /**< Number of times a interrupted query is retried */
|
||||
time_t query_retry_timeout; /**< Timeout for query retries */
|
||||
} MXS_CONFIG;
|
||||
|
||||
/**
|
||||
|
@ -113,7 +113,7 @@ json_t* mxs_logs_to_json(const char* host);
|
||||
static inline bool mxs_log_priority_is_enabled(int priority)
|
||||
{
|
||||
assert((priority & ~LOG_PRIMASK) == 0);
|
||||
return MXS_LOG_PRIORITY_IS_ENABLED(priority);
|
||||
return MXS_LOG_PRIORITY_IS_ENABLED(priority) || priority == LOG_ALERT;
|
||||
}
|
||||
|
||||
int mxs_log_message(int priority,
|
||||
|
@ -29,7 +29,29 @@ uint64_t mxs_leint_consume(uint8_t ** c);
|
||||
char* mxs_lestr_consume_dup(uint8_t** c);
|
||||
char* mxs_lestr_consume(uint8_t** c, size_t *size);
|
||||
|
||||
MYSQL *mxs_mysql_real_connect(MYSQL *mysql, SERVER *server, const char *user, const char *passwd);
|
||||
/**
|
||||
* Creates a connection to a MySQL database engine. If necessary, initializes SSL.
|
||||
*
|
||||
* @param con A valid MYSQL structure.
|
||||
* @param server The server on which the MySQL engine is running.
|
||||
* @param user The MySQL login ID.
|
||||
* @param passwd The password for the user.
|
||||
*
|
||||
* @return New connection or NULL on error
|
||||
*/
|
||||
MYSQL* mxs_mysql_real_connect(MYSQL *mysql, SERVER *server, const char *user, const char *passwd);
|
||||
|
||||
/**
|
||||
* Execute a query
|
||||
*
|
||||
* This function wraps mysql_query in a way that automatic query retry is possible.
|
||||
*
|
||||
* @param conn MySQL connection
|
||||
* @param query Query to execute
|
||||
*
|
||||
* @return return value of mysql_query
|
||||
*/
|
||||
int mxs_mysql_query(MYSQL* conn, const char* query);
|
||||
|
||||
/**
|
||||
* Trim MySQL quote characters surrounding a string.
|
||||
|
@ -494,6 +494,10 @@ add_test_executable(mxs1295_sp_call.cpp mxs1295_sp_call mxs1295 LABELS maxscale
|
||||
# https://jira.mariadb.org/browse/MXS-1451
|
||||
add_test_executable(mxs1451_skip_auth.cpp mxs1451_skip_auth mxs1451_skip_auth LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# MXS-1457: Deleted servers are not ignored when users are loaded
|
||||
# https://jira.mariadb.org/browse/MXS-1457
|
||||
add_test_executable(mxs1457_ignore_deleted.cpp mxs1457_ignore_deleted mxs1457_ignore_deleted LABELS REPL_BACKEND)
|
||||
|
||||
# 'namedserverfilter' test
|
||||
add_test_executable(namedserverfilter.cpp namedserverfilter namedserverfilter LABELS namedserverfilter LIGHT REPL_BACKEND)
|
||||
|
||||
|
@ -1,39 +1,14 @@
|
||||
/**
|
||||
* @file bug509.cpp regression case for bug 509 and 507 ( "Referring to a nonexisting server in servers=... doesn't even raise a warning"
|
||||
* and "rw-split router does not send last_insert_id() to master" )
|
||||
* @file bug509.cpp regression case for bug 509 "rw-split router does not send last_insert_id() to master"
|
||||
*
|
||||
* - "CREATE TABLE t2 (id INT(10) NOT NULL AUTO_INCREMENT, x int, PRIMARY KEY (id));",
|
||||
* - do a number of INSERTs first using RWsplit, then directly Galera nodes.
|
||||
* - do "select @@wsrep_node_address, last_insert_id();" and "select last_insert_id(), @@wsrep_node_address;" and compares results.
|
||||
* - do "insert into t2 (x) values (i);" 1000 times and compares results of
|
||||
* - do "insert into t2 (x) values (i);" 50 times and compares results of
|
||||
* "select @@wsrep_node_address, last_insert_id();" and "select last_insert_id(), @@wsrep_node_address;"
|
||||
*
|
||||
* Test fails if results are different (after 5 seconds of waiting after last INSERT)
|
||||
*/
|
||||
|
||||
/*
|
||||
Kolbe Kegel 2014-09-01 14:48:12 UTC
|
||||
For some reason, the order of terms in the field list of a SELECT statement influences how the rw-split router decides where to send a statement.
|
||||
|
||||
mariadb> select @@wsrep_node_address, last_insert_id();
|
||||
+----------------------+------------------+
|
||||
| @@wsrep_node_address | last_insert_id() |
|
||||
+----------------------+------------------+
|
||||
| 192.168.30.31 | 7 |
|
||||
+----------------------+------------------+
|
||||
1 row in set (0.00 sec)
|
||||
|
||||
mariadb> select last_insert_id(), @@wsrep_node_address;
|
||||
+------------------+----------------------+
|
||||
| last_insert_id() | @@wsrep_node_address |
|
||||
+------------------+----------------------+
|
||||
| 0 | 192.168.30.33 |
|
||||
+------------------+----------------------+
|
||||
1 row in set (0.00 sec)
|
||||
Comment 1 Vilho Raatikka 2014-09-03 20:44:17 UTC
|
||||
Added code to detect last_insert_id() function and now both types of elements are routed to master and their order of appearance doesn't matter.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "testconnections.h"
|
||||
@ -49,59 +24,22 @@ int main(int argc, char *argv[])
|
||||
Test->galera->connect();
|
||||
Test->connect_maxscale();
|
||||
|
||||
if (Test->galera->N < 3)
|
||||
{
|
||||
Test->tprintf("There is not enoght nodes for test\n");
|
||||
delete Test;
|
||||
exit(1);
|
||||
}
|
||||
Test->tprintf("Creating table");
|
||||
Test->try_query(Test->conn_rwsplit, "DROP TABLE IF EXISTS t2;");
|
||||
Test->try_query(Test->conn_rwsplit, "CREATE TABLE t2 (id INT(10) NOT NULL AUTO_INCREMENT, x int, PRIMARY KEY (id));");
|
||||
Test->tprintf("Doing INSERT through readwritesplit");
|
||||
Test->try_query(Test->conn_rwsplit, "START TRANSACTION");
|
||||
Test->try_query(Test->conn_rwsplit, "insert into t2 (x) values (1);");
|
||||
|
||||
Test->tprintf("Creating table\n");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "DROP TABLE IF EXISTS t2;");
|
||||
Test->try_query(Test->conn_rwsplit,
|
||||
(char *) "CREATE TABLE t2 (id INT(10) NOT NULL AUTO_INCREMENT, x int, PRIMARY KEY (id));");
|
||||
Test->tprintf("Doing INSERTs\n");
|
||||
Test->try_query(Test->conn_rwsplit, (char *) "insert into t2 (x) values (1);");
|
||||
char last_insert_id1[1024] = "";
|
||||
char last_insert_id2[1024] = "";
|
||||
find_field(Test->conn_rwsplit, sel1, "last_insert_id()", last_insert_id1);
|
||||
find_field(Test->conn_rwsplit, sel2, "last_insert_id()", last_insert_id2);
|
||||
Test->try_query(Test->conn_rwsplit, "COMMIT");
|
||||
|
||||
Test->try_query(Test->galera->nodes[0], (char *) "insert into t2 (x) values (2);");
|
||||
Test->try_query(Test->galera->nodes[0], (char *) "insert into t2 (x) values (3);");
|
||||
|
||||
Test->try_query(Test->galera->nodes[1], (char *) "insert into t2 (x) values (4);");
|
||||
Test->try_query(Test->galera->nodes[1], (char *) "insert into t2 (x) values (5);");
|
||||
Test->try_query(Test->galera->nodes[1], (char *) "insert into t2 (x) values (6);");
|
||||
|
||||
Test->try_query(Test->galera->nodes[2], (char *) "insert into t2 (x) values (7);");
|
||||
Test->try_query(Test->galera->nodes[2], (char *) "insert into t2 (x) values (8);");
|
||||
Test->try_query(Test->galera->nodes[2], (char *) "insert into t2 (x) values (9);");
|
||||
Test->try_query(Test->galera->nodes[2], (char *) "insert into t2 (x) values (10);");
|
||||
|
||||
Test->stop_timeout();
|
||||
Test->repl->sync_slaves();
|
||||
|
||||
Test->tprintf("Trying \n");
|
||||
char last_insert_id1[1024];
|
||||
char last_insert_id2[1024];
|
||||
if ( (
|
||||
find_field(
|
||||
Test->conn_rwsplit, sel1,
|
||||
"last_insert_id()", &last_insert_id1[0])
|
||||
!= 0 ) || (
|
||||
find_field(
|
||||
Test->conn_rwsplit, sel2,
|
||||
"last_insert_id()", &last_insert_id2[0])
|
||||
!= 0 ))
|
||||
{
|
||||
Test->tprintf("last_insert_id() fied not found!!\n");
|
||||
delete Test;
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Test->tprintf("'%s' gave last_insert_id() %s\n", sel1, last_insert_id1);
|
||||
Test->tprintf("'%s' gave last_insert_id() %s\n", sel2, last_insert_id2);
|
||||
Test->add_result(strcmp(last_insert_id1, last_insert_id2),
|
||||
"last_insert_id() are different depending in which order terms are in SELECT\n");
|
||||
}
|
||||
Test->tprintf("'%s' gave last_insert_id() %s", sel1, last_insert_id1);
|
||||
Test->tprintf("'%s' gave last_insert_id() %s", sel2, last_insert_id2);
|
||||
Test->add_result(strcmp(last_insert_id1, last_insert_id2), "last_insert_id() are different depending in which order terms are in SELECT");
|
||||
|
||||
char id_str[1024];
|
||||
char str1[1024];
|
||||
@ -110,12 +48,13 @@ int main(int argc, char *argv[])
|
||||
for (int i = 100; i < iterations; i++)
|
||||
{
|
||||
Test->set_timeout(50);
|
||||
Test->try_query(Test->conn_rwsplit, "START TRANSACTION");
|
||||
Test->add_result(execute_query(Test->conn_rwsplit, "insert into t2 (x) values (%d);", i), "Query failed");
|
||||
|
||||
sprintf(str1, "select * from t2 where x=%d;", i);
|
||||
|
||||
find_field(Test->conn_rwsplit, sel1, "last_insert_id()", &last_insert_id1[0]);
|
||||
find_field(Test->conn_rwsplit, str1, "id", &id_str[0]);
|
||||
find_field(Test->conn_rwsplit, sel1, "last_insert_id()", last_insert_id1);
|
||||
find_field(Test->conn_rwsplit, str1, "id", id_str);
|
||||
|
||||
int n = 0;
|
||||
|
||||
@ -127,6 +66,8 @@ int main(int argc, char *argv[])
|
||||
n++;
|
||||
}
|
||||
|
||||
Test->try_query(Test->conn_rwsplit, "COMMIT");
|
||||
|
||||
Test->add_result(strcmp(last_insert_id1, id_str),
|
||||
"last_insert_id is not equal to id even after waiting 5 seconds");
|
||||
|
||||
@ -136,6 +77,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
Test->try_query(Test->conn_rwsplit, "DROP TABLE t2;");
|
||||
Test->check_maxscale_alive();
|
||||
|
||||
int rval = Test->global_result;
|
||||
|
@ -88,14 +88,11 @@ int main(int argc, char *argv[])
|
||||
Test->repl->sync_slaves();
|
||||
Test->set_timeout(200);
|
||||
|
||||
sprintf(str, "%s rm -f /tmp/t*.csv; %s chmod 777 /tmp", Test->repl->access_sudo[0],
|
||||
Test->repl->access_sudo[0]);
|
||||
Test->tprintf("%s\n", str);
|
||||
for (int k = 0; k < Test->repl->N; k++)
|
||||
{
|
||||
Test->repl->ssh_node(k, str, false);
|
||||
Test->repl->ssh_node(k, false, "%s rm -f /tmp/t*.csv; %s chmod 777 /tmp",
|
||||
Test->repl->access_sudo[0], Test->repl->access_sudo[0]);
|
||||
}
|
||||
//system(str);
|
||||
|
||||
Test->tprintf("Copying data from t1 to file...\n");
|
||||
Test->tprintf("using RWSplit: SELECT * INTO OUTFILE '/tmp/t1.csv' FROM t1;\n");
|
||||
|
@ -0,0 +1,60 @@
|
||||
[maxscale]
|
||||
threads=###threads###
|
||||
log_info=1
|
||||
|
||||
[MySQL Monitor]
|
||||
type=monitor
|
||||
module=mysqlmon
|
||||
###repl51###
|
||||
servers=server1,server2,server3,server4
|
||||
user=maxskysql
|
||||
passwd=skysql
|
||||
monitor_interval=1000
|
||||
|
||||
[RW Split Router]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server1,server2,server3,server4
|
||||
user=maxskysql
|
||||
passwd=skysql
|
||||
router_options=master_failure_mode=error_on_write
|
||||
|
||||
[RW Split Listener]
|
||||
type=listener
|
||||
service=RW Split Router
|
||||
protocol=MySQLClient
|
||||
port=4006
|
||||
|
||||
[CLI]
|
||||
type=service
|
||||
router=cli
|
||||
|
||||
[CLI Listener]
|
||||
type=listener
|
||||
service=CLI
|
||||
protocol=maxscaled
|
||||
socket=default
|
||||
|
||||
[server1]
|
||||
type=server
|
||||
address=###node_server_IP_1###
|
||||
port=###node_server_port_1###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server2]
|
||||
type=server
|
||||
address=###node_server_IP_2###
|
||||
port=###node_server_port_2###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server3]
|
||||
type=server
|
||||
address=###node_server_IP_3###
|
||||
port=###node_server_port_3###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server4]
|
||||
type=server
|
||||
address=###node_server_IP_4###
|
||||
port=###node_server_port_4###
|
||||
protocol=MySQLBackend
|
@ -35,17 +35,12 @@ int main(int argc, char *argv[])
|
||||
sprintf(str, "%s/krb5.conf", test_dir);
|
||||
for (i = 0; i < Test->repl->N; i++)
|
||||
{
|
||||
Test->repl->ssh_node(i, (char *)
|
||||
"yum clean all", true);
|
||||
Test->repl->ssh_node(i, (char *)
|
||||
"yum install -y MariaDB-gssapi-server MariaDB-gssapi-client krb5-workstation pam_krb5", true);
|
||||
Test->repl->ssh_node(i, true, "yum install -y MariaDB-gssapi-server MariaDB-gssapi-client krb5-workstation pam_krb5");
|
||||
Test->repl->copy_to_node(str, (char *) "~/", i);
|
||||
sprintf(str1, "cp %s/krb5.conf /etc/", Test->repl->access_homedir[i]);
|
||||
Test->repl->ssh_node(i, str1, true);
|
||||
Test->repl->ssh_node(i, true, "cp ~/krb5.conf /etc/");
|
||||
|
||||
Test->repl->copy_to_node((char *) "hosts", (char *) "~/", i);
|
||||
sprintf(str1, "cp %s/hosts /etc/", Test->repl->access_homedir[i]);
|
||||
Test->repl->ssh_node(i, str1, true);
|
||||
Test->repl->ssh_node(i, true, "cp ~/hosts /etc/");
|
||||
}
|
||||
|
||||
Test->tprintf("Copying 'hosts' and krb5.conf files to Maxscale node\n");
|
||||
@ -102,12 +97,12 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
sprintf(str, "%s/kerb.cnf", test_dir);
|
||||
Test->repl->copy_to_node(str, (char *) "~/", i);
|
||||
Test->repl->ssh_node(i, (char *) "cp ~/kerb.cnf /etc/my.cnf.d/", true);
|
||||
Test->repl->ssh_node(i, true, "cp ~/kerb.cnf /etc/my.cnf.d/");
|
||||
|
||||
Test->repl->copy_to_node((char *) "krb5.keytab", (char *) "~/", i);
|
||||
Test->repl->ssh_node(i, (char *) "cp ~/krb5.keytab /etc/", true);
|
||||
Test->repl->ssh_node(i, true, "cp ~/krb5.keytab /etc/");
|
||||
|
||||
Test->repl->ssh_node(i, (char *) "kinit mariadb/maxscale.test@MAXSCALE.TEST -k -t /etc/krb5.keytab", false);
|
||||
Test->repl->ssh_node(i, false, "kinit mariadb/maxscale.test@MAXSCALE.TEST -k -t /etc/krb5.keytab");
|
||||
}
|
||||
|
||||
Test->tprintf("Installing gssapi plugin to all nodes\n");
|
||||
@ -124,18 +119,18 @@ int main(int argc, char *argv[])
|
||||
|
||||
Test->tprintf("Trying use usr1 to execute query: RW Split\n");
|
||||
Test->add_result(
|
||||
Test->repl->ssh_node(1,
|
||||
"echo select User,Host from mysql.user | mysql -uusr1 -h maxscale.maxscale.test -P 4006", false),
|
||||
Test->repl->ssh_node(1, false,
|
||||
"echo select User,Host from mysql.user | mysql -uusr1 -h maxscale.maxscale.test -P 4006"),
|
||||
"Error executing query against RW Split\n");
|
||||
Test->tprintf("Trying use usr1 to execute query: Read Connection Master\n");
|
||||
Test->add_result(
|
||||
Test->repl->ssh_node(1,
|
||||
"echo select User,Host from mysql.user | mysql -uusr1 -h maxscale.maxscale.test -P 4008", false),
|
||||
Test->repl->ssh_node(1, false,
|
||||
"echo select User,Host from mysql.user | mysql -uusr1 -h maxscale.maxscale.test -P 4008"),
|
||||
"Error executing query against Read Connection Master\n");
|
||||
Test->tprintf("Trying use usr1 to execute query: Read Connection Slave\n");
|
||||
Test->add_result(
|
||||
Test->repl->ssh_node(1,
|
||||
"echo select User,Host from mysql.user | mysql -uusr1 -h maxscale.maxscale.test -P 4009", false),
|
||||
Test->repl->ssh_node(1, false,
|
||||
"echo select User,Host from mysql.user | mysql -uusr1 -h maxscale.maxscale.test -P 4009"),
|
||||
"Error executing query against Read Connection Slave\n");
|
||||
|
||||
for (int i = 0; i < Test->repl->N; i++)
|
||||
|
@ -456,7 +456,7 @@ int execute_query_count_rows(MYSQL *conn, const char *sql)
|
||||
return rval;
|
||||
}
|
||||
|
||||
int get_conn_num(MYSQL *conn, char * ip, char *hostname, char * db)
|
||||
int get_conn_num(MYSQL *conn, const char* ip, const char* hostname, const char* db)
|
||||
{
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
@ -584,16 +584,16 @@ unsigned int get_seconds_behind_master(MYSQL *conn)
|
||||
char SBM_str[16];
|
||||
unsigned int SBM = 0;
|
||||
if (find_field(
|
||||
conn, (char *) "show slave status;",
|
||||
(char *) "Seconds_Behind_Master", &SBM_str[0]
|
||||
) != 1)
|
||||
conn, (char *) "show slave status;",
|
||||
(char *) "Seconds_Behind_Master", &SBM_str[0]
|
||||
) != 1)
|
||||
{
|
||||
sscanf(SBM_str, "%u", &SBM);
|
||||
}
|
||||
return SBM;
|
||||
}
|
||||
|
||||
int read_log(char * name, char ** err_log_content_p)
|
||||
int read_log(const char* name, char ** err_log_content_p)
|
||||
{
|
||||
FILE *f;
|
||||
*err_log_content_p = NULL;
|
||||
|
@ -200,7 +200,7 @@ int execute_query_check_one(MYSQL *conn, const char *sql, const char *expected);
|
||||
* @param db name of DB to which connections are counted
|
||||
* @return number of connections
|
||||
*/
|
||||
int get_conn_num(MYSQL *conn, char * ip, char * hostname, char * db);
|
||||
int get_conn_num(MYSQL *conn, const char* ip, const char* hostname, const char* db);
|
||||
|
||||
/**
|
||||
* @brief Find given filed in the SQL query reply
|
||||
@ -227,7 +227,7 @@ unsigned int get_seconds_behind_master(MYSQL *conn);
|
||||
* @param err_log_content pointer to the buffer to store log file content
|
||||
* @return 0 in case of success, 1 in case of error
|
||||
*/
|
||||
int read_log(char * name, char **err_log_content_p);
|
||||
int read_log(const char* name, char **err_log_content_p);
|
||||
|
||||
int get_int_version(const std::string& version);
|
||||
int get_int_version(const char* version);
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
Mariadb_nodes::Mariadb_nodes(const char *pref, const char *test_cwd, bool verbose):
|
||||
Mariadb_nodes::Mariadb_nodes(const char *pref, const char *test_cwd, bool verbose) :
|
||||
v51(false), use_ipv6(false)
|
||||
{
|
||||
strcpy(prefix, pref);
|
||||
@ -119,7 +119,7 @@ int Mariadb_nodes::read_env()
|
||||
ssl = false;
|
||||
sprintf(env_name, "%s_ssl", prefix);
|
||||
env = getenv(env_name);
|
||||
if ((env != NULL) && ((strcasecmp(env, "yes") == 0) || (strcasecmp(env, "true") == 0) ))
|
||||
if ((env != NULL) && ((strcasecmp(env, "yes") == 0) || (strcasecmp(env, "true") == 0)))
|
||||
{
|
||||
ssl = true;
|
||||
}
|
||||
@ -290,9 +290,9 @@ int Mariadb_nodes::find_master()
|
||||
while ((found == 0) && (i < N))
|
||||
{
|
||||
if (find_field(
|
||||
nodes[i], (char *) "show slave status;",
|
||||
(char *) "Master_Host", &str[0]
|
||||
) == 0 )
|
||||
nodes[i], "show slave status;",
|
||||
"Master_Host", &str[0]
|
||||
) == 0)
|
||||
{
|
||||
found = 1;
|
||||
strcpy(master_IP, str);
|
||||
@ -328,13 +328,13 @@ int Mariadb_nodes::change_master(int NewMaster, int OldMaster)
|
||||
{
|
||||
if (i != OldMaster)
|
||||
{
|
||||
execute_query(nodes[i], (char *) "stop slave;");
|
||||
execute_query(nodes[i], "stop slave;");
|
||||
}
|
||||
}
|
||||
execute_query(nodes[NewMaster], create_repl_user);
|
||||
execute_query(nodes[OldMaster], (char *) "reset master;");
|
||||
find_field(nodes[NewMaster], (char *) "show master status", (char *) "File", &log_file[0]);
|
||||
find_field(nodes[NewMaster], (char *) "show master status", (char *) "Position", &log_pos[0]);
|
||||
execute_query(nodes[OldMaster], "reset master;");
|
||||
find_field(nodes[NewMaster], "show master status", "File", &log_file[0]);
|
||||
find_field(nodes[NewMaster], "show master status", "Position", &log_pos[0]);
|
||||
for (i = 0; i < N; i++)
|
||||
{
|
||||
if (i != NewMaster)
|
||||
@ -343,15 +343,15 @@ int Mariadb_nodes::change_master(int NewMaster, int OldMaster)
|
||||
execute_query(nodes[i], str);
|
||||
}
|
||||
}
|
||||
//for (i = 0; i < N; i++) {if (i != NewMaster) {execute_query(nodes[i], (char *) "start slave;"); }}
|
||||
//for (i = 0; i < N; i++) {if (i != NewMaster) {execute_query(nodes[i], "start slave;"); }}
|
||||
}
|
||||
|
||||
int Mariadb_nodes::stop_node(int node)
|
||||
{
|
||||
return ssh_node(node, stop_db_command[node], true);
|
||||
return ssh_node(node, true, stop_db_command[node]);
|
||||
}
|
||||
|
||||
int Mariadb_nodes::start_node(int node, char * param)
|
||||
int Mariadb_nodes::start_node(int node, const char* param)
|
||||
{
|
||||
char cmd[1024];
|
||||
if (v51)
|
||||
@ -362,7 +362,7 @@ int Mariadb_nodes::start_node(int node, char * param)
|
||||
{
|
||||
sprintf(cmd, "%s %s", start_db_command[node], param);
|
||||
}
|
||||
return ssh_node(node, cmd, true);
|
||||
return ssh_node(node, true, cmd);
|
||||
}
|
||||
|
||||
int Mariadb_nodes::stop_nodes()
|
||||
@ -374,7 +374,7 @@ int Mariadb_nodes::stop_nodes()
|
||||
{
|
||||
printf("Stopping node %d\n", i);
|
||||
fflush(stdout);
|
||||
local_result += execute_query(nodes[i], (char *) "stop slave;");
|
||||
local_result += execute_query(nodes[i], "stop slave;");
|
||||
fflush(stdout);
|
||||
local_result += stop_node(i);
|
||||
fflush(stdout);
|
||||
@ -391,7 +391,7 @@ int Mariadb_nodes::stop_slaves()
|
||||
{
|
||||
printf("Stopping slave %d\n", i);
|
||||
fflush(stdout);
|
||||
global_result += execute_query(nodes[i], (char *) "stop slave;");
|
||||
global_result += execute_query(nodes[i], "stop slave;");
|
||||
}
|
||||
close_connections();
|
||||
return global_result;
|
||||
@ -399,7 +399,7 @@ int Mariadb_nodes::stop_slaves()
|
||||
|
||||
int Mariadb_nodes::cleanup_db_node(int node)
|
||||
{
|
||||
return ssh_node(node, cleanup_db_command[node], true);
|
||||
return ssh_node(node, true, cleanup_db_command[node]);
|
||||
}
|
||||
|
||||
int Mariadb_nodes::cleanup_db_nodes()
|
||||
@ -417,8 +417,6 @@ int Mariadb_nodes::cleanup_db_nodes()
|
||||
return local_result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int Mariadb_nodes::start_replication()
|
||||
{
|
||||
char str[1024];
|
||||
@ -428,26 +426,27 @@ int Mariadb_nodes::start_replication()
|
||||
// Start all nodes
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
local_result += start_node(i, (char *) "");
|
||||
sprintf(str,
|
||||
"mysql -u root %s -e \"STOP SLAVE; RESET SLAVE; RESET SLAVE ALL; RESET MASTER; SET GLOBAL read_only=OFF;\"",
|
||||
socket_cmd[i]);
|
||||
ssh_node(i, str, true);
|
||||
local_result += start_node(i, "");
|
||||
ssh_node(i, true,
|
||||
"mysql -u root %s -e \"STOP SLAVE; RESET SLAVE; RESET SLAVE ALL; RESET MASTER; SET GLOBAL read_only=OFF;\"",
|
||||
socket_cmd[i]);
|
||||
ssh_node(i, true, "sudo rm -f /etc/my.cnf.d/kerb.cnf");
|
||||
ssh_node(i, true,
|
||||
"for i in `mysql -ss -u root %s -e \"SHOW DATABASES\"|grep -iv 'mysql\\|information_schema\\|performance_schema'`; "
|
||||
"do mysql -u root %s -e \"DROP DATABASE $i\";"
|
||||
"done", socket_cmd[i], socket_cmd[i]);
|
||||
}
|
||||
|
||||
sprintf(str, "%s/create_user.sh", test_dir);
|
||||
sprintf(dtr, "%s", access_homedir[0]);
|
||||
copy_to_node(str, dtr , 0);
|
||||
sprintf(str, "export node_user=\"%s\"; export node_password=\"%s\"; %s/create_user.sh %s",
|
||||
user_name, password, access_homedir[0], socket_cmd[0]);
|
||||
printf("cmd: %s\n", str);
|
||||
ssh_node(0, str, false);
|
||||
copy_to_node(str, dtr, 0);
|
||||
ssh_node(0, false, "export node_user=\"%s\"; export node_password=\"%s\"; %s/create_user.sh %s",
|
||||
user_name, password, access_homedir[0], socket_cmd[0]);
|
||||
|
||||
// Create a database dump from the master and distribute it to the slaves
|
||||
sprintf(str,
|
||||
"mysqldump --all-databases --add-drop-database --flush-privileges --master-data=1 --gtid %s > /tmp/master_backup.sql",
|
||||
socket_cmd[0]);
|
||||
ssh_node(0, str, true);
|
||||
ssh_node(0, true, "mysql -u root %s -e \"CREATE DATABASE test\"; "
|
||||
"mysqldump --all-databases --add-drop-database --flush-privileges --master-data=1 --gtid %s > /tmp/master_backup.sql",
|
||||
socket_cmd[0], socket_cmd[0]);
|
||||
sprintf(str, "%s/master_backup.sql", test_dir);
|
||||
copy_from_node("/tmp/master_backup.sql", str, 0);
|
||||
|
||||
@ -457,16 +456,11 @@ int Mariadb_nodes::start_replication()
|
||||
printf("Starting node %d\n", i);
|
||||
fflush(stdout);
|
||||
copy_to_node(str, "/tmp/master_backup.sql", i);
|
||||
sprintf(dtr,
|
||||
"mysql -u root %s < /tmp/master_backup.sql",
|
||||
socket_cmd[i]);
|
||||
ssh_node(i, dtr, true);
|
||||
char query[512];
|
||||
|
||||
sprintf(query, "mysql -u root %s -e \"CHANGE MASTER TO MASTER_HOST=\\\"%s\\\", MASTER_PORT=%d, "
|
||||
"MASTER_USER=\\\"repl\\\", MASTER_PASSWORD=\\\"repl\\\";"
|
||||
"START SLAVE;\"", socket_cmd[i], IP_private[0], port[0]);
|
||||
ssh_node(i, query, true);
|
||||
ssh_node(i, true, "mysql -u root %s < /tmp/master_backup.sql",
|
||||
socket_cmd[i]);
|
||||
ssh_node(i, true, "mysql -u root %s -e \"CHANGE MASTER TO MASTER_HOST=\\\"%s\\\", MASTER_PORT=%d, "
|
||||
"MASTER_USER=\\\"repl\\\", MASTER_PASSWORD=\\\"repl\\\";"
|
||||
"START SLAVE;\"", socket_cmd[i], IP_private[0], port[0]);
|
||||
}
|
||||
|
||||
return local_result;
|
||||
@ -481,39 +475,30 @@ int Galera_nodes::start_galera()
|
||||
local_result += stop_nodes();
|
||||
|
||||
// Remove the grastate.dat file
|
||||
ssh_node(0, "rm -f /var/lib/mysql/grastate.dat", true);
|
||||
ssh_node(0, true, "rm -f /var/lib/mysql/grastate.dat");
|
||||
|
||||
printf("Starting new Galera cluster\n");
|
||||
fflush(stdout);
|
||||
ssh_node(0, "echo [mysqld] > cluster_address.cnf", false);
|
||||
ssh_node(0, "echo wsrep_cluster_address=gcomm:// >> cluster_address.cnf", false);
|
||||
ssh_node(0, "cp cluster_address.cnf /etc/my.cnf.d/", true);
|
||||
local_result += start_node(0, (char *) " --wsrep-cluster-address=gcomm://");
|
||||
ssh_node(0, false, "echo [mysqld] > cluster_address.cnf");
|
||||
ssh_node(0, false, "echo wsrep_cluster_address=gcomm:// >> cluster_address.cnf");
|
||||
ssh_node(0, true, "cp cluster_address.cnf /etc/my.cnf.d/");
|
||||
local_result += start_node(0, " --wsrep-cluster-address=gcomm://");
|
||||
|
||||
sprintf(str, "%s/create_user_galera.sh", test_dir);
|
||||
copy_to_node(str, "~/", 0);
|
||||
|
||||
sprintf(str, "export galera_user=\"%s\"; export galera_password=\"%s\"; ./create_user_galera.sh %s", user_name,
|
||||
password, socket_cmd[0]);
|
||||
ssh_node(0, str, false);
|
||||
ssh_node(0, false, "export galera_user=\"%s\"; export galera_password=\"%s\"; ./create_user_galera.sh %s",
|
||||
user_name,
|
||||
password, socket_cmd[0]);
|
||||
|
||||
for (i = 1; i < N; i++)
|
||||
{
|
||||
printf("Starting node %d\n", i);
|
||||
fflush(stdout);
|
||||
ssh_node(i, "echo [mysqld] > cluster_address.cnf", true);
|
||||
sprintf(str, "echo wsrep_cluster_address=gcomm://%s >> cluster_address.cnf", IP_private[0]);
|
||||
ssh_node(i, str, true);
|
||||
ssh_node(i, "cp cluster_address.cnf /etc/my.cnf.d/", true);
|
||||
|
||||
sprintf(&sys1[0], " --wsrep-cluster-address=gcomm://%s", IP_private[0]);
|
||||
if (this->verbose)
|
||||
{
|
||||
printf("%s\n", sys1);
|
||||
fflush(stdout);
|
||||
}
|
||||
local_result += start_node(i, sys1);
|
||||
fflush(stdout);
|
||||
ssh_node(i, true, "echo [mysqld] > cluster_address.cnf");
|
||||
ssh_node(i, true, "echo wsrep_cluster_address=gcomm://%s >> cluster_address.cnf", IP_private[0]);
|
||||
ssh_node(i, true, "cp cluster_address.cnf /etc/my.cnf.d/");
|
||||
sprintf(str, " --wsrep-cluster-address=gcomm://%s", IP_private[0]);
|
||||
local_result += start_node(i, str);
|
||||
}
|
||||
sleep(5);
|
||||
|
||||
@ -526,44 +511,30 @@ int Galera_nodes::start_galera()
|
||||
|
||||
int Mariadb_nodes::clean_iptables(int node)
|
||||
{
|
||||
char sys1[1024];
|
||||
int local_result = 0;
|
||||
|
||||
local_result += ssh_node(node, (char *) "echo \"#!/bin/bash\" > clean_iptables.sh", false);
|
||||
sprintf(sys1,
|
||||
"echo \"while [ \\\"\\$(iptables -n -L INPUT 1|grep '%d')\\\" != \\\"\\\" ]; do iptables -D INPUT 1; done\" >> clean_iptables.sh",
|
||||
port[node]);
|
||||
local_result += ssh_node(node, (char *) sys1, false);
|
||||
sprintf(sys1,
|
||||
"echo \"while [ \\\"\\$(ip6tables -n -L INPUT 1|grep '%d')\\\" != \\\"\\\" ]; do ip6tables -D INPUT 1; done\" >> clean_iptables.sh",
|
||||
port[node]);
|
||||
local_result += ssh_node(node, (char *) sys1, false);
|
||||
local_result += ssh_node(node, false, "echo \"#!/bin/bash\" > clean_iptables.sh");
|
||||
local_result += ssh_node(node, false,
|
||||
"echo \"while [ \\\"\\$(iptables -n -L INPUT 1|grep '%d')\\\" != \\\"\\\" ]; "
|
||||
"do iptables -D INPUT 1; done\" >> clean_iptables.sh",
|
||||
port[node]);
|
||||
local_result += ssh_node(node, false,
|
||||
"echo \"while [ \\\"\\$(ip6tables -n -L INPUT 1|grep '%d')\\\" != \\\"\\\" ]; "
|
||||
"do ip6tables -D INPUT 1; done\" >> clean_iptables.sh",
|
||||
port[node]);
|
||||
|
||||
local_result += ssh_node(node, (char *) "chmod a+x clean_iptables.sh", false);
|
||||
local_result += ssh_node(node, (char *) "./clean_iptables.sh", true);
|
||||
local_result += ssh_node(node, false, "chmod a+x clean_iptables.sh");
|
||||
local_result += ssh_node(node, true, "./clean_iptables.sh");
|
||||
return local_result;
|
||||
}
|
||||
|
||||
int Mariadb_nodes::block_node(int node)
|
||||
{
|
||||
char sys1[1024];
|
||||
int local_result = 0;
|
||||
local_result += clean_iptables(node);
|
||||
sprintf(&sys1[0], "iptables -I INPUT -p tcp --dport %d -j REJECT", port[node]);
|
||||
if (this->verbose)
|
||||
{
|
||||
printf("%s\n", sys1);
|
||||
fflush(stdout);
|
||||
}
|
||||
local_result += ssh_node(node, sys1, true);
|
||||
|
||||
sprintf(&sys1[0], "ip6tables -I INPUT -p tcp --dport %d -j REJECT", port[node]);
|
||||
if (this->verbose)
|
||||
{
|
||||
printf("%s\n", sys1);
|
||||
fflush(stdout);
|
||||
}
|
||||
local_result += ssh_node(node, sys1, true);
|
||||
local_result += ssh_node(node, true, "iptables -I INPUT -p tcp --dport %d -j REJECT", port[node]);
|
||||
local_result += ssh_node(node, true, "ip6tables -I INPUT -p tcp --dport %d -j REJECT", port[node]);
|
||||
|
||||
blocked[node] = true;
|
||||
return local_result;
|
||||
@ -571,29 +542,16 @@ int Mariadb_nodes::block_node(int node)
|
||||
|
||||
int Mariadb_nodes::unblock_node(int node)
|
||||
{
|
||||
char sys1[1024];
|
||||
int local_result = 0;
|
||||
local_result += clean_iptables(node);
|
||||
sprintf(&sys1[0], "iptables -I INPUT -p tcp --dport %d -j ACCEPT", port[node]);
|
||||
if (this->verbose)
|
||||
{
|
||||
printf("%s\n", sys1);
|
||||
fflush(stdout);
|
||||
}
|
||||
local_result += ssh_node(node, sys1, true);
|
||||
sprintf(&sys1[0], "ip6tables -I INPUT -p tcp --dport %d -j ACCEPT", port[node]);
|
||||
if (this->verbose)
|
||||
{
|
||||
printf("%s\n", sys1);
|
||||
fflush(stdout);
|
||||
}
|
||||
local_result += ssh_node(node, sys1, true);
|
||||
|
||||
local_result += ssh_node(node, true, "iptables -I INPUT -p tcp --dport %d -j ACCEPT", port[node]);
|
||||
local_result += ssh_node(node, true, "ip6tables -I INPUT -p tcp --dport %d -j ACCEPT", port[node]);
|
||||
|
||||
blocked[node] = false;
|
||||
return local_result;
|
||||
}
|
||||
|
||||
|
||||
int Mariadb_nodes::unblock_all_nodes()
|
||||
{
|
||||
int rval = 0;
|
||||
@ -610,7 +568,7 @@ int Mariadb_nodes::check_node_ssh(int node)
|
||||
printf("Checking node %d\n", node);
|
||||
fflush(stdout);
|
||||
|
||||
if (ssh_node(0, (char *) "ls > /dev/null", false) != 0)
|
||||
if (ssh_node(0, false, "ls > /dev/null") != 0)
|
||||
{
|
||||
printf("Node %d is not available\n", node);
|
||||
fflush(stdout);
|
||||
@ -846,7 +804,7 @@ int Galera_nodes::check_galera()
|
||||
{
|
||||
char str[1024] = "";
|
||||
|
||||
if (find_field(conn, (char *) "SHOW STATUS WHERE Variable_name='wsrep_cluster_size';", (char *) "Value",
|
||||
if (find_field(conn, "SHOW STATUS WHERE Variable_name='wsrep_cluster_size';", "Value",
|
||||
str) != 0)
|
||||
{
|
||||
printf("wsrep_cluster_size is not found in SHOW STATUS LIKE 'wsrep%%' results\n");
|
||||
@ -906,7 +864,7 @@ int Mariadb_nodes::get_server_id(int index)
|
||||
int id = -1;
|
||||
char str[1024];
|
||||
|
||||
if (find_field(this->nodes[index], "SELECT @@server_id", "@@server_id", (char*) str) == 0)
|
||||
if (find_field(this->nodes[index], "SELECT @@server_id", "@@server_id", (char*)str) == 0)
|
||||
{
|
||||
id = atoi(str);
|
||||
}
|
||||
@ -991,19 +949,55 @@ char * Mariadb_nodes::ssh_node_output(int node, const char *ssh, bool sudo, int
|
||||
return result;
|
||||
}
|
||||
|
||||
int Mariadb_nodes::ssh_node(int node, const char *ssh, bool sudo)
|
||||
int Mariadb_nodes::ssh_node(int node, bool sudo, const char *format, ...)
|
||||
{
|
||||
char sys[strlen(ssh) + 1024];
|
||||
generate_ssh_cmd(sys, node, ssh, sudo);
|
||||
int return_code = system(sys);
|
||||
if (WIFEXITED(return_code))
|
||||
va_list valist;
|
||||
|
||||
va_start(valist, format);
|
||||
int message_len = vsnprintf(NULL, 0, format, valist);
|
||||
va_end(valist);
|
||||
|
||||
if (message_len < 0)
|
||||
{
|
||||
return WEXITSTATUS(return_code);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *sys = (char*)malloc(message_len + 1);
|
||||
|
||||
va_start(valist, format);
|
||||
vsnprintf(sys, message_len + 1, format, valist);
|
||||
va_end(valist);
|
||||
|
||||
char *cmd = (char*)malloc(message_len + 1024);
|
||||
|
||||
if (strcmp(IP[node], "127.0.0.1") == 0)
|
||||
{
|
||||
sprintf(cmd, "bash");
|
||||
}
|
||||
else
|
||||
{
|
||||
return 256;
|
||||
sprintf(cmd,
|
||||
"ssh -i %s -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=quiet %s@%s > /dev/null",
|
||||
sshkey[node], access_user[node], IP[node]);
|
||||
}
|
||||
int rc = 1;
|
||||
FILE *in = popen(cmd, "w");
|
||||
|
||||
if (in)
|
||||
{
|
||||
if (sudo)
|
||||
{
|
||||
fprintf(in, "sudo su -\n");
|
||||
fprintf(in, "cd /home/%s\n", access_user[node]);
|
||||
}
|
||||
|
||||
fprintf(in, "%s\n", sys);
|
||||
rc = pclose(in);
|
||||
}
|
||||
|
||||
free(sys);
|
||||
free(cmd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int Mariadb_nodes::flush_hosts()
|
||||
@ -1028,7 +1022,8 @@ int Mariadb_nodes::flush_hosts()
|
||||
local_result++;
|
||||
}
|
||||
|
||||
if (mysql_query(nodes[i], "SELECT CONCAT('\\'', user, '\\'@\\'', host, '\\'') FROM mysql.user WHERE user = ''") == 0)
|
||||
if (mysql_query(nodes[i],
|
||||
"SELECT CONCAT('\\'', user, '\\'@\\'', host, '\\'') FROM mysql.user WHERE user = ''") == 0)
|
||||
{
|
||||
MYSQL_RES *res = mysql_store_result(nodes[i]);
|
||||
|
||||
@ -1048,7 +1043,7 @@ int Mariadb_nodes::flush_hosts()
|
||||
{
|
||||
printf("Detected anonymous users, dropping them.\n");
|
||||
|
||||
for (auto& s: users)
|
||||
for (auto& s : users)
|
||||
{
|
||||
std::string query = "DROP USER ";
|
||||
query += s;
|
||||
@ -1088,7 +1083,7 @@ int Mariadb_nodes::get_versions()
|
||||
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
if ((local_result += find_field(nodes[i], (char *) "SELECT @@version", (char *) "@@version", version[i])))
|
||||
if ((local_result += find_field(nodes[i], "SELECT @@version", "@@version", version[i])))
|
||||
{
|
||||
printf("Failed to get version: %s\n", mysql_error(nodes[i]));
|
||||
}
|
||||
@ -1099,11 +1094,11 @@ int Mariadb_nodes::get_versions()
|
||||
str[0] = 0;
|
||||
}
|
||||
strcpy(version_major[i], version_number[i]);
|
||||
if (strstr(version_major[i], "5.") == version_major[i])
|
||||
if (strstr(version_major[i], "5.") == version_major[i])
|
||||
{
|
||||
version_major[i][3] = 0;
|
||||
}
|
||||
if (strstr(version_major[i], "10.") == version_major[i])
|
||||
if (strstr(version_major[i], "10.") == version_major[i])
|
||||
{
|
||||
version_major[i][4] = 0;
|
||||
}
|
||||
@ -1152,7 +1147,7 @@ int Mariadb_nodes::truncate_mariadb_logs()
|
||||
for (int node = 0; node < N; node++)
|
||||
{
|
||||
char sys[1024];
|
||||
if (strcmp(IP[node], "127.0.0.1") !=0)
|
||||
if (strcmp(IP[node], "127.0.0.1") != 0)
|
||||
{
|
||||
sprintf(sys,
|
||||
"ssh -i %s -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=quiet %s@%s 'sudo truncate /var/lib/mysql/*.err --size 0;sudo rm -f /etc/my.cnf.d/binlog_enc*\' &",
|
||||
@ -1175,13 +1170,13 @@ int Mariadb_nodes::configure_ssl(bool require)
|
||||
printf("Node %d\n", i);
|
||||
stop_node(i);
|
||||
sprintf(str, "%s/ssl-cert", test_dir);
|
||||
local_result += copy_to_node(str, (char *) "~/", i);
|
||||
local_result += copy_to_node(str, "~/", i);
|
||||
sprintf(str, "%s/ssl.cnf", test_dir);
|
||||
local_result += copy_to_node(str, (char *) "~/", i);
|
||||
local_result += ssh_node(i, (char *) "cp ~/ssl.cnf /etc/my.cnf.d/", true);
|
||||
local_result += ssh_node(i, (char *) "cp -r ~/ssl-cert /etc/", true);
|
||||
local_result += ssh_node(i, (char *) "chown mysql:mysql -R /etc/ssl-cert", true);
|
||||
start_node(i, (char *) "");
|
||||
local_result += copy_to_node(str, "~/", i);
|
||||
local_result += ssh_node(i, true, "cp ~/ssl.cnf /etc/my.cnf.d/");
|
||||
local_result += ssh_node(i, true, "cp -r ~/ssl-cert /etc/");
|
||||
local_result += ssh_node(i, true, "chown mysql:mysql -R /etc/ssl-cert");
|
||||
start_node(i, "");
|
||||
}
|
||||
|
||||
if (require)
|
||||
@ -1189,14 +1184,9 @@ int Mariadb_nodes::configure_ssl(bool require)
|
||||
// Create DB user on first node
|
||||
printf("Set user to require ssl: %s\n", str);
|
||||
sprintf(str, "%s/create_user_ssl.sh", test_dir);
|
||||
copy_to_node(str, (char *) "~/", 0);
|
||||
|
||||
sprintf(str, "export node_user=\"%s\"; export node_password=\"%s\"; ./create_user_ssl.sh %s",
|
||||
user_name,
|
||||
password,
|
||||
socket_cmd[0]);
|
||||
printf("cmd: %s\n", str);
|
||||
ssh_node(0, str, false);
|
||||
copy_to_node(str, "~/", 0);
|
||||
ssh_node(0, false, "export node_user=\"%s\"; export node_password=\"%s\"; "
|
||||
"./create_user_ssl.sh %s", user_name, password, socket_cmd[0]);
|
||||
}
|
||||
|
||||
return local_result;
|
||||
@ -1210,14 +1200,14 @@ int Mariadb_nodes::disable_ssl()
|
||||
local_result += connect();
|
||||
sprintf(str, "DROP USER %s; grant all privileges on *.* to '%s'@'%%' identified by '%s';", user_name,
|
||||
user_name, password);
|
||||
local_result += execute_query(nodes[0], (char *) "");
|
||||
local_result += execute_query(nodes[0], "");
|
||||
close_connections();
|
||||
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
stop_node(i);
|
||||
local_result += ssh_node(i, (char *) "rm -f /etc/my.cnf.d/ssl.cnf", true);
|
||||
start_node(i, (char *) "");
|
||||
local_result += ssh_node(i, true, "rm -f /etc/my.cnf.d/ssl.cnf");
|
||||
start_node(i, "");
|
||||
}
|
||||
|
||||
return local_result;
|
||||
@ -1239,7 +1229,7 @@ int Mariadb_nodes::copy_to_node(const char* src, const char* dest, int i)
|
||||
else
|
||||
{
|
||||
sprintf(sys, "scp -q -r -i %s -o UserKnownHostsFile=/dev/null "
|
||||
"-o StrictHostKeyChecking=no -o LogLevel=quiet %s %s@%s:%s",
|
||||
"-o StrictHostKeyChecking=no -o LogLevel=quiet %s %s@%s:%s",
|
||||
sshkey[i], src, access_user[i], IP[i], dest);
|
||||
}
|
||||
if (verbose)
|
||||
@ -1250,7 +1240,6 @@ int Mariadb_nodes::copy_to_node(const char* src, const char* dest, int i)
|
||||
return system(sys);
|
||||
}
|
||||
|
||||
|
||||
int Mariadb_nodes::copy_from_node(const char* src, const char* dest, int i)
|
||||
{
|
||||
if (i >= N)
|
||||
@ -1266,7 +1255,7 @@ int Mariadb_nodes::copy_from_node(const char* src, const char* dest, int i)
|
||||
else
|
||||
{
|
||||
sprintf(sys, "scp -q -r -i %s -o UserKnownHostsFile=/dev/null "
|
||||
"-o StrictHostKeyChecking=no -o LogLevel=quiet %s@%s:%s %s",
|
||||
"-o StrictHostKeyChecking=no -o LogLevel=quiet %s@%s:%s %s",
|
||||
sshkey[i], access_user[i], IP[i], src, dest);
|
||||
}
|
||||
if (verbose)
|
||||
|
@ -291,7 +291,7 @@ public:
|
||||
* @param param command line parameters for DB server start command
|
||||
* @return 0 if success
|
||||
*/
|
||||
int start_node(int node, char * param);
|
||||
int start_node(int node, const char* param);
|
||||
|
||||
/**
|
||||
* @brief Check node via ssh and restart it if it is not resposible
|
||||
@ -354,11 +354,11 @@ public:
|
||||
/**
|
||||
* @brief executes shell command on the node using ssh
|
||||
* @param index number of the node (index)
|
||||
* @param ssh command to execute
|
||||
* @param sudo if true the command is executed with root privelegues
|
||||
* @return exit code of the coomand
|
||||
* @param ssh command to execute
|
||||
* @return exit code of the command
|
||||
*/
|
||||
int ssh_node(int node, const char *ssh, bool sudo);
|
||||
int ssh_node(int node, bool sudo, const char *ssh, ...);
|
||||
|
||||
/**
|
||||
* @brief Execute 'mysqladmin flush-hosts' on all nodes
|
||||
|
@ -34,12 +34,12 @@ int check_conf(TestConnections* Test, int blocked_node)
|
||||
Test->repl->connect();
|
||||
Test->connect_rwsplit();
|
||||
create_t1(Test->conn_rwsplit);
|
||||
global_result += insert_into_t1(Test->conn_rwsplit, 4);
|
||||
global_result += insert_into_t1(Test->conn_rwsplit, 3);
|
||||
|
||||
printf("Sleeping to let replication happen\n");
|
||||
fflush(stdout);
|
||||
Test->stop_timeout();
|
||||
sleep(30);
|
||||
sleep(15);
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
@ -47,13 +47,13 @@ int check_conf(TestConnections* Test, int blocked_node)
|
||||
{
|
||||
Test->tprintf("Checking data from node %d (%s)\n", i, Test->repl->IP[i]);
|
||||
Test->set_timeout(100);
|
||||
global_result += select_from_t1(Test->repl->nodes[i], 4);
|
||||
global_result += select_from_t1(Test->repl->nodes[i], 3);
|
||||
}
|
||||
}
|
||||
Test->set_timeout(100);
|
||||
printf("Checking data from rwsplit\n");
|
||||
fflush(stdout);
|
||||
global_result += select_from_t1(Test->conn_rwsplit, 4);
|
||||
global_result += select_from_t1(Test->conn_rwsplit, 3);
|
||||
global_result += execute_query(Test->conn_rwsplit, "DROP TABLE t1");
|
||||
|
||||
Test->repl->close_connections();
|
||||
@ -95,7 +95,7 @@ int main(int argc, char *argv[])
|
||||
Test->tprintf("Block slave\n");
|
||||
Test->repl->block_node(0);
|
||||
Test->stop_timeout();
|
||||
sleep(15);
|
||||
sleep(10);
|
||||
Test->set_timeout(120);
|
||||
Test->get_maxadmin_param((char *) "show server server1", (char *) "Status:", maxadmin_result);
|
||||
printf("node0 %s\n", maxadmin_result);
|
||||
@ -110,12 +110,12 @@ int main(int argc, char *argv[])
|
||||
Test->set_timeout(120);
|
||||
Test->tprintf("Unlock slave\n");
|
||||
Test->repl->unblock_node(0);
|
||||
sleep(15);
|
||||
sleep(10);
|
||||
|
||||
Test->set_timeout(120);
|
||||
Test->tprintf("Block master\n");
|
||||
Test->repl->block_node(1);
|
||||
sleep(15);
|
||||
sleep(10);
|
||||
Test->get_maxadmin_param((char *) "show server server2", (char *) "Status:", maxadmin_result);
|
||||
printf("node1 %s\n", maxadmin_result);
|
||||
if (strstr(maxadmin_result, "Down") == NULL )
|
||||
@ -129,21 +129,21 @@ int main(int argc, char *argv[])
|
||||
execute_query(Test->repl->nodes[0], (char *) "SET GLOBAL READ_ONLY=OFF");
|
||||
Test->repl->close_connections();
|
||||
|
||||
sleep(15);
|
||||
sleep(10);
|
||||
Test->set_timeout(120);
|
||||
Test->tprintf("Put some data and check\n");
|
||||
Test->add_result(check_conf(Test, 1), "configuration broken\n");
|
||||
|
||||
printf("Unlock slave\n");
|
||||
Test->repl->unblock_node(1);
|
||||
sleep(15);
|
||||
sleep(10);
|
||||
|
||||
Test->set_timeout(120);
|
||||
printf("Make node 2 slave\n");
|
||||
Test->repl->connect();
|
||||
execute_query(Test->repl->nodes[1], (char *) "SET GLOBAL READ_ONLY=ON");
|
||||
Test->repl->close_connections();
|
||||
sleep(15);
|
||||
sleep(10);
|
||||
|
||||
Test->set_timeout(120);
|
||||
printf("Put some data and check\n");
|
||||
|
@ -84,7 +84,7 @@ void check_group(TestConnections *Test, const char *server, const char *group)
|
||||
void change_master(TestConnections *Test, int slave, int master)
|
||||
{
|
||||
execute_query(Test->repl->nodes[slave], "CHANGE MASTER TO master_host='%s', master_port=3306, "
|
||||
"master_log_file='mar-bin.000001', master_log_pos=310, master_user='repl', master_password='repl';START SLAVE",
|
||||
"master_log_file='mar-bin.000001', master_log_pos=4, master_user='repl', master_password='repl';START SLAVE",
|
||||
Test->repl->IP[master], Test->repl->user_name, Test->repl->password);
|
||||
}
|
||||
|
||||
@ -92,6 +92,12 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections * Test = new TestConnections(argc, argv);
|
||||
|
||||
Test->tprintf("Checking initial state of the servers");
|
||||
check_status(Test, "server1", "Master, Running");
|
||||
check_status(Test, "server2", "Slave, Running");
|
||||
check_status(Test, "server3", "Slave, Running");
|
||||
check_status(Test, "server4", "Slave, Running");
|
||||
|
||||
Test->tprintf("Test 1 - Configure all servers into a multi-master ring with one slave");
|
||||
|
||||
Test->set_timeout(120);
|
||||
|
51
maxscale-system-test/mxs1457_ignore_deleted.cpp
Normal file
51
maxscale-system-test/mxs1457_ignore_deleted.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* MXS-1457: Deleted servers are not ignored when users are loaded
|
||||
*
|
||||
* Check that a corrupt and deleted server is not used to load users
|
||||
*/
|
||||
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections test(argc, argv);
|
||||
|
||||
test.set_timeout(60);
|
||||
test.repl->connect();
|
||||
execute_query(test.repl->nodes[0], "CREATE USER 'auth_test'@'%%' IDENTIFIED BY 'test'");
|
||||
execute_query(test.repl->nodes[0], "GRANT ALL ON *.* to 'auth_test'@'%%'");
|
||||
test.repl->sync_slaves();
|
||||
test.repl->close_connections();
|
||||
|
||||
/**
|
||||
* The monitor needs to be stopped before the slaves are stopped to prevent
|
||||
* it from detecting the broken replication.
|
||||
*/
|
||||
test.ssh_maxscale(true, "maxadmin shutdown monitor \"MySQL Monitor\"");
|
||||
// Stop slaves and drop the user on the master
|
||||
test.repl->stop_slaves();
|
||||
test.repl->connect();
|
||||
execute_query(test.repl->nodes[0], "DROP USER 'auth_test'@'%%'");
|
||||
test.repl->close_connections();
|
||||
|
||||
test.set_timeout(60);
|
||||
MYSQL* conn = open_conn_db(test.rwsplit_port, test.maxscale_ip(), "test", "auth_test", "test", false);
|
||||
test.add_result(mysql_errno(conn) == 0, "Connection with users from master should fail");
|
||||
mysql_close(conn);
|
||||
|
||||
test.ssh_maxscale(true, "maxadmin remove server server1 \"RW Split Router\"");
|
||||
conn = open_conn_db(test.rwsplit_port, test.maxscale_ip(), "test", "auth_test", "test", false);
|
||||
test.add_result(mysql_errno(conn), "Connection should be OK: %s", mysql_error(conn));
|
||||
test.try_query(conn, "SELECT 1");
|
||||
mysql_close(conn);
|
||||
|
||||
test.set_timeout(60);
|
||||
test.repl->connect();
|
||||
execute_query(test.repl->nodes[1], "START SLAVE");
|
||||
execute_query(test.repl->nodes[2], "START SLAVE");
|
||||
execute_query(test.repl->nodes[3], "START SLAVE");
|
||||
test.repl->sync_slaves();
|
||||
test.repl->close_connections();
|
||||
|
||||
return test.global_result;
|
||||
}
|
@ -25,7 +25,7 @@ int main(int argc, char *argv[])
|
||||
for (i = 0; i < Test->repl->N; i++)
|
||||
{
|
||||
Test->set_timeout(30);
|
||||
Test->repl->ssh_node(i, (char *) "touch /tmp/t1.csv", true);
|
||||
Test->repl->ssh_node(i, true, "touch /tmp/t1.csv");
|
||||
}
|
||||
|
||||
Test->add_result(create_t1(Test->conn_rwsplit), "Error creating t1\n");
|
||||
@ -42,7 +42,7 @@ int main(int argc, char *argv[])
|
||||
for (i = 0; i < Test->repl->N; i++)
|
||||
{
|
||||
Test->set_timeout(30);
|
||||
Test->repl->ssh_node(i, (char *) "rm -rf /tmp/t1.csv", true);
|
||||
Test->repl->ssh_node(i, true, "rm -rf /tmp/t1.csv");
|
||||
}
|
||||
|
||||
Test->set_timeout(30);
|
||||
|
@ -28,8 +28,8 @@ int main(int argc, char *argv[])
|
||||
sprintf(cmd, "%s/utf64.cnf", test_dir);
|
||||
for (int i = 0; i < Test->repl->N; i++)
|
||||
{
|
||||
Test->repl->copy_to_node(cmd, (char *) "./", i);
|
||||
Test->repl->ssh_node(i, (char *) "cp ./utf64.cnf /etc/my.cnf.d/", true);
|
||||
Test->repl->copy_to_node(cmd, "./", i);
|
||||
Test->repl->ssh_node(i, true, "cp ./utf64.cnf /etc/my.cnf.d/");
|
||||
}
|
||||
|
||||
Test->repl->start_replication();
|
||||
@ -52,7 +52,7 @@ int main(int argc, char *argv[])
|
||||
Test->tprintf("Restore backend configuration\n");
|
||||
for (int i = 0; i < Test->repl->N; i++)
|
||||
{
|
||||
Test->repl->ssh_node(i, (char *) "rm /etc/my.cnf.d/utf64.cnf", true);
|
||||
Test->repl->ssh_node(i, true, "rm /etc/my.cnf.d/utf64.cnf");
|
||||
}
|
||||
Test->repl->start_replication();
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <stdarg.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <execinfo.h>
|
||||
|
||||
#include "mariadb_func.h"
|
||||
#include "maxadmin_operations.h"
|
||||
@ -18,6 +20,28 @@ static std::string required_repl_version;
|
||||
static std::string required_galera_version;
|
||||
}
|
||||
|
||||
static int signal_set(int sig, void (*handler)(int))
|
||||
{
|
||||
struct sigaction sigact = {};
|
||||
sigact.sa_handler = handler;
|
||||
|
||||
do
|
||||
{
|
||||
errno = 0;
|
||||
sigaction(sig, &sigact, NULL);
|
||||
}
|
||||
while (errno == EINTR);
|
||||
}
|
||||
|
||||
void sigfatal_handler(int i)
|
||||
{
|
||||
void *addrs[128];
|
||||
int count = backtrace(addrs, 128);
|
||||
backtrace_symbols_fd(addrs, count, STDERR_FILENO);
|
||||
signal_set(i, SIG_DFL);
|
||||
raise(i);
|
||||
}
|
||||
|
||||
void TestConnections::check_nodes(bool value)
|
||||
{
|
||||
maxscale::check_nodes = value;
|
||||
@ -45,6 +69,14 @@ TestConnections::TestConnections(int argc, char *argv[]):
|
||||
no_galera(false), binlog_master_gtid(false), binlog_slave_gtid(false),
|
||||
no_vm_revert(true)
|
||||
{
|
||||
signal_set(SIGSEGV, sigfatal_handler);
|
||||
signal_set(SIGABRT, sigfatal_handler);
|
||||
signal_set(SIGFPE, sigfatal_handler);
|
||||
signal_set(SIGILL, sigfatal_handler);
|
||||
#ifdef SIGBUS
|
||||
signal_set(SIGBUS, sigfatal_handler);
|
||||
#endif
|
||||
|
||||
chdir(test_dir);
|
||||
gettimeofday(&start_time, NULL);
|
||||
ports[0] = rwsplit_port;
|
||||
@ -214,7 +246,7 @@ TestConnections::TestConnections(int argc, char *argv[]):
|
||||
|
||||
if (use_snapshots)
|
||||
{
|
||||
snapshot_reverted = revert_snapshot((char *) "clean");
|
||||
snapshot_reverted = revert_snapshot("clean");
|
||||
}
|
||||
|
||||
if (!snapshot_reverted && maxscale::check_nodes)
|
||||
@ -616,7 +648,7 @@ void TestConnections::process_template(const char *template_name, const char *de
|
||||
}
|
||||
|
||||
mdn[j]->connect();
|
||||
execute_query(mdn[j]->nodes[0], (char *) "CREATE DATABASE IF NOT EXISTS test");
|
||||
execute_query(mdn[j]->nodes[0], "CREATE DATABASE IF NOT EXISTS test");
|
||||
mdn[j]->close_connections();
|
||||
}
|
||||
|
||||
@ -630,7 +662,7 @@ void TestConnections::process_template(const char *template_name, const char *de
|
||||
{
|
||||
system("sed -i \"s/###repl51###/mysql51_replication=true/g\" maxscale.cnf");
|
||||
}
|
||||
copy_to_maxscale((char *) "maxscale.cnf", (char *) dest);
|
||||
copy_to_maxscale("maxscale.cnf", (char *) dest);
|
||||
}
|
||||
|
||||
int TestConnections::init_maxscale()
|
||||
@ -657,6 +689,7 @@ int TestConnections::init_maxscale()
|
||||
"%s"
|
||||
"iptables -I INPUT -p tcp --dport 4001 -j ACCEPT;"
|
||||
"rm -f %s/maxscale.log %s/maxscale1.log;"
|
||||
"rm -f /var/log/maxscale/.secrets;" // Needs to be explicitly deleted
|
||||
"rm -rf /tmp/core* /dev/shm/* /var/lib/maxscale/maxscale.cnf.d/ /var/lib/maxscale/*;"
|
||||
"%s",
|
||||
maxscale_access_homedir, maxscale_access_homedir, maxscale_access_homedir,
|
||||
@ -721,7 +754,7 @@ int TestConnections::stop_maxscale()
|
||||
return res;
|
||||
}
|
||||
|
||||
int TestConnections::copy_mariadb_logs(Mariadb_nodes * repl, char * prefix)
|
||||
int TestConnections::copy_mariadb_logs(Mariadb_nodes * repl, const char* prefix)
|
||||
{
|
||||
int local_result = 0;
|
||||
char * mariadb_log;
|
||||
@ -736,7 +769,7 @@ int TestConnections::copy_mariadb_logs(Mariadb_nodes * repl, char * prefix)
|
||||
{
|
||||
if (strcmp(repl->IP[i], "127.0.0.1") != 0) // Do not copy MariaDB logs in case of local backend
|
||||
{
|
||||
mariadb_log = repl->ssh_node_output(i, (char *) "cat /var/lib/mysql/*.err", true, &exit_code);
|
||||
mariadb_log = repl->ssh_node_output(i, "cat /var/lib/mysql/*.err", true, &exit_code);
|
||||
sprintf(str, "LOGS/%s/%s%d_mariadb_log", test_name, prefix, i);
|
||||
f = fopen(str, "w");
|
||||
if (f != NULL)
|
||||
@ -762,8 +795,8 @@ int TestConnections::copy_all_logs()
|
||||
|
||||
if (!no_backend_log_copy)
|
||||
{
|
||||
copy_mariadb_logs(repl, (char *) "node");
|
||||
copy_mariadb_logs(galera, (char *) "galera");
|
||||
copy_mariadb_logs(repl, "node");
|
||||
copy_mariadb_logs(galera, "galera");
|
||||
}
|
||||
|
||||
sprintf(str, "%s/copy_logs.sh %s", test_dir, test_name);
|
||||
@ -867,9 +900,9 @@ int TestConnections::start_binlog()
|
||||
repl->stop_nodes();
|
||||
|
||||
binlog = open_conn_no_db(binlog_port, maxscale_IP, repl->user_name, repl->password, ssl);
|
||||
execute_query(binlog, (char *) "stop slave");
|
||||
execute_query(binlog, (char *) "reset slave all");
|
||||
execute_query(binlog, (char *) "reset master");
|
||||
execute_query(binlog, "stop slave");
|
||||
execute_query(binlog, "reset slave all");
|
||||
execute_query(binlog, "reset master");
|
||||
mysql_close(binlog);
|
||||
|
||||
tprintf("Stopping maxscale\n");
|
||||
@ -994,13 +1027,12 @@ int TestConnections::start_binlog()
|
||||
tprintf("Maxscale binlog master pos : %s\n", log_pos);
|
||||
fflush(stdout);
|
||||
|
||||
tprintf("Setup all backend nodes except first one to be slaves of binlog Maxscale node\n");
|
||||
fflush(stdout);
|
||||
for (i = 2; i < repl->N; i++)
|
||||
{
|
||||
try_query(repl->nodes[i], (char *) "stop slave");
|
||||
repl->set_slave(repl->nodes[i], maxscale_IP, binlog_port, log_file, log_pos);
|
||||
}
|
||||
tprintf("Setup all backend nodes except first one to be slaves of binlog Maxscale node\n");
|
||||
fflush(stdout);
|
||||
for (i = 2; i < repl->N; i++)
|
||||
{
|
||||
try_query(repl->nodes[i], "stop slave;");
|
||||
repl->set_slave(repl->nodes[i], maxscale_IP, binlog_port, log_file, log_pos);
|
||||
}
|
||||
|
||||
repl->close_connections();
|
||||
@ -1069,23 +1101,23 @@ int TestConnections::start_mm()
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
tprintf("Starting back node %d\n", i);
|
||||
global_result += repl->start_node(i, (char *) "");
|
||||
global_result += repl->start_node(i, "");
|
||||
}
|
||||
|
||||
repl->connect();
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
execute_query(repl->nodes[i], (char *) "stop slave");
|
||||
execute_query(repl->nodes[i], (char *) "reset master");
|
||||
execute_query(repl->nodes[i], "stop slave");
|
||||
execute_query(repl->nodes[i], "reset master");
|
||||
}
|
||||
|
||||
execute_query(repl->nodes[0], (char *) "SET GLOBAL READ_ONLY=ON");
|
||||
execute_query(repl->nodes[0], "SET GLOBAL READ_ONLY=ON");
|
||||
|
||||
find_field(repl->nodes[0], (char *) "show master status", (char *) "File", log_file1);
|
||||
find_field(repl->nodes[0], (char *) "show master status", (char *) "Position", log_pos1);
|
||||
find_field(repl->nodes[0], "show master status", "File", log_file1);
|
||||
find_field(repl->nodes[0], "show master status", "Position", log_pos1);
|
||||
|
||||
find_field(repl->nodes[1], (char *) "show master status", (char *) "File", log_file2);
|
||||
find_field(repl->nodes[1], (char *) "show master status", (char *) "Position", log_pos2);
|
||||
find_field(repl->nodes[1], "show master status", "File", log_file2);
|
||||
find_field(repl->nodes[1], "show master status", "Position", log_pos2);
|
||||
|
||||
repl->set_slave(repl->nodes[0], repl->IP[1], repl->port[1], log_file2, log_pos2);
|
||||
repl->set_slave(repl->nodes[1], repl->IP[0], repl->port[0], log_file1, log_pos1);
|
||||
@ -1113,11 +1145,11 @@ void TestConnections::check_log_err(const char * err_msg, bool expected)
|
||||
set_timeout(50);
|
||||
|
||||
tprintf("Reading maxscale.log\n");
|
||||
if ( ( read_log((char *) "maxscale.log", &err_log_content) != 0) || (strlen(err_log_content) < 2) )
|
||||
if ( ( read_log("maxscale.log", &err_log_content) != 0) || (strlen(err_log_content) < 2) )
|
||||
{
|
||||
tprintf("Reading maxscale1.log\n");
|
||||
free(err_log_content);
|
||||
if (read_log((char *) "maxscale1.log", &err_log_content) != 0)
|
||||
if (read_log("maxscale1.log", &err_log_content) != 0)
|
||||
{
|
||||
add_result(1, "Error reading log\n");
|
||||
}
|
||||
@ -1160,7 +1192,7 @@ int TestConnections::find_connected_slave(int * global_result)
|
||||
repl->connect();
|
||||
for (int i = 0; i < repl->N; i++)
|
||||
{
|
||||
conn_num = get_conn_num(repl->nodes[i], maxscale_ip(), maxscale_hostname, (char *) "test");
|
||||
conn_num = get_conn_num(repl->nodes[i], maxscale_ip(), maxscale_hostname, "test");
|
||||
tprintf("connections to %d: %u\n", i, conn_num);
|
||||
if ((i == 0) && (conn_num != 1))
|
||||
{
|
||||
@ -1191,7 +1223,7 @@ int TestConnections::find_connected_slave1()
|
||||
repl->connect();
|
||||
for (int i = 0; i < repl->N; i++)
|
||||
{
|
||||
conn_num = get_conn_num(repl->nodes[i], maxscale_ip(), maxscale_hostname, (char *) "test");
|
||||
conn_num = get_conn_num(repl->nodes[i], maxscale_ip(), maxscale_hostname, "test");
|
||||
tprintf("connections to %d: %u\n", i, conn_num);
|
||||
all_conn += conn_num;
|
||||
if ((i != 0) && (conn_num != 0))
|
||||
@ -1240,13 +1272,13 @@ int TestConnections::check_maxscale_alive()
|
||||
tprintf("Trying simple query against all sevices\n");
|
||||
tprintf("RWSplit \n");
|
||||
set_timeout(10);
|
||||
try_query(conn_rwsplit, (char *) "show databases;");
|
||||
try_query(conn_rwsplit, "show databases;");
|
||||
tprintf("ReadConn Master \n");
|
||||
set_timeout(10);
|
||||
try_query(conn_master, (char *) "show databases;");
|
||||
try_query(conn_master, "show databases;");
|
||||
tprintf("ReadConn Slave \n");
|
||||
set_timeout(10);
|
||||
try_query(conn_slave, (char *) "show databases;");
|
||||
try_query(conn_slave, "show databases;");
|
||||
set_timeout(10);
|
||||
close_maxscale_connections() ;
|
||||
add_result(global_result - gr, "Maxscale is not alive\n");
|
||||
@ -1434,7 +1466,7 @@ int TestConnections::copy_to_maxscale(const char* src, const char* dest)
|
||||
{
|
||||
|
||||
sprintf(sys, "scp -q -i %s -o UserKnownHostsFile=/dev/null "
|
||||
"-o StrictHostKeyChecking=no -o LogLevel=quiet %s %s@%s:%s",
|
||||
"-o StrictHostKeyChecking=no -o LogLevel=quiet %s %s@%s:%s",
|
||||
maxscale_keyfile, src, maxscale_access_user, maxscale_IP, dest);
|
||||
}
|
||||
return system(sys);
|
||||
@ -1452,7 +1484,7 @@ int TestConnections::copy_from_maxscale(char* src, char* dest)
|
||||
else
|
||||
{
|
||||
sprintf(sys, "scp -i %s -o UserKnownHostsFile=/dev/null "
|
||||
"-o StrictHostKeyChecking=no -o LogLevel=quiet %s@%s:%s %s",
|
||||
"-o StrictHostKeyChecking=no -o LogLevel=quiet %s@%s:%s %s",
|
||||
maxscale_keyfile, maxscale_access_user, maxscale_IP, src, dest);
|
||||
}
|
||||
return system(sys);
|
||||
@ -1619,12 +1651,12 @@ int TestConnections::get_client_ip(char * ip)
|
||||
unsigned int conn_num = 0;
|
||||
|
||||
connect_rwsplit();
|
||||
if (execute_query(conn_rwsplit, (char *) "CREATE DATABASE IF NOT EXISTS db_to_check_client_ip") != 0 )
|
||||
if (execute_query(conn_rwsplit, "CREATE DATABASE IF NOT EXISTS db_to_check_clent_ip") != 0 )
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
close_rwsplit();
|
||||
conn = open_conn_db(rwsplit_port, maxscale_IP, (char *) "db_to_check_client_ip", maxscale_user,
|
||||
conn = open_conn_db(rwsplit_port, maxscale_IP, "db_to_check_clent_ip", maxscale_user,
|
||||
maxscale_password, ssl);
|
||||
|
||||
if (conn != NULL)
|
||||
@ -1888,7 +1920,8 @@ int TestConnections::try_query(MYSQL *conn, const char *format, ...)
|
||||
va_end(valist);
|
||||
|
||||
int res = execute_query1(conn, sql, false);
|
||||
add_result(res, "Query '%.*s%s' failed!\n", message_len < 100 ? message_len : 100, sql, message_len < 100 ? "" : "...");
|
||||
add_result(res, "Query '%.*s%s' failed!\n", message_len < 100 ? message_len : 100, sql,
|
||||
message_len < 100 ? "" : "...");
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -1909,7 +1942,7 @@ int TestConnections::find_master_maxadmin(Mariadb_nodes * nodes)
|
||||
char show_server[256];
|
||||
char res[256];
|
||||
sprintf(show_server, "show server server%d", i + 1);
|
||||
get_maxadmin_param(show_server, (char *) "Status", res);
|
||||
get_maxadmin_param(show_server, "Status", res);
|
||||
|
||||
if (strstr(res, "Master"))
|
||||
{
|
||||
@ -1937,7 +1970,7 @@ int TestConnections::find_slave_maxadmin(Mariadb_nodes * nodes)
|
||||
char show_server[256];
|
||||
char res[256];
|
||||
sprintf(show_server, "show server server%d", i + 1);
|
||||
get_maxadmin_param(show_server, (char *) "Status", res);
|
||||
get_maxadmin_param(show_server, "Status", res);
|
||||
|
||||
if (strstr(res, "Slave"))
|
||||
{
|
||||
@ -1992,14 +2025,9 @@ int TestConnections::check_maxadmin_param(const char *command, const char *param
|
||||
return rval;
|
||||
}
|
||||
|
||||
int TestConnections::get_maxadmin_param(const char *command, const char *param, char *result)
|
||||
int TestConnections::get_maxadmin_param(const char* command, const char* param, char* result)
|
||||
{
|
||||
char * buf;
|
||||
|
||||
buf = ssh_maxscale_output(true, "maxadmin %s", command);
|
||||
|
||||
//printf("%s\n", buf);
|
||||
|
||||
char* buf = ssh_maxscale_output(true, "maxadmin %s", command);
|
||||
char *x = strstr(buf, param);
|
||||
|
||||
if (x == NULL)
|
||||
@ -2039,7 +2067,7 @@ int TestConnections::list_dirs()
|
||||
for (int i = 0; i < repl->N; i++)
|
||||
{
|
||||
tprintf("ls on node %d\n", i);
|
||||
repl->ssh_node(i, (char *) "ls -la /var/lib/mysql", true);
|
||||
repl->ssh_node(i, true, "ls -la /var/lib/mysql");
|
||||
fflush(stdout);
|
||||
}
|
||||
tprintf("ls maxscale \n");
|
||||
@ -2092,7 +2120,7 @@ int TestConnections::take_snapshot(char * snapshot_name)
|
||||
return system(str);
|
||||
}
|
||||
|
||||
int TestConnections::revert_snapshot(char * snapshot_name)
|
||||
int TestConnections::revert_snapshot(const char* snapshot_name)
|
||||
{
|
||||
char str[4096];
|
||||
sprintf(str, "%s %s", revert_snapshot_command, snapshot_name);
|
||||
|
@ -220,7 +220,7 @@ public:
|
||||
* @param prefix file name prefix
|
||||
* @return 0 if success
|
||||
*/
|
||||
int copy_mariadb_logs(Mariadb_nodes *repl, char * prefix);
|
||||
int copy_mariadb_logs(Mariadb_nodes *repl, const char* prefix);
|
||||
|
||||
/**
|
||||
* @brief no_backend_log_copy if true logs from backends are not copied (needed if case of Aurora RDS backend or similar)
|
||||
@ -700,7 +700,7 @@ public:
|
||||
* @param snapshot_name name of snapshot to revert
|
||||
* @return 0 in case of success or mdbci error code in case of error
|
||||
*/
|
||||
int revert_snapshot(char * snapshot_name);
|
||||
int revert_snapshot(const char* snapshot_name);
|
||||
|
||||
/**
|
||||
* @brief Test a bad configuration
|
||||
|
@ -110,6 +110,8 @@ const char CN_PORT[] = "port";
|
||||
const char CN_PROTOCOL[] = "protocol";
|
||||
const char CN_QUERY_CLASSIFIER[] = "query_classifier";
|
||||
const char CN_QUERY_CLASSIFIER_ARGS[] = "query_classifier_args";
|
||||
const char CN_QUERY_RETRIES[] = "query_retries";
|
||||
const char CN_QUERY_RETRY_TIMEOUT[] = "query_retry_timeout";
|
||||
const char CN_RELATIONSHIPS[] = "relationships";
|
||||
const char CN_LINKS[] = "links";
|
||||
const char CN_REQUIRED[] = "required";
|
||||
@ -1473,6 +1475,34 @@ handle_global_item(const char *name, const char *value)
|
||||
"'ORACLE'. Using 'DEFAULT' as default.", value, name);
|
||||
}
|
||||
}
|
||||
else if (strcmp(name, CN_QUERY_RETRIES) == 0)
|
||||
{
|
||||
char* endptr;
|
||||
int intval = strtol(value, &endptr, 0);
|
||||
if (*endptr == '\0' && intval >= 0)
|
||||
{
|
||||
gateway.query_retries = intval;
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Invalid timeout value for '%s': %s", CN_QUERY_RETRIES, value);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (strcmp(name, CN_QUERY_RETRY_TIMEOUT) == 0)
|
||||
{
|
||||
char* endptr;
|
||||
int intval = strtol(value, &endptr, 0);
|
||||
if (*endptr == '\0' && intval > 0)
|
||||
{
|
||||
gateway.query_retries = intval;
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Invalid timeout value for '%s': %s", CN_QUERY_RETRY_TIMEOUT, value);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (strcmp(name, CN_LOG_THROTTLING) == 0)
|
||||
{
|
||||
if (*value == 0)
|
||||
@ -1761,6 +1791,8 @@ global_defaults()
|
||||
gateway.admin_ssl_key[0] = '\0';
|
||||
gateway.admin_ssl_cert[0] = '\0';
|
||||
gateway.admin_ssl_ca_cert[0] = '\0';
|
||||
gateway.query_retries = DEFAULT_QUERY_RETRIES;
|
||||
gateway.query_retry_timeout = DEFAULT_QUERY_RETRY_TIMEOUT;
|
||||
|
||||
gateway.thread_stack_size = 0;
|
||||
pthread_attr_t attr;
|
||||
|
@ -383,33 +383,33 @@ sigfatal_handler(int i)
|
||||
}
|
||||
fatal_handling = 1;
|
||||
MXS_CONFIG* cnf = config_get_global_options();
|
||||
fprintf(stderr, "\n\nMaxScale " MAXSCALE_VERSION " received fatal signal %d\n", i);
|
||||
fprintf(stderr, "Fatal: MaxScale " MAXSCALE_VERSION " received fatal signal %d. "
|
||||
"Attempting backtrace.\n", i);
|
||||
fprintf(stderr, "Commit ID: %s System name: %s Release string: %s\n\n",
|
||||
maxscale_commit, cnf->sysname, cnf->release_string);
|
||||
#ifdef HAVE_GLIBC
|
||||
|
||||
MXS_ALERT("Fatal: MaxScale " MAXSCALE_VERSION " received fatal signal %d. Attempting backtrace.", i);
|
||||
void *addrs[128];
|
||||
int count = backtrace(addrs, 128);
|
||||
|
||||
// First print the stack trace to stderr as malloc is likely broken
|
||||
backtrace_symbols_fd(addrs, count, STDERR_FILENO);
|
||||
|
||||
MXS_ALERT("Fatal: MaxScale " MAXSCALE_VERSION " received fatal signal %d. "
|
||||
"Attempting backtrace.", i);
|
||||
MXS_ALERT("Commit ID: %s System name: %s "
|
||||
"Release string: %s",
|
||||
maxscale_commit, cnf->sysname, cnf->release_string);
|
||||
// Then see if we can log them
|
||||
char** symbols = backtrace_symbols(addrs, count);
|
||||
|
||||
#ifdef HAVE_GLIBC
|
||||
if (symbols)
|
||||
{
|
||||
void *addrs[128];
|
||||
int count = backtrace(addrs, 128);
|
||||
char** symbols = backtrace_symbols(addrs, count);
|
||||
|
||||
if (symbols)
|
||||
for (int n = 0; n < count; n++)
|
||||
{
|
||||
for (int n = 0; n < count; n++)
|
||||
{
|
||||
MXS_ALERT(" %s\n", symbols[n]);
|
||||
}
|
||||
MXS_FREE(symbols);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "\nresolving symbols to error log failed, writing call trace to stderr:\n");
|
||||
backtrace_symbols_fd(addrs, count, fileno(stderr));
|
||||
MXS_ALERT(" %s\n", symbols[n]);
|
||||
}
|
||||
MXS_FREE(symbols);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -421,8 +421,6 @@ sigfatal_handler(int i)
|
||||
raise(i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @node Wraps sigaction calls
|
||||
*
|
||||
|
@ -23,9 +23,11 @@
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
#define DEFAULT_NBPOLLS 3 /**< Default number of non block polls before we block */
|
||||
#define DEFAULT_POLLSLEEP 1000 /**< Default poll wait time (milliseconds) */
|
||||
#define DEFAULT_NTHREADS 1 /**< Default number of polling threads */
|
||||
#define DEFAULT_NBPOLLS 3 /**< Default number of non block polls before we block */
|
||||
#define DEFAULT_POLLSLEEP 1000 /**< Default poll wait time (milliseconds) */
|
||||
#define DEFAULT_NTHREADS 1 /**< Default number of polling threads */
|
||||
#define DEFAULT_QUERY_RETRIES 0 /**< Number of retries for interrupted queries */
|
||||
#define DEFAULT_QUERY_RETRY_TIMEOUT 5 /**< Timeout for query retries */
|
||||
|
||||
/**
|
||||
* Maximum length for configuration parameter value.
|
||||
|
@ -812,7 +812,7 @@ bool check_monitor_permissions(MXS_MONITOR* monitor, const char* query)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (mysql_query(mondb->con, query) != 0)
|
||||
else if (mxs_mysql_query(mondb->con, query) != 0)
|
||||
{
|
||||
switch (mysql_errno(mondb->con))
|
||||
{
|
||||
|
@ -21,12 +21,15 @@
|
||||
*/
|
||||
|
||||
#include <maxscale/mysql_utils.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <errmsg.h>
|
||||
|
||||
#include <maxscale/alloc.h>
|
||||
#include <maxscale/log_manager.h>
|
||||
#include <maxscale/debug.h>
|
||||
#include <maxscale/config.h>
|
||||
#include <maxscale/debug.h>
|
||||
#include <maxscale/log_manager.h>
|
||||
|
||||
/**
|
||||
* @brief Calculate the length of a length-encoded integer in bytes
|
||||
@ -147,16 +150,6 @@ char* mxs_lestr_consume(uint8_t** c, size_t *size)
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a connection to a MySQL database engine. If necessary, initializes SSL.
|
||||
*
|
||||
* @param con A valid MYSQL structure.
|
||||
* @param server The server on which the MySQL engine is running.
|
||||
* @param user The MySQL login ID.
|
||||
* @param passwd The password for the user.
|
||||
*/
|
||||
MYSQL *mxs_mysql_real_connect(MYSQL *con, SERVER *server, const char *user, const char *passwd)
|
||||
{
|
||||
SSL_LISTENER *listener = server->server_ssl;
|
||||
@ -183,6 +176,40 @@ MYSQL *mxs_mysql_real_connect(MYSQL *con, SERVER *server, const char *user, cons
|
||||
return mysql;
|
||||
}
|
||||
|
||||
static bool is_connection_error(int errcode)
|
||||
{
|
||||
switch (errcode)
|
||||
{
|
||||
case CR_SOCKET_CREATE_ERROR:
|
||||
case CR_CONNECTION_ERROR:
|
||||
case CR_CONN_HOST_ERROR:
|
||||
case CR_IPSOCK_ERROR:
|
||||
case CR_SERVER_GONE_ERROR:
|
||||
case CR_TCP_CONNECTION:
|
||||
case CR_SERVER_LOST:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int mxs_mysql_query(MYSQL* conn, const char* query)
|
||||
{
|
||||
MXS_CONFIG* cnf = config_get_global_options();
|
||||
time_t start = time(NULL);
|
||||
int rc = mysql_query(conn, query);
|
||||
|
||||
for (int n = 0; rc != 0 && n < cnf->query_retries &&
|
||||
is_connection_error(mysql_errno(conn)) &&
|
||||
time(NULL) - start < cnf->query_retry_timeout; n++)
|
||||
{
|
||||
rc = mysql_query(conn, query);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool mxs_mysql_trim_quotes(char *s)
|
||||
{
|
||||
bool dequoted = true;
|
||||
|
@ -605,13 +605,21 @@ int gssapi_auth_load_users(SERV_LISTENER *listener)
|
||||
|
||||
if (serviceGetUser(listener->service, &user, &pw) && (pw = decrypt_password(pw)))
|
||||
{
|
||||
bool no_active_servers = true;
|
||||
|
||||
for (SERVER_REF *servers = listener->service->dbref; servers; servers = servers->next)
|
||||
{
|
||||
if (!SERVER_REF_IS_ACTIVE(servers) || !SERVER_IS_ACTIVE(servers->server))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
no_active_servers = false;
|
||||
MYSQL *mysql = mysql_init(NULL);
|
||||
|
||||
if (mxs_mysql_real_connect(mysql, servers->server, user, pw))
|
||||
{
|
||||
if (mysql_query(mysql, gssapi_users_query))
|
||||
if (mxs_mysql_query(mysql, gssapi_users_query))
|
||||
{
|
||||
MXS_ERROR("Failed to query server '%s' for GSSAPI users: %s",
|
||||
servers->server->unique_name, mysql_error(mysql));
|
||||
@ -649,6 +657,11 @@ int gssapi_auth_load_users(SERV_LISTENER *listener)
|
||||
}
|
||||
|
||||
MXS_FREE(pw);
|
||||
|
||||
if (no_active_servers)
|
||||
{
|
||||
rval = MXS_AUTH_LOADUSERS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
|
@ -542,7 +542,7 @@ static bool check_server_permissions(SERVICE *service, SERVER* server,
|
||||
bool rval = true;
|
||||
sprintf(query, template, query_pw);
|
||||
|
||||
if (mysql_query(mysql, query) != 0)
|
||||
if (mxs_mysql_query(mysql, query) != 0)
|
||||
{
|
||||
if (mysql_errno(mysql) == ER_TABLEACCESS_DENIED_ERROR)
|
||||
{
|
||||
@ -572,7 +572,7 @@ static bool check_server_permissions(SERVICE *service, SERVER* server,
|
||||
}
|
||||
}
|
||||
|
||||
if (mysql_query(mysql, "SELECT user, host, db FROM mysql.db limit 1") != 0)
|
||||
if (mxs_mysql_query(mysql, "SELECT user, host, db FROM mysql.db limit 1") != 0)
|
||||
{
|
||||
if (mysql_errno(mysql) == ER_TABLEACCESS_DENIED_ERROR)
|
||||
{
|
||||
@ -600,7 +600,7 @@ static bool check_server_permissions(SERVICE *service, SERVER* server,
|
||||
}
|
||||
}
|
||||
|
||||
if (mysql_query(mysql, "SELECT user, host, db FROM mysql.tables_priv limit 1") != 0)
|
||||
if (mxs_mysql_query(mysql, "SELECT user, host, db FROM mysql.tables_priv limit 1") != 0)
|
||||
{
|
||||
if (mysql_errno(mysql) == ER_TABLEACCESS_DENIED_ERROR)
|
||||
{
|
||||
@ -747,7 +747,7 @@ int get_users_from_server(MYSQL *con, SERVER_REF *server_ref, SERVICE *service,
|
||||
|
||||
if (query)
|
||||
{
|
||||
if (mysql_query(con, query) == 0)
|
||||
if (mxs_mysql_query(con, query) == 0)
|
||||
{
|
||||
MYSQL_RES *result = mysql_store_result(con);
|
||||
|
||||
@ -801,7 +801,7 @@ int get_users_from_server(MYSQL *con, SERVER_REF *server_ref, SERVICE *service,
|
||||
}
|
||||
|
||||
/** Load the list of databases */
|
||||
if (mysql_query(con, "SHOW DATABASES") == 0)
|
||||
if (mxs_mysql_query(con, "SHOW DATABASES") == 0)
|
||||
{
|
||||
MYSQL_RES *result = mysql_store_result(con);
|
||||
if (result)
|
||||
@ -855,15 +855,18 @@ static int get_users(SERV_LISTENER *listener, bool skip_local)
|
||||
|
||||
SERVER_REF *server = service->dbref;
|
||||
int total_users = -1;
|
||||
bool no_active_servers = true;
|
||||
|
||||
for (server = service->dbref; !service->svc_do_shutdown && server; server = server->next)
|
||||
{
|
||||
if (skip_local && server_is_mxs_service(server->server))
|
||||
if (!SERVER_REF_IS_ACTIVE(server) || !SERVER_IS_ACTIVE(server->server) ||
|
||||
(skip_local && server_is_mxs_service(server->server)))
|
||||
{
|
||||
total_users = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
no_active_servers = false;
|
||||
|
||||
MYSQL *con = gw_mysql_init();
|
||||
if (con)
|
||||
{
|
||||
@ -897,7 +900,12 @@ static int get_users(SERV_LISTENER *listener, bool skip_local)
|
||||
|
||||
MXS_FREE(dpwd);
|
||||
|
||||
if (server == NULL && total_users == -1)
|
||||
if (no_active_servers)
|
||||
{
|
||||
// This service has no servers or all servers are local MaxScale services
|
||||
total_users = 0;
|
||||
}
|
||||
else if (server == NULL && 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.", service->name);
|
||||
|
@ -592,11 +592,15 @@ static int mysql_auth_load_users(SERV_LISTENER *port)
|
||||
}
|
||||
|
||||
int loaded = replace_mysql_users(port, skip_local);
|
||||
bool injected = false;
|
||||
|
||||
if (loaded < 0)
|
||||
if (loaded <= 0)
|
||||
{
|
||||
MXS_ERROR("[%s] Unable to load users for listener %s listening at [%s]:%d.", service->name,
|
||||
port->name, port->address ? port->address : "::", port->port);
|
||||
if (loaded < 0)
|
||||
{
|
||||
MXS_ERROR("[%s] Unable to load users for listener %s listening at [%s]:%d.", service->name,
|
||||
port->name, port->address ? port->address : "::", port->port);
|
||||
}
|
||||
|
||||
if (instance->inject_service_user)
|
||||
{
|
||||
@ -606,10 +610,20 @@ static int mysql_auth_load_users(SERV_LISTENER *port)
|
||||
{
|
||||
MXS_ERROR("[%s] Failed to inject service user.", port->service->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
injected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loaded == 0 && !skip_local)
|
||||
if (injected)
|
||||
{
|
||||
MXS_NOTICE("[%s] No users were loaded but 'inject_service_user' is enabled. "
|
||||
"Enabling service credentials for authentication until "
|
||||
"database users have been successfully loaded.", service->name);
|
||||
}
|
||||
else if (loaded == 0 && !skip_local)
|
||||
{
|
||||
MXS_WARNING("[%s]: failed to load any user information. Authentication"
|
||||
" will probably fail as a result.", service->name);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <mysqld_error.h>
|
||||
#include <maxscale/alloc.h>
|
||||
#include <maxscale/debug.h>
|
||||
#include <maxscale/mysql_utils.h>
|
||||
|
||||
typedef struct aurora_monitor
|
||||
{
|
||||
@ -60,9 +61,9 @@ void update_server_status(MXS_MONITOR *monitor, MXS_MONITOR_SERVERS *database)
|
||||
MYSQL_RES *result;
|
||||
|
||||
/** Connection is OK, query for replica status */
|
||||
if (mysql_query(database->con, "SELECT @@aurora_server_id, server_id FROM "
|
||||
"information_schema.replica_host_status "
|
||||
"WHERE session_id = 'MASTER_SESSION_ID'") == 0 &&
|
||||
if (mxs_mysql_query(database->con, "SELECT @@aurora_server_id, server_id FROM "
|
||||
"information_schema.replica_host_status "
|
||||
"WHERE session_id = 'MASTER_SESSION_ID'") == 0 &&
|
||||
(result = mysql_store_result(database->con)))
|
||||
{
|
||||
ss_dassert(mysql_field_count(database->con) == 2);
|
||||
|
@ -324,7 +324,7 @@ monitorDatabase(MXS_MONITOR *mon, MXS_MONITOR_SERVERS *database)
|
||||
" 'wsrep_local_index',"
|
||||
" 'wsrep_local_state')";
|
||||
|
||||
if (mysql_query(database->con, cluster_member) == 0
|
||||
if (mxs_mysql_query(database->con, cluster_member) == 0
|
||||
&& (result = mysql_store_result(database->con)) != NULL)
|
||||
{
|
||||
if (mysql_field_count(database->con) < 2)
|
||||
@ -373,7 +373,7 @@ monitorDatabase(MXS_MONITOR *mon, MXS_MONITOR_SERVERS *database)
|
||||
/* Check if the node is a donor and is using xtrabackup, in this case it can stay alive */
|
||||
else if (strcmp(row[1], "2") == 0 && handle->availableWhenDonor == 1)
|
||||
{
|
||||
if (mysql_query(database->con, "SHOW VARIABLES LIKE 'wsrep_sst_method'") == 0
|
||||
if (mxs_mysql_query(database->con, "SHOW VARIABLES LIKE 'wsrep_sst_method'") == 0
|
||||
&& (result2 = mysql_store_result(database->con)) != NULL)
|
||||
{
|
||||
if (mysql_field_count(database->con) < 2)
|
||||
@ -863,7 +863,7 @@ static void update_sst_donor_nodes(MXS_MONITOR *mon, int is_cluster)
|
||||
MXS_MONITOR_SERVERS *ptr = node_list[k];
|
||||
|
||||
/* Get the Galera node name */
|
||||
if (mysql_query(ptr->con, "SHOW VARIABLES LIKE 'wsrep_node_name'") == 0
|
||||
if (mxs_mysql_query(ptr->con, "SHOW VARIABLES LIKE 'wsrep_node_name'") == 0
|
||||
&& (result = mysql_store_result(ptr->con)) != NULL)
|
||||
{
|
||||
if (mysql_field_count(ptr->con) < 2)
|
||||
@ -908,7 +908,7 @@ static void update_sst_donor_nodes(MXS_MONITOR *mon, int is_cluster)
|
||||
{
|
||||
MXS_MONITOR_SERVERS *ptr = node_list[k];
|
||||
/* Set the Galera SST donor node list */
|
||||
if (mysql_query(ptr->con, donor_list) == 0)
|
||||
if (mxs_mysql_query(ptr->con, donor_list) == 0)
|
||||
{
|
||||
MXS_DEBUG("SET GLOBAL rep_sst_donor OK in node %s",
|
||||
ptr->server->unique_name);
|
||||
|
@ -266,7 +266,7 @@ monitorDatabase(MXS_MONITOR* mon, MXS_MONITOR_SERVERS *database)
|
||||
server_string = database->server->version_string;
|
||||
|
||||
/* get server_id form current node */
|
||||
if (mysql_query(database->con, "SELECT @@server_id") == 0
|
||||
if (mxs_mysql_query(database->con, "SELECT @@server_id") == 0
|
||||
&& (result = mysql_store_result(database->con)) != NULL)
|
||||
{
|
||||
long server_id = -1;
|
||||
@ -303,7 +303,7 @@ monitorDatabase(MXS_MONITOR* mon, MXS_MONITOR_SERVERS *database)
|
||||
if (server_version >= 100000)
|
||||
{
|
||||
|
||||
if (mysql_query(database->con, "SHOW ALL SLAVES STATUS") == 0
|
||||
if (mxs_mysql_query(database->con, "SHOW ALL SLAVES STATUS") == 0
|
||||
&& (result = mysql_store_result(database->con)) != NULL)
|
||||
{
|
||||
int i = 0;
|
||||
@ -366,7 +366,7 @@ monitorDatabase(MXS_MONITOR* mon, MXS_MONITOR_SERVERS *database)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mysql_query(database->con, "SHOW SLAVE STATUS") == 0
|
||||
if (mxs_mysql_query(database->con, "SHOW SLAVE STATUS") == 0
|
||||
&& (result = mysql_store_result(database->con)) != NULL)
|
||||
{
|
||||
long master_id = -1;
|
||||
@ -431,7 +431,7 @@ monitorDatabase(MXS_MONITOR* mon, MXS_MONITOR_SERVERS *database)
|
||||
}
|
||||
|
||||
/* get variable 'read_only' set by an external component */
|
||||
if (mysql_query(database->con, "SHOW GLOBAL VARIABLES LIKE 'read_only'") == 0
|
||||
if (mxs_mysql_query(database->con, "SHOW GLOBAL VARIABLES LIKE 'read_only'") == 0
|
||||
&& (result = mysql_store_result(database->con)) != NULL)
|
||||
{
|
||||
if (mysql_field_count(database->con) < 2)
|
||||
|
@ -453,7 +453,7 @@ static inline void monitor_mysql_db(MXS_MONITOR_SERVERS* database, MYSQL_SERVER_
|
||||
|
||||
MYSQL_RES* result;
|
||||
|
||||
if (mysql_query(database->con, query) == 0
|
||||
if (mxs_mysql_query(database->con, query) == 0
|
||||
&& (result = mysql_store_result(database->con)) != NULL)
|
||||
{
|
||||
if (mysql_field_count(database->con) < columns)
|
||||
@ -569,7 +569,7 @@ static MXS_MONITOR_SERVERS *build_mysql51_replication_tree(MXS_MONITOR *mon)
|
||||
int nslaves = 0;
|
||||
if (database->con)
|
||||
{
|
||||
if (mysql_query(database->con, "SHOW SLAVE HOSTS") == 0
|
||||
if (mxs_mysql_query(database->con, "SHOW SLAVE HOSTS") == 0
|
||||
&& (result = mysql_store_result(database->con)) != NULL)
|
||||
{
|
||||
if (mysql_field_count(database->con) < 4)
|
||||
@ -748,7 +748,7 @@ monitorDatabase(MXS_MONITOR *mon, MXS_MONITOR_SERVERS *database)
|
||||
ss_dassert(serv_info);
|
||||
|
||||
/* Check whether current server is MaxScale Binlog Server */
|
||||
if (mysql_query(database->con, "SELECT @@maxscale_version") == 0 &&
|
||||
if (mxs_mysql_query(database->con, "SELECT @@maxscale_version") == 0 &&
|
||||
(result = mysql_store_result(database->con)) != NULL)
|
||||
{
|
||||
serv_info->binlog_relay = true;
|
||||
@ -760,7 +760,7 @@ monitorDatabase(MXS_MONITOR *mon, MXS_MONITOR_SERVERS *database)
|
||||
}
|
||||
|
||||
/* Get server_id and read_only from current node */
|
||||
if (mysql_query(database->con, "SELECT @@server_id, @@read_only") == 0
|
||||
if (mxs_mysql_query(database->con, "SELECT @@server_id, @@read_only") == 0
|
||||
&& (result = mysql_store_result(database->con)) != NULL)
|
||||
{
|
||||
long server_id = -1;
|
||||
@ -1558,8 +1558,8 @@ static void set_master_heartbeat(MYSQL_MONITOR *handle, MXS_MONITOR_SERVERS *dat
|
||||
}
|
||||
|
||||
/* check if the maxscale_schema database and replication_heartbeat table exist */
|
||||
if (mysql_query(database->con, "SELECT table_name FROM information_schema.tables "
|
||||
"WHERE table_schema = 'maxscale_schema' AND table_name = 'replication_heartbeat'"))
|
||||
if (mxs_mysql_query(database->con, "SELECT table_name FROM information_schema.tables "
|
||||
"WHERE table_schema = 'maxscale_schema' AND table_name = 'replication_heartbeat'"))
|
||||
{
|
||||
MXS_ERROR( "Error checking for replication_heartbeat in Master server"
|
||||
": %s", mysql_error(database->con));
|
||||
@ -1581,7 +1581,7 @@ static void set_master_heartbeat(MYSQL_MONITOR *handle, MXS_MONITOR_SERVERS *dat
|
||||
if (0 == returned_rows)
|
||||
{
|
||||
/* create repl_heartbeat table in maxscale_schema database */
|
||||
if (mysql_query(database->con, "CREATE TABLE IF NOT EXISTS "
|
||||
if (mxs_mysql_query(database->con, "CREATE TABLE IF NOT EXISTS "
|
||||
"maxscale_schema.replication_heartbeat "
|
||||
"(maxscale_id INT NOT NULL, "
|
||||
"master_server_id INT NOT NULL, "
|
||||
@ -1601,7 +1601,7 @@ static void set_master_heartbeat(MYSQL_MONITOR *handle, MXS_MONITOR_SERVERS *dat
|
||||
sprintf(heartbeat_purge_query,
|
||||
"DELETE FROM maxscale_schema.replication_heartbeat WHERE master_timestamp < %lu", purge_time);
|
||||
|
||||
if (mysql_query(database->con, heartbeat_purge_query))
|
||||
if (mxs_mysql_query(database->con, heartbeat_purge_query))
|
||||
{
|
||||
MXS_ERROR("Error deleting from maxscale_schema.replication_heartbeat "
|
||||
"table: [%s], %s",
|
||||
@ -1619,7 +1619,7 @@ static void set_master_heartbeat(MYSQL_MONITOR *handle, MXS_MONITOR_SERVERS *dat
|
||||
heartbeat, handle->master->server->node_id, id);
|
||||
|
||||
/* Try to insert MaxScale timestamp into master */
|
||||
if (mysql_query(database->con, heartbeat_insert_query))
|
||||
if (mxs_mysql_query(database->con, heartbeat_insert_query))
|
||||
{
|
||||
|
||||
database->server->rlag = MAX_RLAG_NOT_AVAILABLE;
|
||||
@ -1637,7 +1637,7 @@ static void set_master_heartbeat(MYSQL_MONITOR *handle, MXS_MONITOR_SERVERS *dat
|
||||
"REPLACE INTO maxscale_schema.replication_heartbeat (master_server_id, maxscale_id, master_timestamp ) VALUES ( %li, %lu, %lu)",
|
||||
handle->master->server->node_id, id, heartbeat);
|
||||
|
||||
if (mysql_query(database->con, heartbeat_insert_query))
|
||||
if (mxs_mysql_query(database->con, heartbeat_insert_query))
|
||||
{
|
||||
|
||||
database->server->rlag = MAX_RLAG_NOT_AVAILABLE;
|
||||
@ -1698,7 +1698,7 @@ static void set_slave_heartbeat(MXS_MONITOR* mon, MXS_MONITOR_SERVERS *database)
|
||||
id, handle->master->server->node_id);
|
||||
|
||||
/* if there is a master then send the query to the slave with master_id */
|
||||
if (handle->master != NULL && (mysql_query(database->con, select_heartbeat_query) == 0
|
||||
if (handle->master != NULL && (mxs_mysql_query(database->con, select_heartbeat_query) == 0
|
||||
&& (result = mysql_store_result(database->con)) != NULL))
|
||||
{
|
||||
int rows_found = 0;
|
||||
@ -1972,8 +1972,8 @@ bool check_replicate_ignore_table(MXS_MONITOR_SERVERS* database)
|
||||
MYSQL_RES *result;
|
||||
bool rval = true;
|
||||
|
||||
if (mysql_query(database->con,
|
||||
"show variables like 'replicate_ignore_table'") == 0 &&
|
||||
if (mxs_mysql_query(database->con,
|
||||
"show variables like 'replicate_ignore_table'") == 0 &&
|
||||
(result = mysql_store_result(database->con)) &&
|
||||
mysql_num_fields(result) > 1)
|
||||
{
|
||||
@ -2016,8 +2016,8 @@ bool check_replicate_do_table(MXS_MONITOR_SERVERS* database)
|
||||
MYSQL_RES *result;
|
||||
bool rval = true;
|
||||
|
||||
if (mysql_query(database->con,
|
||||
"show variables like 'replicate_do_table'") == 0 &&
|
||||
if (mxs_mysql_query(database->con,
|
||||
"show variables like 'replicate_do_table'") == 0 &&
|
||||
(result = mysql_store_result(database->con)) &&
|
||||
mysql_num_fields(result) > 1)
|
||||
{
|
||||
@ -2059,8 +2059,8 @@ bool check_replicate_wild_do_table(MXS_MONITOR_SERVERS* database)
|
||||
MYSQL_RES *result;
|
||||
bool rval = true;
|
||||
|
||||
if (mysql_query(database->con,
|
||||
"show variables like 'replicate_wild_do_table'") == 0 &&
|
||||
if (mxs_mysql_query(database->con,
|
||||
"show variables like 'replicate_wild_do_table'") == 0 &&
|
||||
(result = mysql_store_result(database->con)) &&
|
||||
mysql_num_fields(result) > 1)
|
||||
{
|
||||
@ -2106,8 +2106,8 @@ bool check_replicate_wild_ignore_table(MXS_MONITOR_SERVERS* database)
|
||||
MYSQL_RES *result;
|
||||
bool rval = true;
|
||||
|
||||
if (mysql_query(database->con,
|
||||
"show variables like 'replicate_wild_ignore_table'") == 0 &&
|
||||
if (mxs_mysql_query(database->con,
|
||||
"show variables like 'replicate_wild_ignore_table'") == 0 &&
|
||||
(result = mysql_store_result(database->con)) &&
|
||||
mysql_num_fields(result) > 1)
|
||||
{
|
||||
|
@ -229,7 +229,7 @@ monitorDatabase(MXS_MONITOR_SERVERS *database, char *defaultUser, char *defaultP
|
||||
server_string = database->server->version_string;
|
||||
|
||||
/* Check if the the SQL node is able to contact one or more data nodes */
|
||||
if (mysql_query(database->con, "SHOW STATUS LIKE 'Ndb_number_of_ready_data_nodes'") == 0
|
||||
if (mxs_mysql_query(database->con, "SHOW STATUS LIKE 'Ndb_number_of_ready_data_nodes'") == 0
|
||||
&& (result = mysql_store_result(database->con)) != NULL)
|
||||
{
|
||||
if (mysql_field_count(database->con) < 2)
|
||||
@ -256,7 +256,7 @@ monitorDatabase(MXS_MONITOR_SERVERS *database, char *defaultUser, char *defaultP
|
||||
}
|
||||
|
||||
/* Check the the SQL node id in the MySQL cluster */
|
||||
if (mysql_query(database->con, "SHOW STATUS LIKE 'Ndb_cluster_node_id'") == 0
|
||||
if (mxs_mysql_query(database->con, "SHOW STATUS LIKE 'Ndb_cluster_node_id'") == 0
|
||||
&& (result = mysql_store_result(database->con)) != NULL)
|
||||
{
|
||||
if (mysql_field_count(database->con) < 2)
|
||||
|
@ -868,9 +868,12 @@ createInstance(SERVICE *service, char **options)
|
||||
/** Set SSL pointer in in server struct */
|
||||
server->server_ssl = ssl_cfg;
|
||||
|
||||
/* Set server unique name */
|
||||
/* Add server to service backend list */
|
||||
serviceAddBackend(inst->service, server);
|
||||
|
||||
/* Hide backend server struct */
|
||||
service->dbref->server->is_active = false;
|
||||
service->dbref->active = false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -919,6 +922,9 @@ createInstance(SERVICE *service, char **options)
|
||||
else
|
||||
{
|
||||
inst->master_state = BLRM_UNCONNECTED;
|
||||
/* Set backend server as active */
|
||||
service->dbref->server->is_active = true;
|
||||
service->dbref->active = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -979,6 +985,18 @@ createInstance(SERVICE *service, char **options)
|
||||
blr_cache_read_master_data(inst);
|
||||
|
||||
/**
|
||||
* The value of master checksum is known only at registration time, so
|
||||
* as soon as replication succeds the value is updated.
|
||||
* Set now the binlog checksum from the saved value.
|
||||
* This is very useful in case of possible failure in the
|
||||
* registration phase for any reason: master is down, wrong password etc.
|
||||
* In this case a connecting slave will get the checksum value
|
||||
* from previous registration instead of default one (CRC32)
|
||||
* which can be wrong if slave has binlog_checksum = NONE.
|
||||
*/
|
||||
blr_set_checksum(inst, inst->saved_master.chksum2);
|
||||
|
||||
/*
|
||||
* Find latest binlog file in binlogdir or GTID maps repo
|
||||
*/
|
||||
if (blr_file_init(inst) == 0)
|
||||
|
@ -1009,6 +1009,7 @@ extern const char *blr_get_encryption_algorithm(int);
|
||||
extern int blr_check_encryption_algorithm(char *);
|
||||
extern const char *blr_encryption_algorithm_list(void);
|
||||
extern bool blr_get_encryption_key(ROUTER_INSTANCE *);
|
||||
extern void blr_set_checksum(ROUTER_INSTANCE *instance, GWBUF *buf);
|
||||
extern const char *blr_skip_leading_sql_comments(const char *);
|
||||
extern bool blr_fetch_mariadb_gtid(ROUTER_SLAVE *,
|
||||
const char *,
|
||||
|
@ -2523,16 +2523,8 @@ static void blr_register_getchecksum(ROUTER_INSTANCE *router, GWBUF *buf)
|
||||
*/
|
||||
static void blr_register_handle_checksum(ROUTER_INSTANCE *router, GWBUF *buf)
|
||||
{
|
||||
char *val = blr_extract_column(buf, 1);
|
||||
|
||||
if (val && strncasecmp(val, "NONE", 4) == 0)
|
||||
{
|
||||
router->master_chksum = false;
|
||||
}
|
||||
if (val)
|
||||
{
|
||||
MXS_FREE(val);
|
||||
}
|
||||
// Set checksum from master reply
|
||||
blr_set_checksum(router, buf);
|
||||
|
||||
// Response from master should be stored
|
||||
blr_register_cache_response(router,
|
||||
@ -3569,3 +3561,25 @@ static int blr_check_connect_retry(ROUTER_INSTANCE *router)
|
||||
return BLR_MASTER_BACKOFF_TIME * (1 + router->retry_count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set checksum value in router instance
|
||||
*
|
||||
* @param inst The router instance
|
||||
* @param buf The buffer with checksum value
|
||||
*/
|
||||
void blr_set_checksum(ROUTER_INSTANCE *inst, GWBUF *buf)
|
||||
{
|
||||
if (buf)
|
||||
{
|
||||
char *val = blr_extract_column(buf, 1);
|
||||
if (val && strncasecmp(val, "NONE", 4) == 0)
|
||||
{
|
||||
inst->master_chksum = false;
|
||||
}
|
||||
if (val)
|
||||
{
|
||||
MXS_FREE(val);
|
||||
}
|
||||
}
|
||||
}
|
@ -7837,6 +7837,15 @@ static bool blr_handle_admin_stmt(ROUTER_INSTANCE *router,
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Mark as active the master server struct */
|
||||
spinlock_acquire(&router->lock);
|
||||
if (!router->service->dbref->server->is_active)
|
||||
{
|
||||
router->service->dbref->server->is_active = true;
|
||||
router->service->dbref->active = true;
|
||||
}
|
||||
spinlock_release(&router->lock);
|
||||
|
||||
/**
|
||||
* check if router is BLRM_UNCONFIGURED
|
||||
* and change state to BLRM_SLAVE_STOPPED
|
||||
|
Loading…
x
Reference in New Issue
Block a user