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

Reply via email to