Merge branch '2.3' into 2.4

This commit is contained in:
Markus Mäkelä
2020-04-23 14:51:11 +03:00
7 changed files with 99 additions and 252 deletions

View File

@ -121,7 +121,7 @@ configure_file(${CMAKE_SOURCE_DIR}/include/maxscale/paths.h.in ${CMAKE_BINARY_DI
configure_file(${CMAKE_SOURCE_DIR}/include/maxscale/adminusers.h.in ${CMAKE_BINARY_DIR}/include/maxscale/adminusers.h @ONLY) configure_file(${CMAKE_SOURCE_DIR}/include/maxscale/adminusers.h.in ${CMAKE_BINARY_DIR}/include/maxscale/adminusers.h @ONLY)
configure_file(${CMAKE_SOURCE_DIR}/server/test/maxscale_test.h.in ${CMAKE_BINARY_DIR}/include/maxscale/maxscale_test.h @ONLY) configure_file(${CMAKE_SOURCE_DIR}/server/test/maxscale_test.h.in ${CMAKE_BINARY_DIR}/include/maxscale/maxscale_test.h @ONLY)
configure_file(${CMAKE_SOURCE_DIR}/etc/postinst.in ${CMAKE_BINARY_DIR}/postinst @ONLY) configure_file(${CMAKE_SOURCE_DIR}/etc/postinst.in ${CMAKE_BINARY_DIR}/postinst @ONLY)
configure_file(${CMAKE_SOURCE_DIR}/etc/postrm.in ${CMAKE_BINARY_DIR}/postrm @ONLY) configure_file(${CMAKE_SOURCE_DIR}/etc/prerm.in ${CMAKE_BINARY_DIR}/prerm @ONLY)
configure_file(${CMAKE_SOURCE_DIR}/etc/upstart/maxscale.conf.in ${CMAKE_BINARY_DIR}/upstart/maxscale.conf @ONLY) configure_file(${CMAKE_SOURCE_DIR}/etc/upstart/maxscale.conf.in ${CMAKE_BINARY_DIR}/upstart/maxscale.conf @ONLY)
configure_file(${CMAKE_SOURCE_DIR}/test/maxscale_test.cnf ${CMAKE_BINARY_DIR}/maxscale.cnf @ONLY) 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) configure_file(${CMAKE_SOURCE_DIR}/test/maxscale_test_secondary.cnf ${CMAKE_BINARY_DIR}/maxscale_secondary.cnf @ONLY)
@ -256,7 +256,7 @@ if(PACKAGE)
install_program(${CMAKE_BINARY_DIR}/maxscale core) install_program(${CMAKE_BINARY_DIR}/maxscale core)
install_file(${CMAKE_BINARY_DIR}/maxscale.conf core) install_file(${CMAKE_BINARY_DIR}/maxscale.conf core)
install_program(${CMAKE_BINARY_DIR}/postinst core) install_program(${CMAKE_BINARY_DIR}/postinst core)
install_program(${CMAKE_BINARY_DIR}/postrm core) install_program(${CMAKE_BINARY_DIR}/prerm core)
# The inclusion of CPack needs to be the last effective packaging related command. All # The inclusion of CPack needs to be the last effective packaging related command. All
# configurations to packaging done after the call will be ignored. # configurations to packaging done after the call will be ignored.

View File

@ -105,5 +105,5 @@ else()
endif() endif()
message(STATUS "You can install startup scripts and system configuration files for MaxScale by running the 'postinst' shell script located at ${CMAKE_INSTALL_PREFIX}.") message(STATUS "You can install startup scripts and system configuration files for MaxScale by running the 'postinst' shell script located at ${CMAKE_INSTALL_PREFIX}.")
message(STATUS "To remove these installed files, run the 'postrm' shell script located in the same folder.") message(STATUS "To remove these installed files, run the 'prerm' shell script located in the same folder.")
endif() endif()

View File

@ -6,7 +6,7 @@ set(CPACK_DEBIAN_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}")
if(TARGET_COMPONENT STREQUAL "core" OR TARGET_COMPONENT STREQUAL "all") if(TARGET_COMPONENT STREQUAL "core" OR TARGET_COMPONENT STREQUAL "all")
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_BINARY_DIR}/postinst;${CMAKE_BINARY_DIR}/postrm") set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_BINARY_DIR}/postinst;${CMAKE_BINARY_DIR}/prerm")
elseif(TARGET_COMPONENT STREQUAL "devel") elseif(TARGET_COMPONENT STREQUAL "devel")
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}\n${DESCRIPTION_TEXT}") set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}\n${DESCRIPTION_TEXT}")
endif() endif()

View File

@ -39,7 +39,7 @@ set(CPACK_RPM_USER_FILELIST "${IGNORED_DIRS}")
if(TARGET_COMPONENT STREQUAL "core" OR TARGET_COMPONENT STREQUAL "all") if(TARGET_COMPONENT STREQUAL "core" OR TARGET_COMPONENT STREQUAL "all")
set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE ${CMAKE_BINARY_DIR}/postinst) set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE ${CMAKE_BINARY_DIR}/postinst)
set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE ${CMAKE_BINARY_DIR}/postrm) set(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE ${CMAKE_BINARY_DIR}/prerm)
endif() endif()
if(EXTRA_PACKAGE_DEPENDENCIES) if(EXTRA_PACKAGE_DEPENDENCIES)

View File

@ -12,8 +12,9 @@ mkdir -p @MAXSCALE_VARDIR@/lib/maxscale
mkdir -p @MAXSCALE_VARDIR@/cache/maxscale mkdir -p @MAXSCALE_VARDIR@/cache/maxscale
mkdir -p @MAXSCALE_VARDIR@/run/maxscale mkdir -p @MAXSCALE_VARDIR@/run/maxscale
# Create MaxScale user # Create MaxScale user if it doesnt' exist
if [ -f "/etc/passwd" ] && [ "$(grep -c 'maxscale' /etc/passwd)" -eq 0 ] getent passwd maxscale > /dev/null
if [ $? -ne 0 ]
then then
groupadd -r maxscale groupadd -r maxscale
useradd -r -s /bin/false -g maxscale maxscale useradd -r -s /bin/false -g maxscale maxscale
@ -63,7 +64,9 @@ then
fi fi
mkdir -p /etc/systemd/system/maxscale.service.d mkdir -p /etc/systemd/system/maxscale.service.d
systemctl enable maxscale.service systemctl enable maxscale.service > /dev/null
systemctl is-active maxscale.service --quiet > /dev/null && systemctl restart maxscale.service > /dev/null
else else
if [ -d "/etc/init/" ] && [ -f "@CMAKE_INSTALL_PREFIX@/@MAXSCALE_SHAREDIR@/upstart/maxscale.conf" ] if [ -d "/etc/init/" ] && [ -f "@CMAKE_INSTALL_PREFIX@/@MAXSCALE_SHAREDIR@/upstart/maxscale.conf" ]
then then
@ -77,6 +80,8 @@ else
else else
echo "Could not find init script: @CMAKE_INSTALL_PREFIX@/@MAXSCALE_SHAREDIR@/maxscale" >& 2 echo "Could not find init script: @CMAKE_INSTALL_PREFIX@/@MAXSCALE_SHAREDIR@/maxscale" >& 2
fi fi
service maxscale status > /dev/null && service maxscale restart > /dev/null
fi fi
# If no maxscale.cnf file is found in /etc, copy the template file there # If no maxscale.cnf file is found in /etc, copy the template file there

View File

@ -19,13 +19,15 @@ then
if [ -f /usr/lib/systemd/system/maxscale.service ] if [ -f /usr/lib/systemd/system/maxscale.service ]
then then
systemctl stop maxscale.service systemctl stop maxscale.service
systemctl disable maxscale.service systemctl disable maxscale.service > /dev/null
rm /usr/lib/systemd/system/maxscale.service rm /usr/lib/systemd/system/maxscale.service
systemctl daemon-reload
elif [ -f /lib/systemd/system/maxscale.service ] elif [ -f /lib/systemd/system/maxscale.service ]
then then
systemctl stop maxscale.service systemctl stop maxscale.service
systemctl disable maxscale.service systemctl disable maxscale.service > /dev/null
rm /lib/systemd/system/maxscale.service rm /lib/systemd/system/maxscale.service
systemctl daemon-reload
fi fi
if [ -f /etc/logrotate.d/maxscale_logrotate ] if [ -f /etc/logrotate.d/maxscale_logrotate ]

View File

@ -14,269 +14,109 @@
#include "testconnections.h" #include "testconnections.h"
#include "sql_t1.h" #include "sql_t1.h"
typedef struct #include <atomic>
std::atomic<bool> keep_running {true};
void query_thread_master(TestConnections& test)
{ {
int exit_flag; auto conn = test.repl->get_connection(0);
int thread_id;
long i;
int rwsplit_only;
TestConnections* Test;
MYSQL* conn1;
MYSQL* conn2;
MYSQL* conn3;
} openclose_thread_data;
void* query_thread1(void* ptr); std::vector<char> sql;
void* query_thread_master(void* ptr); sql.reserve(1000000);
create_insert_string(&sql[0], 5000, 2);
int main(int argc, char* argv[]) test.expect(conn.connect(), "Connection should work: %s", conn.error());
{
TestConnections* Test = new TestConnections(argc, argv);
Test->maxscales->ssh_node_f(0,
true,
"sysctl net.ipv4.tcp_tw_reuse=1 net.ipv4.tcp_tw_recycle=1 "
"net.core.somaxconn=10000 net.ipv4.tcp_max_syn_backlog=10000");
Test->set_timeout(20);
int threads_num = 40; while (keep_running && test.ok())
openclose_thread_data data[threads_num];
int master_load_threads_num = 3;
openclose_thread_data data_master[master_load_threads_num];
int i;
int run_time = 300;
if (Test->smoke)
{ {
run_time = 10; test.expect(conn.query(sql.data()), "Query failed: %s", conn.error());
std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
for (i = 0; i < threads_num; i++)
{
data[i].i = 0;
data[i].exit_flag = 0;
data[i].Test = Test;
data[i].rwsplit_only = 1;
data[i].thread_id = i;
data[i].conn1 = NULL;
data[i].conn2 = NULL;
data[i].conn3 = NULL;
}
for (i = 0; i < master_load_threads_num; i++)
{
data_master[i].i = 0;
data_master[i].exit_flag = 0;
data_master[i].Test = Test;
data_master[i].rwsplit_only = 1;
data_master[i].thread_id = i;
data_master[i].conn1 = NULL;
data_master[i].conn2 = NULL;
data_master[i].conn3 = NULL;
}
pthread_t thread1[threads_num];
pthread_t thread_master[master_load_threads_num];
Test->repl->connect();
Test->maxscales->connect_maxscale(0);
create_t1(Test->maxscales->conn_rwsplit[0]);
Test->repl->execute_query_all_nodes((char*) "set global max_connections = 2000;");
Test->repl->sync_slaves();
Test->tprintf("Creating user 'user' \n");
execute_query(Test->maxscales->conn_rwsplit[0], (char*) "DROP USER IF EXISTS user@'%%'");
execute_query(Test->maxscales->conn_rwsplit[0], (char*) "CREATE USER user@'%%' IDENTIFIED BY 'pass2'");
execute_query(Test->maxscales->conn_rwsplit[0], (char*) "GRANT SELECT ON test.* TO user@'%%'");
execute_query(Test->maxscales->conn_rwsplit[0], (char*) "DROP TABLE IF EXISTS test.t1");
execute_query(Test->maxscales->conn_rwsplit[0], (char*) "CREATE TABLE test.t1 (x1 int, fl int)");
Test->repl->sync_slaves();
/* Create independent threads each of them will create some load on Master */
for (i = 0; i < master_load_threads_num; i++)
{
pthread_create(&thread_master[i], NULL, query_thread_master, &data_master[i]);
}
/* Create independent threads each of them will execute function */
for (i = 0; i < threads_num; i++)
{
pthread_create(&thread1[i], NULL, query_thread1, &data[i]);
}
Test->tprintf("Threads are running %d seconds \n", run_time);
for (i = 0; i < threads_num; i++)
{
data[i].rwsplit_only = 1;
}
Test->set_timeout(run_time + 60);
sleep(run_time);
Test->repl->flush_hosts();
Test->tprintf("all maxscales->routers[0] are involved, threads are running %d seconds more\n", run_time);
Test->set_timeout(run_time + 100);
for (i = 0; i < threads_num; i++)
{
data[i].rwsplit_only = 0;
}
sleep(run_time);
Test->set_timeout(120);
Test->tprintf("Waiting for all threads exit\n");
for (i = 0; i < threads_num; i++)
{
data[i].exit_flag = 1;
pthread_join(thread1[i], NULL);
}
Test->tprintf("Waiting for all master load threads exit\n");
for (i = 0; i < master_load_threads_num; i++)
{
data_master[i].exit_flag = 1;
pthread_join(thread_master[i], NULL);
}
Test->tprintf("Flushing backend hosts\n");
Test->set_timeout(60);
Test->repl->flush_hosts();
Test->tprintf("Dropping tables and users\n");
Test->set_timeout(60);
execute_query(Test->maxscales->conn_rwsplit[0], (char*) "DROP TABLE test.t1;");
execute_query(Test->maxscales->conn_rwsplit[0], (char*) "DROP USER user@'%%'");
Test->maxscales->close_maxscale_connections(0);
Test->set_timeout(160);
Test->tprintf("Trying to connect Maxscale\n");
Test->maxscales->connect_maxscale(0);
Test->tprintf("Closing Maxscale connections\n");
Test->maxscales->close_maxscale_connections(0);
Test->tprintf("Checking if Maxscale alive\n");
Test->check_maxscale_alive(0);
Test->tprintf("Checking log for unwanted errors\n");
Test->log_excludes(0, "due to authentication failure");
Test->log_excludes(0, "due to handshake failure");
// We need to wait for the TCP connections in TIME_WAIT state so that
// later tests don't fail due to a lack of file descriptors
Test->tprintf("Waiting for network connections to die");
sleep(30);
int rval = Test->global_result;
delete Test;
return rval;
} }
void* query_thread1(void* ptr) void query_thread(TestConnections& test)
{ {
openclose_thread_data* data = (openclose_thread_data*) ptr; while (keep_running && test.ok())
while (data->exit_flag == 0)
{ {
data->conn1 = data->Test->maxscales->open_rwsplit_connection(0); std::vector<Connection> conns;
conns.emplace_back(test.maxscales->rwsplit());
conns.emplace_back(test.maxscales->readconn_master());
conns.emplace_back(test.maxscales->readconn_slave());
if (data->conn1 != NULL) for (auto& conn : conns)
{ {
if (mysql_errno(data->conn1) == 0) if (conn.connect())
{ {
mysql_change_user(data->conn1, (char*) "user", (char*) "pass2", (char*) "test"); test.expect(conn.change_user("user", "pass2"), "Change user to user:pass2 should work");
mysql_change_user(data->conn1, test.expect(conn.reset_connection(), "Change user back should work");
data->Test->repl->user_name,
data->Test->repl->password,
(char*) "test");
} }
std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
if (data->rwsplit_only == 0)
{
data->conn2 = data->Test->maxscales->open_readconn_master_connection(0);
if (data->conn2 != NULL)
{
if (mysql_errno(data->conn2) == 0)
{
mysql_change_user(data->conn2, (char*) "user", (char*) "pass2", (char*) "test");
mysql_change_user(data->conn2,
data->Test->repl->user_name,
data->Test->repl->password,
(char*) "test");
}
}
data->conn3 = data->Test->maxscales->open_readconn_slave_connection(0);
if (data->conn3 != NULL)
{
if (mysql_errno(data->conn3) == 0)
{
mysql_change_user(data->conn3, (char*) "user", (char*) "pass2", (char*) "test");
mysql_change_user(data->conn3,
data->Test->repl->user_name,
data->Test->repl->password,
(char*) "test");
}
}
}
if (data->conn1 != NULL)
{
mysql_close(data->conn1);
data->conn1 = NULL;
}
if (data->rwsplit_only == 0)
{
if (data->conn2 != NULL)
{
mysql_close(data->conn2);
data->conn2 = NULL;
}
if (data->conn3 != NULL)
{
mysql_close(data->conn3);
data->conn3 = NULL;
}
}
data->i++;
} }
return NULL;
} }
void* query_thread_master(void* ptr) int main(int argc, char** argv)
{ {
openclose_thread_data* data = (openclose_thread_data*) ptr; TestConnections test(argc, argv);
char sql[1000000]; test.set_timeout(20);
data->conn1 = open_conn(data->Test->repl->port[0],
data->Test->repl->IP[0],
data->Test->repl->user_name,
data->Test->repl->password,
false);
create_insert_string(sql, 5000, 2);
if (data->conn1 != NULL) test.repl->connect();
test.maxscales->connect_maxscale(0);
create_t1(test.maxscales->conn_rwsplit[0]);
test.repl->execute_query_all_nodes("set global max_connections = 2000;");
test.repl->sync_slaves();
test.tprintf("Creating user 'user' ");
test.try_query(test.maxscales->conn_rwsplit[0], "DROP USER IF EXISTS user@'%%'");
test.try_query(test.maxscales->conn_rwsplit[0], "CREATE USER user@'%%' IDENTIFIED BY 'pass2'");
test.try_query(test.maxscales->conn_rwsplit[0], "GRANT SELECT ON test.* TO user@'%%'");
test.try_query(test.maxscales->conn_rwsplit[0], "DROP TABLE IF EXISTS test.t1");
test.try_query(test.maxscales->conn_rwsplit[0], "CREATE TABLE test.t1 (x1 int, fl int)");
test.repl->sync_slaves();
std::vector<std::thread> threads;
test.stop_timeout();
for (int i = 0; i < 3; i++)
{ {
while (data->exit_flag == 0) threads.emplace_back(query_thread_master, std::ref(test));
{
data->Test->try_query(data->conn1, "%s", sql);
data->i++;
}
}
else
{
data->Test->add_result(1, "Error creating MYSQL struct for Master conn\n");
} }
return NULL; for (int i = 0; i < 40; i++)
{
threads.emplace_back(query_thread, std::ref(test));
}
const int RUN_TIME = 10;
test.tprintf("Threads are running %d seconds ", RUN_TIME);
sleep(RUN_TIME);
keep_running = false;
test.set_timeout(120);
test.tprintf("Waiting for all threads to exit");
for (auto& a : threads)
{
a.join();
}
test.tprintf("Flushing backend hosts");
test.set_timeout(60);
test.repl->flush_hosts();
test.tprintf("Dropping tables and users");
test.set_timeout(60);
test.try_query(test.maxscales->conn_rwsplit[0], "DROP TABLE test.t1;");
test.try_query(test.maxscales->conn_rwsplit[0], "DROP USER user@'%%'");
test.maxscales->close_maxscale_connections(0);
test.set_timeout(160);
test.check_maxscale_alive(0);
test.log_excludes(0, "due to authentication failure");
test.log_excludes(0, "due to handshake failure");
return test.global_result;
} }