def _check_candidate_fail(group_id, slave_id): """Check if the candidate has all the prerequisites to become the new master. """ allowed_status = (_server.MySQLServer.SECONDARY, _server.MySQLServer.SPARE) group = _server.Group.fetch(group_id) slave = _retrieve_server(slave_id, group_id) slave.connect() if group.master == slave.uuid: raise _errors.ServerError("Candidate slave (%s) is already master." % (slave_id, )) master_issues, why_master_issues = _replication.check_master_issues(slave) if master_issues: raise _errors.ServerError("Server (%s) is not a valid candidate slave " "due to the following reason(s): (%s)." % (slave.uuid, why_master_issues)) if slave.status not in allowed_status: raise _errors.ServerError("Server (%s) is faulty." % (slave_id, )) _events.trigger_within_procedure(WAIT_SLAVE_FAIL, group_id, str(slave.uuid))
def _check_candidate_fail(group_id, slave_id): """Check if the candidate has all the prerequisites to become the new master. """ allowed_status = (_server.MySQLServer.SECONDARY, _server.MySQLServer.SPARE) group = _server.Group.fetch(group_id) slave = _retrieve_server(slave_id, group_id) slave.connect() if group.master == slave.uuid: raise _errors.ServerError( "Candidate slave (%s) is already master." % (slave_id, ) ) master_issues = _replication.check_master_issues(slave) if master_issues: raise _errors.ServerError( "Server (%s) is not a valid candidate slave " "due to the following reason(s): (%s)." % (slave.uuid, master_issues) ) if slave.status not in allowed_status: raise _errors.ServerError("Server (%s) is faulty." % (slave_id, )) _events.trigger_within_procedure(WAIT_SLAVE_FAIL, group_id, str(slave.uuid))
def _check_candidate_switch(group_id, slave_id): """Check if the candidate has all the features to become the new master. """ allowed_status = (_server.MySQLServer.SECONDARY, _server.MySQLServer.SPARE) group = _server.Group.fetch(group_id) if not group.master: raise _errors.GroupError( "Group (%s) does not contain a valid " "master. Please, run a promote or failover." % (group_id, ) ) slave = _retrieve_server(slave_id, group_id) slave.connect() if group.master == slave.uuid: raise _errors.ServerError( "Candidate slave (%s) is already master." % (slave_id, ) ) master_issues = _replication.check_master_issues(slave) if master_issues: raise _errors.ServerError( "Server (%s) is not a valid candidate slave " "due to the following reason(s): (%s)." % (slave.uuid, master_issues) ) slave_issues = _replication.check_slave_issues(slave) if slave_issues: raise _errors.ServerError( "Server (%s) is not a valid candidate slave " "due to the following reason: (%s)." % (slave.uuid, slave_issues) ) master_uuid = _replication.slave_has_master(slave) if master_uuid is None or group.master != _uuid.UUID(master_uuid): raise _errors.GroupError( "The group's master (%s) is different from the candidate's " "master (%s)." % (group.master, master_uuid) ) if slave.status not in allowed_status: raise _errors.ServerError("Server (%s) is faulty." % (slave_id, )) _events.trigger_within_procedure( BLOCK_WRITE_SWITCH, group_id, master_uuid, str(slave.uuid) )
def _check_candidate_switch(group_id, slave_id): """Check if the candidate has all the features to become the new master. """ allowed_status = (_server.MySQLServer.SECONDARY, _server.MySQLServer.SPARE) group = _server.Group.fetch(group_id) if not group.master: raise _errors.GroupError("Group (%s) does not contain a valid " "master. Please, run a promote or failover." % (group_id, )) slave = _retrieve_server(slave_id, group_id) slave.connect() if group.master == slave.uuid: raise _errors.ServerError("Candidate slave (%s) is already master." % (slave_id, )) master_issues, why_master_issues = _replication.check_master_issues(slave) if master_issues: raise _errors.ServerError("Server (%s) is not a valid candidate slave " "due to the following reason(s): (%s)." % (slave.uuid, why_master_issues)) slave_issues, why_slave_issues = _replication.check_slave_issues(slave) if slave_issues: raise _errors.ServerError("Server (%s) is not a valid candidate slave " "due to the following reason: (%s)." % (slave.uuid, why_slave_issues)) master_uuid = _replication.slave_has_master(slave) if master_uuid is None or group.master != _uuid.UUID(master_uuid): raise _errors.GroupError( "The group's master (%s) is different from the candidate's " "master (%s)." % (group.master, master_uuid)) if slave.status not in allowed_status: raise _errors.ServerError("Server (%s) is faulty." % (slave_id, )) _events.trigger_within_procedure(BLOCK_WRITE_SWITCH, group_id, master_uuid, str(slave.uuid))
def _do_find_candidate(group_id, event): """Find the best candidate in a group that may be used to replace the current master if there is any. It chooses the slave that has processed more transactions and may become a master, e.g. has the binary log enabled. This function does not consider purged transactions and delays in the slave while picking up a slave. :param group_id: Group's id from where a candidate will be chosen. :return: Return the uuid of the best candidate to become a master in the group. """ forbidden_status = (_server.MySQLServer.FAULTY, _server.MySQLServer.SPARE) group = _server.Group.fetch(group_id) master_uuid = None if group.master: master_uuid = str(group.master) chosen_uuid = None chosen_gtid_status = None for candidate in group.servers(): if master_uuid != str(candidate.uuid) and \ candidate.status not in forbidden_status: try: candidate.connect() gtid_status = candidate.get_gtid_status() master_issues, why_master_issues = \ _replication.check_master_issues(candidate) slave_issues = False why_slave_issues = {} if event == FIND_CANDIDATE_SWITCH: slave_issues, why_slave_issues = \ _replication.check_slave_issues(candidate) has_valid_master = (master_uuid is None or \ _replication.slave_has_master(candidate) == master_uuid) can_become_master = False if chosen_gtid_status: n_trans = 0 try: n_trans = _replication.get_slave_num_gtid_behind( candidate, chosen_gtid_status) except _errors.InvalidGtidError: pass if n_trans == 0 and not master_issues and \ has_valid_master and not slave_issues: chosen_gtid_status = gtid_status chosen_uuid = str(candidate.uuid) can_become_master = True elif not master_issues and has_valid_master and \ not slave_issues: chosen_gtid_status = gtid_status chosen_uuid = str(candidate.uuid) can_become_master = True if not can_become_master: _LOGGER.warning( "Candidate (%s) cannot become a master due to the " "following reasons: issues to become a " "master (%s), prerequistes as a slave (%s), valid " "master (%s).", candidate.uuid, why_master_issues, why_slave_issues, has_valid_master) except _errors.DatabaseError as error: _LOGGER.warning("Error accessing candidate (%s): %s.", candidate.uuid, error) if not chosen_uuid: raise _errors.GroupError( "There is no valid candidate that can be automatically " "chosen in group (%s). Please, choose one manually." % (group_id, )) return chosen_uuid
def _do_find_candidate(group_id, event): """Find the best candidate in a group that may be used to replace the current master if there is any. It chooses the slave that has processed more transactions and may become a master, e.g. has the binary log enabled. This function does not consider purged transactions and delays in the slave while picking up a slave. :param group_id: Group's id from where a candidate will be chosen. :return: Return the uuid of the best candidate to become a master in the group. """ forbidden_status = (_server.MySQLServer.FAULTY, _server.MySQLServer.SPARE) group = _server.Group.fetch(group_id) master_uuid = None if group.master: master_uuid = str(group.master) chosen_uuid = None chosen_gtid_status = None for candidate in group.servers(): if master_uuid != str(candidate.uuid) and \ candidate.status not in forbidden_status: try: candidate.connect() gtid_status = candidate.get_gtid_status() master_issues = \ _replication.check_master_issues(candidate) if event == FIND_CANDIDATE_SWITCH: slave_issues = \ _replication.check_slave_issues(candidate) else: slave_issues = {} has_valid_master = (master_uuid is None or \ _replication.slave_has_master(candidate) == master_uuid) can_become_master = False if chosen_gtid_status: n_trans = 0 try: n_trans = _replication.get_slave_num_gtid_behind( candidate, chosen_gtid_status ) except _errors.InvalidGtidError: pass if n_trans == 0 and not master_issues and \ has_valid_master and not slave_issues: chosen_gtid_status = gtid_status chosen_uuid = str(candidate.uuid) can_become_master = True elif not master_issues and has_valid_master and \ not slave_issues: chosen_gtid_status = gtid_status chosen_uuid = str(candidate.uuid) can_become_master = True if not can_become_master: _LOGGER.warning( "Candidate (%s) cannot become a master due to the " "following reasons: issues to become a " "master (%s), prerequistes as a slave (%s), valid " "master (%s).", candidate.uuid, master_issues, slave_issues, has_valid_master ) except _errors.DatabaseError as error: _LOGGER.warning( "Error accessing candidate (%s).", candidate.uuid, exc_info=error ) if not chosen_uuid: raise _errors.GroupError( "There is no valid candidate that can be automatically " "chosen in group (%s). Please, choose one manually." % (group_id, ) ) return chosen_uuid