示例#1
0
    def test_nextStateNotMissingIfInitial(self):
        """
        L{MissingTransitionNextState} is not raised if a value defined by
        C{state} appears nowhere in C{transitions} as a next state but is given
        as C{initial}.
        """
        transitions = TransitionTable()
        transitions = transitions.addTransition(
            MoreState.amber, Input.apple, [Output.aardvark], MoreState.amber)
        transitions = transitions.addTerminalState(MoreState.blue)

        constructFiniteStateMachine(
            Input, Output, MoreState, transitions,
            MoreState.blue, [], {}, NULL_WORLD)
示例#2
0
    def test_nextStateNotMissingIfInitial(self):
        """
        L{MissingTransitionNextState} is not raised if a value defined by
        C{state} appears nowhere in C{transitions} as a next state but is given
        as C{initial}.
        """
        transitions = TransitionTable()
        transitions = transitions.addTransition(MoreState.amber, Input.apple,
                                                [Output.aardvark],
                                                MoreState.amber)
        transitions = transitions.addTerminalState(MoreState.blue)

        constructFiniteStateMachine(Input, Output, MoreState, transitions,
                                    MoreState.blue, [], {}, NULL_WORLD)
示例#3
0
 def __init__(self):
     self._fsm = constructFiniteStateMachine(
         inputs=Input, outputs=Output, states=State, table=table,
         initial=State.IDLE,
         richInputs=[RequestStart, InstanceStarted, StartFailed,
                     RequestStop, InstanceStopped, StopFailed],
         inputContext={}, world=MethodSuffixOutputer(self))
示例#4
0
    def test_noRepeatedTerminalLogging(self, logger):
        """
        When the L{IFiniteStateMachine} receives an input in a terminal state
        (and does not generate an output or change to a different state, as is
        required in terminal states) it does not re-log the completion of its
        initialization event.
        """
        # Accept this input in MoreState.blue but remain a terminal state (no
        # output, no state change).
        transitions = TRANSITIONS.addTransition(MoreState.blue, Input.apple,
                                                [], MoreState.blue)

        fsm = constructFiniteStateMachine(
            Input, Output, MoreState, transitions, MoreState.amber,
            [Gravenstein], {Output.aardvark: IFood},
            MethodSuffixOutputer(AnimalWorld([])), logger)

        fsm.receive(Gravenstein())
        howMany = len(logger.messages)

        fsm.receive(Gravenstein())

        # No additional initialization messages please!
        self.assertEqual([], [
            msg for msg in logger.messages[howMany:]
            if msg[u"action_type"] == u"fsm:initialize"
        ])
示例#5
0
def main():
    hardware = TurnstileController(digitalPin=0x13)
    turnstileFSM = constructFiniteStateMachine(
        inputs=TurnstileInput,
        outputs=TurnstileOutput,
        states=TurnstileState,
        table=table,
        initial=TurnstileState.LOCKED,
        richInputs={},
        inputContext={},
        world=MethodSuffixOutputer(Turnstile(hardware)),
    )
    while True:
        if hardware.paymentMade():
            hardware.resetNotification()
            turnstileFSM.receive(TurnstileInput.FARE_PAID)
        elif hardware.armTurned():
            hardware.resetNotification()
            turnstileFSM.receive(TurnstileInput.ARM_TURNED)
        elif hardware.finishedLocking():
            hardware.resetNotification()
            turnstileFSM.receive(TurnstileInput.ARM_LOCKED)
        elif hardware.finishedUnlocking():
            hardware.resetNotification()
            turnstileFSM.receive(TurnstileInput.ARM_UNLOCKED)
        else:
            time.sleep(0.1)
示例#6
0
def build_convergence_loop_fsm(reactor, deployer):
    """
    Create a convergence loop FSM.

    :param IReactorTime reactor: Used to schedule delays in the loop.

    :param IDeployer deployer: Used to discover local state and calcualte
        necessary changes to match desired configuration.
    """
    I = ConvergenceLoopInputs
    O = ConvergenceLoopOutputs
    S = ConvergenceLoopStates

    table = TransitionTable()
    table = table.addTransition(
        S.STOPPED, I.STATUS_UPDATE, [O.STORE_INFO, O.CONVERGE], S.CONVERGING)
    table = table.addTransitions(
        S.CONVERGING, {
            I.STATUS_UPDATE: ([O.STORE_INFO], S.CONVERGING),
            I.STOP: ([], S.CONVERGING_STOPPING),
            I.ITERATION_DONE: ([O.CONVERGE], S.CONVERGING),
        })
    table = table.addTransitions(
        S.CONVERGING_STOPPING, {
            I.STATUS_UPDATE: ([O.STORE_INFO], S.CONVERGING),
            I.ITERATION_DONE: ([], S.STOPPED),
        })

    loop = ConvergenceLoop(reactor, deployer)
    fsm = constructFiniteStateMachine(
        inputs=I, outputs=O, states=S, initial=S.STOPPED, table=table,
        richInputs=[_ClientStatusUpdate], inputContext={},
        world=MethodSuffixOutputer(loop))
    loop.fsm = fsm
    return fsm
示例#7
0
def build_convergence_loop_fsm(reactor, deployer):
    """
    Create a convergence loop FSM.

    :param IReactorTime reactor: Used to schedule delays in the loop.

    :param IDeployer deployer: Used to discover local state and calcualte
        necessary changes to match desired configuration.
    """
    I = ConvergenceLoopInputs
    O = ConvergenceLoopOutputs
    S = ConvergenceLoopStates

    table = TransitionTable()
    table = table.addTransition(
        S.STOPPED, I.STATUS_UPDATE, [O.STORE_INFO, O.CONVERGE], S.CONVERGING)
    table = table.addTransitions(
        S.CONVERGING, {
            I.STATUS_UPDATE: ([O.STORE_INFO], S.CONVERGING),
            I.STOP: ([], S.CONVERGING_STOPPING),
            I.ITERATION_DONE: ([O.CONVERGE], S.CONVERGING),
        })
    table = table.addTransitions(
        S.CONVERGING_STOPPING, {
            I.STATUS_UPDATE: ([O.STORE_INFO], S.CONVERGING),
            I.ITERATION_DONE: ([], S.STOPPED),
        })

    loop = ConvergenceLoop(reactor, deployer)
    fsm = constructFiniteStateMachine(
        inputs=I, outputs=O, states=S, initial=S.STOPPED, table=table,
        richInputs=[_ClientStatusUpdate], inputContext={},
        world=MethodSuffixOutputer(loop))
    loop.fsm = fsm
    return fsm
示例#8
0
def setup_driver():
    """
    Instantiate all of the driver components

    includes the following objects:
    trace, dbus, radio, state machine actions, finite state machine.

    Returns list of [fsm, radio, dbus] object references.
    """
    trace = si446xtrace.Trace(1000)
    dbus = Si446xDbus(OBJECT_PATH, trace=trace)
    radio = Si446xRadio(device=0, callback=dbus.async_interrupt, trace=trace)
    print('init radio done')
    actions = Si446xFsmActionHandlers(radio, dbus)
    machine = constructFiniteStateMachine(
        inputs=Events,
        outputs=Actions,
        states=States,
        table=table,
        initial=States.S_SDN,
        richInputs=[],
        inputContext={},
        world=MethodSuffixOutputer(actions),
    )
    fsm = {'actions': actions, 'machine': machine, 'trace': trace}
    dbus.marry(fsm, radio)
    return [fsm, radio, dbus]
示例#9
0
    def test_noRepeatedTerminalLogging(self, logger):
        """
        When the L{IFiniteStateMachine} receives an input in a terminal state
        (and does not generate an output or change to a different state, as is
        required in terminal states) it does not re-log the completion of its
        initialization event.
        """
        # Accept this input in MoreState.blue but remain a terminal state (no
        # output, no state change).
        transitions = TRANSITIONS.addTransition(
            MoreState.blue, Input.apple, [], MoreState.blue)

        fsm = constructFiniteStateMachine(
            Input, Output, MoreState, transitions, MoreState.amber,
            [Gravenstein], {Output.aardvark: IFood},
            MethodSuffixOutputer(AnimalWorld([])), logger)

        fsm.receive(Gravenstein())
        howMany = len(logger.messages)

        fsm.receive(Gravenstein())

        # No additional initialization messages please!
        self.assertEqual([], [
                msg for msg in logger.messages[howMany:]
                if msg[u"action_type"] == u"fsm:initialize"])
示例#10
0
 def test_initializationLogging(self, logger):
     """
     The initialization of the L{IFiniteStateMachine} created by
     L{constructFiniteStateMachine} is logged.
     """
     constructFiniteStateMachine(
         Input, Output, MoreState, TRANSITIONS, MoreState.amber,
         [Gravenstein], {Output.aardvark: IFood},
         MethodSuffixOutputer(AnimalWorld([])), logger)
     self.assertTrue(
         issuperset(logger.messages[0], {
                 u"fsm_identifier": u"<AnimalWorld>",
                 u"fsm_state": u"<MoreState=amber>",
                 u"action_status": u"started",
                 u"action_type": u"fsm:initialize",
                 }))
示例#11
0
def build_cluster_status_fsm(convergence_loop_fsm):
    """
    Create a new cluster status FSM.

    The automatic reconnection logic is handled by the
    ``AgentLoopService``; the world object here just gets notified of
    disconnects, it need schedule the reconnect itself.

    :param convergence_loop_fsm: A convergence loop FSM as output by
    ``build_convergence_loop_fsm``.
    """
    S = ClusterStatusStates
    I = ClusterStatusInputs
    O = ClusterStatusOutputs
    table = TransitionTable()
    # We may be shut down in any state, in which case we disconnect if
    # necessary.
    table = table.addTransitions(
        S.DISCONNECTED,
        {
            # Store the client, then wait for cluster status to be sent
            # over AMP:
            I.CONNECTED_TO_CONTROL_SERVICE: ([O.STORE_CLIENT], S.IGNORANT),
            I.SHUTDOWN: ([], S.SHUTDOWN),
        },
    )
    table = table.addTransitions(
        S.IGNORANT,
        {
            # We never told agent to start, so no need to tell it to stop:
            I.DISCONNECTED_FROM_CONTROL_SERVICE: ([], S.DISCONNECTED),
            # Tell agent latest cluster status, implicitly starting it:
            I.STATUS_UPDATE: ([O.UPDATE_STATUS], S.KNOWLEDGEABLE),
            I.SHUTDOWN: ([O.DISCONNECT], S.SHUTDOWN),
        },
    )
    table = table.addTransitions(
        S.KNOWLEDGEABLE,
        {
            # Tell agent latest cluster status:
            I.STATUS_UPDATE: ([O.UPDATE_STATUS], S.KNOWLEDGEABLE),
            I.DISCONNECTED_FROM_CONTROL_SERVICE: ([O.STOP], S.DISCONNECTED),
            I.SHUTDOWN: ([O.STOP, O.DISCONNECT], S.SHUTDOWN),
        },
    )
    table = table.addTransitions(
        S.SHUTDOWN, {I.DISCONNECTED_FROM_CONTROL_SERVICE: ([], S.SHUTDOWN), I.STATUS_UPDATE: ([], S.SHUTDOWN)}
    )

    return constructFiniteStateMachine(
        inputs=I,
        outputs=O,
        states=S,
        initial=S.DISCONNECTED,
        table=table,
        richInputs=[_ConnectedToControlService, _StatusUpdate],
        inputContext={},
        world=MethodSuffixOutputer(ClusterStatus(convergence_loop_fsm)),
    )
示例#12
0
    def setUp(self):
        self.animals = []
        self.initial = MoreState.amber

        self.world = AnimalWorld(self.animals)
        self.fsm = constructFiniteStateMachine(
            Input, Output, MoreState, TRANSITIONS, self.initial, [Gravenstein],
            {Output.aardvark: IFood}, MethodSuffixOutputer(self.world))
示例#13
0
文件: _loop.py 项目: jongiddy/flocker
def build_cluster_status_fsm(convergence_loop_fsm):
    """
    Create a new cluster status FSM.

    The automatic reconnection logic is handled by the
    ``AgentLoopService``; the world object here just gets notified of
    disconnects, it need schedule the reconnect itself.

    :param convergence_loop_fsm: A convergence loop FSM as output by
    ``build_convergence_loop_fsm``.
    """
    S = ClusterStatusStates
    I = ClusterStatusInputs
    O = ClusterStatusOutputs
    table = TransitionTable()
    # We may be shut down in any state, in which case we disconnect if
    # necessary.
    table = table.addTransitions(
        S.DISCONNECTED,
        {
            # Store the client, then wait for cluster status to be sent
            # over AMP:
            I.CONNECTED_TO_CONTROL_SERVICE: ([O.STORE_CLIENT], S.IGNORANT),
            I.SHUTDOWN: ([], S.SHUTDOWN),
        })
    table = table.addTransitions(
        S.IGNORANT,
        {
            # We never told agent to start, so no need to tell it to stop:
            I.DISCONNECTED_FROM_CONTROL_SERVICE: ([], S.DISCONNECTED),
            # Tell agent latest cluster status, implicitly starting it:
            I.STATUS_UPDATE: ([O.UPDATE_STATUS], S.KNOWLEDGEABLE),
            I.SHUTDOWN: ([O.DISCONNECT], S.SHUTDOWN),
        })
    table = table.addTransitions(
        S.KNOWLEDGEABLE,
        {
            # Tell agent latest cluster status:
            I.STATUS_UPDATE: ([O.UPDATE_STATUS], S.KNOWLEDGEABLE),
            I.DISCONNECTED_FROM_CONTROL_SERVICE: ([O.STOP], S.DISCONNECTED),
            I.SHUTDOWN: ([O.STOP, O.DISCONNECT], S.SHUTDOWN),
        })
    table = table.addTransitions(
        S.SHUTDOWN, {
            I.DISCONNECTED_FROM_CONTROL_SERVICE: ([], S.SHUTDOWN),
            I.STATUS_UPDATE: ([], S.SHUTDOWN),
        })

    return constructFiniteStateMachine(
        inputs=I,
        outputs=O,
        states=S,
        initial=S.DISCONNECTED,
        table=table,
        richInputs=[_ConnectedToControlService, _StatusUpdate],
        inputContext={},
        world=MethodSuffixOutputer(ClusterStatus(convergence_loop_fsm)))
示例#14
0
 def test_initializationLogging(self, logger):
     """
     The initialization of the L{IFiniteStateMachine} created by
     L{constructFiniteStateMachine} is logged.
     """
     constructFiniteStateMachine(Input, Output, MoreState, TRANSITIONS,
                                 MoreState.amber, [Gravenstein],
                                 {Output.aardvark: IFood},
                                 MethodSuffixOutputer(AnimalWorld([])),
                                 logger)
     self.assertTrue(
         issuperset(
             logger.messages[0], {
                 u"fsm_identifier": u"<AnimalWorld>",
                 u"fsm_state": u"<MoreState=amber>",
                 u"action_status": u"started",
                 u"action_type": u"fsm:initialize",
             }))
示例#15
0
    def setUp(self):
        self.animals = []
        self.initial = MoreState.amber

        self.world = AnimalWorld(self.animals)
        self.fsm = constructFiniteStateMachine(
            Input, Output, MoreState, TRANSITIONS, self.initial,
            [Gravenstein], {Output.aardvark: IFood},
            MethodSuffixOutputer(self.world))
示例#16
0
 def test_empty(self):
     """
     L{_FiniteStateMachine._isTerminal} returns C{True} if a state that
     defines handling of no input symbols.
     """
     fsm = constructFiniteStateMachine(
         Input, Output, MoreState, TRANSITIONS, MoreState.amber,
         [Gravenstein], {Output.aardvark: IFood},
         MethodSuffixOutputer(AnimalWorld([])))
     self.assertTrue(fsm._isTerminal(MoreState.blue))
示例#17
0
 def test_logger(self):
     """
     L{constructFiniteStateMachine} returns a FSM that also has a C{logger}
     attribute that is an L{eliot.Logger} instance.
     """
     fsm = constructFiniteStateMachine(
         Input, Output, MoreState, TRANSITIONS, MoreState.amber,
         [Gravenstein], {Output.aardvark: IFood},
         MethodSuffixOutputer(AnimalWorld([])))
     self.assertIsInstance(fsm.logger, Logger)
示例#18
0
 def test_empty(self):
     """
     L{_FiniteStateMachine._isTerminal} returns C{True} if a state that
     defines handling of no input symbols.
     """
     fsm = constructFiniteStateMachine(
         Input, Output, MoreState, TRANSITIONS, MoreState.amber,
         [Gravenstein], {Output.aardvark: IFood},
         MethodSuffixOutputer(AnimalWorld([])))
     self.assertTrue(fsm._isTerminal(MoreState.blue))
示例#19
0
 def test_logger(self):
     """
     L{constructFiniteStateMachine} returns a FSM that also has a C{logger}
     attribute that is an L{eliot.Logger} instance.
     """
     fsm = constructFiniteStateMachine(
         Input, Output, MoreState, TRANSITIONS, MoreState.amber,
         [Gravenstein], {Output.aardvark: IFood},
         MethodSuffixOutputer(AnimalWorld([])))
     self.assertIsInstance(fsm.logger, Logger)
示例#20
0
 def test_loggerOverride(self, logger):
     """
     If an argument is given for the C{logger} argument to
     L{constructFiniteStateMachine} then that object is used as the logger
     of the resulting finite state machine.
     """
     fsm = constructFiniteStateMachine(
         Input, Output, MoreState, TRANSITIONS, MoreState.amber,
         [Gravenstein], {Output.aardvark: IFood},
         MethodSuffixOutputer(AnimalWorld([])), logger)
     self.assertIs(logger, fsm.logger)
示例#21
0
 def test_loggerOverride(self, logger):
     """
     If an argument is given for the C{logger} argument to
     L{constructFiniteStateMachine} then that object is used as the logger
     of the resulting finite state machine.
     """
     fsm = constructFiniteStateMachine(
         Input, Output, MoreState, TRANSITIONS, MoreState.amber,
         [Gravenstein], {Output.aardvark: IFood},
         MethodSuffixOutputer(AnimalWorld([])), logger)
     self.assertIs(logger, fsm.logger)
示例#22
0
 def test_stateChange(self):
     """
     L{_FiniteStateMachine._isTerminal} returns C{False} if a state defines
     handling of inputs that cause a state change.
     """
     transitions = TRANSITIONS.addTransition(
         MoreState.blue, Input.apple, [], MoreState.amber)
     fsm = constructFiniteStateMachine(
         Input, Output, MoreState, transitions, MoreState.amber,
         [Gravenstein], {Output.aardvark: IFood},
         MethodSuffixOutputer(AnimalWorld([])))
     self.assertFalse(fsm._isTerminal(MoreState.blue))
示例#23
0
 def test_nextStateGivenSymbolInput(self, logger):
     """
     L{IFiniteStateMachine.receive} changes L{IFiniteStateMachine.state} to
     the next state defined for the given symbolic input in the machine's
     current state.
     """
     self.fsm = constructFiniteStateMachine(
         Input, Output, MoreState, TRANSITIONS, MoreState.amber,
         [Gravenstein], {}, MethodSuffixOutputer(AnimalWorld([])), logger)
     self.fsm.logger = logger
     self.fsm.receive(Input.apple)
     self.assertEqual(MoreState.blue, self.fsm.state)
示例#24
0
 def test_nextStateGivenSymbolInput(self, logger):
     """
     L{IFiniteStateMachine.receive} changes L{IFiniteStateMachine.state} to
     the next state defined for the given symbolic input in the machine's
     current state.
     """
     self.fsm = constructFiniteStateMachine(
         Input, Output, MoreState, TRANSITIONS, MoreState.amber,
         [Gravenstein], {}, MethodSuffixOutputer(AnimalWorld([])), logger)
     self.fsm.logger = logger
     self.fsm.receive(Input.apple)
     self.assertEqual(MoreState.blue, self.fsm.state)
示例#25
0
 def test_stateChange(self):
     """
     L{_FiniteStateMachine._isTerminal} returns C{False} if a state defines
     handling of inputs that cause a state change.
     """
     transitions = TRANSITIONS.addTransition(MoreState.blue, Input.apple,
                                             [], MoreState.amber)
     fsm = constructFiniteStateMachine(
         Input, Output, MoreState, transitions, MoreState.amber,
         [Gravenstein], {Output.aardvark: IFood},
         MethodSuffixOutputer(AnimalWorld([])))
     self.assertFalse(fsm._isTerminal(MoreState.blue))
示例#26
0
 def test_selfTransition(self):
     """
     L{_FiniteStateMachine._isTerminal} returns C{True} if a state defines
     handling of inputs that generate no outputs and do not change the state
     of the machine.
     """
     transitions = TRANSITIONS.addTransition(MoreState.blue, Input.apple,
                                             [], MoreState.blue)
     fsm = constructFiniteStateMachine(
         Input, Output, MoreState, transitions, MoreState.amber,
         [Gravenstein], {Output.aardvark: IFood},
         MethodSuffixOutputer(AnimalWorld([])))
     self.assertTrue(fsm._isTerminal(MoreState.blue))
示例#27
0
 def test_selfTransition(self):
     """
     L{_FiniteStateMachine._isTerminal} returns C{True} if a state defines
     handling of inputs that generate no outputs and do not change the state
     of the machine.
     """
     transitions = TRANSITIONS.addTransition(
         MoreState.blue, Input.apple, [], MoreState.blue)
     fsm = constructFiniteStateMachine(
         Input, Output, MoreState, transitions, MoreState.amber,
         [Gravenstein], {Output.aardvark: IFood},
         MethodSuffixOutputer(AnimalWorld([])))
     self.assertTrue(fsm._isTerminal(MoreState.blue))
示例#28
0
    def test_outputFromSymbolInput(self, logger):
        """
        L{IFiniteStateMachine.receive} finds the transition for the symbol
        input in the machine's current state and returns the corresponding
        output.
        """
        self.fsm = constructFiniteStateMachine(
            Input, Output, MoreState, TRANSITIONS, self.initial, [Gravenstein],
            {}, MethodSuffixOutputer(self.world))

        self.fsm.logger = logger
        self.world.logger = logger
        self.assertEqual([Output.aardvark], self.fsm.receive(Input.apple))
示例#29
0
 def test_FiniteStateInterpreterRepr(self):
     """
     The result of L{_FiniteStateInterpreter.__repr__} is a string that
     includes the L{IOutputExecutor} provider that
     L{_FiniteStateInterpreter} can drive.
     """
     fsm = constructFiniteStateMachine(
         Input, Output, MoreState, TRANSITIONS, self.initial,
         [Gravenstein], {Output.aardvark: IFood},
         MethodSuffixOutputer(self.world), None)
     self.assertEqual(
         repr(fsm),
         "<FSM / %s>" % (MethodSuffixOutputer(self.world),))
示例#30
0
    def test_outputFromSymbolInput(self, logger):
        """
        L{IFiniteStateMachine.receive} finds the transition for the symbol
        input in the machine's current state and returns the corresponding
        output.
        """
        self.fsm = constructFiniteStateMachine(
            Input, Output, MoreState, TRANSITIONS, self.initial,
            [Gravenstein], {}, MethodSuffixOutputer(self.world))

        self.fsm.logger = logger
        self.world.logger = logger
        self.assertEqual([Output.aardvark], self.fsm.receive(Input.apple))
示例#31
0
 def test_FiniteStateInterpreterRepr(self):
     """
     The result of L{_FiniteStateInterpreter.__repr__} is a string that
     includes the L{IOutputExecutor} provider that
     L{_FiniteStateInterpreter} can drive.
     """
     fsm = constructFiniteStateMachine(Input, Output, MoreState,
                                       TRANSITIONS, self.initial,
                                       [Gravenstein],
                                       {Output.aardvark: IFood},
                                       MethodSuffixOutputer(self.world),
                                       None)
     self.assertEqual(repr(fsm),
                      "<FSM / %s>" % (MethodSuffixOutputer(self.world), ))
示例#32
0
def build_convergence_loop_fsm(reactor, deployer):
    """
    Create a convergence loop FSM.

    Once cluster config+cluster state updates from control service are
    received the basic loop is:

    1. Discover local state.
    2. Calculate ``IStateChanges`` based on local state and cluster
       configuration and cluster state we received from control service.
    3. Execute the change.
    4. Sleep.

    However, if an update is received during sleep then we calculate based
    on that updated config+state whether a ``IStateChange`` needs to
    happen. If it does that means this change will have impact on what we
    do, so we interrupt the sleep. If calculation suggests a no-op then we
    keep sleeping. Notably we do **not** do a discovery of local state
    when an update is received while sleeping, since that is an expensive
    operation that can involve talking to external resources. Moreover an
    external update only implies external state/config changed, so we're
    not interested in the latest local state in trying to decide if this
    update requires us to do something; a recently cached version should
    suffice.

    :param IReactorTime reactor: Used to schedule delays in the loop.

    :param IDeployer deployer: Used to discover local state and calcualte
        necessary changes to match desired configuration.
    """
    loop = ConvergenceLoop(reactor, deployer)
    fsm = constructFiniteStateMachine(
        inputs=ConvergenceLoopInputs,
        outputs=ConvergenceLoopOutputs,
        states=ConvergenceLoopStates,
        initial=ConvergenceLoopStates.STOPPED,
        table=_CONVERGENCE_LOOP_FSM_TABLE,
        richInputs=[_ClientStatusUpdate, _Sleep],
        inputContext={},
        world=MethodSuffixOutputer(loop))
    loop.fsm = fsm
    return fsm
示例#33
0
def build_convergence_loop_fsm(reactor, deployer):
    """
    Create a convergence loop FSM.

    Once cluster config+cluster state updates from control service are
    received the basic loop is:

    1. Discover local state.
    2. Calculate ``IStateChanges`` based on local state and cluster
       configuration and cluster state we received from control service.
    3. Execute the change.
    4. Sleep.

    However, if an update is received during sleep then we calculate based
    on that updated config+state whether a ``IStateChange`` needs to
    happen. If it does that means this change will have impact on what we
    do, so we interrupt the sleep. If calculation suggests a no-op then we
    keep sleeping. Notably we do **not** do a discovery of local state
    when an update is received while sleeping, since that is an expensive
    operation that can involve talking to external resources. Moreover an
    external update only implies external state/config changed, so we're
    not interested in the latest local state in trying to decide if this
    update requires us to do something; a recently cached version should
    suffice.

    :param IReactorTime reactor: Used to schedule delays in the loop.

    :param IDeployer deployer: Used to discover local state and calcualte
        necessary changes to match desired configuration.
    """
    loop = ConvergenceLoop(reactor, deployer)
    fsm = constructFiniteStateMachine(
        inputs=ConvergenceLoopInputs,
        outputs=ConvergenceLoopOutputs,
        states=ConvergenceLoopStates,
        initial=ConvergenceLoopStates.STOPPED,
        table=_CONVERGENCE_LOOP_FSM_TABLE,
        richInputs=[_ClientStatusUpdate, _Sleep],
        inputContext={},
        world=MethodSuffixOutputer(loop))
    loop.fsm = fsm
    return fsm
示例#34
0
    def test_terminalLogging(self, logger):
        """
        When the L{IFiniteStateMachine} enters a terminal state the
        initialization action is finished successfully.
        """
        fsm = constructFiniteStateMachine(
            Input, Output, MoreState, TRANSITIONS, MoreState.amber,
            [Gravenstein], {Output.aardvark: IFood},
            MethodSuffixOutputer(AnimalWorld([])), logger)

        fsm.receive(Gravenstein())

        (initialize, ) = LoggedAction.of_type(logger.messages,
                                              LOG_FSM_INITIALIZE)

        assertContainsFields(
            self, initialize.end_message, {
                u"fsm_terminal_state": u"<MoreState=blue>",
                u"action_status": u"succeeded",
            })
示例#35
0
文件: _loop.py 项目: AlexRRR/flocker
def build_cluster_status_fsm(convergence_loop_fsm):
    """
    Create a new cluster status FSM.

    The automatic reconnection logic is handled by the
    ``AgentLoopService``; the world object here just gets notified of
    disconnects, it need schedule the reconnect itself.

    :param convergence_loop_fsm: A convergence loop FSM as output by
    ``build_convergence_loop_fsm``.
    """
    return constructFiniteStateMachine(
        inputs=ClusterStatusInputs,
        outputs=ClusterStatusOutputs,
        states=ClusterStatusStates,
        initial=ClusterStatusStates.DISCONNECTED,
        table=_CLUSTER_STATUS_FSM_TABLE,
        richInputs=[_ConnectedToControlService, _StatusUpdate],
        inputContext={},
        world=MethodSuffixOutputer(ClusterStatus(convergence_loop_fsm)))
示例#36
0
def build_cluster_status_fsm(convergence_loop_fsm):
    """
    Create a new cluster status FSM.

    The automatic reconnection logic is handled by the
    ``AgentLoopService``; the world object here just gets notified of
    disconnects, it need schedule the reconnect itself.

    :param convergence_loop_fsm: A convergence loop FSM as output by
    ``build_convergence_loop_fsm``.
    """
    return constructFiniteStateMachine(
        inputs=ClusterStatusInputs,
        outputs=ClusterStatusOutputs,
        states=ClusterStatusStates,
        initial=ClusterStatusStates.DISCONNECTED,
        table=_CLUSTER_STATUS_FSM_TABLE,
        richInputs=[_ConnectedToControlService, _StatusUpdate],
        inputContext={},
        world=MethodSuffixOutputer(ClusterStatus(convergence_loop_fsm)))
示例#37
0
    def test_terminalLogging(self, logger):
        """
        When the L{IFiniteStateMachine} enters a terminal state the
        initialization action is finished successfully.
        """
        fsm = constructFiniteStateMachine(
            Input, Output, MoreState, TRANSITIONS, MoreState.amber,
            [Gravenstein], {Output.aardvark: IFood},
            MethodSuffixOutputer(AnimalWorld([])), logger)

        fsm.receive(Gravenstein())

        self.assertTrue(
            issuperset(logger.messages[3], {
                    u"fsm_terminal_state": u"<MoreState=blue>",
                    # Prove it associates with the initialization action.
                    u"action_type": u"fsm:initialize",
                    u"action_status": u"succeeded",
                    u"task_uuid": logger.messages[0][u"task_uuid"],
                    u"task_level": u"/",
                    }))
示例#38
0
    def test_terminalLogging(self, logger):
        """
        When the L{IFiniteStateMachine} enters a terminal state the
        initialization action is finished successfully.
        """
        fsm = constructFiniteStateMachine(
            Input, Output, MoreState, TRANSITIONS, MoreState.amber,
            [Gravenstein], {Output.aardvark: IFood},
            MethodSuffixOutputer(AnimalWorld([])), logger)

        fsm.receive(Gravenstein())

        (initialize,) = LoggedAction.of_type(
            logger.messages, LOG_FSM_INITIALIZE
        )

        assertContainsFields(
            self, initialize.end_message, {
                u"fsm_terminal_state": u"<MoreState=blue>",
                u"action_status": u"succeeded",
            }
        )
示例#39
0
    def test_terminalLogging(self, logger):
        """
        When the L{IFiniteStateMachine} enters a terminal state the
        initialization action is finished successfully.
        """
        fsm = constructFiniteStateMachine(
            Input, Output, MoreState, TRANSITIONS, MoreState.amber,
            [Gravenstein], {Output.aardvark: IFood},
            MethodSuffixOutputer(AnimalWorld([])), logger)

        fsm.receive(Gravenstein())

        self.assertTrue(
            issuperset(
                logger.messages[3],
                {
                    u"fsm_terminal_state": u"<MoreState=blue>",
                    # Prove it associates with the initialization action.
                    u"action_type": u"fsm:initialize",
                    u"action_status": u"succeeded",
                    u"task_uuid": logger.messages[0][u"task_uuid"],
                    u"task_level": u"/",
                }))
示例#40
0
        print("Engaging the lock.")

    def output_DISENGAGE_LOCK(self, disengage):
        print("Disengaging the lock.")

outputer = MethodSuffixOutputer(Outputer())
# end outputer

# begin construct
from machinist import constructFiniteStateMachine

turnstile = constructFiniteStateMachine(
    inputs=Input,
    outputs=Output,
    states=State,
    table=table,
    initial=State.LOCKED,
    richInputs=[],
    inputContext={},
    world=outputer,
)
# end construct

# begin inputs
def cycle():
    turnstile.receive(Input.FARE_PAID)
    turnstile.receive(Input.ARM_UNLOCKED)
    turnstile.receive(Input.ARM_TURNED)
    turnstile.receive(Input.ARM_LOCKED)
# end inputs

if __name__ == '__main__':
示例#41
0
    def output_DISENGAGE_LOCK(self, disengage):
        print("Disengaging the lock.")


outputer = MethodSuffixOutputer(Outputer())
# end outputer

# begin construct
from machinist import constructFiniteStateMachine

turnstile = constructFiniteStateMachine(
    inputs=Input,
    outputs=Output,
    states=State,
    table=table,
    initial=State.LOCKED,
    richInputs=[],
    inputContext={},
    world=outputer,
)

# end construct


# begin inputs
def cycle():
    turnstile.receive(Input.FARE_PAID)
    turnstile.receive(Input.ARM_UNLOCKED)
    turnstile.receive(Input.ARM_TURNED)
    turnstile.receive(Input.ARM_LOCKED)