~chuck-bell/mysql-utilities/mysql-utilities

« back to all changes in this revision

Viewing changes to mysql/utilities/common/rpl.py

  • Committer: chuck.bell at oracle
  • Date: 2011-09-29 14:14:38 UTC
  • Revision ID: chuck.bell@oracle.com-20110929141438-clzfl7m2769wt2jm
WL#5983 : allow user to specify binary log file and position (mysqlreplicate)

This patch adds new features to mysqlreplicate to permit starting replication
from the beginning, starting from a specific log file, and starting from a
specific log file and position.

Show diffs side-by-side

added added

removed removed

Lines of Context:
67
67
    options={}. This will allow for reduced code needed to call multiple tests.
68
68
    """  
69
69
    
70
 
    def __init__(self, master, slave, verbose=False):
 
70
    def __init__(self, master, slave, options):
71
71
        """Constructor
72
72
        
73
73
        master[in]         Master Server object
74
74
        slave[in]          Slave Server object
75
 
        verbose[in]        print extra data during operations (optional)
 
75
        options[in]        Options for class
 
76
          verbose          print extra data during operations (optional)
76
77
                           default value = False
 
78
          master_log_file  master log file
 
79
                           default value = None
 
80
          master_log_pos   position in log file
 
81
                           default = -1 (no position specified)
 
82
          from_beginning   if True, start from beginning of logged events
 
83
                           default = False
77
84
        """
78
 
        self.verbose = verbose
 
85
        self.verbosity = options.get("verbosity", 0)
 
86
        self.master_log_file = options.get("master_log_file", None)
 
87
        self.master_log_pos = options.get("master_log_pos", 0)
 
88
        self.from_beginning = options.get("from_beginning", False)
79
89
        self.master = master
80
90
        self.slave = slave
81
91
        self.master_server_id = None
563
573
        # Create user class instance
564
574
        user = User(self.master,
565
575
                    "%s@%s:%s" % (rpl_user, self.master.host, self.master.port),
566
 
                    self.verbose)
 
576
                    self.verbosity)
567
577
 
568
578
        r_user, r_pass = re.match("(\w+)(?:\:(\w+))?", rpl_user).groups()
569
579
        
570
580
        # Check to see if rpl_user is present, else create her
571
581
        if not user.exists():
572
 
            if self.verbose:
 
582
            if self.verbosity > 0:
573
583
                print "# Creating replication user..."
574
584
            user.create()
575
585
        
576
586
        # Check to see if rpl_user has the correct grants, else grant rights
577
587
        if not user.has_privilege("*", "*", "REPLICATION SLAVE"):
578
 
            if self.verbose:
 
588
            if self.verbosity > 0:
579
589
                print "# Granting replication access to replication user..."
580
590
            query_str = "GRANT REPLICATION SLAVE ON *.* TO '%s'@'%s' " % \
581
591
                        (r_user, self.slave.host)
594
604
            print "ERROR: Cannot retrieve master status."
595
605
            exit(1)
596
606
            
597
 
        master_file = res[0][0]
598
 
        master_pos = res[0][1]
 
607
        # If master log file, pos not specified, read master log file info
 
608
        read_master_info = False
 
609
        if self.master_log_file is None:
 
610
            res = self.master.exec_query("SHOW MASTER STATUS")
 
611
            if not res:
 
612
                print "ERROR: Cannot retrieve master status."
 
613
                exit(1)
 
614
 
 
615
            read_master_info = True
 
616
            self.master_log_file = res[0][0]
 
617
            self.master_log_pos = res[0][1]
 
618
        else:
 
619
            # Check to make sure file is accessible and valid
 
620
            found = False
 
621
            res = self.master.exec_query("SHOW BINARY LOGS",
 
622
                                         self.query_options)
 
623
            if res:
 
624
                for row in res:
 
625
                    if row[0] == self.master_log_file:
 
626
                        found = True
 
627
                        break
 
628
            if not found:
 
629
                raise UtilError("Master binary log file not listed as a "
 
630
                                "valid binary log file on the master.")
 
631
                
 
632
        if self.master_log_file is None:
 
633
            raise UtilError("No master log file specified.")
599
634
         
600
635
        # Stop slave first
601
636
        res = self.slave.exec_query("SHOW SLAVE STATUS")
604
639
                res = self.slave.exec_query("STOP SLAVE", self.query_options)
605
640
        
606
641
        # Connect slave to master
607
 
        if self.verbose:
 
642
        if self.verbosity > 0:
608
643
            print "# Connecting slave to master..."
609
644
        change_master = "CHANGE MASTER TO MASTER_HOST = '%s', " % \
610
645
                        self.master.host
611
646
        change_master += "MASTER_USER = '%s', " % r_user
612
647
        change_master += "MASTER_PASSWORD = '%s', " % r_pass
613
 
        change_master += "MASTER_PORT = %s, " % self.master.port
614
 
        change_master += "MASTER_LOG_FILE = '%s', " % master_file
615
 
        change_master += "MASTER_LOG_POS = %s" % master_pos
 
648
        change_master += "MASTER_PORT = %s" % self.master.port
 
649
        if not self.from_beginning:
 
650
            change_master += ", MASTER_LOG_FILE = '%s' " % self.master_log_file
 
651
            if self.master_log_pos >= 0:
 
652
                change_master += ", MASTER_LOG_POS = %s" % self.master_log_pos
616
653
        res = self.slave.exec_query(change_master, self.query_options)
617
 
        if self.verbose:
 
654
        if self.verbosity > 0:
618
655
            print "# %s" % change_master
619
656
        
620
657
        # Start slave
621
 
        if self.verbose:
622
 
            print "# Starting slave..."
 
658
        if self.verbosity > 0:
 
659
            if not self.from_beginning:
 
660
                if read_master_info:
 
661
                    print "# Starting slave from master's last position..."
 
662
                else:
 
663
                    msg = "# Starting slave from master log file '%s'" % \
 
664
                          self.master_log_file
 
665
                    if self.master_log_pos >= 0:
 
666
                        msg += " using position %s" % self.master_log_pos
 
667
                    msg += "..."
 
668
                    print msg 
 
669
            else:
 
670
                print "# Starting slave from the beginning..."
623
671
        res = self.slave.exec_query("START SLAVE", self.query_options)
624
672
        
625
673
        # Check slave status
628
676
            time.sleep(1)
629
677
            res = self.slave.exec_query("SHOW SLAVE STATUS")
630
678
            status = res[0][0]
631
 
            if self.verbose:
 
679
            if self.verbosity > 0:
632
680
                print "# status: %s" % status
633
681
                print "# error: %s:%s" % (res[0][34], res[0][35])
634
682
            if status == "Waiting for master to send event":
635
683
                break
636
 
            if self.verbose:
 
684
            if self.verbosity > 0:
637
685
                print "# Waiting for slave to synchronize with master"
638
686
            i += 1
639
687
        if i == num_tries:
640
688
            print "ERROR: failed to synch slave with master."
641
689
            result = False
642
690
            
643
 
        # unlock tables on master
644
 
        if self.verbose:
645
 
            print "# Unlocking tables on master..."
646
 
        query_str = "UNLOCK TABLES"
647
 
        res = self.master.exec_query(query_str, self.query_options)
648
691
        if result is True:
649
692
            self.replicating = True
650
693
        return result
663
706
        if not self.replicating:
664
707
            print "ERROR: Replication is not running among master and slave."
665
708
        print "# Testing replication setup..."
666
 
        if self.verbose:
 
709
        if self.verbosity > 0:
667
710
            print "# Creating a test database on master named %s..." % db
668
711
        res = self.master.exec_query("CREATE DATABASE %s" % db,
669
712
                                     self.query_options)
679
722
                    i = num_tries
680
723
                    break
681
724
            i += 1
682
 
            if i < num_tries and self.verbose:
 
725
            if i < num_tries and self.verbosity > 0:
683
726
                print "# Waiting for slave to synchronize with master"
684
727
        if i == num_tries:
685
728
            print "ERROR: Unable to complete testing."