Martin Sivák has uploaded a new change for review. Change subject: Document the Agent FSM using docstrings and autogenerate the graphviz sources ......................................................................
Document the Agent FSM using docstrings and autogenerate the graphviz sources This adds two special lines to state class docstrings: :transition[ destination]: description - describes transition from current class to destination - it is treated as staying in the current state when destination is not provided :transitions_from StateClass: - used to support inheritance, copies all transitions from StateClass to the current class This patch also adds a script that reads the state_machine.py and states.py modules and generates the fill graphviz source for the state machine. make fsm then generates the new source and png file with the state machine. Change-Id: Ie6de8b20a8908aa0906404283829775b5487a850 Signed-off-by: Martin Sivak <[email protected]> --- M Makefile.am M doc/agent-fsm.gv M ovirt_hosted_engine_ha/agent/state_machine.py M ovirt_hosted_engine_ha/agent/states.py 4 files changed, 182 insertions(+), 31 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-hosted-engine-ha refs/changes/15/24815/1 diff --git a/Makefile.am b/Makefile.am index 697fb61..72c2aed 100644 --- a/Makefile.am +++ b/Makefile.am @@ -89,3 +89,8 @@ sed '/^$$/d' "$(srcdir)/m4/.gitignore" | while read f; do \ rm -f $(srcdir)/m4/$$f; \ done + +fsm: + PYTHONPATH=. python build/build-aux/gen_gv.py > doc/agent-fsm.gv + dot doc/agent-fsm.gv -Tpng -o doc/agent-fsm.png + diff --git a/doc/agent-fsm.gv b/doc/agent-fsm.gv index 8100c0d..0182885 100644 --- a/doc/agent-fsm.gv +++ b/doc/agent-fsm.gv @@ -1,3 +1,34 @@ +// <module 'ovirt_hosted_engine_ha.agent.state_machine' from '/home/msivak/Work/ovirt-hosted-engine-ha/ovirt_hosted_engine_ha/agent/state_machine.pyc'> +// <class 'ovirt_hosted_engine_ha.lib.fsm.machine.BaseFSM'> +// skip +// <class 'ovirt_hosted_engine_ha.lib.fsm.machine.BaseState'> +// <class 'ovirt_hosted_engine_ha.agent.state_machine.EngineStateMachine'> +// skip +// <class 'ovirt_hosted_engine_ha.agent.state_data.HostedEngineData'> +// skip +// <class 'ovirt_hosted_engine_ha.agent.states.ReinitializeFSM'> +// <class 'ovirt_hosted_engine_ha.agent.state_machine.StartState'> +// <class 'ovirt_hosted_engine_ha.agent.state_data.StatsData'> +// skip +// <module 'ovirt_hosted_engine_ha.agent.states' from '/home/msivak/Work/ovirt-hosted-engine-ha/ovirt_hosted_engine_ha/agent/states.pyc'> +// <class 'ovirt_hosted_engine_ha.lib.fsm.machine.BaseFSM'> +// skip +// <class 'ovirt_hosted_engine_ha.lib.fsm.machine.BaseState'> +// <class 'ovirt_hosted_engine_ha.agent.states.EngineDown'> +// <class 'ovirt_hosted_engine_ha.agent.states.EngineForceStop'> +// <class 'ovirt_hosted_engine_ha.agent.states.EngineMigratingAway'> +// <class 'ovirt_hosted_engine_ha.agent.states.EngineStart'> +// <class 'ovirt_hosted_engine_ha.agent.states.EngineState'> +// <class 'ovirt_hosted_engine_ha.agent.states.EngineStop'> +// <class 'ovirt_hosted_engine_ha.agent.states.EngineUnexpectedlyDown'> +// <class 'ovirt_hosted_engine_ha.agent.states.EngineUp'> +// <class 'ovirt_hosted_engine_ha.agent.states.EngineUpBadHealth'> +// copy rule EngineUp -> EngineUpBadHealth +// <class 'ovirt_hosted_engine_ha.agent.states.GlobalMaintenance'> +// <class 'ovirt_hosted_engine_ha.agent.states.LocalMaintenance'> +// <class 'ovirt_hosted_engine_ha.agent.states.LocalMaintenanceMigrateVm'> +// <class 'ovirt_hosted_engine_ha.agent.states.ReinitializeFSM'> +// <class 'ovirt_hosted_engine_ha.agent.states.UnknownLocalVmState'> /** * This file contains the source for a graphviz FSM diagram of the HA agent * state machine. To create an image, fsm.png in this case, run the following: @@ -10,35 +41,74 @@ */ digraph finite_state_machine { - ranksep = 0.3; - node [shape = doublecircle]; ENTRY; - node [shape = circle]; OFF START ON STOP MIGRATE; - - ENTRY -> OFF [ label = "VM down locally" ]; - ENTRY -> ON [ label = "VM up \nlocally " ]; - - OFF -> OFF [ label = "VM down locally" ]; - OFF -> ON [ label = "VM unexpectedly \nrunning locally " ]; - OFF -> START [ label = "VM down \nglobally, host has \nhighest score " ]; - OFF -> MAINTENANCE [ label = "Maintenance\nmode enabled" ]; - - START -> OFF [ label = "VM startup \nfailed " ]; - START -> ON [ label = "VM powered on" ]; - - ON -> ON [ label = "VM up locally" ]; - ON -> OFF [ label = "VM died \nunexpectedly " ]; - ON -> MIGRATE [ label = "VM up locally, \nother host has \nmuch better score " ]; - ON -> STOP [ label = "VM timed out \nwith bad health \nstatus " ]; - ON -> MAINTENANCE [ label = "Maintenance\nmode enabled" ]; - - STOP -> STOP [ label = "VM shutdown\nin progress" ]; - STOP -> OFF [ label = "VM shutdown\nsuccessful" ]; - STOP -> ENTRY [ label = "VM failed to stop,\nunknown state" ]; - - MIGRATE -> MIGRATE [ label = "VM migration\nin progress" ]; - MIGRATE -> OFF [ label = "VM migration\nsuccessful" ]; - MIGRATE -> STOP [ label = "VM migration\nfailed" ]; - - MAINTENANCE -> MAINTENANCE [ label = "Maintenance\nmode enabled" ]; - MAINTENANCE -> ENTRY [ label = "Maintenance\nmode disabled" ]; +ranksep = 0.5; +node [shape = doublecircle]; StartState; +node [shape = circle]; EngineMigratingAway LocalMaintenanceMigrateVm EngineStop EngineStart ReinitializeFSM GlobalMaintenance UnknownLocalVmState EngineUp EngineDown LocalMaintenance EngineUpBadHealth EngineUnexpectedlyDown EngineForceStop ; +EngineMigratingAway -> EngineMigratingAway [ label = "" ]; +EngineMigratingAway -> EngineDown [ label = "" ]; +EngineMigratingAway -> GlobalMaintenance [ label = "" ]; +EngineMigratingAway -> UnknownLocalVmState [ label = "" ]; +EngineMigratingAway -> ReinitializeFSM [ label = "" ]; +LocalMaintenanceMigrateVm -> EngineStop [ label = "" ]; +LocalMaintenanceMigrateVm -> GlobalMaintenance [ label = "" ]; +LocalMaintenanceMigrateVm -> UnknownLocalVmState [ label = "" ]; +LocalMaintenanceMigrateVm -> EngineMigratingAway [ label = "" ]; +EngineStop -> EngineStop [ label = "" ]; +EngineStop -> ReinitializeFSM [ label = "" ]; +EngineStop -> GlobalMaintenance [ label = "" ]; +EngineStop -> UnknownLocalVmState [ label = "" ]; +EngineStop -> LocalMaintenance [ label = "" ]; +EngineStop -> EngineForceStop [ label = "" ]; +EngineStart -> EngineDown [ label = "" ]; +EngineStart -> GlobalMaintenance [ label = "" ]; +EngineStart -> UnknownLocalVmState [ label = "" ]; +EngineStart -> EngineUp [ label = "" ]; +EngineStart -> LocalMaintenance [ label = "" ]; +ReinitializeFSM -> EngineDown [ label = "" ]; +ReinitializeFSM -> GlobalMaintenance [ label = "" ]; +ReinitializeFSM -> UnknownLocalVmState [ label = "" ]; +ReinitializeFSM -> EngineUp [ label = "" ]; +ReinitializeFSM -> LocalMaintenance [ label = "" ]; +GlobalMaintenance -> ReinitializeFSM [ label = "" ]; +GlobalMaintenance -> GlobalMaintenance [ label = "" ]; +GlobalMaintenance -> LocalMaintenance [ label = "" ]; +UnknownLocalVmState -> GlobalMaintenance [ label = "" ]; +UnknownLocalVmState -> UnknownLocalVmState [ label = "" ]; +UnknownLocalVmState -> LocalMaintenance [ label = "" ]; +EngineUp -> EngineMigratingAway [ label = "" ]; +EngineUp -> GlobalMaintenance [ label = "" ]; +EngineUp -> EngineUnexpectedlyDown [ label = "" ]; +EngineUp -> LocalMaintenanceMigrateVm [ label = "" ]; +EngineUp -> UnknownLocalVmState [ label = "" ]; +EngineUp -> EngineUp [ label = "" ]; +EngineUp -> EngineUpBadHealth [ label = "" ]; +EngineUp -> EngineStop [ label = "" ]; +StartState -> ReinitializeFSM [ label = "" ]; +EngineDown -> EngineStart [ label = "" ]; +EngineDown -> GlobalMaintenance [ label = "" ]; +EngineDown -> UnknownLocalVmState [ label = "" ]; +EngineDown -> EngineUp [ label = "" ]; +EngineDown -> EngineDown [ label = "" ]; +EngineDown -> LocalMaintenance [ label = "" ]; +LocalMaintenance -> ReinitializeFSM [ label = "" ]; +LocalMaintenance -> LocalMaintenance [ label = "" ]; +EngineUpBadHealth -> EngineMigratingAway [ label = "" ]; +EngineUpBadHealth -> LocalMaintenanceMigrateVm [ label = "" ]; +EngineUpBadHealth -> EngineStop [ label = "" ]; +EngineUpBadHealth -> GlobalMaintenance [ label = "" ]; +EngineUpBadHealth -> UnknownLocalVmState [ label = "" ]; +EngineUpBadHealth -> EngineUp [ label = "" ]; +EngineUpBadHealth -> EngineUpBadHealth [ label = "" ]; +EngineUpBadHealth -> EngineUnexpectedlyDown [ label = "" ]; +EngineUnexpectedlyDown -> EngineUnexpectedlyDown [ label = "" ]; +EngineUnexpectedlyDown -> GlobalMaintenance [ label = "" ]; +EngineUnexpectedlyDown -> UnknownLocalVmState [ label = "" ]; +EngineUnexpectedlyDown -> EngineUp [ label = "" ]; +EngineUnexpectedlyDown -> EngineDown [ label = "" ]; +EngineUnexpectedlyDown -> LocalMaintenance [ label = "" ]; +EngineForceStop -> EngineDown [ label = "" ]; +EngineForceStop -> ReinitializeFSM [ label = "" ]; +EngineForceStop -> GlobalMaintenance [ label = "" ]; +EngineForceStop -> UnknownLocalVmState [ label = "" ]; +EngineForceStop -> LocalMaintenance [ label = "" ]; } diff --git a/ovirt_hosted_engine_ha/agent/state_machine.py b/ovirt_hosted_engine_ha/agent/state_machine.py index debb7fb..f3e3567 100644 --- a/ovirt_hosted_engine_ha/agent/state_machine.py +++ b/ovirt_hosted_engine_ha/agent/state_machine.py @@ -10,6 +10,9 @@ class StartState(BaseState): + """ + :transition ReinitializeFSM: + """ def consume(self, fsm, new_data, logger): return ReinitializeFSM(new_data) diff --git a/ovirt_hosted_engine_ha/agent/states.py b/ovirt_hosted_engine_ha/agent/states.py index 08723a6..49779db 100644 --- a/ovirt_hosted_engine_ha/agent/states.py +++ b/ovirt_hosted_engine_ha/agent/states.py @@ -197,6 +197,9 @@ This state is entered any time the host gets to local maintenance state. It monitors the environment and once the maintenance is completed, the FSM is reinitialized. + + :transition: + :transition ReinitializeFSM: """ def score(self, logger): logger.info('Score is 0 due to local maintenance mode', @@ -223,6 +226,10 @@ """ This is an idler state that does not do anything while the global maintenance mode is enabled. + + :transition: + :transition LocalMaintenance: + :transition ReinitializeFSM: """ @check_global_maintenance(None) @check_local_maintenance(LocalMaintenance) @@ -239,6 +246,10 @@ """ Error state that is used when we are not able to determine the status of the local engine VM. + + :transition: + :transition GlobalMaintenance: + :transition LocalMaintenance: """ @check_global_maintenance(GlobalMaintenance) @check_local_vm_unknown(None) @@ -256,6 +267,12 @@ """ Determine the best state to start with based on the current information about the environment. + + :transition GlobalMaintenance: + :transition LocalMaintenance: + :transition UnknownLocalVmState: + :transition EngineUp: + :transition EngineDown: """ def score(self, logger): return 0 @@ -288,6 +305,11 @@ when the engine runs locally.. It tries to migrate it to the best remote host and then moves to local maintenance state. + + :transition GlobalMaintenance: + :transition UnknownLocalVmState: + :transition EngineStop: + :transition EngineMigratingAway: """ @check_global_maintenance(GlobalMaintenance) @check_local_vm_unknown(UnknownLocalVmState) @@ -315,6 +337,15 @@ """ When the engine is up and running locally, this state is used to monitor it. + + :transition GlobalMaintenance: + :transition UnknownLocalVmState: + :transition LocalMaintenanceMigrateVm: + :transition EngineUnexpectedlyDown: + :transition EngineMigratingAway: + :transition EngineStop: + :transition EngineUpBadHealth: + :transition: """ def _penalize_memory(self, vm_mem, lm, logger, score, score_cfg): # if the vm is up, do not check memory usage @@ -363,6 +394,13 @@ This state is used when the engine is running elsewhere and the local host has nothing to do except wait for the engine host to become bad. + + :transition GlobalMaintenance: + :transition UnknownLocalVmState: + :transition LocalMaintenance: + :transition EngineUp: + :transition: + :transition EngineStart: """ @check_global_maintenance(GlobalMaintenance) @check_local_vm_unknown(UnknownLocalVmState) @@ -420,6 +458,12 @@ """ This state is used to force-stop the local VM. Used only if the regular stop procedure did not finish on time. + + :transition GlobalMaintenance: + :transition LocalMaintenance: + :transition UnknownLocalVmState: + :transition EngineDown: + :transition ReinitializeFSM: """ @check_global_maintenance(GlobalMaintenance) @check_local_maintenance(LocalMaintenance) @@ -441,6 +485,13 @@ This state is responsible for stopping the local VM in preparation of starting it elsewhere. If the stop action takes too long, it falls back to EngineForceStop. + + :transition GlobalMaintenance: + :transition LocalMaintenance: + :transition UnknownLocalVmState: + :transition EngineForceStop: + :transition EngineStop: + :transition ReinitializeFSM: """ @check_global_maintenance(GlobalMaintenance) @check_local_maintenance(LocalMaintenance) @@ -485,6 +536,9 @@ the VM is UP and the engine does not report healthy state. If the engine stays in this state too long, the VM is stopped and started somewhere else. + + :transition EngineStop: + :transitions_from EngineUp: """ @check_timeout(EngineStop, constants.ENGINE_BAD_HEALTH_TIMEOUT_SECS) def consume(self, fsm, new_data, logger): @@ -520,6 +574,13 @@ score to effectively move it to another host. This also serves as a shortcut for the user to start host maintenance mode, though it still should be set manually lest the score recover after a timeout. + + :transition GlobalMaintenance: + :transition UnknownLocalVmState: + :transition LocalMaintenance: + :transition EngineDown: + :transition EngineUp: + :transition: """ @check_global_maintenance(GlobalMaintenance) @@ -577,6 +638,12 @@ class EngineStart(EngineState): """ This state is responsible for starting the VM on the local machine. + + :transition GlobalMaintenance: + :transition UnknownLocalVmState: + :transition LocalMaintenance: + :transition EngineUp: + :transition EngineDown: """ @check_global_maintenance(GlobalMaintenance) @check_local_vm_unknown(UnknownLocalVmState) @@ -605,6 +672,12 @@ """ This state is responsible for monitoring a migration of the engine VM to some other machine. + + :transition GlobalMaintenance: + :transition UnknownLocalVmState: + :transition: + :transition EngineDown: + :transition ReinitializeFSM: """ def collect(self, fsm, new_data, logger): """ -- To view, visit http://gerrit.ovirt.org/24815 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ie6de8b20a8908aa0906404283829775b5487a850 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-hosted-engine-ha Gerrit-Branch: master Gerrit-Owner: Martin Sivák <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
