#pragma once /** * @file mariadb_nodes.h - backend nodes routines * * @verbatim * Revision History * * Date Who Description * 17/11/14 Timofey Turenko Initial implementation * * @endverbatim */ #include "mariadb_func.h" #include #include #include "nodes.h" /** * @brief A class to handle backend nodes * Contains references up to 256 nodes, info about IP, port, ssh key, use name and password for each node * Node parameters should be defined in the enviromental variables in the follwing way: * prefix_N - N number of nodes in the setup * prefix_NNN - IP adress of the node (NNN 3 digits node index) * prefix_port_NNN - MariaDB port number of the node * prefix_User - User name to access backend setup (should have full access to 'test' DB with GRANT OPTION) * prefix_Password - Password to access backend setup */ class Mariadb_nodes : public Nodes { public: /** * @brief Constructor * @param pref name of backend setup (like 'repl' or 'galera') */ Mariadb_nodes(const char *pref, const char *test_cwd, bool verbose, std::string network_config); virtual ~Mariadb_nodes(); /** * @brief MYSQL structs for every backend node */ MYSQL* nodes[256]; /** * @brief IP address strings for every backend node */ /** * @brief MariaDB port for every backend node */ int port[256]; /** * @brief Unix socket to connecto to MariaDB */ char * socket[256]; /** * @brief 'socket=$socket' line */ char * socket_cmd[256]; /** * @brief User name to access backend nodes */ char * user_name; /** * @brief Password to access backend nodes */ char * password; /** * @brief master index of node which was last configured to be Master */ int master; /** * @brief start_db_command Command to start DB server */ char * start_db_command[256]; /** * @brief stop_db_command Command to start DB server */ char * stop_db_command[256]; /** * @brief cleanup_db_command Command to remove all * data files and re-install DB with mysql_install_db */ char * cleanup_db_command[256]; /** * @brief ssl if true ssl will be used */ int ssl; /** * @brief no_set_pos if set to true setup_binlog function do not set log position */ bool no_set_pos; /** * @brief version Value of @@version */ char version[256][256]; /** * @brief version major part of number value of @@version */ char version_major[256][256]; /** * @brief version Number part of @@version */ char version_number[256][256]; /** * @brief connect open connections to all nodes * @return 0 in case of success */ /** * @brief v51 true indicates that one backed is 5.1 */ bool v51; /** * @brief test_dir path to test application */ char test_dir[4096]; /** * @brief List of blocked nodes */ bool blocked[256]; /** * @brief Open connctions to all backend nodes (to 'test' DB) * @return 0 in case of success */ /** * @brief make_snapshot_command Command line to create a snapshot of all VMs */ char* take_snapshot_command; /** * @brief revert_snapshot_command Command line to revert a snapshot of all VMs */ char* revert_snapshot_command; int connect(int i, const std::string& db = "test"); int connect(const std::string& db = "test"); /** * Get a Connection to a node */ Connection get_connection(int i, const std::string& db = "test") { return Connection(IP[i], port[i], user_name, password, db, ssl); } /** * Repeatedly try to connect with one second sleep in between attempts * * @return True on success */ bool robust_connect(int n); /** * @brief Close connections opened by connect() * * This sets the values of used @c nodes to NULL. */ void close_connections(); // Alias for close_connections() void disconnect() { close_connections(); } /** * @brief reads IP, Ports, sshkeys for every node from enviromental variables as well as number of nodes *(N) and User/Password */ void read_env(); /** * @brief prints all nodes information * @return 0 */ void print_env(); /** * @brief find_master Tries to find Master node * @return Index of Master node */ int find_master(); /** * @brief change_master set a new master node for Master/Slave setup * @param NewMaster index of new Master node * @param OldMaster index of current Master node */ void change_master(int NewMaster, int OldMaster); /** * @brief stop_nodes stops mysqld on all nodes * @return 0 in case of success */ int stop_nodes(); /** * @brief stop_slaves isues 'stop slave;' to all nodes * @return 0 in case of success */ int stop_slaves(); /** * @brief cleanup_db_node Removes all data files and reinstall DB * with mysql_install_db * @param node * @return 0 in case of success */ int cleanup_db_node(int node); /** * @brief cleanup_db_node Removes all data files and reinstall DB * with mysql_install_db for all nodes * @param node * @return 0 in case of success */ int cleanup_db_nodes(); /** * @brief configures nodes and starts Master/Slave replication * @return 0 in case of success */ virtual int start_replication(); // Create the default users used by all tests void create_users(int node); /** * @brif BlockNode setup firewall on a backend node to block MariaDB port * @param node Index of node to block * @return 0 in case of success */ int block_node(int node); /** * @brief UnblockNode setup firewall on a backend node to unblock MariaDB port * @param node Index of node to unblock * @return 0 in case of success */ int unblock_node(int node); /** * @brief Unblock all nodes for this cluster * @return 0 in case of success */ int unblock_all_nodes(); /** * @brief clean_iptables removes all itables rules connected to MariaDB port to avoid duplicates * @param node Index of node to clean * @return 0 in case of success */ int clean_iptables(int node); /** * @brief Stop DB server on the node * @param node Node index * @return 0 if success */ int stop_node(int node); /** * @brief Start DB server on the node * @param node Node index * @param param command line parameters for DB server start command * @return 0 if success */ int start_node(int node, const char* param = ""); /** * @brief Check if all slaves have "Slave_IO_Running" set to "Yes" and master has N-1 slaves * @param master Index of master node * @return 0 if everything is ok */ virtual int check_replication(); /** * @brief executes 'CHANGE MASTER TO ..' and 'START SLAVE' * @param MYSQL conn struct of slave node * @param master_host IP address of master node * @param master_port port of master node * @param log_file name of log file * @param log_pos initial position * @return 0 if everything is ok */ int set_slave(MYSQL* conn, char master_host[], int master_port, char log_file[], char log_pos[]); /** * @brief Creates 'repl' user on all nodes * @return 0 if everything is ok */ int set_repl_user(); /** * @brief Get the server_id of the node * @param index The index of the node whose server_id to retrieve * @return Node id of the server or -1 on error */ int get_server_id(int index); std::string get_server_id_str(int index); /** * Get server IDs of all servers * * @return List of server IDs */ std::vector get_all_server_ids(); /** * @brief Execute 'mysqladmin flush-hosts' on all nodes * @return 0 in case of success */ int flush_hosts(); /** * @brief Execute query on all nodes * @param sql query to execute * @return 0 in case of success */ int execute_query_all_nodes(const char* sql); /** * @brief execute 'SELECT @@version' against one node and store result in 'version' field * @param i Node index * @return 0 in case of success */ int get_version(int i); /** * @brief execute 'SELECT @@version' against all nodes and store result in 'version' field * @return 0 in case of success */ int get_versions(); /** * @brief Return lowest server version in the cluster * @return The version string of the server with the lowest version number */ std::string get_lowest_version(); /** * @brief truncate_mariadb_logs clean ups MariaDB logs on backend nodes * @return 0 if success */ int truncate_mariadb_logs(); /** * @brief configure_ssl Modifies my.cnf in order to enable ssl, redefine access user to require ssl * @return 0 if success */ int configure_ssl(bool require); /** * @brief disable_ssl Modifies my.cnf in order to get rid of ssl, redefine access user to allow * connections without ssl * @return 0 if success */ int disable_ssl(); /** * @brief Synchronize slaves with the master * * Only works with master-slave replication and should not be used with Galera clusters. * The function expects that the first node, @c nodes[0], is the master. */ virtual void sync_slaves(int node = 0); /** * @brief Close all connections to this node * * This will kill all connections that have been created to this node. */ void close_active_connections(); /** * @brief Check and fix replication */ bool fix_replication(); /** * Copy current server settings to a backup directory. Any old backups are overwritten. * * @param node Node to modify */ void stash_server_settings(int node); /** * Restore server settings from a backup directory. Current settings files are overwritten and * backup settings files are removed. * * @param node Node to modify */ void restore_server_settings(int node); /** * Comment any line starting with the given setting name in server settings files. * * @param node Node to modify * @param setting Setting to remove */ void disable_server_setting(int node, const char* setting); /** * Add the following lines to the /etc/mysql.cnf.d/server.cnf-file: * [server] * parameter * * @param node Node to modify * @param setting Line to add */ void add_server_setting(int node, const char* setting); /** * Get the configuration file name for a particular node * * @param node Node number for which the configuration is requested * * @return The name of the configuration file */ virtual std::string get_config_name(int node); /** * Restore the original configuration for all servers */ void reset_server_settings(); // Same but for an individual server void reset_server_settings(int node); /** * @brief revert_nodes_snapshot Execute MDBCI snapshot revert command for all nodes * @return true in case of success */ bool revert_nodes_snapshot(); /** * @brief prepare_server Initialize MariaDB setup (run mysql_install_db) and create test users * Tries to detect Mysql 5.7 installation and disable 'validate_password' pluging * @param i Node index * @return 0 in case of success */ virtual int prepare_server(int i); int prepare_servers(); /** * Static functions */ /** Whether to require GTID based replication, defaults to false */ static void require_gtid(bool value); /** * Configure a server as a slave of another server * * The servers are configured with GTID replicating using the configured * GTID position, either slave_pos or current_pos. * * @param slave The node index to assign as slave * @param master The node index of the master * @param type Replication type */ void replicate_from(int slave, int master, const char* type = "current_pos"); /** * @brief limit_nodes Restart replication for only new_N nodes * @param new_N new number of nodes in replication */ void limit_nodes(int new_N); /** * @brief cnf_servers Generates backend servers description for maxscale.cnf * @return Servers description including IPs, ports */ std::string cnf_servers(); /** * @brief cnf_servers_line Generates list of backend servers for serivces definition in maxscale.cnf * @return List of servers, e.g server1,server2,server3,... */ std::string cnf_servers_line(); /** * @brief cnf_server_name Prefix for backend server name ('server', 'gserver') */ std::string cnf_server_name; private: bool check_master_node(MYSQL* conn); bool bad_slave_thread_status(MYSQL* conn, const char* field, int node); }; class Galera_nodes : public Mariadb_nodes { public: Galera_nodes(const char *pref, const char *test_cwd, bool verbose, std::string network_config) : Mariadb_nodes(pref, test_cwd, verbose, network_config) { } int start_galera(); virtual int start_replication() { return start_galera(); } int check_galera(); virtual int check_replication() { return check_galera(); } std::string get_config_name(int node) override; virtual void sync_slaves(int node = 0) { sleep(10); } };