예제 #1
0
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))
예제 #2
0
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))
예제 #3
0
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)
        )
예제 #4
0
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))
예제 #5
0
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
예제 #6
0
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