示例#1
0
def test_process_backup_instance_faulty_msg_quorum_for_different_replicas(backup_instance_faulty_processor):
    '''
    Test for case when process_backup_instance_faulty_msg received messages for different instances.
    Firstly f messages for [1,2], secondly 1 message for [2]. As a result, replica 2 should be removed
    and replica 1 are not.
    '''
    node = backup_instance_faulty_processor.node
    node.config.REPLICAS_REMOVING_WITH_PRIMARY_DISCONNECTED = "quorum"
    instance_to_remove = 2
    instance_not_removed = 1
    nodes = set()
    msg = BackupInstanceFaulty(node.viewNo,
                               [instance_to_remove, instance_not_removed],
                               Suspicions.BACKUP_PRIMARY_DISCONNECTED.code)
    # send node.quorums.backup_instance_faulty - 1 BackupInstanceFaulty messages for 1, 2 replicas
    for node_name in node.allNodeNames[:node.quorums.backup_instance_faulty.value - 1]:
        nodes.add(node_name)
        backup_instance_faulty_processor.process_backup_instance_faulty_msg(msg, node_name)

    assert not node.replicas.remove_replica_calls

    msg = BackupInstanceFaulty(node.viewNo,
                               [instance_to_remove],
                               Suspicions.BACKUP_PRIMARY_DISCONNECTED.code)
    # send BackupInstanceFaulty message for 2 replica
    node_name = node.allNodeNames[node.quorums.backup_instance_faulty.value - 1]
    backup_instance_faulty_processor.process_backup_instance_faulty_msg(msg, node_name)

    # check that 2nd replica was removed and 1st replica did not.
    assert instance_to_remove not in backup_instance_faulty_processor.backup_instances_faulty
    assert len(node.replicas.remove_replica_calls) == 1
    assert node.replicas.remove_replica_calls[0] == instance_to_remove
    assert nodes.issubset(backup_instance_faulty_processor.backup_instances_faulty[instance_not_removed].keys())
示例#2
0
def test_process_backup_instance_faulty_without_quorum(
        backup_instance_faulty_processor):
    '''
    Send (quorum - 1) messages from different nodes and (quorum - 1) from current node.
    Replica shouldn't be removed in both cases.
    '''
    node = backup_instance_faulty_processor.node
    node.config.REPLICAS_REMOVING_WITH_DEGRADATION = "quorum"
    instance_to_remove = 1
    msg = BackupInstanceFaulty(node.viewNo, [instance_to_remove],
                               Suspicions.BACKUP_PRIMARY_DEGRADED.code)
    nodes = set()
    # check that node.quorums.backup_instance_faulty - 1 messages don't leads to replica removing
    for node_name in node.allNodeNames[1:node.quorums.backup_instance_faulty.
                                       value - 1]:
        nodes.add(node_name)
        backup_instance_faulty_processor.process_backup_instance_faulty_msg(
            msg, node_name)

    assert nodes.issubset(backup_instance_faulty_processor.
                          backup_instances_faulty[instance_to_remove].keys())
    assert not node.replicas.remove_replica_calls

    # check that node.quorums.backup_instance_faulty - 1 own messages don't lead to replica removing
    for _ in range(node.quorums.backup_instance_faulty.value - 1):
        backup_instance_faulty_processor.process_backup_instance_faulty_msg(
            msg, node.name)

    assert nodes.issubset(backup_instance_faulty_processor.
                          backup_instances_faulty[instance_to_remove].keys())
    assert backup_instance_faulty_processor.backup_instances_faulty[instance_to_remove][node.name] == \
           node.quorums.backup_instance_faulty.value - 1
    assert not node.replicas.remove_replica_calls
示例#3
0
def test_process_backup_instance_faulty_msg_quorum_degradation(
        backup_instance_faulty_processor):
    '''
    Send (quorum - 1) of messages with BACKUP_PRIMARY_DEGRADED from different nodes and
    check that it is not lead to a replica removing. But after sending one more message,
    the replica will be removed.
    '''
    node = backup_instance_faulty_processor.node
    node.config.REPLICAS_REMOVING_WITH_DEGRADATION = "quorum"
    instance_to_remove = 1
    msg = BackupInstanceFaulty(node.viewNo, [instance_to_remove],
                               Suspicions.BACKUP_PRIMARY_DEGRADED.code)
    nodes = set()
    # check that node.quorums.backup_instance_faulty - 1 messages don't leads to replica removing
    for node_name in node.allNodeNames[:node.quorums.backup_instance_faulty.
                                       value - 1]:
        nodes.add(node_name)
        backup_instance_faulty_processor.process_backup_instance_faulty_msg(
            msg, node_name)

    assert nodes.issubset(backup_instance_faulty_processor.
                          backup_instances_faulty[instance_to_remove])
    assert not node.replicas.remove_replica_calls

    # check that messages from all nodes lead to replica removing
    for node_name in node.allNodeNames[node.quorums.backup_instance_faulty.
                                       value - 1:]:
        backup_instance_faulty_processor.process_backup_instance_faulty_msg(
            msg, node_name)

    assert not backup_instance_faulty_processor.backup_instances_faulty
    assert len(node.replicas.remove_replica_calls) == 1
    assert node.replicas.remove_replica_calls[0] == instance_to_remove
示例#4
0
def test_quorum_collection(tdir):
    node = FakeNode(tdir)
    proc = BackupInstanceFaultyProcessor(node)
    backup_faulty = BackupInstanceFaulty(0, [1], Suspicions.BACKUP_PRIMARY_DEGRADED.code)
    proc.process_backup_instance_faulty_msg(backup_faulty, 'someone')

    assert len(proc.backup_instances_faulty[1].keys()) == 1
示例#5
0
 def __send_backup_instance_faulty(self, instances: List[int],
                                   reason: Suspicion):
     if not self.node.view_change_in_progress and not instances:
         return
     logger.info(
         "{} sending a backup instance faulty message with view_no {} "
         "and reason '{}' for instances: {}".format(self.node.name,
                                                    self.node.viewNo,
                                                    reason.reason,
                                                    instances))
     msg = BackupInstanceFaulty(self.node.viewNo, instances, reason.code)
     self.process_backup_instance_faulty_msg(msg, self.node.name)
     self.node.send(msg)
示例#6
0
def test_process_backup_instance_empty_msg(backup_instance_faulty_processor):
    '''
    Check that BackupInstanceFaulty message with empty list of instances will not be processed.
    '''
    node = backup_instance_faulty_processor.node
    node.config.REPLICAS_REMOVING_WITH_DEGRADATION = "quorum"
    msg = BackupInstanceFaulty(node.viewNo, [],
                               Suspicions.BACKUP_PRIMARY_DEGRADED.code)

    backup_instance_faulty_processor.process_backup_instance_faulty_msg(
        msg, node.name)

    assert not backup_instance_faulty_processor.backup_instances_faulty
    assert not node.replicas.remove_replica_calls
示例#7
0
def test_process_backup_instance_faulty_msg_local_disconnection(backup_instance_faulty_processor):
    '''
    Check that BackupInstanceFaulty message with REPLICAS_REMOVING_WITH_PRIMARY_DISCONNECTED
    will not be processed.
    '''
    node = backup_instance_faulty_processor.node
    node.config.REPLICAS_REMOVING_WITH_PRIMARY_DISCONNECTED = "local"
    msg = BackupInstanceFaulty(node.viewNo,
                               [1, 2],
                               Suspicions.BACKUP_PRIMARY_DISCONNECTED.code)

    backup_instance_faulty_processor.process_backup_instance_faulty_msg(msg, node.name)

    assert not backup_instance_faulty_processor.backup_instances_faulty
    assert not node.replicas.remove_replica_calls
 def __send_backup_instance_faulty(self, instances: List[int],
                                   reason: Suspicion):
     if not self.node.view_change_in_progress and instances and \
             not any(inst_id in self.backup_instances_faulty and
                     self.node.name in self.backup_instances_faulty[inst_id]
                     for inst_id in instances):
         return
     logger.info("{} sending an backup instance faulty with view_no {} "
                 "and reason {} for instances: ".format(
                     self.node.name, self.node.viewNo, reason.reason,
                     instances))
     for inst_id in instances:
         self.backup_instances_faulty.setdefault(inst_id, set()) \
             .add(self.node.name)
     self.node.send(
         BackupInstanceFaulty(self.node.viewNo, instances, reason.code))
示例#9
0
def test_process_backup_instance_faulty_msg_quorum_from_itself(backup_instance_faulty_processor):
    '''
    Send quorum of messages from current node.
    Replica should be removed.
    '''
    node = backup_instance_faulty_processor.node
    node.config.REPLICAS_REMOVING_WITH_PRIMARY_DISCONNECTED = "quorum"
    instance_to_remove = 1
    msg = BackupInstanceFaulty(node.viewNo,
                               [instance_to_remove],
                               Suspicions.BACKUP_PRIMARY_DISCONNECTED.code)
    # check that node.quorums.backup_instance_faulty own messages lead to replica removing
    for _ in range(node.quorums.backup_instance_faulty.value):
        backup_instance_faulty_processor.process_backup_instance_faulty_msg(msg, node.name)

    assert not backup_instance_faulty_processor.backup_instances_faulty
    assert len(node.replicas.remove_replica_calls) == 1
    assert node.replicas.remove_replica_calls[0] == instance_to_remove
示例#10
0
def test_process_backup_instance_faulty_msg_quorum_disconnection(backup_instance_faulty_processor):
    '''
    Send quorum of messages with BACKUP_PRIMARY_DISCONNECTED from different nodes.
    Replica should be removed.
    '''
    node = backup_instance_faulty_processor.node
    node.config.REPLICAS_REMOVING_WITH_PRIMARY_DISCONNECTED = "quorum"
    instance_to_remove = 1
    msg = BackupInstanceFaulty(node.viewNo,
                               [instance_to_remove],
                               Suspicions.BACKUP_PRIMARY_DISCONNECTED.code)
    for node_name in node.allNodeNames:
        backup_instance_faulty_processor.process_backup_instance_faulty_msg(msg, node_name)

    # check that messages from all nodes lead to replica removing
    assert not backup_instance_faulty_processor.backup_instances_faulty
    assert len(node.replicas.remove_replica_calls) == 1
    assert node.replicas.remove_replica_calls[0] == instance_to_remove
示例#11
0
def test_process_backup_instance_faulty_msg_quorum_from_others(backup_instance_faulty_processor):
    '''
    Send quorum of messages from different nodes exception current node.
    Replica should be removed.
    '''
    node = backup_instance_faulty_processor.node
    node.config.REPLICAS_REMOVING_WITH_PRIMARY_DISCONNECTED = "quorum"
    instance_to_remove = 1
    msg = BackupInstanceFaulty(node.viewNo,
                               [instance_to_remove],
                               Suspicions.BACKUP_PRIMARY_DISCONNECTED.code)
    # send messages from all nodes with exception of current node
    for node_name in node.allNodeNames[1:]:
        backup_instance_faulty_processor.process_backup_instance_faulty_msg(msg, node_name)

    # check that remove_replica was called
    assert not backup_instance_faulty_processor.backup_instances_faulty
    assert len(node.replicas.remove_replica_calls) == 1
    assert node.replicas.remove_replica_calls[0] == instance_to_remove