The test expected the wrong error message to be in the log. To better cope with changes in the text, the test now uses a regular expression to do the matching.
		
			
				
	
	
		
			2316 lines
		
	
	
		
			60 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			2316 lines
		
	
	
		
			60 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include <getopt.h>
 | 
						|
#include <libgen.h>
 | 
						|
#include <pthread.h>
 | 
						|
#include <stdarg.h>
 | 
						|
#include <sys/time.h>
 | 
						|
#include <time.h>
 | 
						|
#include <signal.h>
 | 
						|
#include <execinfo.h>
 | 
						|
 | 
						|
#include "mariadb_func.h"
 | 
						|
#include "maxadmin_operations.h"
 | 
						|
#include "sql_t1.h"
 | 
						|
#include "testconnections.h"
 | 
						|
 | 
						|
namespace maxscale
 | 
						|
{
 | 
						|
static bool start = true;
 | 
						|
static bool check_nodes = true;
 | 
						|
static bool multiple_maxscales = false;
 | 
						|
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;
 | 
						|
}
 | 
						|
 | 
						|
void TestConnections::skip_maxscale_start(bool value)
 | 
						|
{
 | 
						|
    maxscale::start = !value;
 | 
						|
}
 | 
						|
 | 
						|
void TestConnections::require_repl_version(const char *version)
 | 
						|
{
 | 
						|
    maxscale::required_repl_version = version;
 | 
						|
}
 | 
						|
 | 
						|
void TestConnections::require_galera_version(const char *version)
 | 
						|
{
 | 
						|
    maxscale::required_galera_version = version;
 | 
						|
}
 | 
						|
 | 
						|
void TestConnections::multiple_maxscales(bool value)
 | 
						|
{
 | 
						|
    maxscale::multiple_maxscales = value;
 | 
						|
}
 | 
						|
 | 
						|
void TestConnections::set_secondary_maxscale(const char* ip_var, const char* ip6_var)
 | 
						|
{
 | 
						|
    const char* ip = getenv(ip_var);
 | 
						|
    const char* ip6 = getenv(ip6_var);
 | 
						|
 | 
						|
    if (ip || ip6)
 | 
						|
    {
 | 
						|
        TestConnections::multiple_maxscales(true);
 | 
						|
        if (ip)
 | 
						|
        {
 | 
						|
            setenv("maxscale2_IP", ip, 1);
 | 
						|
        }
 | 
						|
        if (ip6)
 | 
						|
        {
 | 
						|
            setenv("maxscale2_network6", ip6, 1);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
TestConnections::TestConnections(int argc, char *argv[]):
 | 
						|
    enable_timeouts(true),
 | 
						|
    global_result(0),
 | 
						|
    rwsplit_port(4006),
 | 
						|
    readconn_master_port(4008),
 | 
						|
    readconn_slave_port(4009),
 | 
						|
    binlog_port(5306),
 | 
						|
    conn_rwsplit(NULL),
 | 
						|
    conn_master(NULL),
 | 
						|
    conn_slave(NULL),
 | 
						|
    use_ipv6(false),
 | 
						|
    use_snapshots(false),
 | 
						|
    no_backend_log_copy(false),
 | 
						|
    verbose(false),
 | 
						|
    smoke(true),
 | 
						|
    binlog_cmd_option(0),
 | 
						|
    ssl(false),
 | 
						|
    backend_ssl(false),
 | 
						|
    binlog_master_gtid(false),
 | 
						|
    binlog_slave_gtid(false),
 | 
						|
    no_galera(false),
 | 
						|
    no_vm_revert(true),
 | 
						|
    threads(4)
 | 
						|
{
 | 
						|
    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;
 | 
						|
    ports[1] = readconn_master_port;
 | 
						|
    ports[2] = readconn_slave_port;
 | 
						|
 | 
						|
    read_env();
 | 
						|
 | 
						|
    char * gal_env = getenv("galera_000_network");
 | 
						|
    if ((gal_env == NULL) || (strcmp(gal_env, "") == 0 ))
 | 
						|
    {
 | 
						|
        no_galera = true;
 | 
						|
        tprintf("Galera backend variables are not defined, Galera won't be used\n");
 | 
						|
    }
 | 
						|
 | 
						|
    bool maxscale_init = true;
 | 
						|
 | 
						|
    static struct option long_options[] =
 | 
						|
    {
 | 
						|
 | 
						|
        {"verbose", no_argument, 0, 'v'},
 | 
						|
        {"silent", no_argument, 0, 'n'},
 | 
						|
        {"help", no_argument, 0, 'h'},
 | 
						|
        {"no-maxscale-start", no_argument, 0, 's'},
 | 
						|
        {"no-nodes-check", no_argument, 0, 'r'},
 | 
						|
        {"quiet", no_argument, 0, 'q'},
 | 
						|
        {"restart-galera", no_argument, 0, 'g'},
 | 
						|
        {"no-timeouts", no_argument, 0, 'z'},
 | 
						|
        {"no-galera", no_argument, 0, 'y'},
 | 
						|
        {0, 0, 0, 0}
 | 
						|
    };
 | 
						|
 | 
						|
    int c;
 | 
						|
    int option_index = 0;
 | 
						|
    bool restart_galera = false;
 | 
						|
 | 
						|
    while ((c = getopt_long(argc, argv, "vnqhsirgzy", long_options, &option_index)) != -1)
 | 
						|
    {
 | 
						|
        switch (c)
 | 
						|
        {
 | 
						|
        case 'v':
 | 
						|
            verbose = true;
 | 
						|
            break;
 | 
						|
 | 
						|
        case 'n':
 | 
						|
            verbose = false;
 | 
						|
            break;
 | 
						|
 | 
						|
        case 'q':
 | 
						|
            freopen("/dev/null", "w", stdout);
 | 
						|
            break;
 | 
						|
 | 
						|
        case 'h':
 | 
						|
            printf("Options:\n"
 | 
						|
                   "-h, --help\n"
 | 
						|
                   "-v, --verbose\n"
 | 
						|
                   "-q, --silent\n"
 | 
						|
                   "-s, --no-maxscale-start\n"
 | 
						|
                   "-i, --no-maxscale-init\n"
 | 
						|
                   "-g, --restart-galera\n"
 | 
						|
                   "-y, --no-galera\n"
 | 
						|
                   "-z, --no-timeouts\n");
 | 
						|
            exit(0);
 | 
						|
            break;
 | 
						|
 | 
						|
        case 's':
 | 
						|
            printf("Maxscale won't be started\n");
 | 
						|
            maxscale::start = false;
 | 
						|
            break;
 | 
						|
        case 'i':
 | 
						|
            printf("Maxscale won't be started and Maxscale.cnf won't be uploaded\n");
 | 
						|
            maxscale_init = false;
 | 
						|
            break;
 | 
						|
 | 
						|
        case 'r':
 | 
						|
            printf("Nodes are not checked before test and are not restarted\n");
 | 
						|
            maxscale::check_nodes = false;
 | 
						|
            break;
 | 
						|
 | 
						|
        case 'g':
 | 
						|
            printf("Restarting Galera setup\n");
 | 
						|
            restart_galera = true;
 | 
						|
            break;
 | 
						|
 | 
						|
        case 'z':
 | 
						|
            enable_timeouts = false;
 | 
						|
            break;
 | 
						|
 | 
						|
        case 'y':
 | 
						|
            printf("Do not use Galera setup\n");
 | 
						|
            no_galera = true;
 | 
						|
            break;
 | 
						|
 | 
						|
        default:
 | 
						|
            printf("UNKNOWN OPTION: %c\n", c);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (optind < argc)
 | 
						|
    {
 | 
						|
        test_name = argv[optind];
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        test_name = basename(argv[0]);
 | 
						|
    }
 | 
						|
 | 
						|
    sprintf(get_logs_command, "%s/get_logs.sh", test_dir);
 | 
						|
 | 
						|
    sprintf(ssl_options, "--ssl-cert=%s/ssl-cert/client-cert.pem --ssl-key=%s/ssl-cert/client-key.pem",
 | 
						|
            test_dir, test_dir);
 | 
						|
    setenv("ssl_options", ssl_options, 1);
 | 
						|
 | 
						|
    repl = new Mariadb_nodes("node", test_dir, verbose);
 | 
						|
    if (!no_galera)
 | 
						|
    {
 | 
						|
        galera = new Galera_nodes("galera", test_dir, verbose);
 | 
						|
        //galera->use_ipv6 = use_ipv6;
 | 
						|
        galera->use_ipv6 = false;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        galera = repl;
 | 
						|
    }
 | 
						|
 | 
						|
    repl->use_ipv6 = use_ipv6;
 | 
						|
 | 
						|
 | 
						|
    if (maxscale::required_repl_version.length())
 | 
						|
    {
 | 
						|
        int ver_repl_required = get_int_version(maxscale::required_repl_version);
 | 
						|
        std::string ver_repl = repl->get_lowest_version();
 | 
						|
        int int_ver_repl = get_int_version(ver_repl);
 | 
						|
 | 
						|
        if (int_ver_repl < ver_repl_required)
 | 
						|
        {
 | 
						|
            tprintf("Test requires a higher version of backend servers, skipping test.");
 | 
						|
            tprintf("Required version: %s", maxscale::required_repl_version.c_str());
 | 
						|
            tprintf("Master-slave version: %s", ver_repl.c_str());
 | 
						|
            exit(0);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (maxscale::required_galera_version.length())
 | 
						|
    {
 | 
						|
        int ver_galera_required = get_int_version(maxscale::required_galera_version);
 | 
						|
        std::string ver_galera = galera->get_lowest_version();
 | 
						|
        int int_ver_galera = get_int_version(ver_galera);
 | 
						|
 | 
						|
        if (int_ver_galera < ver_galera_required)
 | 
						|
        {
 | 
						|
            tprintf("Test requires a higher version of backend servers, skipping test.");
 | 
						|
            tprintf("Required version: %s", maxscale::required_galera_version.c_str());
 | 
						|
            tprintf("Galera version: %s", ver_galera.c_str());
 | 
						|
            exit(0);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ((restart_galera) && (!no_galera))
 | 
						|
    {
 | 
						|
        galera->stop_nodes();
 | 
						|
        galera->start_replication();
 | 
						|
    }
 | 
						|
 | 
						|
    bool snapshot_reverted = false;
 | 
						|
 | 
						|
    if (use_snapshots)
 | 
						|
    {
 | 
						|
        snapshot_reverted = revert_snapshot("clean");
 | 
						|
    }
 | 
						|
 | 
						|
    if (!snapshot_reverted && maxscale::check_nodes)
 | 
						|
    {
 | 
						|
        if (!repl->fix_replication() )
 | 
						|
        {
 | 
						|
            exit(200);
 | 
						|
        }
 | 
						|
        if (!no_galera)
 | 
						|
        {
 | 
						|
            if (!galera->fix_replication())
 | 
						|
            {
 | 
						|
                exit(200);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (maxscale_init)
 | 
						|
    {
 | 
						|
        init_maxscale();
 | 
						|
 | 
						|
        if (maxscale::multiple_maxscales && !secondary_maxscale_IP.empty())
 | 
						|
        {
 | 
						|
            set_active_maxscale(MXS_SECONDARY);
 | 
						|
            init_maxscale();
 | 
						|
            set_active_maxscale(MXS_PRIMARY);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (backend_ssl)
 | 
						|
    {
 | 
						|
        tprintf("Configuring backends for ssl \n");
 | 
						|
        repl->configure_ssl(true);
 | 
						|
        if (!no_galera)
 | 
						|
        {
 | 
						|
            galera->configure_ssl(false);
 | 
						|
            galera->start_replication();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    char str[1024];
 | 
						|
    sprintf(str, "mkdir -p LOGS/%s", test_name);
 | 
						|
    system(str);
 | 
						|
 | 
						|
    timeout = 999999999;
 | 
						|
    set_log_copy_interval(999999999);
 | 
						|
    pthread_create( &timeout_thread_p, NULL, timeout_thread, this);
 | 
						|
    pthread_create( &log_copy_thread_p, NULL, log_copy_thread, this);
 | 
						|
    tprintf("Starting test");
 | 
						|
    gettimeofday(&start_time, NULL);
 | 
						|
}
 | 
						|
 | 
						|
TestConnections::~TestConnections()
 | 
						|
{
 | 
						|
    if (backend_ssl)
 | 
						|
    {
 | 
						|
        repl->disable_ssl();
 | 
						|
        //galera->disable_ssl();
 | 
						|
    }
 | 
						|
 | 
						|
    copy_all_logs();
 | 
						|
 | 
						|
    if (global_result != 0 )
 | 
						|
    {
 | 
						|
        if (no_vm_revert)
 | 
						|
        {
 | 
						|
            tprintf("no_vm_revert flag is set, not reverting VMs\n");
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            tprintf("Reverting snapshot\n");
 | 
						|
            revert_snapshot((char*) "clean");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    delete repl;
 | 
						|
    if (!no_galera)
 | 
						|
    {
 | 
						|
        delete galera;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void TestConnections::add_result(int result, const char *format, ...)
 | 
						|
{
 | 
						|
    timeval t2;
 | 
						|
    gettimeofday(&t2, NULL);
 | 
						|
    double elapsedTime = (t2.tv_sec - start_time.tv_sec);
 | 
						|
    elapsedTime += (double) (t2.tv_usec - start_time.tv_usec) / 1000000.0;
 | 
						|
 | 
						|
    if (result != 0)
 | 
						|
    {
 | 
						|
        global_result += result;
 | 
						|
 | 
						|
        printf("%04f: TEST_FAILED! ", elapsedTime);
 | 
						|
 | 
						|
        va_list argp;
 | 
						|
        va_start(argp, format);
 | 
						|
        vprintf(format, argp);
 | 
						|
        va_end(argp);
 | 
						|
 | 
						|
        if (format[strlen(format) - 1] != '\n')
 | 
						|
        {
 | 
						|
            printf("\n");
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::read_env()
 | 
						|
{
 | 
						|
 | 
						|
    char *env;
 | 
						|
 | 
						|
    if (verbose)
 | 
						|
    {
 | 
						|
        printf("Reading test setup configuration from environmental variables\n");
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("maxscale_IP");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(maxscale_IP, "%s", env);
 | 
						|
        primary_maxscale_IP = env;
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("maxscale_network6");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(maxscale_IP6, "%s", env);
 | 
						|
        primary_maxscale_IP6 = env;
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("maxscale2_IP");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        secondary_maxscale_IP = env;
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("maxscale2_network6");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        secondary_maxscale_IP = env;
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("maxscale_user");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(maxscale_user, "%s", env);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        sprintf(maxscale_user, "skysql");
 | 
						|
    }
 | 
						|
    env = getenv("maxscale_password");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(maxscale_password, "%s", env);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        sprintf(maxscale_password, "skysql");
 | 
						|
    }
 | 
						|
    env = getenv("maxadmin_password");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(maxadmin_password, "%s", env);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        sprintf(maxadmin_password, "mariadb");
 | 
						|
    }
 | 
						|
    env = getenv("maxscale_keyfile");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(maxscale_keyfile, "%s", env);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        sprintf(maxscale_keyfile, "skysql");
 | 
						|
    }
 | 
						|
 | 
						|
    //env = getenv("get_logs_command"); if (env != NULL) {sprintf(get_logs_command, "%s", env);}
 | 
						|
 | 
						|
    env = getenv("sysbench_dir");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(sysbench_dir, "%s", env);
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("maxscale_cnf");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(maxscale_cnf, "%s", env);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        sprintf(maxscale_cnf, "/etc/maxscale.cnf");
 | 
						|
    }
 | 
						|
    env = getenv("maxscale_log_dir");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(maxscale_log_dir, "%s", env);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        sprintf(maxscale_log_dir, "/var/log/maxscale/");
 | 
						|
    }
 | 
						|
    env = getenv("maxscale_binlog_dir");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(maxscale_binlog_dir, "%s", env);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        sprintf(maxscale_binlog_dir, "/var/lib/maxscale/Binlog_Service/");
 | 
						|
    }
 | 
						|
    //env = getenv("test_dir"); if (env != NULL) {sprintf(test_dir, "%s", env);}
 | 
						|
    env = getenv("maxscale_whoami");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(maxscale_access_user, "%s", env);
 | 
						|
    }
 | 
						|
    env = getenv("maxscale_access_sudo");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(maxscale_access_sudo, "%s", env);
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("ssl");
 | 
						|
    if ((env != NULL) && ((strcasecmp(env, "yes") == 0) || (strcasecmp(env, "true") == 0) ))
 | 
						|
    {
 | 
						|
        ssl = true;
 | 
						|
    }
 | 
						|
    env = getenv("mysql51_only");
 | 
						|
    if ((env != NULL) && ((strcasecmp(env, "yes") == 0) || (strcasecmp(env, "true") == 0) ))
 | 
						|
    {
 | 
						|
        maxscale::check_nodes = false;
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("no_nodes_check");
 | 
						|
    if ((env != NULL) && ((strcasecmp(env, "yes") == 0) || (strcasecmp(env, "true") == 0) ))
 | 
						|
    {
 | 
						|
        maxscale::check_nodes = false;
 | 
						|
    }
 | 
						|
    env = getenv("no_backend_log_copy");
 | 
						|
    if ((env != NULL) && ((strcasecmp(env, "yes") == 0) || (strcasecmp(env, "true") == 0) ))
 | 
						|
    {
 | 
						|
        no_backend_log_copy = true;
 | 
						|
    }
 | 
						|
    env = getenv("use_ipv6");
 | 
						|
    if ((env != NULL) && ((strcasecmp(env, "yes") == 0) || (strcasecmp(env, "true") == 0) ))
 | 
						|
    {
 | 
						|
        use_ipv6 = true;
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("maxscale_hostname");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(maxscale_hostname, "%s", env);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        sprintf(maxscale_hostname, "%s", maxscale_IP);
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("backend_ssl");
 | 
						|
    if (env != NULL && ((strcasecmp(env, "yes") == 0) || (strcasecmp(env, "true") == 0) ))
 | 
						|
    {
 | 
						|
        backend_ssl = true;
 | 
						|
    }
 | 
						|
 | 
						|
    if (strcmp(maxscale_access_user, "root") == 0)
 | 
						|
    {
 | 
						|
        sprintf(maxscale_access_homedir, "/%s/", maxscale_access_user);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        sprintf(maxscale_access_homedir, "/home/%s/", maxscale_access_user);
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("smoke");
 | 
						|
    if (env)
 | 
						|
    {
 | 
						|
        smoke = strcasecmp(env, "yes") == 0 || strcasecmp(env, "true") == 0 ||
 | 
						|
                strcasecmp(env, "1") == 0 || strcasecmp(env, "on") == 0;
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("threads");
 | 
						|
    if ((env != NULL))
 | 
						|
    {
 | 
						|
        sscanf(env, "%d", &threads);
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("use_snapshots");
 | 
						|
    if (env != NULL && ((strcasecmp(env, "yes") == 0) || (strcasecmp(env, "true") == 0) ))
 | 
						|
    {
 | 
						|
        use_snapshots = true;
 | 
						|
    }
 | 
						|
    env = getenv("take_snapshot_command");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(take_snapshot_command, "%s", env);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        sprintf(take_snapshot_command, "exit 1");
 | 
						|
    }
 | 
						|
    env = getenv("revert_snapshot_command");
 | 
						|
    if (env != NULL)
 | 
						|
    {
 | 
						|
        sprintf(revert_snapshot_command, "%s", env);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        sprintf(revert_snapshot_command, "exit 1");
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("no_maxscale_start");
 | 
						|
    if (env != NULL && ((strcasecmp(env, "yes") == 0) || (strcasecmp(env, "true") == 0) ))
 | 
						|
    {
 | 
						|
        maxscale::start = false;
 | 
						|
    }
 | 
						|
 | 
						|
    env = getenv("no_vm_revert");
 | 
						|
    if ((env != NULL) && ((strcasecmp(env, "no") == 0) || (strcasecmp(env, "false") == 0) ))
 | 
						|
    {
 | 
						|
        no_vm_revert = false;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::print_env()
 | 
						|
{
 | 
						|
    int  i;
 | 
						|
    printf("Maxscale IP\t%s\n", maxscale_IP);
 | 
						|
    printf("Maxscale User name\t%s\n", maxscale_user);
 | 
						|
    printf("Maxscale Password\t%s\n", maxscale_password);
 | 
						|
    printf("Maxscale SSH key\t%s\n", maxscale_keyfile);
 | 
						|
    printf("Maxadmin password\t%s\n", maxadmin_password);
 | 
						|
    printf("Access user\t%s\n", maxscale_access_user);
 | 
						|
    repl->print_env();
 | 
						|
    galera->print_env();
 | 
						|
}
 | 
						|
 | 
						|
const char * get_template_name(char * test_name)
 | 
						|
{
 | 
						|
    int i = 0;
 | 
						|
    while (cnf_templates[i].test_name && strcmp(cnf_templates[i].test_name, test_name) != 0)
 | 
						|
    {
 | 
						|
        i++;
 | 
						|
    }
 | 
						|
 | 
						|
    if (cnf_templates[i].test_name)
 | 
						|
    {
 | 
						|
        return cnf_templates[i].test_template;
 | 
						|
    }
 | 
						|
 | 
						|
    printf("Failed to find configuration template for test '%s', using default template '%s'.\n", test_name,
 | 
						|
           default_template);
 | 
						|
    return default_template;
 | 
						|
}
 | 
						|
 | 
						|
void TestConnections::process_template(const char *template_name, const char *dest)
 | 
						|
{
 | 
						|
    char str[4096];
 | 
						|
    char template_file[1024];
 | 
						|
 | 
						|
    sprintf(template_file, "%s/cnf/maxscale.cnf.template.%s", test_dir, template_name);
 | 
						|
    sprintf(str, "cp %s maxscale.cnf", template_file);
 | 
						|
    if (system(str) != 0)
 | 
						|
    {
 | 
						|
        tprintf("Error copying maxscale.cnf template\n");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (backend_ssl)
 | 
						|
    {
 | 
						|
        tprintf("Adding ssl settings\n");
 | 
						|
        system("sed -i \"s|type=server|type=server\\nssl=required\\nssl_cert=/###access_homedir###/certs/client-cert.pem\\nssl_key=/###access_homedir###/certs/client-key.pem\\nssl_ca_cert=/###access_homedir###/certs/ca.pem|g\" maxscale.cnf");
 | 
						|
    }
 | 
						|
 | 
						|
    sprintf(str, "sed -i \"s/###threads###/%d/\"  maxscale.cnf", threads);
 | 
						|
    system(str);
 | 
						|
 | 
						|
    Mariadb_nodes * mdn[2];
 | 
						|
    char * IPcnf;
 | 
						|
    mdn[0] = repl;
 | 
						|
    mdn[1] = galera;
 | 
						|
    int i, j;
 | 
						|
 | 
						|
    for (j = 0; j < 2; j++)
 | 
						|
    {
 | 
						|
        for (i = 0; i < mdn[j]->N; i++)
 | 
						|
        {
 | 
						|
            if (mdn[j]->use_ipv6)
 | 
						|
            {
 | 
						|
                IPcnf = mdn[j]->IP6[i];
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                IPcnf = mdn[j]->IP[i];
 | 
						|
            }
 | 
						|
            sprintf(str, "sed -i \"s/###%s_server_IP_%0d###/%s/\" maxscale.cnf",
 | 
						|
                    mdn[j]->prefix, i + 1, IPcnf);
 | 
						|
            system(str);
 | 
						|
 | 
						|
            sprintf(str, "sed -i \"s/###%s_server_port_%0d###/%d/\" maxscale.cnf",
 | 
						|
                    mdn[j]->prefix, i + 1, mdn[j]->port[i]);
 | 
						|
            system(str);
 | 
						|
        }
 | 
						|
 | 
						|
        mdn[j]->connect();
 | 
						|
        execute_query(mdn[j]->nodes[0], "CREATE DATABASE IF NOT EXISTS test");
 | 
						|
        mdn[j]->close_connections();
 | 
						|
    }
 | 
						|
 | 
						|
    sprintf(str, "sed -i \"s/###access_user###/%s/g\" maxscale.cnf", maxscale_access_user);
 | 
						|
    system(str);
 | 
						|
 | 
						|
    sprintf(str, "sed -i \"s|###access_homedir###|%s|g\" maxscale.cnf", maxscale_access_homedir);
 | 
						|
    system(str);
 | 
						|
 | 
						|
    if (repl->v51)
 | 
						|
    {
 | 
						|
        system("sed -i \"s/###repl51###/mysql51_replication=true/g\" maxscale.cnf");
 | 
						|
    }
 | 
						|
    copy_to_maxscale("maxscale.cnf", (char *) dest);
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::init_maxscale()
 | 
						|
{
 | 
						|
    const char * template_name = get_template_name(test_name);
 | 
						|
    tprintf("Template is %s\n", template_name);
 | 
						|
 | 
						|
    process_template(template_name, maxscale_access_homedir);
 | 
						|
 | 
						|
    ssh_maxscale(true, "cp maxscale.cnf %s;rm -rf %s/certs;mkdir -m a+wrx %s/certs;", maxscale_cnf,
 | 
						|
                 maxscale_access_homedir, maxscale_access_homedir);
 | 
						|
 | 
						|
    char str[4096];
 | 
						|
    char dtr[4096];
 | 
						|
    sprintf(str, "%s/ssl-cert/*", test_dir);
 | 
						|
    sprintf(dtr, "%s/certs/", maxscale_access_homedir);
 | 
						|
    copy_to_maxscale(str, dtr);
 | 
						|
    sprintf(str, "cp %s/ssl-cert/* .", test_dir);
 | 
						|
    system(str);
 | 
						|
 | 
						|
    ssh_maxscale(true, "chown maxscale:maxscale -R %s/certs;"
 | 
						|
                 "chmod 664 %s/certs/*.pem;"
 | 
						|
                 " chmod a+x %s;"
 | 
						|
                 "%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,
 | 
						|
                 maxscale::start ? "killall -9 maxscale;" : "",
 | 
						|
                 maxscale_log_dir, maxscale_log_dir, maxscale::start ? "service maxscale restart" : "");
 | 
						|
 | 
						|
    fflush(stdout);
 | 
						|
 | 
						|
    if (maxscale::start)
 | 
						|
    {
 | 
						|
        int waits;
 | 
						|
 | 
						|
        for (waits = 0; waits < 15; waits++)
 | 
						|
        {
 | 
						|
            if (ssh_maxscale(true, "/bin/sh -c \"maxadmin help > /dev/null || exit 1\"") == 0)
 | 
						|
            {
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            sleep(1);
 | 
						|
        }
 | 
						|
 | 
						|
        if (waits > 0)
 | 
						|
        {
 | 
						|
            tprintf("Waited %d seconds for MaxScale to start", waits);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::connect_maxscale()
 | 
						|
{
 | 
						|
    return connect_rwsplit() +
 | 
						|
           connect_readconn_master() +
 | 
						|
           connect_readconn_slave();
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::close_maxscale_connections()
 | 
						|
{
 | 
						|
    mysql_close(conn_master);
 | 
						|
    mysql_close(conn_slave);
 | 
						|
    mysql_close(conn_rwsplit);
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::restart_maxscale()
 | 
						|
{
 | 
						|
    int res = ssh_maxscale(true, "service maxscale restart");
 | 
						|
    fflush(stdout);
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::start_maxscale()
 | 
						|
{
 | 
						|
    int res = ssh_maxscale(true, "service maxscale start");
 | 
						|
    fflush(stdout);
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::stop_maxscale()
 | 
						|
{
 | 
						|
    int res = ssh_maxscale(true, "service maxscale stop");
 | 
						|
    check_maxscale_processes(0);
 | 
						|
    fflush(stdout);
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::copy_mariadb_logs(Mariadb_nodes * repl, const char* prefix)
 | 
						|
{
 | 
						|
    int local_result = 0;
 | 
						|
    char * mariadb_log;
 | 
						|
    FILE * f;
 | 
						|
    int i;
 | 
						|
    int exit_code;
 | 
						|
    char str[4096];
 | 
						|
 | 
						|
    sprintf(str, "mkdir -p LOGS/%s", test_name);
 | 
						|
    system(str);
 | 
						|
    for (i = 0; i < repl->N; i++)
 | 
						|
    {
 | 
						|
        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, "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)
 | 
						|
            {
 | 
						|
                fwrite(mariadb_log, sizeof(char), strlen(mariadb_log), f);
 | 
						|
                fclose(f);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                printf("Error writing MariaDB log");
 | 
						|
                local_result = 1;
 | 
						|
            }
 | 
						|
            free(mariadb_log);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return local_result;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::copy_all_logs()
 | 
						|
{
 | 
						|
    char str[4096];
 | 
						|
    set_timeout(300);
 | 
						|
 | 
						|
    if (!no_backend_log_copy)
 | 
						|
    {
 | 
						|
        copy_mariadb_logs(repl, "node");
 | 
						|
        copy_mariadb_logs(galera, "galera");
 | 
						|
    }
 | 
						|
 | 
						|
    sprintf(str, "%s/copy_logs.sh %s", test_dir, test_name);
 | 
						|
    tprintf("Executing %s\n", str);
 | 
						|
    if (system(str) != 0)
 | 
						|
    {
 | 
						|
        tprintf("copy_logs.sh executing FAILED!\n");
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        tprintf("copy_logs.sh OK!\n");
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::copy_all_logs_periodic()
 | 
						|
{
 | 
						|
    char str[4096];
 | 
						|
    //set_timeout(300);
 | 
						|
 | 
						|
    timeval t2;
 | 
						|
    gettimeofday(&t2, NULL);
 | 
						|
    double elapsedTime = (t2.tv_sec - start_time.tv_sec);
 | 
						|
    elapsedTime += (double) (t2.tv_usec - start_time.tv_usec) / 1000000.0;
 | 
						|
 | 
						|
    sprintf(str, "%s/copy_logs.sh %s %04f", test_dir, test_name, elapsedTime);
 | 
						|
    tprintf("Executing %s\n", str);
 | 
						|
    if (system(str) != 0)
 | 
						|
    {
 | 
						|
        tprintf("copy_logs.sh executing FAILED!\n");
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        tprintf("copy_logs.sh OK!\n");
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::prepare_binlog()
 | 
						|
{
 | 
						|
    char version_str[1024] = "";
 | 
						|
 | 
						|
    repl->connect();
 | 
						|
    find_field(repl->nodes[0], "SELECT @@version", "@@version", version_str);
 | 
						|
    tprintf("Master server version '%s'", version_str);
 | 
						|
 | 
						|
    if (*version_str &&
 | 
						|
        strstr(version_str, "10.0") == NULL &&
 | 
						|
        strstr(version_str, "10.1") == NULL &&
 | 
						|
        strstr(version_str, "10.2") == NULL)
 | 
						|
    {
 | 
						|
        add_result(ssh_maxscale(true,
 | 
						|
                                "sed -i \"s/,mariadb10-compatibility=1//\" %s",
 | 
						|
                                maxscale_cnf), "Error editing maxscale.cnf");
 | 
						|
    }
 | 
						|
 | 
						|
    tprintf("Removing all binlog data from Maxscale node");
 | 
						|
    add_result(ssh_maxscale(true, "rm -rf %s", maxscale_binlog_dir),
 | 
						|
               "Removing binlog data failed");
 | 
						|
 | 
						|
    tprintf("Creating binlog dir");
 | 
						|
    add_result(ssh_maxscale(true, "mkdir -p %s", maxscale_binlog_dir),
 | 
						|
               "Creating binlog data dir failed");
 | 
						|
    tprintf("Set 'maxscale' as a owner of binlog dir");
 | 
						|
    add_result(ssh_maxscale(false,
 | 
						|
                            "%s mkdir -p %s; %s chown maxscale:maxscale -R %s",
 | 
						|
                            maxscale_access_sudo, maxscale_binlog_dir,
 | 
						|
                            maxscale_access_sudo, maxscale_binlog_dir),
 | 
						|
               "directory ownership change failed");
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::start_binlog()
 | 
						|
{
 | 
						|
    char sys1[4096];
 | 
						|
    MYSQL * binlog;
 | 
						|
    char log_file[256];
 | 
						|
    char log_pos[256];
 | 
						|
    char cmd_opt[256];
 | 
						|
 | 
						|
    int i;
 | 
						|
    int global_result = 0;
 | 
						|
    bool no_pos;
 | 
						|
 | 
						|
    no_pos = repl->no_set_pos;
 | 
						|
 | 
						|
    switch (binlog_cmd_option)
 | 
						|
    {
 | 
						|
    case 1:
 | 
						|
        sprintf(cmd_opt, "--binlog-checksum=CRC32");
 | 
						|
        break;
 | 
						|
    case 2:
 | 
						|
        sprintf(cmd_opt, "--binlog-checksum=NONE");
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        sprintf(cmd_opt, " ");
 | 
						|
    }
 | 
						|
 | 
						|
    repl->stop_nodes();
 | 
						|
 | 
						|
    binlog = open_conn_no_db(binlog_port, maxscale_IP, repl->user_name, repl->password, ssl);
 | 
						|
    execute_query(binlog, "stop slave");
 | 
						|
    execute_query(binlog, "reset slave all");
 | 
						|
    execute_query(binlog, "reset master");
 | 
						|
    mysql_close(binlog);
 | 
						|
 | 
						|
    tprintf("Stopping maxscale\n");
 | 
						|
    add_result(stop_maxscale(), "Maxscale stopping failed\n");
 | 
						|
 | 
						|
    for (i = 0; i < repl->N; i++)
 | 
						|
    {
 | 
						|
        repl->start_node(i, cmd_opt);
 | 
						|
    }
 | 
						|
    sleep(5);
 | 
						|
 | 
						|
    tprintf("Connecting to all backend nodes\n");
 | 
						|
    repl->connect();
 | 
						|
 | 
						|
    tprintf("Stopping everything\n");
 | 
						|
    for (i = 0; i < repl->N; i++)
 | 
						|
    {
 | 
						|
        execute_query(repl->nodes[i], "stop slave");
 | 
						|
        execute_query(repl->nodes[i], "reset slave all");
 | 
						|
        execute_query(repl->nodes[i], "reset master");
 | 
						|
    }
 | 
						|
 | 
						|
    prepare_binlog();
 | 
						|
 | 
						|
    tprintf("Testing binlog when MariaDB is started with '%s' option\n", cmd_opt);
 | 
						|
 | 
						|
    tprintf("ls binlog data dir on Maxscale node\n");
 | 
						|
    add_result(ssh_maxscale(true, "ls -la %s/", maxscale_binlog_dir), "ls failed\n");
 | 
						|
 | 
						|
    if (binlog_master_gtid)
 | 
						|
    {
 | 
						|
        // GTID to connect real Master
 | 
						|
        tprintf("GTID for connection 1st slave to master!\n");
 | 
						|
        try_query(repl->nodes[1], (char *) "stop slave");
 | 
						|
        try_query(repl->nodes[1], (char *) "SET @@global.gtid_slave_pos=''");
 | 
						|
        sprintf(sys1, "CHANGE MASTER TO MASTER_HOST='%s', MASTER_PORT=%d, MASTER_USER='repl', MASTER_PASSWORD='repl', MASTER_USE_GTID=Slave_pos",
 | 
						|
                repl->IP[0], repl->port[0]);
 | 
						|
        try_query(repl->nodes[1], sys1);
 | 
						|
        try_query(repl->nodes[1], (char *) "start slave");
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        tprintf("show master status\n");
 | 
						|
        find_field(repl->nodes[0], (char *) "show master status", (char *) "File", &log_file[0]);
 | 
						|
        find_field(repl->nodes[0], (char *) "show master status", (char *) "Position", &log_pos[0]);
 | 
						|
        tprintf("Real master file: %s\n", log_file);
 | 
						|
        tprintf("Real master pos : %s\n", log_pos);
 | 
						|
 | 
						|
        tprintf("Stopping first slave (node 1)\n");
 | 
						|
        try_query(repl->nodes[1], (char *) "stop slave;");
 | 
						|
        //repl->no_set_pos = true;
 | 
						|
        repl->no_set_pos = false;
 | 
						|
        tprintf("Configure first backend slave node to be slave of real master\n");
 | 
						|
        repl->set_slave(repl->nodes[1], repl->IP[0],  repl->port[0], log_file, log_pos);
 | 
						|
    }
 | 
						|
 | 
						|
    tprintf("Starting back Maxscale\n");
 | 
						|
    add_result(start_maxscale(), "Maxscale start failed\n");
 | 
						|
 | 
						|
    tprintf("Connecting to MaxScale binlog router (with any DB)\n");
 | 
						|
    binlog = open_conn_no_db(binlog_port, maxscale_IP, repl->user_name, repl->password, ssl);
 | 
						|
 | 
						|
    add_result(mysql_errno(binlog), "Error connection to binlog router %s\n", mysql_error(binlog));
 | 
						|
 | 
						|
    if (binlog_master_gtid)
 | 
						|
    {
 | 
						|
        // GTID to connect real Master
 | 
						|
        tprintf("GTID for connection binlog router to master!\n");
 | 
						|
        try_query(binlog, (char *) "stop slave");
 | 
						|
        try_query(binlog, (char *) "SET @@global.gtid_slave_pos=''");
 | 
						|
        sprintf(sys1, "CHANGE MASTER TO MASTER_HOST='%s', MASTER_PORT=%d, MASTER_USER='repl', MASTER_PASSWORD='repl', MASTER_USE_GTID=Slave_pos",
 | 
						|
                repl->IP[0], repl->port[0]);
 | 
						|
        try_query(binlog, sys1);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        repl->no_set_pos = true;
 | 
						|
        tprintf("configuring Maxscale binlog router\n");
 | 
						|
        repl->set_slave(binlog, repl->IP[0], repl->port[0], log_file, log_pos);
 | 
						|
 | 
						|
 | 
						|
    }
 | 
						|
    // ssl between binlog router and Master
 | 
						|
    if (backend_ssl)
 | 
						|
    {
 | 
						|
        sprintf(sys1,
 | 
						|
                "CHANGE MASTER TO master_ssl_cert='%s/certs/client-cert.pem', master_ssl_ca='%s/certs/ca.pem', master_ssl=1, master_ssl_key='%s/certs/client-key.pem'",
 | 
						|
                maxscale_access_homedir, maxscale_access_homedir, maxscale_access_homedir);
 | 
						|
        tprintf("Configuring Master ssl: %s\n", sys1);
 | 
						|
        try_query(binlog, sys1);
 | 
						|
    }
 | 
						|
    try_query(binlog, "start slave");
 | 
						|
    try_query(binlog, "show slave status");
 | 
						|
 | 
						|
    if (binlog_slave_gtid)
 | 
						|
    {
 | 
						|
        tprintf("GTID for connection slaves to binlog router!\n");
 | 
						|
        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");
 | 
						|
            try_query(repl->nodes[i], (char *) "SET @@global.gtid_slave_pos=''");
 | 
						|
            sprintf(sys1, "CHANGE MASTER TO MASTER_HOST='%s', MASTER_PORT=%d, MASTER_USER='repl', MASTER_PASSWORD='repl', MASTER_USE_GTID=Slave_pos",
 | 
						|
                    maxscale_IP, binlog_port);
 | 
						|
            try_query(repl->nodes[i], sys1);
 | 
						|
            try_query(repl->nodes[i], (char *) "start slave");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        repl->no_set_pos = false;
 | 
						|
 | 
						|
        // get Master status from Maxscale binlog
 | 
						|
        tprintf("show master status\n");
 | 
						|
        fflush(stdout);
 | 
						|
        find_field(binlog, (char *) "show master status", (char *) "File", &log_file[0]);
 | 
						|
        find_field(binlog, (char *) "show master status", (char *) "Position", &log_pos[0]);
 | 
						|
 | 
						|
        tprintf("Maxscale binlog master file: %s\n", log_file);
 | 
						|
        fflush(stdout);
 | 
						|
        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], "stop slave;");
 | 
						|
            repl->set_slave(repl->nodes[i],  maxscale_IP, binlog_port, log_file, log_pos);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    repl->close_connections();
 | 
						|
    try_query(binlog, "show slave status");
 | 
						|
    mysql_close(binlog);
 | 
						|
    repl->no_set_pos = no_pos;
 | 
						|
    return global_result;
 | 
						|
}
 | 
						|
 | 
						|
bool TestConnections::replicate_from_master()
 | 
						|
{
 | 
						|
    bool rval = true;
 | 
						|
 | 
						|
    /** Stop the binlogrouter */
 | 
						|
    MYSQL* conn = open_conn_no_db(binlog_port, maxscale_IP, repl->user_name, repl->password, ssl);
 | 
						|
 | 
						|
    if (execute_query(conn, "stop slave"))
 | 
						|
    {
 | 
						|
        rval = false;
 | 
						|
    }
 | 
						|
    mysql_close(conn);
 | 
						|
 | 
						|
    repl->execute_query_all_nodes("STOP SLAVE");
 | 
						|
 | 
						|
    /** Clean up MaxScale directories */
 | 
						|
    ssh_maxscale(true, "service maxscale stop");
 | 
						|
    prepare_binlog();
 | 
						|
    ssh_maxscale(true, "service maxscale start");
 | 
						|
 | 
						|
    char log_file[256] = "";
 | 
						|
    char log_pos[256] = "4";
 | 
						|
 | 
						|
    repl->connect();
 | 
						|
    execute_query(repl->nodes[0], "RESET MASTER");
 | 
						|
 | 
						|
    conn = open_conn_no_db(binlog_port, maxscale_IP, repl->user_name, repl->password, ssl);
 | 
						|
 | 
						|
    if (find_field(repl->nodes[0], "show master status", "File", log_file) ||
 | 
						|
        repl->set_slave(conn, repl->IP[0], repl->port[0], log_file, log_pos) ||
 | 
						|
        execute_query(conn, "start slave"))
 | 
						|
    {
 | 
						|
        rval = false;
 | 
						|
    }
 | 
						|
 | 
						|
    mysql_close(conn);
 | 
						|
 | 
						|
    return rval;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::start_mm()
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    char log_file1[256];
 | 
						|
    char log_pos1[256];
 | 
						|
    char log_file2[256];
 | 
						|
    char log_pos2[256];
 | 
						|
 | 
						|
    tprintf("Stopping maxscale\n");
 | 
						|
    fflush(stdout);
 | 
						|
    int global_result = stop_maxscale();
 | 
						|
 | 
						|
    tprintf("Stopping all backend nodes\n");
 | 
						|
    fflush(stdout);
 | 
						|
    global_result += repl->stop_nodes();
 | 
						|
 | 
						|
    for (i = 0; i < 2; i++)
 | 
						|
    {
 | 
						|
        tprintf("Starting back node %d\n", i);
 | 
						|
        global_result += repl->start_node(i, "");
 | 
						|
    }
 | 
						|
 | 
						|
    repl->connect();
 | 
						|
    for (i = 0; i < 2; i++)
 | 
						|
    {
 | 
						|
        execute_query(repl->nodes[i], "stop slave");
 | 
						|
        execute_query(repl->nodes[i], "reset master");
 | 
						|
    }
 | 
						|
 | 
						|
    execute_query(repl->nodes[0], "SET GLOBAL READ_ONLY=ON");
 | 
						|
 | 
						|
    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], "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);
 | 
						|
 | 
						|
    repl->close_connections();
 | 
						|
 | 
						|
    tprintf("Starting back Maxscale\n");
 | 
						|
    fflush(stdout);
 | 
						|
    global_result += start_maxscale();
 | 
						|
 | 
						|
    return global_result;
 | 
						|
}
 | 
						|
 | 
						|
bool TestConnections::log_matches(const char* pattern)
 | 
						|
{
 | 
						|
    return ssh_maxscale(true, "grep '%s' /var/log/maxscale/maxscale*.log", pattern) == 0;
 | 
						|
}
 | 
						|
 | 
						|
void TestConnections::log_includes(const char* pattern)
 | 
						|
{
 | 
						|
    add_result(!log_matches(pattern), "Log does not match pattern '%s'", pattern);
 | 
						|
}
 | 
						|
 | 
						|
void TestConnections::log_excludes(const char* pattern)
 | 
						|
{
 | 
						|
    add_result(log_matches(pattern), "Log matches pattern '%s'", pattern);
 | 
						|
}
 | 
						|
 | 
						|
void TestConnections::check_log_err(const char * err_msg, bool expected)
 | 
						|
{
 | 
						|
 | 
						|
    char * err_log_content;
 | 
						|
 | 
						|
    tprintf("Getting logs\n");
 | 
						|
    char sys1[4096];
 | 
						|
    set_timeout(100);
 | 
						|
    sprintf(&sys1[0], "rm -f *.log; %s %s", get_logs_command, maxscale_IP);
 | 
						|
    //tprintf("Executing: %s\n", sys1);
 | 
						|
    system(sys1);
 | 
						|
    set_timeout(50);
 | 
						|
 | 
						|
    tprintf("Reading maxscale.log\n");
 | 
						|
    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("maxscale1.log", &err_log_content) != 0)
 | 
						|
        {
 | 
						|
            add_result(1, "Error reading log\n");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    //printf("\n\n%s\n\n", err_log_content);
 | 
						|
    if (err_log_content != NULL)
 | 
						|
    {
 | 
						|
        if (expected)
 | 
						|
        {
 | 
						|
            if (strstr(err_log_content, err_msg) == NULL)
 | 
						|
            {
 | 
						|
                add_result(1, "There is NO \"%s\" error in the log\n", err_msg);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                tprintf("There is proper \"%s \" error in the log\n", err_msg);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            if (strstr(err_log_content, err_msg) != NULL)
 | 
						|
            {
 | 
						|
                add_result(1, "There is UNEXPECTED error \"%s\" error in the log\n", err_msg);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                tprintf("There are no unxpected errors \"%s \" error in the log\n", err_msg);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        free(err_log_content);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::find_connected_slave(int * global_result)
 | 
						|
{
 | 
						|
    int conn_num;
 | 
						|
    int all_conn = 0;
 | 
						|
    int current_slave = -1;
 | 
						|
    repl->connect();
 | 
						|
    for (int i = 0; i < repl->N; i++)
 | 
						|
    {
 | 
						|
        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))
 | 
						|
        {
 | 
						|
            tprintf("There is no connection to master\n");
 | 
						|
            *global_result = 1;
 | 
						|
        }
 | 
						|
        all_conn += conn_num;
 | 
						|
        if ((i != 0) && (conn_num != 0))
 | 
						|
        {
 | 
						|
            current_slave = i;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if (all_conn != 2)
 | 
						|
    {
 | 
						|
        tprintf("total number of connections is not 2, it is %d\n", all_conn);
 | 
						|
        *global_result = 1;
 | 
						|
    }
 | 
						|
    tprintf("Now connected slave node is %d (%s)\n", current_slave, repl->IP[current_slave]);
 | 
						|
    repl->close_connections();
 | 
						|
    return current_slave;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::find_connected_slave1()
 | 
						|
{
 | 
						|
    int conn_num;
 | 
						|
    int all_conn = 0;
 | 
						|
    int current_slave = -1;
 | 
						|
    repl->connect();
 | 
						|
    for (int i = 0; i < repl->N; i++)
 | 
						|
    {
 | 
						|
        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))
 | 
						|
        {
 | 
						|
            current_slave = i;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    tprintf("Now connected slave node is %d (%s)\n", current_slave, repl->IP[current_slave]);
 | 
						|
    repl->close_connections();
 | 
						|
    return current_slave;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::check_maxscale_processes(int expected)
 | 
						|
{
 | 
						|
    char* maxscale_num = ssh_maxscale_output(false, "ps -C maxscale | grep maxscale | wc -l");
 | 
						|
    if (maxscale_num == NULL)
 | 
						|
    {
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    char* nl = strchr(maxscale_num, '\n');
 | 
						|
    if (nl)
 | 
						|
    {
 | 
						|
        *nl = '\0';
 | 
						|
    }
 | 
						|
 | 
						|
    if (atoi(maxscale_num) != expected)
 | 
						|
    {
 | 
						|
        tprintf("%s maxscale processes detected, trying agin in 5 seconds\n", maxscale_num);
 | 
						|
        sleep(5);
 | 
						|
        maxscale_num = ssh_maxscale_output(false, "ps -C maxscale | grep maxscale | wc -l");
 | 
						|
        if (atoi(maxscale_num) != expected)
 | 
						|
        {
 | 
						|
            add_result(1, "Number of MaxScale processes is not %d, it is %s\n", expected, maxscale_num);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::check_maxscale_alive()
 | 
						|
{
 | 
						|
    int gr = global_result;
 | 
						|
    set_timeout(10);
 | 
						|
    tprintf("Connecting to Maxscale\n");
 | 
						|
    add_result(connect_maxscale(), "Can not connect to Maxscale\n");
 | 
						|
    tprintf("Trying simple query against all sevices\n");
 | 
						|
    tprintf("RWSplit \n");
 | 
						|
    set_timeout(10);
 | 
						|
    try_query(conn_rwsplit, "show databases;");
 | 
						|
    tprintf("ReadConn Master \n");
 | 
						|
    set_timeout(10);
 | 
						|
    try_query(conn_master, "show databases;");
 | 
						|
    tprintf("ReadConn Slave \n");
 | 
						|
    set_timeout(10);
 | 
						|
    try_query(conn_slave, "show databases;");
 | 
						|
    set_timeout(10);
 | 
						|
    close_maxscale_connections()    ;
 | 
						|
    add_result(global_result - gr, "Maxscale is not alive\n");
 | 
						|
    stop_timeout();
 | 
						|
 | 
						|
    check_maxscale_processes(1);
 | 
						|
 | 
						|
    return global_result - gr;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::test_maxscale_connections(bool rw_split, bool rc_master, bool rc_slave)
 | 
						|
{
 | 
						|
    int rval = 0;
 | 
						|
    int rc;
 | 
						|
 | 
						|
    tprintf("Testing RWSplit, expecting %s\n", (rw_split ? "success" : "failure"));
 | 
						|
    rc = execute_query(conn_rwsplit, "select 1");
 | 
						|
    if ((rc == 0) != rw_split)
 | 
						|
    {
 | 
						|
        tprintf("Error: Query %s\n", (rw_split ? "failed" : "succeeded"));
 | 
						|
        rval++;
 | 
						|
    }
 | 
						|
 | 
						|
    tprintf("Testing ReadConnRoute Master, expecting %s\n", (rc_master ? "success" : "failure"));
 | 
						|
    rc = execute_query(conn_master, "select 1");
 | 
						|
    if ((rc == 0) != rc_master)
 | 
						|
    {
 | 
						|
        tprintf("Error: Query %s", (rc_master ? "failed" : "succeeded"));
 | 
						|
        rval++;
 | 
						|
    }
 | 
						|
 | 
						|
    tprintf("Testing ReadConnRoute Slave, expecting %s\n", (rc_slave ? "success" : "failure"));
 | 
						|
    rc = execute_query(conn_slave, "select 1");
 | 
						|
    if ((rc == 0) != rc_slave)
 | 
						|
    {
 | 
						|
        tprintf("Error: Query %s", (rc_slave ? "failed" : "succeeded"));
 | 
						|
        rval++;
 | 
						|
    }
 | 
						|
    return rval;
 | 
						|
}
 | 
						|
 | 
						|
void TestConnections::generate_ssh_cmd(char * cmd, char * ssh, bool sudo)
 | 
						|
{
 | 
						|
    if (strcmp(maxscale_IP, "127.0.0.1") == 0)
 | 
						|
    {
 | 
						|
        if (sudo)
 | 
						|
        {
 | 
						|
            sprintf(cmd,
 | 
						|
                    "%s %s",
 | 
						|
                    maxscale_access_sudo, ssh);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            sprintf(cmd,
 | 
						|
                    "%s",
 | 
						|
                    ssh);
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        if (sudo)
 | 
						|
        {
 | 
						|
            sprintf(cmd,
 | 
						|
                    "ssh -i %s -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=quiet %s@%s '%s %s'",
 | 
						|
                    maxscale_keyfile, maxscale_access_user, maxscale_IP, maxscale_access_sudo, ssh);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            sprintf(cmd,
 | 
						|
                    "ssh -i %s -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=quiet %s@%s '%s\'",
 | 
						|
                    maxscale_keyfile, maxscale_access_user, maxscale_IP, ssh);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
char* TestConnections::ssh_maxscale_output(bool sudo, const char* format, ...)
 | 
						|
{
 | 
						|
    va_list valist;
 | 
						|
 | 
						|
    va_start(valist, format);
 | 
						|
    int message_len = vsnprintf(NULL, 0, format, valist);
 | 
						|
    va_end(valist);
 | 
						|
 | 
						|
    if (message_len < 0)
 | 
						|
    {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    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);
 | 
						|
    generate_ssh_cmd(cmd, sys, sudo);
 | 
						|
//tprintf("############ssh smd %s\n:", cmd);
 | 
						|
    FILE *output = popen(cmd, "r");
 | 
						|
    if (output == NULL)
 | 
						|
    {
 | 
						|
        printf("Error opening ssh %s\n", strerror(errno));
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
    char buffer[1024];
 | 
						|
    size_t rsize = sizeof(buffer);
 | 
						|
    char* result = (char*)calloc(rsize, sizeof(char));
 | 
						|
 | 
						|
    while (fgets(buffer, sizeof(buffer), output))
 | 
						|
    {
 | 
						|
        result = (char*)realloc(result, sizeof(buffer) + rsize);
 | 
						|
        rsize += sizeof(buffer);
 | 
						|
        strcat(result, buffer);
 | 
						|
    }
 | 
						|
 | 
						|
    free(sys);
 | 
						|
    free(cmd);
 | 
						|
    pclose(output);
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
int  TestConnections::ssh_maxscale(bool sudo, const char* format, ...)
 | 
						|
{
 | 
						|
    va_list valist;
 | 
						|
 | 
						|
    va_start(valist, format);
 | 
						|
    int message_len = vsnprintf(NULL, 0, format, valist);
 | 
						|
    va_end(valist);
 | 
						|
 | 
						|
    if (message_len < 0)
 | 
						|
    {
 | 
						|
        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(maxscale_IP, "127.0.0.1") == 0)
 | 
						|
    {
 | 
						|
        tprintf("starting bash\n");
 | 
						|
        sprintf(cmd, "bash");
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        sprintf(cmd,
 | 
						|
                "ssh -i %s -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=quiet %s@%s%s",
 | 
						|
                maxscale_keyfile, maxscale_access_user, maxscale_IP, verbose ? "" :  " > /dev/null");
 | 
						|
    }
 | 
						|
    int rc = 1;
 | 
						|
    FILE *in = popen(cmd, "w");
 | 
						|
 | 
						|
    if (in)
 | 
						|
    {
 | 
						|
        if (sudo)
 | 
						|
        {
 | 
						|
            fprintf(in, "sudo su -\n");
 | 
						|
            fprintf(in, "cd /home/%s\n", maxscale_access_user);
 | 
						|
        }
 | 
						|
 | 
						|
        fprintf(in, "%s\n", sys);
 | 
						|
        rc = pclose(in);
 | 
						|
    }
 | 
						|
 | 
						|
    free(sys);
 | 
						|
    free(cmd);
 | 
						|
    return WEXITSTATUS(rc);
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::copy_to_maxscale(const char* src, const char* dest)
 | 
						|
{
 | 
						|
    char sys[strlen(src) + strlen(dest) + 1024];
 | 
						|
    if (strcmp(maxscale_IP, "127.0.0.1") == 0)
 | 
						|
    {
 | 
						|
        sprintf(sys, "cp %s %s",
 | 
						|
                src, dest);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
 | 
						|
        sprintf(sys, "scp -q -i %s -o UserKnownHostsFile=/dev/null "
 | 
						|
                "-o StrictHostKeyChecking=no -o LogLevel=quiet %s %s@%s:%s",
 | 
						|
                maxscale_keyfile, src, maxscale_access_user, maxscale_IP, dest);
 | 
						|
    }
 | 
						|
    return system(sys);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int TestConnections::copy_from_maxscale(char* src, char* dest)
 | 
						|
{
 | 
						|
    char sys[strlen(src) + strlen(dest) + 1024];
 | 
						|
    if (strcmp(maxscale_IP, "127.0.0.1") == 0)
 | 
						|
    {
 | 
						|
        sprintf(sys, "cp %s %s",
 | 
						|
                src, dest);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        sprintf(sys, "scp -i %s -o UserKnownHostsFile=/dev/null "
 | 
						|
                "-o StrictHostKeyChecking=no -o LogLevel=quiet %s@%s:%s %s",
 | 
						|
                maxscale_keyfile, maxscale_access_user, maxscale_IP, src, dest);
 | 
						|
    }
 | 
						|
    return system(sys);
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::create_connections(int conn_N, bool rwsplit_flag, bool master_flag, bool slave_flag,
 | 
						|
                                        bool galera_flag)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    int local_result = 0;
 | 
						|
    MYSQL * rwsplit_conn[conn_N];
 | 
						|
    MYSQL * master_conn[conn_N];
 | 
						|
    MYSQL * slave_conn[conn_N];
 | 
						|
    MYSQL * galera_conn[conn_N];
 | 
						|
 | 
						|
 | 
						|
    tprintf("Opening %d connections to each router\n", conn_N);
 | 
						|
    for (i = 0; i < conn_N; i++)
 | 
						|
    {
 | 
						|
        set_timeout(20);
 | 
						|
 | 
						|
        if (verbose)
 | 
						|
        {
 | 
						|
            tprintf("opening %d-connection: ", i + 1);
 | 
						|
        }
 | 
						|
 | 
						|
        if (rwsplit_flag)
 | 
						|
        {
 | 
						|
            if (verbose)
 | 
						|
            {
 | 
						|
                printf("RWSplit \t");
 | 
						|
            }
 | 
						|
 | 
						|
            rwsplit_conn[i] = open_rwsplit_connection();
 | 
						|
            if (!rwsplit_conn[i])
 | 
						|
            {
 | 
						|
                local_result++;
 | 
						|
                tprintf("RWSplit connection failed\n");
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (master_flag)
 | 
						|
        {
 | 
						|
            if (verbose)
 | 
						|
            {
 | 
						|
                printf("ReadConn master \t");
 | 
						|
            }
 | 
						|
 | 
						|
            master_conn[i] = open_readconn_master_connection();
 | 
						|
            if ( mysql_errno(master_conn[i]) != 0 )
 | 
						|
            {
 | 
						|
                local_result++;
 | 
						|
                tprintf("ReadConn master connection failed, error: %s\n", mysql_error(master_conn[i]) );
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (slave_flag)
 | 
						|
        {
 | 
						|
            if (verbose)
 | 
						|
            {
 | 
						|
                printf("ReadConn slave \t");
 | 
						|
            }
 | 
						|
 | 
						|
            slave_conn[i] = open_readconn_slave_connection();
 | 
						|
            if ( mysql_errno(slave_conn[i]) != 0 )
 | 
						|
            {
 | 
						|
                local_result++;
 | 
						|
                tprintf("ReadConn slave connection failed, error: %s\n", mysql_error(slave_conn[i]) );
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (galera_flag)
 | 
						|
        {
 | 
						|
            if (verbose)
 | 
						|
            {
 | 
						|
                printf("Galera \n");
 | 
						|
            }
 | 
						|
 | 
						|
            galera_conn[i] = open_conn(4016, maxscale_IP, maxscale_user, maxscale_password, ssl);
 | 
						|
            if ( mysql_errno(galera_conn[i]) != 0)
 | 
						|
            {
 | 
						|
                local_result++;
 | 
						|
                tprintf("Galera connection failed, error: %s\n", mysql_error(galera_conn[i]));
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    for (i = 0; i < conn_N; i++)
 | 
						|
    {
 | 
						|
        set_timeout(20);
 | 
						|
 | 
						|
        if (verbose)
 | 
						|
        {
 | 
						|
            tprintf("Trying query against %d-connection: ", i + 1);
 | 
						|
        }
 | 
						|
 | 
						|
        if (rwsplit_flag)
 | 
						|
        {
 | 
						|
            if (verbose)
 | 
						|
            {
 | 
						|
                tprintf("RWSplit \t");
 | 
						|
            }
 | 
						|
            local_result += execute_query(rwsplit_conn[i], "select 1;");
 | 
						|
        }
 | 
						|
        if (master_flag)
 | 
						|
        {
 | 
						|
            if (verbose)
 | 
						|
            {
 | 
						|
                tprintf("ReadConn master \t");
 | 
						|
            }
 | 
						|
            local_result += execute_query(master_conn[i], "select 1;");
 | 
						|
        }
 | 
						|
        if (slave_flag)
 | 
						|
        {
 | 
						|
            if (verbose)
 | 
						|
            {
 | 
						|
                tprintf("ReadConn slave \t");
 | 
						|
            }
 | 
						|
            local_result += execute_query(slave_conn[i], "select 1;");
 | 
						|
        }
 | 
						|
        if (galera_flag)
 | 
						|
        {
 | 
						|
            if (verbose)
 | 
						|
            {
 | 
						|
                tprintf("Galera \n");
 | 
						|
            }
 | 
						|
            local_result += execute_query(galera_conn[i], "select 1;");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    //global_result += check_pers_conn(Test, pers_conn_expected);
 | 
						|
    tprintf("Closing all connections\n");
 | 
						|
    for (i = 0; i < conn_N; i++)
 | 
						|
    {
 | 
						|
        set_timeout(20);
 | 
						|
        if (rwsplit_flag)
 | 
						|
        {
 | 
						|
            mysql_close(rwsplit_conn[i]);
 | 
						|
        }
 | 
						|
        if (master_flag)
 | 
						|
        {
 | 
						|
            mysql_close(master_conn[i]);
 | 
						|
        }
 | 
						|
        if (slave_flag)
 | 
						|
        {
 | 
						|
            mysql_close(slave_conn[i]);
 | 
						|
        }
 | 
						|
        if (galera_flag)
 | 
						|
        {
 | 
						|
            mysql_close(galera_conn[i]);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    stop_timeout();
 | 
						|
 | 
						|
    return local_result;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::get_client_ip(char * ip)
 | 
						|
{
 | 
						|
    MYSQL * conn;
 | 
						|
    MYSQL_RES *res;
 | 
						|
    MYSQL_ROW row;
 | 
						|
    int ret = 1;
 | 
						|
    unsigned long long int num_fields;
 | 
						|
    //unsigned long long int row_i=0;
 | 
						|
    unsigned long long int rows;
 | 
						|
    unsigned long long int i;
 | 
						|
    unsigned int conn_num = 0;
 | 
						|
 | 
						|
    connect_rwsplit();
 | 
						|
    if (execute_query(conn_rwsplit, "CREATE DATABASE IF NOT EXISTS db_to_check_client_ip") != 0 )
 | 
						|
    {
 | 
						|
        return ret;
 | 
						|
    }
 | 
						|
    close_rwsplit();
 | 
						|
    conn = open_conn_db(rwsplit_port, maxscale_IP, "db_to_check_client_ip", maxscale_user,
 | 
						|
                        maxscale_password, ssl);
 | 
						|
 | 
						|
    if (conn != NULL)
 | 
						|
    {
 | 
						|
        if (mysql_query(conn, "show processlist;") != 0)
 | 
						|
        {
 | 
						|
            printf("Error: can't execute SQL-query: show processlist\n");
 | 
						|
            printf("%s\n\n", mysql_error(conn));
 | 
						|
            conn_num = 0;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            res = mysql_store_result(conn);
 | 
						|
            if (res == NULL)
 | 
						|
            {
 | 
						|
                printf("Error: can't get the result description\n");
 | 
						|
                conn_num = -1;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                num_fields = mysql_num_fields(res);
 | 
						|
                rows = mysql_num_rows(res);
 | 
						|
                for (i = 0; i < rows; i++)
 | 
						|
                {
 | 
						|
                    row = mysql_fetch_row(res);
 | 
						|
                    if ( (row[2] != NULL ) && (row[3] != NULL) )
 | 
						|
                    {
 | 
						|
                        if  (strstr(row[3], "db_to_check_client_ip") != NULL)
 | 
						|
                        {
 | 
						|
                            ret = 0;
 | 
						|
                            strcpy(ip, row[2]);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            mysql_free_result(res);
 | 
						|
        }
 | 
						|
        execute_query(conn_rwsplit, "DROP DATABASE db_to_check_client_ip");
 | 
						|
    }
 | 
						|
 | 
						|
    mysql_close(conn);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::set_timeout(long int timeout_seconds)
 | 
						|
{
 | 
						|
    if (enable_timeouts)
 | 
						|
    {
 | 
						|
        timeout = timeout_seconds;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::set_log_copy_interval(long int interval_seconds)
 | 
						|
{
 | 
						|
    log_copy_to_go = interval_seconds;
 | 
						|
    log_copy_interval = interval_seconds;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::stop_timeout()
 | 
						|
{
 | 
						|
    timeout = 999999999;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::tprintf(const char *format, ...)
 | 
						|
{
 | 
						|
    timeval t2;
 | 
						|
    gettimeofday(&t2, NULL);
 | 
						|
    double elapsedTime = (t2.tv_sec - start_time.tv_sec);
 | 
						|
    elapsedTime += (double) (t2.tv_usec - start_time.tv_usec) / 1000000.0;
 | 
						|
 | 
						|
    struct tm tm_now;
 | 
						|
    localtime_r(&t2.tv_sec, &tm_now);
 | 
						|
    unsigned int msec = t2.tv_usec / 1000;
 | 
						|
 | 
						|
    printf("%02u:%02u:%02u.%03u %04f: ", tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec, msec, elapsedTime);
 | 
						|
 | 
						|
    va_list argp;
 | 
						|
    va_start(argp, format);
 | 
						|
    vprintf(format, argp);
 | 
						|
    va_end(argp);
 | 
						|
 | 
						|
    /** Add a newline if the message doesn't have one */
 | 
						|
    if (format[strlen(format) - 1] != '\n')
 | 
						|
    {
 | 
						|
        printf("\n");
 | 
						|
    }
 | 
						|
 | 
						|
    fflush(stdout);
 | 
						|
    fflush(stderr);
 | 
						|
}
 | 
						|
 | 
						|
void *timeout_thread( void *ptr )
 | 
						|
{
 | 
						|
    TestConnections * Test = (TestConnections *) ptr;
 | 
						|
    struct timespec tim;
 | 
						|
    while (Test->timeout > 0)
 | 
						|
    {
 | 
						|
        tim.tv_sec = 1;
 | 
						|
        tim.tv_nsec = 0;
 | 
						|
        nanosleep(&tim, NULL);
 | 
						|
        Test->timeout--;
 | 
						|
    }
 | 
						|
    Test->tprintf("\n **** Timeout! *** \n");
 | 
						|
    Test->~TestConnections();
 | 
						|
    exit(250);
 | 
						|
}
 | 
						|
 | 
						|
void *log_copy_thread( void *ptr )
 | 
						|
{
 | 
						|
    TestConnections * Test = (TestConnections *) ptr;
 | 
						|
    struct timespec tim;
 | 
						|
    while (true)
 | 
						|
    {
 | 
						|
        while (Test->log_copy_to_go > 0)
 | 
						|
        {
 | 
						|
            tim.tv_sec = 1;
 | 
						|
            tim.tv_nsec = 0;
 | 
						|
            nanosleep(&tim, NULL);
 | 
						|
            Test->log_copy_to_go--;
 | 
						|
        }
 | 
						|
        Test->log_copy_to_go = Test->log_copy_interval;
 | 
						|
        Test->tprintf("\n **** Copying all logs *** \n");
 | 
						|
        Test->copy_all_logs_periodic();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::insert_select(int N)
 | 
						|
{
 | 
						|
    int result = 0;
 | 
						|
 | 
						|
    tprintf("Create t1\n");
 | 
						|
    set_timeout(30);
 | 
						|
    create_t1(conn_rwsplit);
 | 
						|
 | 
						|
    tprintf("Insert data into t1\n");
 | 
						|
    set_timeout(N * 16 + 30);
 | 
						|
    insert_into_t1(conn_rwsplit, N);
 | 
						|
    stop_timeout();
 | 
						|
    repl->sync_slaves();
 | 
						|
 | 
						|
    tprintf("SELECT: rwsplitter\n");
 | 
						|
    set_timeout(30);
 | 
						|
    result += select_from_t1(conn_rwsplit, N);
 | 
						|
 | 
						|
    tprintf("SELECT: master\n");
 | 
						|
    set_timeout(30);
 | 
						|
    result += select_from_t1(conn_master, N);
 | 
						|
 | 
						|
    tprintf("SELECT: slave\n");
 | 
						|
    set_timeout(30);
 | 
						|
    result += select_from_t1(conn_slave, N);
 | 
						|
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::use_db(char * db)
 | 
						|
{
 | 
						|
    int local_result = 0;
 | 
						|
    char sql[100];
 | 
						|
 | 
						|
    sprintf(sql, "USE %s;", db);
 | 
						|
    set_timeout(20);
 | 
						|
    tprintf("selecting DB '%s' for rwsplit\n", db);
 | 
						|
    local_result += execute_query(conn_rwsplit, sql);
 | 
						|
    tprintf("selecting DB '%s' for readconn master\n", db);
 | 
						|
    local_result += execute_query(conn_slave, sql);
 | 
						|
    tprintf("selecting DB '%s' for readconn slave\n", db);
 | 
						|
    local_result += execute_query(conn_master, sql);
 | 
						|
    for (int i = 0; i < repl->N; i++)
 | 
						|
    {
 | 
						|
        tprintf("selecting DB '%s' for direct connection to node %d\n", db, i);
 | 
						|
        local_result += execute_query(repl->nodes[i], sql);
 | 
						|
    }
 | 
						|
    return local_result;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::check_t1_table(bool presence, char * db)
 | 
						|
{
 | 
						|
    const char *expected = presence ? "" : "NOT";
 | 
						|
    const char *actual = presence ? "NOT" : "";
 | 
						|
    int start_result = global_result;
 | 
						|
 | 
						|
    add_result(use_db(db), "use db failed\n");
 | 
						|
    stop_timeout();
 | 
						|
    repl->sync_slaves();
 | 
						|
 | 
						|
    tprintf("Checking: table 't1' should %s be found in '%s' database\n", expected, db);
 | 
						|
    set_timeout(30);
 | 
						|
    int exists = check_if_t1_exists(conn_rwsplit);
 | 
						|
 | 
						|
    if (exists == presence)
 | 
						|
    {
 | 
						|
        tprintf("RWSplit: ok\n");
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        add_result(1, "Table t1 is %s found in '%s' database using RWSplit\n", actual, db);
 | 
						|
    }
 | 
						|
 | 
						|
    set_timeout(30);
 | 
						|
    exists = check_if_t1_exists(conn_master);
 | 
						|
 | 
						|
    if (exists == presence)
 | 
						|
    {
 | 
						|
        tprintf("ReadConn master: ok\n");
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        add_result(1, "Table t1 is %s found in '%s' database using Readconnrouter with router option master\n",
 | 
						|
                   actual, db);
 | 
						|
    }
 | 
						|
 | 
						|
    set_timeout(30);
 | 
						|
    exists = check_if_t1_exists(conn_slave);
 | 
						|
 | 
						|
    if (exists == presence)
 | 
						|
    {
 | 
						|
        tprintf("ReadConn slave: ok\n");
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        add_result(1, "Table t1 is %s found in '%s' database using Readconnrouter with router option slave\n", actual,
 | 
						|
                   db);
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    for (int i = 0; i < repl->N; i++)
 | 
						|
    {
 | 
						|
        set_timeout(30);
 | 
						|
        exists = check_if_t1_exists(repl->nodes[i]);
 | 
						|
        if (exists == presence)
 | 
						|
        {
 | 
						|
            tprintf("Node %d: ok\n", i);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            add_result(1, "Table t1 is %s found in '%s' database using direct connect to node %d\n", actual, db, i);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    stop_timeout();
 | 
						|
 | 
						|
    return global_result - start_result;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::try_query(MYSQL *conn, const char *format, ...)
 | 
						|
{
 | 
						|
    va_list valist;
 | 
						|
 | 
						|
    va_start(valist, format);
 | 
						|
    int message_len = vsnprintf(NULL, 0, format, valist);
 | 
						|
    va_end(valist);
 | 
						|
 | 
						|
    char sql[message_len + 1];
 | 
						|
 | 
						|
    va_start(valist, format);
 | 
						|
    vsnprintf(sql, sizeof(sql), format, valist);
 | 
						|
    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 ? "" : "...");
 | 
						|
    return res;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::try_query_all(const char *sql)
 | 
						|
{
 | 
						|
    return try_query(conn_rwsplit, sql) +
 | 
						|
           try_query(conn_master, sql) +
 | 
						|
           try_query(conn_slave, sql);
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::find_master_maxadmin(Mariadb_nodes * nodes)
 | 
						|
{
 | 
						|
    bool found = false;
 | 
						|
    int master = -1;
 | 
						|
 | 
						|
    for (int i = 0; i < nodes->N; i++)
 | 
						|
    {
 | 
						|
        char show_server[256];
 | 
						|
        char res[256];
 | 
						|
        sprintf(show_server, "show server server%d", i + 1);
 | 
						|
        get_maxadmin_param(show_server, "Status", res);
 | 
						|
 | 
						|
        if (strstr(res, "Master"))
 | 
						|
        {
 | 
						|
            if (found)
 | 
						|
            {
 | 
						|
                master = -1;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                master = i;
 | 
						|
                found = true;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return master;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::find_slave_maxadmin(Mariadb_nodes * nodes)
 | 
						|
{
 | 
						|
    int slave = -1;
 | 
						|
 | 
						|
    for (int i = 0; i < nodes->N; i++)
 | 
						|
    {
 | 
						|
        char show_server[256];
 | 
						|
        char res[256];
 | 
						|
        sprintf(show_server, "show server server%d", i + 1);
 | 
						|
        get_maxadmin_param(show_server, "Status", res);
 | 
						|
 | 
						|
        if (strstr(res, "Slave"))
 | 
						|
        {
 | 
						|
            slave = i;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return slave;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::execute_maxadmin_command(char * cmd)
 | 
						|
{
 | 
						|
    return ssh_maxscale(true, "maxadmin %s", cmd);
 | 
						|
}
 | 
						|
int TestConnections::execute_maxadmin_command_print(char * cmd)
 | 
						|
{
 | 
						|
    printf("%s\n", ssh_maxscale_output(true, "maxadmin %s", cmd));
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::check_maxadmin_param(const char *command, const char *param, const char *value)
 | 
						|
{
 | 
						|
    char result[1024];
 | 
						|
    int rval = 1;
 | 
						|
 | 
						|
    if (get_maxadmin_param((char*)command, (char*)param, (char*)result) == 0)
 | 
						|
    {
 | 
						|
        char *end = strchr(result, '\0') - 1;
 | 
						|
 | 
						|
        while (isspace(*end))
 | 
						|
        {
 | 
						|
            *end-- = '\0';
 | 
						|
        }
 | 
						|
 | 
						|
        char *start = result;
 | 
						|
 | 
						|
        while (isspace(*start))
 | 
						|
        {
 | 
						|
            start++;
 | 
						|
        }
 | 
						|
 | 
						|
        if (strcmp(start, value) == 0)
 | 
						|
        {
 | 
						|
            rval = 0;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            printf("Expected %s, got %s\n", value, start);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return rval;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::get_maxadmin_param(const char* command, const char* param, char* result)
 | 
						|
{
 | 
						|
    char* buf = ssh_maxscale_output(true, "maxadmin %s", command);
 | 
						|
    char *x = strstr(buf, param);
 | 
						|
 | 
						|
    if (x == NULL)
 | 
						|
    {
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
 | 
						|
    x += strlen(param);
 | 
						|
 | 
						|
    // Skip any trailing parts of the parameter name
 | 
						|
    while (!isspace(*x))
 | 
						|
    {
 | 
						|
        x++;
 | 
						|
    }
 | 
						|
 | 
						|
    // Trim leading whitespace
 | 
						|
    while (!isspace(*x))
 | 
						|
    {
 | 
						|
        x++;
 | 
						|
    }
 | 
						|
 | 
						|
    char *end = strchr(x, '\n');
 | 
						|
 | 
						|
    // Trim trailing whitespace
 | 
						|
    while (isspace(*end))
 | 
						|
    {
 | 
						|
        *end-- = '\0';
 | 
						|
    }
 | 
						|
 | 
						|
    strcpy(result, x);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::list_dirs()
 | 
						|
{
 | 
						|
    for (int i = 0; i < repl->N; i++)
 | 
						|
    {
 | 
						|
        tprintf("ls on node %d\n", i);
 | 
						|
        repl->ssh_node(i, true, "ls -la /var/lib/mysql");
 | 
						|
        fflush(stdout);
 | 
						|
    }
 | 
						|
    tprintf("ls maxscale \n");
 | 
						|
    ssh_maxscale(true, "ls -la /var/lib/maxscale/");
 | 
						|
    fflush(stdout);
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
long unsigned TestConnections::get_maxscale_memsize()
 | 
						|
{
 | 
						|
    char * ps_out = ssh_maxscale_output(false, "ps -e -o pid,vsz,comm= | grep maxscale");
 | 
						|
    long unsigned mem = 0;
 | 
						|
    pid_t pid;
 | 
						|
    sscanf(ps_out, "%d %lu", &pid, &mem);
 | 
						|
    return mem;
 | 
						|
}
 | 
						|
 | 
						|
void TestConnections::check_current_operations(int value)
 | 
						|
{
 | 
						|
    char value_str[512];
 | 
						|
    sprintf(value_str, "%d", value);
 | 
						|
 | 
						|
    for (int i = 0; i < repl->N; i++)
 | 
						|
    {
 | 
						|
        char command[512];
 | 
						|
        sprintf(command, "show server server%d", i + 1);
 | 
						|
        add_result(check_maxadmin_param(command, "Current no. of operations:", value_str),
 | 
						|
                   "Current no. of operations is not %s", value_str);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void TestConnections::check_current_connections(int value)
 | 
						|
{
 | 
						|
    char value_str[512];
 | 
						|
    sprintf(value_str, "%d", value);
 | 
						|
 | 
						|
    for (int i = 0; i < repl->N; i++)
 | 
						|
    {
 | 
						|
        char command[512];
 | 
						|
        sprintf(command, "show server server%d", i + 1);
 | 
						|
        add_result(check_maxadmin_param(command, "Current no. of conns:", value_str),
 | 
						|
                   "Current no. of conns is not %s", value_str);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::take_snapshot(char * snapshot_name)
 | 
						|
{
 | 
						|
    char str[4096];
 | 
						|
    sprintf(str, "%s %s", take_snapshot_command, snapshot_name);
 | 
						|
    return system(str);
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::revert_snapshot(const char* snapshot_name)
 | 
						|
{
 | 
						|
    char str[4096];
 | 
						|
    sprintf(str, "%s %s", revert_snapshot_command, snapshot_name);
 | 
						|
    return system(str);
 | 
						|
}
 | 
						|
 | 
						|
bool TestConnections::test_bad_config(const char *config)
 | 
						|
{
 | 
						|
    char src[PATH_MAX];
 | 
						|
 | 
						|
    process_template(config, "./");
 | 
						|
 | 
						|
    // Set the timeout to prevent hangs with configurations that work
 | 
						|
    set_timeout(20);
 | 
						|
 | 
						|
    return ssh_maxscale(true, "cp maxscale.cnf /etc/maxscale.cnf; service maxscale stop; "
 | 
						|
                        "maxscale -U maxscale -lstdout &> /dev/null && sleep 1 && pkill -9 maxscale") == 0;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::connect_rwsplit()
 | 
						|
{
 | 
						|
    if (use_ipv6)
 | 
						|
    {
 | 
						|
        conn_rwsplit = open_conn(rwsplit_port, maxscale_IP6, maxscale_user, maxscale_password, ssl);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        conn_rwsplit = open_conn(rwsplit_port, maxscale_IP, maxscale_user, maxscale_password, ssl);
 | 
						|
    }
 | 
						|
    routers[0] = conn_rwsplit;
 | 
						|
 | 
						|
    int rc = 0;
 | 
						|
    int my_errno = mysql_errno(conn_rwsplit);
 | 
						|
 | 
						|
    if (my_errno)
 | 
						|
    {
 | 
						|
        if (verbose)
 | 
						|
        {
 | 
						|
            tprintf("Failed to connect to readwritesplit: %d, %s", my_errno, mysql_error(conn_rwsplit));
 | 
						|
        }
 | 
						|
        rc = my_errno;
 | 
						|
    }
 | 
						|
 | 
						|
    return rc;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::connect_readconn_master()
 | 
						|
{
 | 
						|
    if (use_ipv6)
 | 
						|
    {
 | 
						|
        conn_master = open_conn(readconn_master_port, maxscale_IP6, maxscale_user, maxscale_password, ssl);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        conn_master = open_conn(readconn_master_port, maxscale_IP, maxscale_user, maxscale_password, ssl);
 | 
						|
    }
 | 
						|
    routers[1] = conn_master;
 | 
						|
 | 
						|
    int rc = 0;
 | 
						|
    int my_errno = mysql_errno(conn_master);
 | 
						|
 | 
						|
    if (my_errno)
 | 
						|
    {
 | 
						|
        if (verbose)
 | 
						|
        {
 | 
						|
            tprintf("Failed to connect to readwritesplit: %d, %s", my_errno, mysql_error(conn_master));
 | 
						|
        }
 | 
						|
        rc = my_errno;
 | 
						|
    }
 | 
						|
 | 
						|
    return rc;
 | 
						|
}
 | 
						|
 | 
						|
int TestConnections::connect_readconn_slave()
 | 
						|
{
 | 
						|
    if (use_ipv6)
 | 
						|
    {
 | 
						|
        conn_slave = open_conn(readconn_slave_port, maxscale_IP6, maxscale_user, maxscale_password, ssl);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        conn_slave = open_conn(readconn_slave_port, maxscale_IP, maxscale_user, maxscale_password, ssl);
 | 
						|
    }
 | 
						|
    routers[2] = conn_slave;
 | 
						|
 | 
						|
    int rc = 0;
 | 
						|
    int my_errno = mysql_errno(conn_slave);
 | 
						|
 | 
						|
    if (my_errno)
 | 
						|
    {
 | 
						|
        if (verbose)
 | 
						|
        {
 | 
						|
            tprintf("Failed to connect to readwritesplit: %d, %s", my_errno, mysql_error(conn_slave));
 | 
						|
        }
 | 
						|
        rc = my_errno;
 | 
						|
    }
 | 
						|
 | 
						|
    return rc;
 | 
						|
}
 | 
						|
 | 
						|
char* TestConnections::maxscale_ip() const
 | 
						|
{
 | 
						|
    return use_ipv6 ?  (char*)maxscale_IP6 : (char*)maxscale_IP;
 | 
						|
}
 | 
						|
 | 
						|
void TestConnections::set_active_maxscale(enum test_target target)
 | 
						|
{
 | 
						|
    switch (target)
 | 
						|
    {
 | 
						|
        case MXS_PRIMARY:
 | 
						|
            strcpy(maxscale_IP, primary_maxscale_IP.c_str());
 | 
						|
            strcpy(maxscale_IP6, primary_maxscale_IP6.c_str());
 | 
						|
            break;
 | 
						|
 | 
						|
        case MXS_SECONDARY:
 | 
						|
            strcpy(maxscale_IP, secondary_maxscale_IP.c_str());
 | 
						|
            strcpy(maxscale_IP6, secondary_maxscale_IP6.c_str());
 | 
						|
            break;
 | 
						|
 | 
						|
        default:
 | 
						|
            tprintf("Wrong enum value for 'set_active_maxscale': 0x%02x", target);
 | 
						|
            exit(1);
 | 
						|
            break;
 | 
						|
    }
 | 
						|
}
 |