Commit d78de86d authored by Drew Devereux's avatar Drew Devereux
Browse files

Merge branch 'MCCS-163' into 'master'

[MCCS-163] Update DeviceStateMachine with hardware power support

See merge request ska-telescope/lmc-base-classes!28
parents 7e07894c 13666a0c
# GitLab CI in conjunction with GitLab Runner can use Docker Engine to test and build any application.
# Docker, when used with GitLab CI, runs each job in a separate and isolated container using the predefined image that is set up in .gitlab-ci.yml.
# In this case we use the latest python docker image to build and test this project.
image: nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.2
image: nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.2.1
include:
- project: 'ska-telescope/templates-repository'
......@@ -29,7 +29,7 @@ stages:
clean shell runner:
stage: .pre
tags:
- docker-executor
- k8srunner
script:
# Gitlab CI badges creation
- rm -rf build/*
......@@ -37,7 +37,7 @@ clean shell runner:
build wheel for publication: # Executed on a tag
stage: build
tags:
- docker-executor
- k8srunner
script:
- python3 setup.py egg_info -b+$CI_COMMIT_SHORT_SHA sdist bdist_wheel
rules:
......@@ -49,7 +49,7 @@ build wheel for publication: # Executed on a tag
build wheel for development: # Executed on non-tagged commit
stage: build
tags:
- docker-executor
- k8srunner
script:
- python3 setup.py egg_info -b+dev.$CI_COMMIT_SHORT_SHA sdist bdist_wheel
rules:
......@@ -61,7 +61,7 @@ build wheel for development: # Executed on non-tagged commit
unit tests:
stage: test
tags:
- docker-executor
- k8srunner
script:
- echo $(ls -d ./dist/*.whl | grep $CI_COMMIT_SHORT_SHA)
- python3 -m pip install -U $(ls -d ./dist/*.whl | grep $CI_COMMIT_SHORT_SHA)
......@@ -74,7 +74,7 @@ unit tests:
linting:
stage: linting
tags:
- docker-executor
- k8srunner
script:
- echo $(ls -d ./dist/*.whl | grep $CI_COMMIT_SHORT_SHA)
- python3 -m pip install -U $(ls -d ./dist/*.whl | grep $CI_COMMIT_SHORT_SHA)
......@@ -86,7 +86,7 @@ linting:
publish to nexus:
stage: publish
tags:
- docker-executor
- k8srunner
variables:
TWINE_USERNAME: $TWINE_USERNAME
TWINE_PASSWORD: $TWINE_PASSWORD
......@@ -105,7 +105,7 @@ release docker image:
before_script:
- docker login -u $DOCKER_REGISTRY_USERNAME -p $DOCKER_REGISTRY_PASSWORD $DOCKER_REGISTRY_HOST
tags:
- docker-executor
- k8srunner
script:
- make build
- make push
......@@ -118,7 +118,7 @@ release docker image:
pages:
stage: pages
tags:
- docker-executor
- k8srunner
script:
- cp -R build public
- mv public/htmlcov/* public
......
release=0.6.6
tag=lmcbaseclasses-0.6.6
release=0.7.0
tag=lmcbaseclasses-0.7.0
# Use SKA python image as base image
FROM nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.2 AS buildenv
FROM nexus.engageska-portugal.pt/ska-docker/ska-python-runtime:9.3.2 AS runtime
FROM nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.2.1 AS buildenv
FROM nexus.engageska-portugal.pt/ska-docker/ska-python-runtime:9.3.2.1 AS runtime
# create ipython profile to so that itango doesn't fail if ipython hasn't run yet
RUN ipython profile create
# TODO: move this dependency to ska-docker/docker/tango/ska-python-buildenv/requirements.txt
RUN python3 -m pip install --user pytest-forked
# Note: working dir is `/app` which will have a copy of our repo
# The pip install will be a "user installation" so update path to access console scripts
ENV PATH=/home/tango/.local/bin:$PATH
......
......@@ -17,7 +17,7 @@ SHELL = /bin/bash
#
DOCKER_REGISTRY_USER:=tango-example
PROJECT = lmcbaseclasses
IMAGE_FOR_DIAGRAMS = nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.2.1
#
# include makefile to pick up the standard Make targets, e.g., 'make build'
# build, 'make push' docker push procedure, etc. The other Make targets
......@@ -40,10 +40,21 @@ lint: ## lint lmcbaseclasses Python code
pylint --output-format=pylint2junit.JunitReporter src/ska > build/reports/linting.xml
test-in-docker: build ## Build the docker image and run tests inside it.
@docker run $(IMAGE):$(VERSION) make test
@docker run --rm $(IMAGE):$(VERSION) make test
lint-in-docker: build ## Build the docker image and run lint inside it.
@docker run $(IMAGE):$(VERSION) make lint
@docker run --rm $(IMAGE):$(VERSION) make lint
generate-diagrams-in-docker: ## Build the docker image and generate state machine diagrams inside it.
@docker run --rm -v $(PWD):/diagrams $(IMAGE_FOR_DIAGRAMS) bash -c "cd /diagrams && make generate-diagrams-in-docker-internals"
generate-diagrams-in-docker-internals: ## Generate state machine diagrams (within a container!)
test -f /.dockerenv # ensure running in docker container
apt-get update
apt-get install --yes graphviz graphviz-dev gsfonts pkg-config
python3 -m pip install pygraphviz
cd /diagrams/docs/source && python3 draw_state_machines.py
ls -lo /diagrams/docs/source/images/
help: ## show this help.
@grep -hE '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
......
......@@ -25,6 +25,13 @@ The lmc-base-classe repository contains set of eight classes as mentioned in SKA
## Version History
#### 0.7.0
- Separate adminMode state machine from opState state machine
- Add support for STANDBY opState
- Add Standby() and Disable() commands to SKABaseDevice
- Breaking behavioural changes to adminMode and opState state machines
- Breaking change to `_straight_to_state` method signature
#### 0.6.6
- Documentation bugfix
......@@ -36,7 +43,7 @@ The lmc-base-classe repository contains set of eight classes as mentioned in SKA
- Refactor state machine to use pytransitions library.
- Minor behavioural change: Off() command is accepted in every obsState, rather
than only EMPTY obsState.
- support `straight_to_state` shortcuts to simplify test setups
- support `_straight_to_state` shortcuts to simplify test setups
- Refactor of state machine testing to make it more portable
#### 0.6.3
......
......@@ -10,6 +10,11 @@ SKA BaseDevice
:maxdepth: 2
.. automodule:: ska.base.base_device
.. autoclass:: ska.base.DeviceStateModel
:members:
:undoc-members:
.. autoclass:: ska.base.SKABaseDevice
:members:
:undoc-members:
......@@ -2,35 +2,125 @@
State Machine
=============
The state machine modules implements SKA's two fundamental state machines: the
base device state machine, and the observation state machine.
Base device state machine
-------------------------
The base device state machine provides basic state needed for all devices,
covering initialisation, off and on states, and a fault state. This state
machine is implemented by all SKA Tango devices that inherit from these LMC
base classes, though some devices with standby power modes may need to
implement further states.
.. figure:: images/device_state_diagram.png
:width: 80%
:alt: Diagram of the device state machine, taken from SKA design
documentation, showing the state machine as designed
Diagram of the device state machine, taken from SKA design
documentation, showing the state machine as designed
.. figure:: images/BaseDeviceStateMachine.png
The state machine module implements three fundamental SKA state
machines:
* the admin mode state machine
* the operational state (opState, represented in TANGO devices by TANGO
state) state machine
* the observation state machine.
Admin mode state machine
------------------------
The admin mode state machine allows for transitions between the five
administrative modes:
* NOT_FITTED: this is the lowest state of readiness, representing
devices that cannot be deployed without some external action, such as
plugging hardware in or updating network settings.)
* RESERVED: the device is fitted but redundant to other devices. It is
ready to take over should other devices fail.
* OFFLINE: the device has been declared by SKA operations not currently
to be used for operations (or whatever other function it provides)
* MAINTENANCE: the device cannot be used for science purposes but can be
operationed for engineering / maintenance purposes, such as testing,
debugging, etc
* ONLINE: the device can be used for science purposes.
The admin mode state machine allows for
* any transition between the modes NOT_FITTED, RESERVED and OFFLINE
(e.g. an unfitted device being fitted as a redundant or non-redundant
device, a redundant device taking over when another device fails, etc)
* any transition between the modes OFFLINE, MAINTENANCE and ONLINE (e.g.
an online device being taken offline or put into maintenance mode to
diagnose a fault, a faulty device moving between maintenance and
offline mode as it undergoes sporadic periods of diagnosis.
Diagrams of the admin mode state machine are shown below.
.. figure:: images/AdminModeStateMachine.png
:alt: Diagram of the admin mode state machine, as designed
Diagram of the admin mode state machine, as designed
.. figure:: images/AdminModeStateMachine_autogenerated.png
:alt: Diagram of the admin mode state machine, as implemented
Diagram of the admin mode state machine, automatically generated from
the implementation. The equivalence of this diagram to the diagram
above demonstrates that the machine has been implemented as designed.
Operational state state machine
-------------------------------
The operational state (opState) machine represents the operational state
of a SKA device. It is represented in TANGO devices using the TANGO
"state", so the states used are a subset of the TANGO states: INIT,
FAULT, DISABLE, STANDBY, OFF and ON.
* INIT: the device is currently initialising
* FAULT: the device has experienced an error from which it could not
recover.
* DISABLE: the device is in its lowest state of readiness, from which
it may take some time to become fully operational. For example, if the
device manages hardware, that hardware may be switched off.
* STANDBY: the device is unready, but can be made ready quickly. For
example, if the device manages hardware, that hardware may be in a
low-power standby mode.
* OFF: the device is fully operational but is not currently in use
* ON: the device is in use
The operational state state machine allows for:
* transition from INIT or FAULT into any of the three "readiness states"
DISABLE, STANDBY and OFF.
* all transitions between these three "readiness states" DISABLE,
STANDBY and OFF.
* transition between OFF and ON.
.. figure:: images/OperationStateMachine_decoupled.png
:alt: Diagram of the operational state state machine, as designed,
ignoring coupling with admin mode
Diagram of the operational state (opState) state machine, as
designed, ignoring coupling with admin mode
Unfortunately, operational state is inextricably coupled with admin
mode: there are admin modes that imply disablement, and operational
states such as ON should not be possible in such admin modes.
To facilitate this, the entire operational state state machine is
accessible only when the admin mode is ONLINE or MAINTENANCE. When in
any other admin mode, the only permitted operational states are INIT,
FAULT and DISABLE. This constraint is implemented into the operational
state state machine by
* three extra states: INIT_ADMIN, FAULT_ADMIN and DISABLED_ADMIN
* two extra transition triggers: "admin_on" and "admin_off", which allow
for transition between INIT and INIT_ADMIN; FAULT and FAULT_ADMIN; and
DISABLE and DISABLE_ADMIN.
This implementation minimises the coupling between admin mode and
operational state, allowing the two machines to be conceptualised almost
separately.
Diagrams of the operational state state machine are shown below.
.. figure:: images/OperationStateMachine_coupled.png
:alt: Diagram of the operational state state machine, as designed,
showing coupling with admin mode
Diagram of the operational state (opState) state machine, as
designed, showing coupling with admin mode
.. figure:: images/OperationStateMachine_autogenerated.png
:width: 80%
:alt: Diagram of the device state machine, automatically generated
from the state machine as specified in code.
:alt: Diagram of the operational state state machine, as implemented
Diagram of the device state machine, automatically generated from the
state machine as specified in code. The equivalence of this diagram to
the diagram previous demonstrates that the machine has been
Diagram of the operational state state machine, automatically
generated from the implementation. The equivalence of this diagram
to the diagram above demonstrates that the machine has been
implemented as designed.
......@@ -39,31 +129,37 @@ Observation state machine
The observation state machine is implemented by devices that manage
observations (currently only subarray devices).
.. figure:: images/ADR-8.png
.. figure:: images/ObservationStateMachine_adr8.png
:width: 80%
:alt: Diagram of the observation state machine, as decided and published in ADR-8.
:alt: Diagram of the observation state machine, as decided and
published in ADR-8.
Diagram of the observation state machine, as decided and published in ADR-8.
Diagram of the observation state machine, as decided and published in
ADR-8.
.. figure:: images/ObservationStateMachine.png
.. figure:: images/ObservationStateMachine_autogenerated.png
:width: 80%
:alt: Diagram of the observation state machine, automatically generated from
the state machine as specified in code.
:alt: Diagram of the observation state machine, automatically
generated from the implementation
Diagram of the observation state machine, automatically generated from
the state machine as specified in code. The equivalance of this
diagram to the diagram previous demonstrates that the machine has been
implemented in conformance with ADR-8.
the implementation. The equivalance of this diagram to the diagram
previous demonstrates that the machine has been implemented in
conformance with ADR-8.
API
---
.. toctree::
:maxdepth: 2
.. automodule:: ska.base.state_machine
:members:
:undoc-members:
.. autoclass:: OperationStateMachine
:members:
.. autoclass:: AdminModeStateMachine
:members:
.. autoclass:: ObservationStateMachine
:members:
"""
This module draws diagrams of the state machines.
Usage:
~/ska-src/lmc-base-classes$ docker run --rm -ti -v $PWD:/app continuumio/miniconda3 bash
(base) root@293f3b699c9b:/opt/project/src/ska/base# history
$ conda install --yes pygraphviz
$ pip install transitions
$ apt-get update && apt-get install gsfonts
$ cd /app/docs/source
$ python draw_state_machines.py
(Or see the top level Makefile)
"""
import importlib
import sys
from unittest import mock
from transitions.extensions import GraphMachine
# local import, so we can run this without installing the whole package
sys.path.append("../../src/ska/base")
import state_machine
def patch_in_graph_machine():
with mock.patch("transitions.Machine", GraphMachine):
mod = sys.modules["state_machine"]
importlib.reload(mod)
def draw(machine_class):
machine_name = machine_class.__name__
graphing_options = {
"title": f"\n{machine_name}",
"show_conditions": True,
"show_state_attributes": True,
"show_auto_transitions": False,
}
machine = machine_class(None, **graphing_options)
machine.get_graph().draw(f"images/{machine_name}_autogenerated.png", prog='dot')
if __name__ == "__main__":
patch_in_graph_machine()
draw(state_machine.OperationStateMachine)
draw(state_machine.AdminModeStateMachine)
draw(state_machine.ObservationStateMachine)
......@@ -3,19 +3,22 @@ __all__ = (
"control_model",
"state_machine",
"SKAAlarmHandler",
"SKABaseDevice", "SKABaseDeviceStateModel",
"SKABaseDevice",
"DeviceStateModel",
"SKACapability",
"SKALogger",
"SKAMaster",
"SKAObsDevice",
"SKASubarray", "SKASubarrayStateModel", "SKASubarrayResourceManager",
"SKASubarray",
"SKASubarrayStateModel",
"SKASubarrayResourceManager",
"SKATelState",
)
# Note: order of imports is important - start with lowest in the hierarchy
# SKABaseDevice, and then classes that inherit from it
from .base_device import SKABaseDevice, SKABaseDeviceStateModel
from .base_device import SKABaseDevice, DeviceStateModel
from .alarm_handler_device import SKAAlarmHandler
from .logger_device import SKALogger
from .master_device import SKAMaster
......@@ -25,5 +28,7 @@ from .tel_state_device import SKATelState
from .obs_device import SKAObsDevice
from .capability_device import SKACapability
from .subarray_device import (
SKASubarray, SKASubarrayStateModel, SKASubarrayResourceManager
SKASubarray,
SKASubarrayStateModel,
SKASubarrayResourceManager,
)
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment