506 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			506 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef MARIADB_NODES_H
 | |
| #define MARIADB_NODES_H
 | |
| 
 | |
| /**
 | |
|  * @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 <errno.h>
 | |
| #include <string>
 | |
| 
 | |
| /**
 | |
|  * @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:
 | |
|     /**
 | |
|      * @brief Constructor
 | |
|      * @param pref  name of backend setup (like 'repl' or 'galera')
 | |
|      */
 | |
|     Mariadb_nodes(const char *pref, const char *test_cwd, bool verbose);
 | |
| 
 | |
|     ~Mariadb_nodes();
 | |
| 
 | |
|     /**
 | |
|     * @brief  MYSQL structs for every backend node
 | |
|     */
 | |
|     MYSQL *nodes[256];
 | |
|     /**
 | |
|      * @brief  IP address strings for every backend node
 | |
|      */
 | |
|     char IP[256][1024];
 | |
|     /**
 | |
|      * @brief  private IP address strings for every backend node (for AWS)
 | |
|      */
 | |
|     char IP_private[256][1024];
 | |
|     /**
 | |
|      * @brief  IP address strings for every backend node (IPv6)
 | |
|      */
 | |
|     char IP6[256][1024];
 | |
|     /**
 | |
|      * @brief use_ipv6 If true IPv6 addresses will be used to connect Maxscale and backed
 | |
|      * Also IPv6 addresses go to maxscale.cnf
 | |
|      */
 | |
|     bool use_ipv6;
 | |
|     /**
 | |
|      * @brief  MariaDB port for every backend node
 | |
|      */
 | |
|     int port[256];
 | |
|     /**
 | |
|      * @brief Unix socket to connecto to MariaDB
 | |
|      */
 | |
|     char socket[256][1024];
 | |
|     /**
 | |
|      * @brief 'socket=$socket' line
 | |
|      */
 | |
|     char socket_cmd[256][1024];
 | |
|     /**
 | |
|      * @brief  Path to ssh key for every backend node
 | |
|      */
 | |
|     char sshkey[256][4096];
 | |
|     /**
 | |
|      * @brief Number of backend nodes
 | |
|      */
 | |
|     int N;
 | |
|     /**
 | |
|      * @brief   User name to access backend nodes
 | |
|      */
 | |
|     char user_name[256];
 | |
|     /**
 | |
|      * @brief   Password to access backend nodes
 | |
|      */
 | |
|     char password[256];
 | |
|     /**
 | |
|      * @brief master index of node which was last configured to be Master
 | |
|      */
 | |
|     int master;
 | |
|     /**
 | |
|      * @brief     name of backend setup (like 'repl' or 'galera')
 | |
|      */
 | |
|     char prefix[16];
 | |
|     /**
 | |
|      * @brief start_db_command Command to start DB server
 | |
|      */
 | |
|     char start_db_command[256][4096];
 | |
| 
 | |
|     /**
 | |
|      * @brief stop_db_command Command to start DB server
 | |
|      */
 | |
|     char stop_db_command[256][4096];
 | |
| 
 | |
|     /**
 | |
|      * @brief cleanup_db_command Command to remove all
 | |
|      * data files and re-install DB with mysql_install_db
 | |
|      */
 | |
|     char cleanup_db_command[256][4096];
 | |
| 
 | |
|     /**
 | |
|      * @brief ssl if true ssl will be used
 | |
|      */
 | |
|     int ssl;
 | |
| 
 | |
|     /**
 | |
|      * @brief access_user Unix users name to access nodes via ssh
 | |
|      */
 | |
|     char access_user[256][256];
 | |
| 
 | |
|     /**
 | |
|      * @brief access_sudo empty if sudo is not needed or "sudo " if sudo is needed.
 | |
|      */
 | |
|     char access_sudo[256][64];
 | |
| 
 | |
| 
 | |
|     /**
 | |
|      * @brief access_homedir home directory of access_user
 | |
|      */
 | |
|     char access_homedir[256][256];
 | |
| 
 | |
|     /**
 | |
|      * @brief no_set_pos if set to true setup_binlog function do not set log position
 | |
|      */
 | |
|     bool no_set_pos;
 | |
| 
 | |
|     /**
 | |
|      * @brief Verbose command output
 | |
|      */
 | |
|     bool verbose;
 | |
| 
 | |
|     /**
 | |
|      * @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
 | |
|     */
 | |
|     int connect();
 | |
| 
 | |
|     /**
 | |
|      * @brief Close connections opened by connect()
 | |
|      *
 | |
|      * This sets the values of used @c nodes to NULL.
 | |
|      */
 | |
|     void close_connections();
 | |
| 
 | |
|     /**
 | |
|      * @brief reads IP, Ports, sshkeys for every node from enviromental variables as well as number of nodes (N) and  User/Password
 | |
|      * @return 0
 | |
|      */
 | |
|     int read_env();
 | |
|     /**
 | |
|      * @brief  prints all nodes information
 | |
|      * @return 0
 | |
|      */
 | |
|     int 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
 | |
|      * @return  0 in case of success
 | |
|      */
 | |
|     int 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();
 | |
| 
 | |
|     /**
 | |
|      * @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 node via ssh and restart it if it is not resposible
 | |
|      * @param node Node index
 | |
|      * @return 0 if node is ok, 1 if start failed
 | |
|      */
 | |
|     int check_nodes();
 | |
| 
 | |
|     /**
 | |
|      * @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);
 | |
| 
 | |
|     /**
 | |
|      * @brief Generate command line to execute command on the node via ssh
 | |
|      * @param cmd result
 | |
|      * @param index index number of the node (index)
 | |
|      * @param ssh command to execute
 | |
|      * @param sudo if true the command is executed with root privelegues
 | |
|      */
 | |
|     void generate_ssh_cmd(char * cmd, int node, const char *ssh, bool sudo);
 | |
| 
 | |
|     /**
 | |
|      * @brief executes shell command on the node using ssh
 | |
|      * @param index number of the node (index)
 | |
|      * @param ssh command to execute
 | |
|      * @param sudo if true the command is executed with root privelegues
 | |
|      * @param pointer to variable to store process exit code
 | |
|      * @return output of the command
 | |
|      */
 | |
|     char *ssh_node_output(int node, const char *ssh, bool sudo, int *exit_code);
 | |
| 
 | |
|     /**
 | |
|      * @brief executes shell command on the node using ssh
 | |
|      * @param index number of the node (index)
 | |
|      * @param sudo if true the command is executed with root privelegues
 | |
|      * @param ssh command to execute
 | |
|      * @return exit code of the command
 | |
|      */
 | |
|     int ssh_node(int node, bool sudo, const char *ssh, ...);
 | |
| 
 | |
|     /**
 | |
|      * @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 all nodes and store result in 'version' fied
 | |
|      * @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 Copy a local file to the Node i machine
 | |
|      * @param src Source file on the local filesystem
 | |
|      * @param dest Destination file on the remote file system
 | |
|      * @param i Node index
 | |
|      * @return exit code of the system command or 1 in case of i > N
 | |
|      */
 | |
|     int copy_to_node(const char* src, const char* dest, int i);
 | |
| 
 | |
|     /**
 | |
|      * @brief Copy a local file to the Node i machine
 | |
|      * @param src Source file on the remote filesystem
 | |
|      * @param dest Destination file on the local file system
 | |
|      * @param i Node index
 | |
|      * @return exit code of the system command or 1 in case of i > N
 | |
|      */
 | |
|     int copy_from_node(const char* src, const char* dest, int i);
 | |
| 
 | |
|     /**
 | |
|      * @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.
 | |
|      */
 | |
|     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);
 | |
| private:
 | |
| 
 | |
|     int check_node_ssh(int node);
 | |
|     bool check_master_node(MYSQL *conn);
 | |
| };
 | |
| 
 | |
| class Galera_nodes : public Mariadb_nodes
 | |
| {
 | |
| public:
 | |
| 
 | |
|     Galera_nodes(const char *pref, const char *test_cwd, bool verbose) :
 | |
|         Mariadb_nodes(pref, test_cwd, verbose) { }
 | |
| 
 | |
|     int start_galera();
 | |
| 
 | |
|     virtual int start_replication()
 | |
|     {
 | |
|         return start_galera();
 | |
|     }
 | |
| 
 | |
|     int check_galera();
 | |
| 
 | |
|     virtual int check_replication()
 | |
|     {
 | |
|         return check_galera();
 | |
|     }
 | |
| };
 | |
| 
 | |
| #endif // MARIADB_NODES_H
 | 
