MariaDBMon: Move replication manipulation functions to a separate file
Refactoring continues. This update moves some of the replication manipulation functions to a separate file and turns them into class methods.
This commit is contained in:
191
server/modules/monitor/mariadbmon/cluster_manipulation.cc
Normal file
191
server/modules/monitor/mariadbmon/cluster_manipulation.cc
Normal file
@ -0,0 +1,191 @@
|
||||
#include "mariadbmon.hh"
|
||||
|
||||
#include <sstream>
|
||||
#include <maxscale/mysql_utils.h>
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
||||
*
|
||||
* Change Date: 2020-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generate a CHANGE MASTER TO-query.
|
||||
*
|
||||
* @param master_host Master hostname/address
|
||||
* @param master_port Master port
|
||||
* @return Generated query
|
||||
*/
|
||||
string MariaDBMonitor::generate_change_master_cmd(const string& master_host, int master_port)
|
||||
{
|
||||
std::stringstream change_cmd;
|
||||
change_cmd << "CHANGE MASTER TO MASTER_HOST = '" << master_host << "', ";
|
||||
change_cmd << "MASTER_PORT = " << master_port << ", ";
|
||||
change_cmd << "MASTER_USE_GTID = current_pos, ";
|
||||
change_cmd << "MASTER_USER = '" << m_replication_user << "', ";
|
||||
const char MASTER_PW[] = "MASTER_PASSWORD = '";
|
||||
const char END[] = "';";
|
||||
#if defined(SS_DEBUG)
|
||||
std::stringstream change_cmd_nopw;
|
||||
change_cmd_nopw << change_cmd.str();
|
||||
change_cmd_nopw << MASTER_PW << "******" << END;;
|
||||
MXS_DEBUG("Change master command is '%s'.", change_cmd_nopw.str().c_str());
|
||||
#endif
|
||||
change_cmd << MASTER_PW << m_replication_password << END;
|
||||
return change_cmd.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects slaves to replicate from another master server.
|
||||
*
|
||||
* @param slaves An array of slaves
|
||||
* @param new_master The replication master
|
||||
* @param redirected_slaves A vector where to insert successfully redirected slaves.
|
||||
* @return The number of slaves successfully redirected.
|
||||
*/
|
||||
int MariaDBMonitor::redirect_slaves(MXS_MONITORED_SERVER* new_master, const ServerVector& slaves,
|
||||
ServerVector* redirected_slaves)
|
||||
{
|
||||
ss_dassert(redirected_slaves != NULL);
|
||||
MXS_NOTICE("Redirecting slaves to new master.");
|
||||
string change_cmd = generate_change_master_cmd(new_master->server->name, new_master->server->port);
|
||||
int successes = 0;
|
||||
for (ServerVector::const_iterator iter = slaves.begin(); iter != slaves.end(); iter++)
|
||||
{
|
||||
if (redirect_one_slave(*iter, change_cmd.c_str()))
|
||||
{
|
||||
successes++;
|
||||
redirected_slaves->push_back(*iter);
|
||||
}
|
||||
}
|
||||
return successes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the new master to replicate from the cluster external master.
|
||||
*
|
||||
* @param new_master The server being promoted
|
||||
* @param err_out Error output
|
||||
* @return True if new master accepted commands
|
||||
*/
|
||||
bool MariaDBMonitor::start_external_replication(MXS_MONITORED_SERVER* new_master, json_t** err_out)
|
||||
{
|
||||
bool rval = false;
|
||||
string change_cmd = generate_change_master_cmd(external_master_host, external_master_port);
|
||||
if (mxs_mysql_query(new_master->con, change_cmd.c_str()) == 0 &&
|
||||
mxs_mysql_query(new_master->con, "START SLAVE;") == 0)
|
||||
{
|
||||
MXS_NOTICE("New master starting replication from external master %s:%d.",
|
||||
external_master_host.c_str(), external_master_port);
|
||||
rval = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
PRINT_MXS_JSON_ERROR(err_out, "Could not start replication from external master: '%s'.",
|
||||
mysql_error(new_master->con));
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new slave connection on a server. Should be used on a demoted master server.
|
||||
*
|
||||
* @param old_master The server which will start replication
|
||||
* @param new_master Replication target
|
||||
* @return True if commands were accepted. This does not guarantee that replication proceeds
|
||||
* successfully.
|
||||
*/
|
||||
bool MariaDBMonitor::switchover_start_slave(MXS_MONITORED_SERVER* old_master, SERVER* new_master)
|
||||
{
|
||||
bool rval = false;
|
||||
string change_cmd = generate_change_master_cmd(new_master->name, new_master->port);
|
||||
if (mxs_mysql_query(old_master->con, change_cmd.c_str()) == 0 &&
|
||||
mxs_mysql_query(old_master->con, "START SLAVE;") == 0)
|
||||
{
|
||||
MXS_NOTICE("Old master '%s' starting replication from '%s'.",
|
||||
old_master->server->unique_name, new_master->unique_name);
|
||||
rval = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Old master '%s' could not start replication: '%s'.",
|
||||
old_master->server->unique_name, mysql_error(old_master->con));
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect one slave server to another master
|
||||
*
|
||||
* @param slave Server to redirect
|
||||
* @param change_cmd Change master command, usually generated by generate_change_master_cmd()
|
||||
* @return True if slave accepted all commands
|
||||
*/
|
||||
bool MariaDBMonitor::redirect_one_slave(MXS_MONITORED_SERVER* slave, const char* change_cmd)
|
||||
{
|
||||
bool rval = false;
|
||||
if (mxs_mysql_query(slave->con, "STOP SLAVE;") == 0 &&
|
||||
mxs_mysql_query(slave->con, "RESET SLAVE;") == 0 && // To erase any old I/O or SQL errors
|
||||
mxs_mysql_query(slave->con, change_cmd) == 0 &&
|
||||
mxs_mysql_query(slave->con, "START SLAVE;") == 0)
|
||||
{
|
||||
rval = true;
|
||||
MXS_NOTICE("Slave '%s' redirected to new master.", slave->server->unique_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_WARNING("Slave '%s' redirection failed: '%s'.", slave->server->unique_name,
|
||||
mysql_error(slave->con));
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
uint32_t MariaDBMonitor::do_rejoin(const ServerVector& joinable_servers)
|
||||
{
|
||||
SERVER* master = this->master->server;
|
||||
uint32_t servers_joined = 0;
|
||||
if (!joinable_servers.empty())
|
||||
{
|
||||
string change_cmd = generate_change_master_cmd(master->name, master->port);
|
||||
for (ServerVector::const_iterator iter = joinable_servers.begin();
|
||||
iter != joinable_servers.end();
|
||||
iter++)
|
||||
{
|
||||
MXS_MONITORED_SERVER* joinable = *iter;
|
||||
const char* name = joinable->server->unique_name;
|
||||
const char* master_name = master->unique_name;
|
||||
MySqlServerInfo* redir_info = get_server_info(this, joinable);
|
||||
|
||||
bool op_success;
|
||||
if (redir_info->n_slaves_configured == 0)
|
||||
{
|
||||
MXS_NOTICE("Directing standalone server '%s' to replicate from '%s'.", name, master_name);
|
||||
op_success = join_cluster(joinable, change_cmd.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_NOTICE("Server '%s' is replicating from a server other than '%s', "
|
||||
"redirecting it to '%s'.", name, master_name, master_name);
|
||||
op_success = redirect_one_slave(joinable, change_cmd.c_str());
|
||||
}
|
||||
|
||||
if (op_success)
|
||||
{
|
||||
servers_joined++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return servers_joined;
|
||||
}
|
||||
|
||||
bool MariaDBMonitor::cluster_can_be_joined()
|
||||
{
|
||||
return (master != NULL && SERVER_IS_MASTER(master->server) && master_gtid_domain >= 0);
|
||||
}
|
Reference in New Issue
Block a user