def testDuplicateInstanceChangeMsgsMarkNodeAsSuspicious(looper, nodeSet, up):
    maliciousNode = nodeSet.Alpha
    maliciousNode.send(InstanceChange(0))

    def chk(instId):
        for node in nodeSet:
            if node.name != maliciousNode.name:
                param = getAllArgs(node, Node.processInstanceChange)
                assert param[0]['instChg'].viewNo == instId
                assert param[0]['frm'] == maliciousNode.name

    looper.run(eventually(chk, 0, retryWait=1, timeout=20))
    maliciousNode.send(InstanceChange(0))

    def g():
        for node in nodeSet:
            if node.name != maliciousNode.name:
                frm, reason, code = getAllArgs(node, Node.reportSuspiciousNode)
                assert frm == maliciousNode.name
                assert isinstance(reason, SuspiciousNode)
                assert len(
                    getNodeSuspicions(
                        node, Suspicions.DUPLICATE_INST_CHNG.code)) == 12

    looper.run(eventually(g, retryWait=1, timeout=20))
Example #2
0
def testDoNotSendInstChngMsgIfMasterDoesntSeePerformanceProblem(
        nodeSet, looper, ensureView):
    """
    A node that received an INSTANCE_CHANGE message must not send an
    INSTANCE_CHANGE message if it doesn't observe too much difference in
    performance between its replicas.
    """

    curViewNo = ensureView

    # Count sent instance changes of all nodes
    sentInstChanges = {}
    instChngMethodName = Node.sendInstanceChange.__name__
    for n in nodeSet:
        sentInstChanges[n.name] = n.spylog.count(instChngMethodName)

    # Send an instance change message to all nodes
    icMsg = InstanceChange(curViewNo)
    nodeSet.Alpha.send(icMsg)

    # Check that that message is discarded.
    looper.run(eventually(checkViewNoForNodes, nodeSet, timeout=3))
    # No node should have sent a view change and thus must not have called
    # `sendInstanceChange`
    for n in nodeSet:
        assert n.spylog.count(instChngMethodName) == \
                   sentInstChanges.get(n.name, 0)
Example #3
0
def testDiscardInstChngMsgIfMasterDoesntSeePerformanceProblem(
        nodeSet, looper, ensureView):
    """
    A node that received an INSTANCE_CHANGE message must not send an
    INSTANCE_CHANGE message if it doesn't observe too much difference in
    performance between its replicas.
    """

    curViewNo = ensureView

    # Send an instance change message to all nodes
    icMsg = InstanceChange(curViewNo)
    nodeSet.Alpha.send(icMsg)

    # ensure every node but Alpha discards the invalid instance change request
    looper.run(
        eventually(checkDiscardMsg,
                   nodeSet,
                   icMsg,
                   'did not find the master to be slow',
                   nodeSet.Alpha,
                   timeout=5))

    # Check that that message is discarded.
    looper.run(eventually(checkViewNoForNodes, nodeSet, timeout=3))
def testMultipleInstanceChangeMsgsMarkNodeAsSuspicious(looper, nodeSet, up):
    maliciousNode = nodeSet.Alpha
    for i in range(0, 5):
        maliciousNode.send(InstanceChange(i))

    def chk(instId):
        for node in nodeSet:
            if node.name != maliciousNode.name:
                args = getAllArgs(node, Node.processInstanceChange)
                assert len(args) == 5
                for arg in args:
                    assert arg['frm'] == maliciousNode.name

    for i in range(0, 5):
        looper.run(eventually(chk, i, retryWait=1, timeout=20))

    def g():
        for node in nodeSet:
            if node.name != maliciousNode.name:
                frm, reason, code = getAllArgs(node, Node.reportSuspiciousNode)
                assert frm == maliciousNode.name
                assert isinstance(reason, SuspiciousNode)
                assert len(
                    getNodeSuspicions(
                        node, Suspicions.FREQUENT_INST_CHNG.code)) == 13

    looper.run(eventually(g, retryWait=1, timeout=20))
def testInstanceChangeMsgTypeChecking(nodeSet, looper, up):
    nodeA = nodeSet.Alpha
    nodeB = nodeSet.Beta

    ridBeta = nodeA.nodestack.getRemote(nodeB.name).uid
    badViewNo = "BAD"
    nodeA.send(InstanceChange(badViewNo), ridBeta)
    looper.runFor(0.2)
    params = nodeB.spylog.getLastParams(TestNode.discard)

    def chk():
        assert isinstance(params['msg'], InstanceChange)
        assert DISCARD_REASON in params['reason']

    looper.run(eventually(chk, timeout=5))
Example #6
0
def testDiscardInstChngMsgFrmPastView(nodeSet, looper, ensureView):
    """
    Once a view change is done, any further INSTANCE_CHANGE messages for that
    view must be discarded by the node.
    """

    curViewNo = ensureView

    # Send an instance change for an old instance message to all nodes
    icMsg = InstanceChange(curViewNo - 1)
    nodeSet.Alpha.send(icMsg)

    # ensure every node but Alpha discards the invalid instance change request
    looper.run(
        eventually(checkDiscardMsg,
                   nodeSet,
                   icMsg,
                   'less than its view no',
                   nodeSet.Alpha,
                   timeout=5))

    # Check that that message is discarded.
    looper.run(eventually(checkViewNoForNodes, nodeSet, timeout=3))