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
Example #3
0
    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
Example #6
0
    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):
        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