diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 82cbc3f552989949dbe2d5ac79cdd47b83152971..f86c6aae22888186e57415c7aa721f8bee417064 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -106,26 +106,27 @@ docker_build_image_all: - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh recv-sim latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh sdptr-sim latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh unb2-sim latest + - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-antennafield latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-apsct latest - - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-ccd latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-apspu latest - - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-tilebeam latest + - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-boot latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-beamlet latest + - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-ccd latest + - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-configuration latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-digitalbeam latest - - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-antennafield latest - - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-boot latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-docker latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-observation latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-observation-control latest - - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-psoc latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-pcon latest + - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-psoc latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-recv latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-sdp latest + - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-temperature-manager latest + - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-tilebeam latest + - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-unb2 latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-bst latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-sst latest - - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-unb2 latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-xst latest - - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-temperature-manager latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh archiver-timescale latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh hdbpp latest - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh hdbppts-cm latest @@ -310,6 +311,17 @@ docker_build_image_device_ccd: script: # Do not remove 'bash' or statement will be ignored by primitive docker shell - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-ccd $tag +docker_build_image_device_configuration: + extends: .base_docker_images_except + only: + refs: + - merge_requests + changes: + - docker-compose/device-configuration.yml + - docker-compose/lofar-device-base/* + script: +# Do not remove 'bash' or statement will be ignored by primitive docker shell + - bash $CI_PROJECT_DIR/sbin/tag_and_push_docker_image.sh device-configuration $tag docker_build_image_device_apspu: extends: .base_docker_images_except only: diff --git a/CDB/LOFAR_ConfigDb.json b/CDB/LOFAR_ConfigDb.json index b2d2f517e83667a1659c39d091f73bc2580df01f..0370c7c90fa9f51ead4c9f2e26dd856929a541c4 100644 --- a/CDB/LOFAR_ConfigDb.json +++ b/CDB/LOFAR_ConfigDb.json @@ -17,6 +17,13 @@ } } }, + "Configuration": { + "STAT": { + "Configuration": { + "STAT/Configuration/1": {} + } + } + }, "Observation": { "STAT": { "Observation": { diff --git a/docker-compose/device-configuration.yml b/docker-compose/device-configuration.yml new file mode 100644 index 0000000000000000000000000000000000000000..3a7f1a62413f4ef3e4a7df6f08b637b72b194c20 --- /dev/null +++ b/docker-compose/device-configuration.yml @@ -0,0 +1,53 @@ +# +# Docker compose file that launches an interactive iTango session. +# +# Connect to the interactive session with 'docker attach itango'. +# Disconnect with the Docker deattach sequence: <CTRL>+<P> <CTRL>+<Q> +# +# Defines: +# - itango: iTango interactive session +# +# Requires: +# - lofar-device-base.yml +# +version: '3' + +services: + device-configuration: + image: device-configuration + # build explicitly, as docker-compose does not understand a local image + # being shared among services. + build: + context: . + dockerfile: lofar-device-base/Dockerfile + args: + SOURCE_IMAGE: ${LOCAL_DOCKER_REGISTRY_HOST}/${LOCAL_DOCKER_REGISTRY_USER}/tango-itango:${TANGO_ITANGO_VERSION} + container_name: ${CONTAINER_NAME_PREFIX}device-configuration + logging: + driver: "json-file" + options: + max-size: "100m" + max-file: "10" + networks: + - control + ports: + - "5722:5722" # unique port for this DS + - "5822:5822" # ZeroMQ event port + - "5922:5922" # ZeroMQ heartbeat port + extra_hosts: + - "host.docker.internal:host-gateway" + volumes: + - ..:/opt/lofar/tango:rw + environment: + - TANGO_HOST=${TANGO_HOST} + - TANGO_ZMQ_EVENT_PORT=5822 + - TANGO_ZMQ_HEARTBEAT_PORT=5922 + working_dir: /opt/lofar/tango + entrypoint: + - bin/start-ds.sh + # configure CORBA to _listen_ on 0:port, but tell others we're _reachable_ through ${HOSTNAME}:port, since CORBA + # can't know about our Docker port forwarding + - l2ss-configuration-device Configuration STAT -v -ORBendPoint giop:tcp:device-configuration:5722 -ORBendPointPublish giop:tcp:${HOSTNAME}:5722 + restart: on-failure + stop_signal: SIGINT # request a graceful shutdown of Tango + stop_grace_period: 2s diff --git a/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py b/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py index 350ecb1e87f4829ddd60698831bbf75d941782a9..4b33c8132113cfb9acc6f03f3ace5df6be4c4b1e 100644 --- a/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py +++ b/docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py @@ -16,6 +16,7 @@ digitalbeam = DeviceProxy("STAT/DigitalBeam/1") antennafield = DeviceProxy("STAT/AntennaField/1") docker = DeviceProxy("STAT/Docker/1") temperaturemanager = DeviceProxy("STAT/TemperatureManager/1") +configuration = DeviceProxy("STAT/Configuration/1") # Put them in a list in case one wants to iterate -devices = [apsct, ccd, apspu, recv, sdp, bst, sst, xst, unb2, boot, tilebeam, beamlet, digitalbeam, antennafield, temperaturemanager, docker] +devices = [apsct, ccd, apspu, recv, sdp, bst, sst, xst, unb2, boot, tilebeam, beamlet, digitalbeam, antennafield, temperaturemanager, docker, configuration] diff --git a/docker-compose/jupyterlab/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py b/docker-compose/jupyterlab/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py index 350ecb1e87f4829ddd60698831bbf75d941782a9..4b33c8132113cfb9acc6f03f3ace5df6be4c4b1e 100644 --- a/docker-compose/jupyterlab/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py +++ b/docker-compose/jupyterlab/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py @@ -16,6 +16,7 @@ digitalbeam = DeviceProxy("STAT/DigitalBeam/1") antennafield = DeviceProxy("STAT/AntennaField/1") docker = DeviceProxy("STAT/Docker/1") temperaturemanager = DeviceProxy("STAT/TemperatureManager/1") +configuration = DeviceProxy("STAT/Configuration/1") # Put them in a list in case one wants to iterate -devices = [apsct, ccd, apspu, recv, sdp, bst, sst, xst, unb2, boot, tilebeam, beamlet, digitalbeam, antennafield, temperaturemanager, docker] +devices = [apsct, ccd, apspu, recv, sdp, bst, sst, xst, unb2, boot, tilebeam, beamlet, digitalbeam, antennafield, temperaturemanager, docker, configuration] diff --git a/docker-compose/tango-prometheus-exporter/lofar2-policy.json b/docker-compose/tango-prometheus-exporter/lofar2-policy.json index 606f06499472aa11324b7566739efd6de37fdcab..bfb587489da949275dd15f31f372cd0aac4938c2 100644 --- a/docker-compose/tango-prometheus-exporter/lofar2-policy.json +++ b/docker-compose/tango-prometheus-exporter/lofar2-policy.json @@ -17,6 +17,8 @@ }, "stat/ccd/1": { }, + "stat/configuration/1": { + }, "stat/apspu/1": { }, "stat/beamlet/1": { diff --git a/sbin/run_integration_test.sh b/sbin/run_integration_test.sh index 563b2c7fbf793bcbd9db84a45635433c0b742c26..ffd18c715408dcb7db2803541f843a4c5e791caf 100755 --- a/sbin/run_integration_test.sh +++ b/sbin/run_integration_test.sh @@ -76,7 +76,7 @@ sleep 1 # dsconfig container must be up and running... # shellcheck disable=SC2016 echo '/usr/local/bin/wait-for-it.sh ${TANGO_HOST} --strict --timeout=300 -- true' | make run dsconfig bash - -DEVICES="device-boot device-apsct device-ccd device-apspu device-sdp device-recv device-bst device-sst device-unb2 device-xst device-beamlet device-digitalbeam device-tilebeam device-psoc device-pcon device-antennafield device-temperature-manager device-observation device-observation-control" +DEVICES="device-boot device-apsct device-ccd device-apspu device-sdp device-recv device-bst device-sst device-unb2 device-xst device-beamlet device-digitalbeam device-tilebeam device-psoc device-pcon device-antennafield device-temperature-manager device-observation device-observation-control device-configuration" SIMULATORS="sdptr-sim recv-sim unb2-sim apsct-sim apspu-sim ccd-sim" diff --git a/sbin/tag_and_push_docker_image.sh b/sbin/tag_and_push_docker_image.sh index d3b5ea894e0b13eb3bcb7755656381235d664a5a..c785e4c8f27981f393dd353f814ce6a0b127e7d3 100755 --- a/sbin/tag_and_push_docker_image.sh +++ b/sbin/tag_and_push_docker_image.sh @@ -72,6 +72,7 @@ LOCAL_IMAGES=( "device-antennafield device-antennafield y" "device-apsct device-apsct y" "device-apspu device-apspu y" "device-ccd device-ccd y" + "device-configuration device-configuration y" "device-boot device-boot y" "device-docker device-docker y" "device-observation device-observation y" "device-observation-control device-observation-control y" diff --git a/tangostationcontrol/docs/source/devices/configuration.rst b/tangostationcontrol/docs/source/devices/configuration.rst new file mode 100644 index 0000000000000000000000000000000000000000..65f8c028080a37db71a2f7a0ebbbf07c8e69ae02 --- /dev/null +++ b/tangostationcontrol/docs/source/devices/configuration.rst @@ -0,0 +1,7 @@ +.. _configuration: + +Configuration +-------------------- + +The ``Configuration == DeviceProxy("STAT/Configuration/1")`` Configuration Device controls the loading, updating, exposing +and dumping of the whole Station Configuration diff --git a/tangostationcontrol/docs/source/index.rst b/tangostationcontrol/docs/source/index.rst index 4c56206dfce3ab37b07f103a963d06846ccd8f12..250804f4e5955534b8fb4589187ff6df16943a47 100644 --- a/tangostationcontrol/docs/source/index.rst +++ b/tangostationcontrol/docs/source/index.rst @@ -30,6 +30,7 @@ Even without having access to any LOFAR2.0 hardware, you can install the full st devices/docker devices/psoc devices/ccd + devices/configuration devices/temperature-manager devices/configure configure_station diff --git a/tangostationcontrol/setup.cfg b/tangostationcontrol/setup.cfg index f42357ef73a2f50734d03f26444b32b905ac0042..36318820cb55f877113ff2fb6dd84dc8cde4751e 100644 --- a/tangostationcontrol/setup.cfg +++ b/tangostationcontrol/setup.cfg @@ -56,6 +56,7 @@ console_scripts = l2ss-unb2 = tangostationcontrol.devices.unb2:main l2ss-xst = tangostationcontrol.devices.sdp.xst:main l2ss-temperature-manager = tangostationcontrol.devices.temperature_manager:main + l2ss-configuration-device = tangostationcontrol.devices.configuration_device:main # The following entry points should eventually be removed / replaced l2ss-hardware-device-template = tangostationcontrol.examples.HW_device_template:main diff --git a/tangostationcontrol/tangostationcontrol/devices/README.md b/tangostationcontrol/tangostationcontrol/devices/README.md index 64390631beb1222e68c536757766e50fba64bcbc..0a1081baac732665cb9693fd9cb43f40c0b7dcfa 100644 --- a/tangostationcontrol/tangostationcontrol/devices/README.md +++ b/tangostationcontrol/tangostationcontrol/devices/README.md @@ -9,7 +9,7 @@ If a new device is added, it will (likely) need to be referenced in several plac - Adjust `CDB/LOFAR_ConfigDb.json` to create the device in the Tango device database, - Adjust `docker-compose/jupyter/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py` and `docker-compose/jupyterlab/ipython-profiles/stationcontrol-jupyter/startup/01-devices.py` to make an alias for it available in Jupyter and Jupyter-Lab, - Adjust `tangostationcontrol/tangostationcontrol/devices/boot.py` to add the device to the station initialisation sequence, -- Add to `docker-compose/` to create a YaML file to start the device in a docker container. NOTE: it needs a unique 57xx port assigned (current _unused_ port value: 5722), a unique 58xx port for ZMQ events, and a unique 59xx port for ZMQ heartbeat +- Add to `docker-compose/` to create a YaML file to start the device in a docker container. NOTE: it needs a unique 57xx port assigned (current _unused_ port value: 5723), a unique 58xx port for ZMQ events, and a unique 59xx port for ZMQ heartbeat - Adjust `tangostationcontrol/setup.cfg` to add an entry point for the device in the package installation, - Add to `tangostationcontrol/tangostationcontrol/integration_test/default/devices/` to add an integration test, - Adjust `sbin/run_integration_test.sh` to have the device started when running the integration tests, diff --git a/tangostationcontrol/tangostationcontrol/devices/boot.py b/tangostationcontrol/tangostationcontrol/devices/boot.py index 42ce74d74c7efc6ca27d4b4ef8a53988441fd04a..e0899c743403aeac6ee7c143251a31295a391108 100644 --- a/tangostationcontrol/tangostationcontrol/devices/boot.py +++ b/tangostationcontrol/tangostationcontrol/devices/boot.py @@ -251,6 +251,7 @@ class Boot(lofar_device): "STAT/TileBeam/1", # Accesses AntennaField "STAT/DigitalBeam/1", # Accessed SDP and Beamlet "STAT/TemperatureManager/1", + "STAT/Configuration/1", ], ) diff --git a/tangostationcontrol/tangostationcontrol/devices/configuration_device.py b/tangostationcontrol/tangostationcontrol/devices/configuration_device.py index 9394c070572f472457daac59b8beb10c50bf273f..bc8222cd3880f990ada373cbfd85980505786521 100644 --- a/tangostationcontrol/tangostationcontrol/devices/configuration_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/configuration_device.py @@ -40,6 +40,14 @@ class Configuration(lofar_device): def read_tangodb_properties_RW(self): return self._dump_configdb() + def write_tangodb_properties_RW(self, tangodb_properties): + """ Takes a JSON string which represents the station configuration + and loads the whole configuration from scratch. + + N.B. it does not update, it loads a full new configuration. + """ + self.proxy.tangodb_properties_RW = tangodb_properties + def _dump_configdb(self): """ Returns the TangoDB station configuration as a JSON string """ return 'Configuration' diff --git a/tangostationcontrol/tangostationcontrol/devices/docker_device.py b/tangostationcontrol/tangostationcontrol/devices/docker_device.py index 71e13119de523f829092d040ab62bc11330ac4ad..a746ad1cd949ed488a90802d0ac7ccd903133ec3 100644 --- a/tangostationcontrol/tangostationcontrol/devices/docker_device.py +++ b/tangostationcontrol/tangostationcontrol/devices/docker_device.py @@ -48,6 +48,8 @@ class Docker(lofar_device): device_boot_R = attribute_wrapper(comms_annotation={"container": "device-boot"}, datatype=bool) device_boot_RW = attribute_wrapper(comms_annotation={"container": "device-boot"}, datatype=bool, access=AttrWriteType.READ_WRITE) device_docker_R = attribute_wrapper(comms_annotation={"container": "device-docker"}, datatype=bool) + device_configuration_R = attribute_wrapper(comms_annotation={"container": "device-configuration"}, datatype=bool) + device_configuration_RW = attribute_wrapper(comms_annotation={"container": "device-configuration"}, datatype=bool, access=AttrWriteType.READ_WRITE) # device_docker_RW is not available, as we cannot start our own container` device_temperature_manager_R = attribute_wrapper(comms_annotation={"container": "device-temperature-manager"}, datatype=bool) device_temperature_manager_RW = attribute_wrapper(comms_annotation={"container": "device-temperature-manager"}, datatype=bool, access=AttrWriteType.READ_WRITE) diff --git a/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_configuration.py b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_configuration.py new file mode 100644 index 0000000000000000000000000000000000000000..4a34cad03da20d5d06ccfc012307228862d5557f --- /dev/null +++ b/tangostationcontrol/tangostationcontrol/integration_test/default/devices/test_device_configuration.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# +# This file is part of the LOFAR 2.0 Station Software +# +# +# +# Distributed under the terms of the APACHE license. +# See LICENSE.txt for more info. + +from .base import AbstractTestBases + + +class TestDeviceConfiguration(AbstractTestBases.TestDeviceBase): + + def setUp(self): + super().setUp("STAT/Configuration/1")