def run(self): cmd_base = "mysqlrplsync.py" master_con = self.build_connection_string(self.server1).strip(" ") slave1_con = self.build_connection_string(self.server2).strip(" ") slave2_con = self.build_connection_string(self.server3).strip(" ") slaves_con = "{0},{1}".format(slave1_con, slave2_con) # Check the data consistency of empty servers. test_num = 1 comment = ("Test case {0} - check empty servers." "").format(test_num) cmd = "{0} --master={1} --slaves={2} {3}".format(cmd_base, master_con, slaves_con, ssl_util_opts()) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Create example database on master and wait for it to be replicated # on all slaves. if self.debug: print("\nCreate test database and tables on master.") rpl_sync.create_test_db(self.server1) # Wait for slaves to catch up, otherwise mysqlrplsync might find tables # missing on slaves (which is normal). if self.debug: print("\nWait for slaves to catch up with master.") self.wait_for_slaves() # Load data on the master in a separated thread to perform the data # consistency checks at the same time. load_thread = threading.Thread(target=rpl_sync.load_test_data, args=(self.server1,)) load_thread.daemon = True load_thread.start() if self.debug: print("\nThread to load/insert data started.") start_time = time.time() end_time = None # Check data consistency specifying the master and using discovery. test_num += 1 comment = ( "Test case {0} - data consistency check with active " "replication using master and slaves discovery." "" ).format(test_num) cmd = ("{0} --master={1} --discover-slaves-login=root:root {2}" "").format( cmd_base, master_con, ssl_util_opts() ) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) if self.debug: alive = load_thread.is_alive() print("\nIs thread (loading data) still alive? " "{0}.".format(alive)) if not alive and not end_time: end_time = time.time() print("\nTime to load data took less than: {0} " "sec.".format(end_time - start_time)) else: print("\nWaiting for thread (loading data) to finish.") # Wait for all the data to finish to be loaded. load_thread.join() if self.debug and not end_time: end_time = time.time() print("\nTime to load data: {0} " "sec.".format(end_time - start_time)) # Drop test database and recreate it on master. if self.debug: print("\nDrop test database on master.") rpl_sync.drop_test_db(self.server1) if self.debug: print("\nCreate test database and tables on master.") rpl_sync.create_test_db(self.server1) # Wait for slaves to catch up (avoiding non-deterministic results). if self.debug: print("\nWait for slaves to catch up with master.") self.wait_for_slaves() # Start a new thread to load/insert data (can only be started once). load_thread = threading.Thread(target=rpl_sync.load_test_data, args=(self.server1,)) load_thread.daemon = True load_thread.start() if self.debug: print("\nThread to load/insert data started.") start_time = time.time() end_time = None # Check data consistency specifying only the slaves. test_num += 1 comment = ( "Test case {0} - data consistency check with active " "replication only between slaves (no master)." "" ).format(test_num) cmd = "{0} --slaves={1} {2}".format(cmd_base, slaves_con, ssl_util_opts()) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) if self.debug: alive = load_thread.is_alive() print("\nIs thread (loading data) still alive? " "{0}.".format(alive)) if not alive and not end_time: end_time = time.time() print("\nTime to load data took less than: {0} " "sec.".format(end_time - start_time)) else: print("Waiting for thread (loading data) to finish.") # Wait for all the data to finish to be loaded. load_thread.join() if self.debug and not end_time: end_time = time.time() print("\nTime to load data: {0} " "sec.".format(end_time - start_time)) # Perform data consistency check after loading all data. test_num += 1 comment = ("Test case {0} - data consistency check between master and " "specified slaves.").format(test_num) cmd = "{0} --master={1} --slaves={2} {3}".format(cmd_base, master_con, slaves_con, ssl_util_opts()) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Mask out non-deterministic data self.do_masks() return True
def run(self): cmd_base = "mysqlrplsync.py" master_con = self.build_connection_string(self.server1).strip(' ') slave1_con = self.build_connection_string(self.server2).strip(' ') slave2_con = self.build_connection_string(self.server3).strip(' ') slaves_con = "{0},{1}".format(slave1_con, slave2_con) # Check the data consistency of empty servers. test_num = 1 comment = ("Test case {0} - check empty servers." "").format(test_num) cmd = "{0} --master={1} --slaves={2} {3}".format(cmd_base, master_con, slaves_con, ssl_util_opts()) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Create example database on master and wait for it to be replicated # on all slaves. if self.debug: print("\nCreate test database and tables on master.") rpl_sync.create_test_db(self.server1) # Wait for slaves to catch up, otherwise mysqlrplsync might find tables # missing on slaves (which is normal). if self.debug: print("\nWait for slaves to catch up with master.") self.wait_for_slaves() # Load data on the master in a separated thread to perform the data # consistency checks at the same time. load_thread = threading.Thread(target=rpl_sync.load_test_data, args=(self.server1,)) load_thread.daemon = True load_thread.start() if self.debug: print("\nThread to load/insert data started.") start_time = time.time() end_time = None # Check data consistency specifying the master and using discovery. test_num += 1 comment = ("Test case {0} - data consistency check with active " "replication using master and slaves discovery." "").format(test_num) cmd = ("{0} --master={1} --discover-slaves-login=root:root {2}" "").format(cmd_base, master_con, ssl_util_opts()) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) if self.debug: alive = load_thread.is_alive() print("\nIs thread (loading data) still alive? " "{0}.".format(alive)) if not alive and not end_time: end_time = time.time() print("\nTime to load data took less than: {0} " "sec.".format(end_time - start_time)) else: print("\nWaiting for thread (loading data) to finish.") # Wait for all the data to finish to be loaded. load_thread.join() if self.debug and not end_time: end_time = time.time() print("\nTime to load data: {0} " "sec.".format(end_time - start_time)) # Drop test database and recreate it on master. if self.debug: print("\nDrop test database on master.") rpl_sync.drop_test_db(self.server1) if self.debug: print("\nCreate test database and tables on master.") rpl_sync.create_test_db(self.server1) # Wait for slaves to catch up (avoiding non-deterministic results). if self.debug: print("\nWait for slaves to catch up with master.") self.wait_for_slaves() # Start a new thread to load/insert data (can only be started once). load_thread = threading.Thread(target=rpl_sync.load_test_data, args=(self.server1,)) load_thread.daemon = True load_thread.start() if self.debug: print("\nThread to load/insert data started.") start_time = time.time() end_time = None # Check data consistency specifying only the slaves. test_num += 1 comment = ("Test case {0} - data consistency check with active " "replication only between slaves (no master)." "").format(test_num) cmd = "{0} --slaves={1} {2}".format(cmd_base, slaves_con, ssl_util_opts()) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) if self.debug: alive = load_thread.is_alive() print("\nIs thread (loading data) still alive? " "{0}.".format(alive)) if not alive and not end_time: end_time = time.time() print("\nTime to load data took less than: {0} " "sec.".format(end_time - start_time)) else: print("Waiting for thread (loading data) to finish.") # Wait for all the data to finish to be loaded. load_thread.join() if self.debug and not end_time: end_time = time.time() print("\nTime to load data: {0} " "sec.".format(end_time - start_time)) # Perform data consistency check after loading all data. test_num += 1 comment = ("Test case {0} - data consistency check between master and " "specified slaves.").format(test_num) cmd = "{0} --master={1} --slaves={2} {3}".format(cmd_base, master_con, slaves_con, ssl_util_opts()) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Mask out non-deterministic data self.do_masks() return True
def run(self): # Create user to test privileges on master and slave. # Missing privilege on the master (SUPER and REPLICATION CLIENT). if self.debug: print("\nCreate user with missing privileges (SUPER and " "REPLICATION CLIENT) on master.") master_grants = ['LOCK TABLES', 'SELECT'] change_user_privileges(self.server1, 'm_user', 'm_pwd', self.server1.host, grant_list=master_grants, revoke_list=None, disable_binlog=True, create_user=True) if self.debug: print("\nCreate user with all required privileges on slave.") slave_grants = ['SUPER', 'SELECT'] change_user_privileges(self.server2, 's_user', 's_pwd', self.server1.host, grant_list=slave_grants, revoke_list=None, disable_binlog=True, create_user=True) master_con = self.build_custom_connection_string( self.server1, 'm_user', 'm_pwd') slave1_con = self.build_custom_connection_string( self.server2, 's_user', 's_pwd') cmd_base = "mysqlrplsync.py --master={0} --slaves={1}".format( master_con, slave1_con) if self.debug: print("\nCreate test database and tables on master.") rpl_sync.create_test_db(self.server1) if self.debug: print("\nWait for slaves to catch up with master.") self.wait_for_slaves([self.server2]) # Test sync using a master user with missing privilege: SUPER and # REPLICATION CLIENT. test_num = 1 comment = ("Test case {0} - sync (fail) using 'm_user' without: " "SUPER and REPLICATION CLIENT.".format(test_num)) res = self.run_test_case(1, cmd_base, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Grant all required privileges except LOCK TABLES to user on master. if self.debug: print("\nGrant required privileges except LOCK TABLES on master.") master_grants = ['SUPER'] master_revokes = ['LOCK TABLES'] change_user_privileges(self.server1, 'm_user', 'm_pwd', self.server1.host, grant_list=master_grants, revoke_list=master_revokes, disable_binlog=True, create_user=False) # Test sync using a master user with missing privilege: LOCK TABLES. test_num += 1 comment = ("Test case {0} - sync (fail) using 'm_user' without: " "LOCK TABLES.".format(test_num)) res = self.run_test_case(1, cmd_base, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Grant all required privileges except SELECT to user on master. if self.debug: print("\nGrant required privileges except SELECT on master.") master_grants = ['LOCK TABLES'] master_revokes = ['SELECT'] change_user_privileges(self.server1, 'm_user', 'm_pwd', self.server1.host, grant_list=master_grants, revoke_list=master_revokes, disable_binlog=True, create_user=False) # Test sync using a master user with missing privilege: LOCK TABLES. test_num += 1 comment = ("Test case {0} - sync (fail) using 'm_user' without: " "SELECT.".format(test_num)) res = self.run_test_case(1, cmd_base, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Grant all required privileges to user on master. if self.debug: print("\nGrant required privileges on master.") master_grants = ['SELECT'] change_user_privileges(self.server1, 'm_user', 'm_pwd', self.server1.host, grant_list=master_grants, revoke_list=None, disable_binlog=True, create_user=False) # Grant all required privileges except SUPER to user on slave. if self.debug: print("\nGrant required privileges except SUPER on slave.") slave_revokes = ['SUPER'] change_user_privileges(self.server2, 's_user', 's_pwd', self.server2.host, grant_list=None, revoke_list=slave_revokes, disable_binlog=True, create_user=False) # Test sync using a slave user with missing privilege: SUPER. test_num += 1 comment = ("Test case {0} - sync (fail) using 's_user' without: " "SUPER.".format(test_num)) res = self.run_test_case(1, cmd_base, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Grant all required privileges except SELECT to user on slave. if self.debug: print("\nGrant required privileges except SELECT on slave.") slave_grants = ['SUPER'] slave_revokes = ['SELECT'] change_user_privileges(self.server2, 's_user', 's_pwd', self.server2.host, grant_list=slave_grants, revoke_list=slave_revokes, disable_binlog=True, create_user=False) # Test sync using a slave user with missing privilege: SELECT. test_num += 1 comment = ("Test case {0} - sync (fail) using 's_user' without: " "SELECT.".format(test_num)) res = self.run_test_case(1, cmd_base, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Grant all required privileges to user on slave. if self.debug: print("\nGrant required privileges on slave.") slave_grants = ['SELECT'] change_user_privileges(self.server2, 's_user', 's_pwd', self.server2.host, grant_list=slave_grants, revoke_list=None, disable_binlog=True, create_user=False) # Test sync with master and slave users with all required privileges. # Using SUPER (not REPLICATION CLIENT) for master. test_num += 1 comment = ("Test case {0} - sync (succeed) using: 'm_user' with " "SUPER, LOCK TABLES and SELECT; 's_user' with SUPER and " "SELECT.".format(test_num)) res = self.run_test_case(0, cmd_base, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Replace SUPER with REPLICATION CLIENT for user on master. if self.debug: print("\nReplace SUPER with REPLICATION CLIENT on master.") master_grants = ['REPLICATION CLIENT'] master_revokes = ['SUPER'] change_user_privileges(self.server1, 'm_user', 'm_pwd', self.server1.host, grant_list=master_grants, revoke_list=master_revokes, disable_binlog=True, create_user=False) # Test sync with master and slave users with all required privileges. # Using REPLICATION CLIENT (not SUPER) for master. test_num += 1 comment = ("Test case {0} - sync (succeed) using: 'm_user' with " "REPLICATION CLIENT, LOCK TABLES and SELECT; 's_user' with " "SUPER and SELECT.".format(test_num)) res = self.run_test_case(0, cmd_base, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Mask out non-deterministic data self.do_masks() return True
def run(self): cmd_base = "mysqlrplsync.py" master1_con = self.build_connection_string(self.server1).strip(' ') master2_con = self.build_connection_string(self.server2).strip(' ') slave1_con = self.build_connection_string(self.server3).strip(' ') slave2_con = self.build_connection_string(self.server4).strip(' ') slaves_con = ",".join([slave1_con, slave2_con]) slave3_con = self.build_connection_string(self.server5).strip(' ') slave4_con = self.build_connection_string(self.server6).strip(' ') slave5_con = self.build_connection_string(self.server7).strip(' ') if self.debug: print("\nCreate test databases and tables on master.") rpl_sync.create_test_db(self.server1, db_num=4) if self.debug: print("\nWait for slaves to catch up with master.") self.wait_for_slaves([self.server3, self.server4]) # Skip check of databases with replication filters (case 1). # master: --binlog-do-db=test_rplsync_db1 # slave1: --replicate-do-table=test_rplsync_db1.t1 # slave2: --replicate-ignore-table=test_rplsync_db1.t2 # --replicate-wild-ignore-table=test\_rplsync\_db1.%3 test_num = 1 comment = ("Test case {0} - check replication filters skip (case 1)." "").format(test_num) cmd = "{0} --master={1} --slaves={2} -v".format( cmd_base, master1_con, slaves_con) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) test_num += 1 comment = ("Test case {0} - check replication filters skip (case 1) - " "only with slaves.").format(test_num) cmd = "{0} --slaves={1} -v".format(cmd_base, slaves_con) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) if self.debug: print("\nDrop test databases on master.") rpl_sync.drop_test_db(self.server1, db_num=4) if self.debug: print("\nWait for slaves to catch up with master.") self.wait_for_slaves([self.server3, self.server4]) if self.debug: print("\nReset topology with a new master.") self.reset_master([self.server2, self.server3, self.server4]) self.reset_topology([self.server3, self.server4], master=self.server2) if self.debug: print("\nCreate test databases and tables on master.") rpl_sync.create_test_db(self.server2, db_num=4) if self.debug: print("\nWait for slaves to catch up with master.") self.wait_for_slaves([self.server3, self.server4], master=self.server2) # Skip check of databases with replication filters (case 2). # master: --binlog-ignore-db=test_rplsync_db2 # slave1: --replicate-do-table=test_rplsync_db1.t1 # slave2: --replicate-ignore-table=test_rplsync_db1.t2 # --replicate-wild-ignore-table=test\_rplsync\_db1.%3 test_num += 1 comment = ("Test case {0} - check replication filters skip (case 2)." "").format(test_num) cmd = "{0} --master={1} --slaves={2} -v".format( cmd_base, master2_con, slaves_con) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) test_num += 1 comment = ("Test case {0} - check replication filters skip (case 2) - " "only with slaves.").format(test_num) cmd = "{0} --slaves={1} -v".format(cmd_base, slaves_con) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) if self.debug: print("\nReset topology with new slaves.") self.reset_master( [self.server2, self.server5, self.server6, self.server7]) self.reset_topology([self.server5, self.server6, self.server7], master=self.server2) # Options replicate-do-db, replicate-ignore-db, and # replicate-wild-do-db are not supported due to known issues on the # server, leading to inconsistent GTID_EXECUTED sets. test_num += 1 comment = ("Test case {0} - error using replicate-do-db." "").format(test_num) cmd = "{0} --master={1} --slaves={2}".format(cmd_base, master2_con, slave3_con) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) test_num += 1 comment = ("Test case {0} - error using replicate-ignore-db." "").format(test_num) cmd = "{0} --master={1} --slaves={2}".format(cmd_base, master2_con, slave4_con) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) test_num += 1 comment = ("Test case {0} - error using replicate-wild-do-db." "").format(test_num) cmd = "{0} --master={1} --slaves={2}".format(cmd_base, master2_con, slave5_con) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Mask out non-deterministic data self.do_masks() return True
def run(self): cmd_base = "mysqlrplsync.py" master1_con = self.build_connection_string(self.server1).strip(' ') master2_con = self.build_connection_string(self.server2).strip(' ') slave1_con = self.build_connection_string(self.server3).strip(' ') slave2_con = self.build_connection_string(self.server4).strip(' ') slaves_con = ",".join([slave1_con, slave2_con]) slave3_con = self.build_connection_string(self.server5).strip(' ') slave4_con = self.build_connection_string(self.server6).strip(' ') slave5_con = self.build_connection_string(self.server7).strip(' ') if self.debug: print("\nCreate test databases and tables on master.") rpl_sync.create_test_db(self.server1, db_num=4) if self.debug: print("\nWait for slaves to catch up with master.") self.wait_for_slaves([self.server3, self.server4]) # Skip check of databases with replication filters (case 1). # master: --binlog-do-db=test_rplsync_db1 # slave1: --replicate-do-table=test_rplsync_db1.t1 # slave2: --replicate-ignore-table=test_rplsync_db1.t2 # --replicate-wild-ignore-table=test\_rplsync\_db1.%3 test_num = 1 comment = ("Test case {0} - check replication filters skip (case 1)." "").format(test_num) cmd = "{0} --master={1} --slaves={2} -v".format(cmd_base, master1_con, slaves_con) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) test_num += 1 comment = ("Test case {0} - check replication filters skip (case 1) - " "only with slaves.").format(test_num) cmd = "{0} --slaves={1} -v".format(cmd_base, slaves_con) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) if self.debug: print("\nDrop test databases on master.") rpl_sync.drop_test_db(self.server1, db_num=4) if self.debug: print("\nWait for slaves to catch up with master.") self.wait_for_slaves([self.server3, self.server4]) if self.debug: print("\nReset topology with a new master.") self.reset_master([self.server2, self.server3, self.server4]) self.reset_topology([self.server3, self.server4], master=self.server2) if self.debug: print("\nCreate test databases and tables on master.") rpl_sync.create_test_db(self.server2, db_num=4) if self.debug: print("\nWait for slaves to catch up with master.") self.wait_for_slaves([self.server3, self.server4], master=self.server2) # Skip check of databases with replication filters (case 2). # master: --binlog-ignore-db=test_rplsync_db2 # slave1: --replicate-do-table=test_rplsync_db1.t1 # slave2: --replicate-ignore-table=test_rplsync_db1.t2 # --replicate-wild-ignore-table=test\_rplsync\_db1.%3 test_num += 1 comment = ("Test case {0} - check replication filters skip (case 2)." "").format(test_num) cmd = "{0} --master={1} --slaves={2} -v".format(cmd_base, master2_con, slaves_con) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) test_num += 1 comment = ("Test case {0} - check replication filters skip (case 2) - " "only with slaves.").format(test_num) cmd = "{0} --slaves={1} -v".format(cmd_base, slaves_con) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) if self.debug: print("\nReset topology with new slaves.") self.reset_master([self.server2, self.server5, self.server6, self.server7]) self.reset_topology([self.server5, self.server6, self.server7], master=self.server2) # Options replicate-do-db, replicate-ignore-db, and # replicate-wild-do-db are not supported due to known issues on the # server, leading to inconsistent GTID_EXECUTED sets. test_num += 1 comment = ("Test case {0} - error using replicate-do-db." "").format(test_num) cmd = "{0} --master={1} --slaves={2}".format(cmd_base, master2_con, slave3_con) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) test_num += 1 comment = ("Test case {0} - error using replicate-ignore-db." "").format(test_num) cmd = "{0} --master={1} --slaves={2}".format(cmd_base, master2_con, slave4_con) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) test_num += 1 comment = ("Test case {0} - error using replicate-wild-do-db." "").format(test_num) cmd = "{0} --master={1} --slaves={2}".format(cmd_base, master2_con, slave5_con) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Mask out non-deterministic data self.do_masks() return True
def run(self): cmd_base = "mysqlrplsync.py" master_con = self.build_connection_string(self.server1).strip(' ') slave1_con = self.build_connection_string(self.server2).strip(' ') slave2_con = self.build_connection_string(self.server3).strip(' ') slave3_con = self.build_connection_string(self.server4).strip(' ') slaves_con = ",".join([slave1_con, slave2_con, slave3_con]) # Show help. test_num = 1 comment = ("Test case {0} - show help." "").format(test_num) cmd = "{0} --help".format(cmd_base) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) if self.debug: print("\nCreate test databases and tables on master.") rpl_sync.create_test_db(self.server1) # Add another database (empty) to be replicated on all slaves and # checked when using the --exclude option. self.server1.exec_query('CREATE DATABASE empty_db') if self.debug: print("\nInsert data into test database on master.") rpl_sync.load_test_data(self.server1) if self.debug: print("\nWait for slaves to catch up with master.") self.wait_for_slaves() # Skip servers with GTID disabled. test_num += 1 comment = ("Test case {0} - skip slave with GTID OFF." "").format(test_num) cmd = "{0} --master={1} --slaves={2}".format(cmd_base, master_con, slaves_con) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) slaves_con = ",".join([slave1_con, slave2_con]) if self.debug: print("\nStop one of the slaves.") self.server2.exec_query('STOP SLAVE') # Skip sync for stopped slaves. test_num += 1 comment = ("Test case {0} - skip sync for stopped slaves." "").format(test_num) cmd = "{0} --master={1} --slaves={2}".format(cmd_base, master_con, slaves_con) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) if self.debug: print("\nCreate a new database on stopped slave and on master.") self.server2.exec_query('CREATE DATABASE `only_on_slave_db`') self.server1.exec_query('SET SQL_LOG_BIN=0') self.server1.exec_query('CREATE DATABASE `only_on_master_db`') self.server1.exec_query('SET SQL_LOG_BIN=1') # Identify missing databases. test_num += 1 comment = ("Test case {0} - identify missing database." "").format(test_num) cmd = "{0} --master={1} --slaves={2}".format(cmd_base, master_con, slaves_con) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) if self.debug: print("\nChange table definition on slave.") self.server2.exec_query('ALTER TABLE `test_rplsync_db`.`t0` ' 'MODIFY rnd_txt0 VARCHAR(50)') # Different table definition. test_num += 1 comment = ("Test case {0} - identify table with different definition." "").format(test_num) cmd = "{0} --master={1} --slaves={2}".format(cmd_base, master_con, slaves_con) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) if self.debug: print("\nRemove tables on master and slave.") last_tbl = '`t{0}`'.format(rpl_sync.TEST_DB_NUM_TABLES - 1) self.server1.exec_query('SET SQL_LOG_BIN=0') self.server1.exec_query('DROP TABLE `test_rplsync_db`.' '{0}'.format(last_tbl)) self.server1.exec_query('SET SQL_LOG_BIN=1') self.server2.exec_query('DROP TABLE `test_rplsync_db`.`t0`') # Identify missing tables. test_num += 1 comment = ("Test case {0} - identify missing tables." "").format(test_num) cmd = "{0} --master={1} --slaves={2}".format(cmd_base, master_con, slaves_con) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) if self.debug: print("\nChanging data on slaves.") self.server2.exec_query("UPDATE `test_rplsync_db`.`t1` " "SET rnd_txt0='changed value' " "WHERE id=1".format(last_tbl)) self.server3.exec_query("INSERT INTO `test_rplsync_db`.`t0` " "(rnd_txt0) VALUES ('new value')") # Identify data difference. test_num += 1 comment = ("Test case {0} - identify data differences on tables." "").format(test_num) cmd = "{0} --master={1} --slaves={2}".format(cmd_base, master_con, slaves_con) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Check a specific database. test_num += 1 comment = ("Test case {0} - check a specific database." "").format(test_num) cmd = ("{0} --master={1} --slaves={2} " "test_rplsync_db").format(cmd_base, master_con, slaves_con) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Exclude check of a specific database. test_num += 1 comment = ("Test case {0} - exclude a specific database." "").format(test_num) cmd = ("{0} --master={1} --slaves={2} " "--exclude=test_rplsync_db").format(cmd_base, master_con, slaves_con) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Check a specific table. test_num += 1 comment = ("Test case {0} - check a specific table." "").format(test_num) cmd = ("{0} --master={1} --slaves={2} " "test_rplsync_db.t0").format(cmd_base, master_con, slaves_con) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Exclude check of a specific table. test_num += 1 comment = ("Test case {0} - exclude a specific table." "").format(test_num) cmd = ("{0} --master={1} --slaves={2} " "--exclude=test_rplsync_db.t0").format(cmd_base, master_con, slaves_con) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Include/exclude data to check (using backtick quotes). test_num += 1 comment = ("Test case {0} - include/exclude data (using backticks)." "").format(test_num) if os.name == 'posix': cmd_arg = ("'`test_rplsync_db`' --exclude='`test_rplsync_db`.`t0`," "`test_rplsync_db`.`t1`'") else: cmd_arg = ('"`test_rplsync_db`" --exclude="`test_rplsync_db`.`t0`,' '`test_rplsync_db`.`t1`"') cmd = ("{0} --master={1} --slaves={2} " "{3}").format(cmd_base, master_con, slaves_con, cmd_arg) res = self.run_test_case(1, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Check a specific database that does not exist. test_num += 1 comment = ("Test case {0} - check a non existing database." "").format(test_num) cmd = ("{0} --master={1} --slaves={2} " "no_exist_db").format(cmd_base, master_con, slaves_con) res = self.run_test_case(0, cmd, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Mask out non-deterministic data self.do_masks() return True
def run(self): # Create user to test privileges on master and slave. # Missing privilege on the master (SUPER and REPLICATION CLIENT). if self.debug: print("\nCreate user with missing privileges (SUPER and " "REPLICATION CLIENT) on master.") master_grants = ['LOCK TABLES', 'SELECT'] change_user_privileges(self.server1, 'm_user', 'm_pwd', self.server1.host, grant_list=master_grants, revoke_list=None, disable_binlog=True, create_user=True) if self.debug: print("\nCreate user with all required privileges on slave.") slave_grants = ['SUPER', 'SELECT'] change_user_privileges(self.server2, 's_user', 's_pwd', self.server1.host, grant_list=slave_grants, revoke_list=None, disable_binlog=True, create_user=True) master_con = self.build_custom_connection_string(self.server1, 'm_user', 'm_pwd') slave1_con = self.build_custom_connection_string(self.server2, 's_user', 's_pwd') cmd_base = "mysqlrplsync.py --master={0} --slaves={1}".format( master_con, slave1_con ) if self.debug: print("\nCreate test database and tables on master.") rpl_sync.create_test_db(self.server1) if self.debug: print("\nWait for slaves to catch up with master.") self.wait_for_slaves([self.server2]) # Test sync using a master user with missing privilege: SUPER and # REPLICATION CLIENT. test_num = 1 comment = ("Test case {0} - sync (fail) using 'm_user' without: " "SUPER and REPLICATION CLIENT.".format(test_num)) res = self.run_test_case(1, cmd_base, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Grant all required privileges except LOCK TABLES to user on master. if self.debug: print("\nGrant required privileges except LOCK TABLES on master.") master_grants = ['SUPER'] master_revokes = ['LOCK TABLES'] change_user_privileges(self.server1, 'm_user', 'm_pwd', self.server1.host, grant_list=master_grants, revoke_list=master_revokes, disable_binlog=True, create_user=False) # Test sync using a master user with missing privilege: LOCK TABLES. test_num += 1 comment = ("Test case {0} - sync (fail) using 'm_user' without: " "LOCK TABLES.".format(test_num)) res = self.run_test_case(1, cmd_base, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Grant all required privileges except SELECT to user on master. if self.debug: print("\nGrant required privileges except SELECT on master.") master_grants = ['LOCK TABLES'] master_revokes = ['SELECT'] change_user_privileges(self.server1, 'm_user', 'm_pwd', self.server1.host, grant_list=master_grants, revoke_list=master_revokes, disable_binlog=True, create_user=False) # Test sync using a master user with missing privilege: LOCK TABLES. test_num += 1 comment = ("Test case {0} - sync (fail) using 'm_user' without: " "SELECT.".format(test_num)) res = self.run_test_case(1, cmd_base, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Grant all required privileges to user on master. if self.debug: print("\nGrant required privileges on master.") master_grants = ['SELECT'] change_user_privileges(self.server1, 'm_user', 'm_pwd', self.server1.host, grant_list=master_grants, revoke_list=None, disable_binlog=True, create_user=False) # Grant all required privileges except SUPER to user on slave. if self.debug: print("\nGrant required privileges except SUPER on slave.") slave_revokes = ['SUPER'] change_user_privileges(self.server2, 's_user', 's_pwd', self.server2.host, grant_list=None, revoke_list=slave_revokes, disable_binlog=True, create_user=False) # Test sync using a slave user with missing privilege: SUPER. test_num += 1 comment = ("Test case {0} - sync (fail) using 's_user' without: " "SUPER.".format(test_num)) res = self.run_test_case(1, cmd_base, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Grant all required privileges except SELECT to user on slave. if self.debug: print("\nGrant required privileges except SELECT on slave.") slave_grants = ['SUPER'] slave_revokes = ['SELECT'] change_user_privileges(self.server2, 's_user', 's_pwd', self.server2.host, grant_list=slave_grants, revoke_list=slave_revokes, disable_binlog=True, create_user=False) # Test sync using a slave user with missing privilege: SELECT. test_num += 1 comment = ("Test case {0} - sync (fail) using 's_user' without: " "SELECT.".format(test_num)) res = self.run_test_case(1, cmd_base, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Grant all required privileges to user on slave. if self.debug: print("\nGrant required privileges on slave.") slave_grants = ['SELECT'] change_user_privileges(self.server2, 's_user', 's_pwd', self.server2.host, grant_list=slave_grants, revoke_list=None, disable_binlog=True, create_user=False) # Test sync with master and slave users with all required privileges. # Using SUPER (not REPLICATION CLIENT) for master. test_num += 1 comment = ("Test case {0} - sync (succeed) using: 'm_user' with " "SUPER, LOCK TABLES and SELECT; 's_user' with SUPER and " "SELECT.".format(test_num)) res = self.run_test_case(0, cmd_base, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Replace SUPER with REPLICATION CLIENT for user on master. if self.debug: print("\nReplace SUPER with REPLICATION CLIENT on master.") master_grants = ['REPLICATION CLIENT'] master_revokes = ['SUPER'] change_user_privileges(self.server1, 'm_user', 'm_pwd', self.server1.host, grant_list=master_grants, revoke_list=master_revokes, disable_binlog=True, create_user=False) # Test sync with master and slave users with all required privileges. # Using REPLICATION CLIENT (not SUPER) for master. test_num += 1 comment = ("Test case {0} - sync (succeed) using: 'm_user' with " "REPLICATION CLIENT, LOCK TABLES and SELECT; 's_user' with " "SUPER and SELECT.".format(test_num)) res = self.run_test_case(0, cmd_base, comment) if not res: raise MUTLibError("{0}: failed".format(comment)) # Mask out non-deterministic data self.do_masks() return True