diff --git a/.copier-answers.yml b/.copier-answers.yml index 4d644d8..043e23c 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier; NEVER EDIT MANUALLY -_commit: 3.4.1 +_commit: 4.0.0 _src_path: gh:epics-containers/ioc-template description: generic IOC for the lakeshore temperature controller git_platform: github.com diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 23301e0..c369aa0 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -13,10 +13,10 @@ } }, "remoteEnv": { - // allows X11 apps to run inside the container - "DISPLAY": "${localEnv:DISPLAY}", // provides a name for epics-containers to use in bash prompt etc. - "EC_PROJECT": "${localWorkspaceFolderBasename}" + "EC_PROJECT": "${localWorkspaceFolderBasename}", + "EPICS_CA_AUTO_ADDR_LIST": "NO", + "EPICS_CA_ADDR_LIST": "127.0.0.1" }, "features": { // add quality of life features for developers including git config integration @@ -26,9 +26,9 @@ } }, // IMPORTANT for this devcontainer to work with docker EC_REMOTE_USER must be - // set to vscode. You will run as vscode with full sudo rights. + // set to your user name. You will run with full sudo rights. // For podman it should be left blank. You will run as root but host mounts - // will be owned by your user. + // will be owned by your user id. "remoteUser": "${localEnv:EC_REMOTE_USER}", "customizations": { "vscode": { @@ -48,8 +48,9 @@ // One time global setup commands inside the container "postCreateCommand": "bash .devcontainer/postCreateCommand ${devcontainerId}", "runArgs": [ - // Allow the container to access the host X11 display and EPICS CA - "--net=host", + // IMPORTANT: this network must exist before the container is created + // source compose/environment.sh to create it before first use + "--network=channel_access_devcontainer", // Make sure SELinux does not disable write access to host filesystems like tmp "--security-opt=label=disable" ], @@ -60,6 +61,8 @@ // we also mount the project folder into a know location in the container // this is where the ibek-support and ioc folders reside in the container build // in this way the devcontainer and runtime look very similar - "source=${localWorkspaceFolder},target=/epics/generic-source,type=bind" + "source=${localWorkspaceFolder},target=/epics/generic-source,type=bind", + // Mount the opi folder so we can use phoebus from outside the container + "source=${localWorkspaceFolder}/opi/auto-generated,target=/epics/opi,type=bind" ] } \ No newline at end of file diff --git a/.devcontainer/initializeCommand b/.devcontainer/initializeCommand index 732ec1f..5cd42cd 100644 --- a/.devcontainer/initializeCommand +++ b/.devcontainer/initializeCommand @@ -3,4 +3,11 @@ # custom initialization goes here - runs outside of the dev container # just before the container is launched but after the container is created +FOLDER=$(dirname $(readlink -f $0)) + echo "devcontainerID ${1}" + +# make sure the shared network is created +# TODO this would be better done with compose but compose and podman +# in devcontainers is not currently stable. +source $FOLDER/../compose/environment.sh diff --git a/.devcontainer/postCreateCommand b/.devcontainer/postCreateCommand index 457b5c4..ac30849 100644 --- a/.devcontainer/postCreateCommand +++ b/.devcontainer/postCreateCommand @@ -23,9 +23,9 @@ echo 'source <(ibek --show-completion bash)' >> $HOME/.bashrc echo 'source <(ibek --show-completion zsh)' >> $HOME/.zshrc # pick theme and RPS1 with no unicode chars to avoid completion corruption in zsh -sed -i $HOME/.zshrc -e 's/ZSH_THEME="devcontainers"/ZSH_THEME="lukerandall"/' -e '/^RPS1=/d' +sed -i $HOME/.zshrc -e 's/ZSH_THEME="devcontainers"/ZSH_THEME="dst"/' -e '/^RPS1=/d' # override the response PS - this shows the last exit code in red only -echo "RPS1=$'%(?..%{\C-[[01;31m%}%? %{\C-[[00m%})'" >> $HOME/.zshrc +# echo "RPS1=$'%(?..%{\C-[[01;31m%}%? %{\C-[[00m%})'" >> $HOME/.zshrc # allow personalization of all devcontainers in this subdirectory # by placing a .devcontainer_rc file in the workspace root diff --git a/.gitignore b/.gitignore index 1cac73b..ed6e374 100644 --- a/.gitignore +++ b/.gitignore @@ -11,8 +11,11 @@ ibek # dont save workspaces as other users will have differing folders *workspace -# config folder is there to be replaced there is just a dummy with Readme. +# config folder is a container mount at /epics/ioc/config ioc/config +# the opi folder is also mounted into the container at /epics/ioc/opi +opi/auto-generated/* +!opi/auto-generated/.placeholder # podman may leave this around in aborted builds .build.swp diff --git a/Dockerfile b/Dockerfile index 5235875..f40d080 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,6 +23,9 @@ WORKDIR ${SOURCE_FOLDER}/ibek-support # copy the global ibek files COPY ibek-support/_global/ _global +COPY ibek-support/pvxs/ pvxs/ +RUN pvxs/install.sh 1.3.1 + COPY ibek-support/iocStats/ iocStats RUN iocStats/install.sh 3.2.0 @@ -57,5 +60,4 @@ COPY --from=runtime_prep /assets / # install runtime system dependencies, collected from install.sh scripts RUN ibek support apt-install-runtime-packages --skip-non-native -CMD "bash -c ${IOC}/start.sh" - +CMD ["bash", "-c", "${IOC}/start.sh"] diff --git a/README.md b/README.md index a52bd29..5371df9 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,20 @@ To update to the latest version of the template: pip install copier cd ioc-lakeshore340 copier update -a --trust . -``` \ No newline at end of file +``` + +## Developer Container + +This repository includes a developer container configuration for Visual Studio Code. This allows you to run the Generic IOC locally and debug it. See https://epics-containers.github.io/main/tutorials/dev_container.html. + +### IMPORTANT: First Time Preparation + +The devcontainer uses a docker network that it can share with a ca-gateway in order that your PVs are accessible from your host machine. We arrange to create this network once and as long as you don't delete it or reset docker it will be available for all your devcontainers going forward. + +To create the network run the following commands: + +```bash +cd ioc-adsimdetector +source ./compose/environment.sh +``` + diff --git a/build b/build index 0b94f16..95ab316 100755 --- a/build +++ b/build @@ -22,13 +22,14 @@ cd $(dirname ${0}) # use docker if available else use podman if ! docker version &>/dev/null; then docker=podman; else docker=docker; fi -if $docker buildx version &>/dev/null; then builx=buildx; load=--load; fi +if $docker buildx version &>/dev/null; then buildx=buildx; load=--load ; fi +if [[ $DOCKER_BUILDKIT == "0" ]]; then buildx=; load=; fi # make sure new repos get their submodule ibek-support if [ ! -d ibek-support/_global ] ; then git submodule update --init ; fi # build and developer images set -x -$docker build $buildx -t ${TAG} "${@}" $load \ +$docker $buildx build -t ${TAG} "${@}" $load \ --build-arg IMAGE_EXT=$IMAGE_EXT \ $runtime --target $TARGET . diff --git a/compose/compose.yaml b/compose/compose.yaml new file mode 100644 index 0000000..2aacfd1 --- /dev/null +++ b/compose/compose.yaml @@ -0,0 +1,11 @@ +# This docker compose definition stands up a ca-gateway and phoebus instance. +# This enables interactive testing to the IOC developer container +# +# To lauch these services:- +# source ./environment.sh +# docker compose up -d +# + +include: + - services/gateway/compose.yml + - services/phoebus/compose.yml diff --git a/compose/environment.sh b/compose/environment.sh new file mode 100644 index 0000000..5b9e9a4 --- /dev/null +++ b/compose/environment.sh @@ -0,0 +1,55 @@ +#! /bin/bash + +# Setup environment variables required to launch the services described in this +# repo. A standard install of docker compose and permission to run docker +# are the only other requirements (membership of the docker group). +# +# docker compose may be backed by podman or docker container engines, see +# https://epics-containers.github.io/main/tutorials/setup_workstation.html. + + +# This script must be sourced +if [ "$0" = "$BASH_SOURCE" ]; then + echo "ERROR: Please source this script (source ./environment.sh)" + exit 1 +fi + +# if there is a docker-compose module then load it +if [[ $(module avail docker-compose 2>/dev/null) != "" ]] ; then + module load docker-compose +fi + +function check_docker { + # return 0 if docker is detected, or 1 otherwise, + # cope with the possibility that podman is aliased to docker + if [[ $(docker version) =~ "Docker" ]]&> /dev/null; then + return 0 + fi + return 1 +} + +if check_docker; then + USER_ID=$(id -u); USER_GID=$(id -g) +else + USER_ID=0; USER_GID=0 + alias docker=podman +fi + +# make sure we have a network to share beteen the devcontainer and gateway container +if ! docker network inspect channel_access_devcontainer &>/dev/null ; then + docker network create --subnet="170.21.0.0/16" channel_access_devcontainer +fi + +# ensure local container users can access X11 server +xhost +SI:localuser:$(id -un) + +# Set up the environment for compose ########################################### + +# set user id for the phoebus container for easy X11 forwarding. +export UIDGID=$USER_ID:$USER_GID +# choose test profile for docker compose +export COMPOSE_PROFILES=test +# for test profile our ca-gateway publishes PVS on the loopback interface +export EPICS_CA_ADDR_LIST=127.0.0.1 +# make a short alias for docker-compose for convenience +alias ec='docker compose' diff --git a/compose/services/gateway/compose.yml b/compose/services/gateway/compose.yml new file mode 100644 index 0000000..dcd2f3e --- /dev/null +++ b/compose/services/gateway/compose.yml @@ -0,0 +1,54 @@ +# ca gateway for exposing container network PVs to the host's loopback interface + +services: + + # ca-gateway for test / dev ################################################## + + ca-gateway: &ca-gateway + + container_name: ca-gateway + + image: ghcr.io/epics-containers/docker-ca-gateway:2.1.3ec1 + + expose: + - 5064-5065/udp + - 5064-5065 + + ports: + # bind to localhost to isolate channel access to this host only + - 127.0.0.1:5064:5064/udp + - 127.0.0.1:5064-5065:5064-5065 + + restart: unless-stopped + + networks: + channel_access_devcontainer: + + configs: + - source: ca-gateway_config + target: /config + + command: -cip 170.21.255.255 -pvlist /config/pvlist -access /config/access -log /dev/stdout -debug 1 + + profiles: + - test + - dev + + # debugging version of gateway container ##################################### + ca-gateway-debug: + + <<: *ca-gateway + + # this image is not distroless and has network tools installed + image: ghcr.io/epics-containers/docker-ca-gateway-debug:2.1.3ec1 + + profiles: + - debug + +configs: + ca-gateway_config: + file: ./config + +networks: + channel_access_devcontainer: + external: true \ No newline at end of file diff --git a/compose/services/gateway/config/access b/compose/services/gateway/config/access new file mode 100644 index 0000000..f69d0e8 --- /dev/null +++ b/compose/services/gateway/config/access @@ -0,0 +1,6 @@ +# See /EPICS/extensions/src/gateway/GATEWAY.access for more detailed example + +ASG(DEFAULT) { + RULE(1,READ) + RULE(1,WRITE) +} diff --git a/compose/services/gateway/config/pvlist b/compose/services/gateway/config/pvlist new file mode 100644 index 0000000..209c98b --- /dev/null +++ b/compose/services/gateway/config/pvlist @@ -0,0 +1,7 @@ +# See /EPICS/extensions/src/gateway/GATEWAY.pvlist for more detailed example + +EVALUATION ORDER ALLOW, DENY + +[0-9].* ALLOW +[a-z].* ALLOW +[A-Z].* ALLOW diff --git a/compose/services/phoebus/compose.yml b/compose/services/phoebus/compose.yml new file mode 100644 index 0000000..0f759d7 --- /dev/null +++ b/compose/services/phoebus/compose.yml @@ -0,0 +1,34 @@ +# for development and testing it is useful to bring up phoebus instanced to +# interact with the local IOCs PVs. + +services: + phoebus: + container_name: phoebus + image: ghcr.io/epics-containers/ec-phoebus:4.7.3ec2 + environment: + DISPLAY: $DISPLAY + tty: true + # pick a server port for phoebus so it does not reconnect to existing phoebus + command: phoebus-product/phoebus.sh -settings /config/settings.ini -resource /opi/auto-generated/index.bob -server 7010 + volumes: + - /tmp/.X11-unix:/tmp/.X11-unix + - ~/.Xauthority:/root/.Xauthority + - ../../../opi:/opi + - ../../../..:/workspaces + + # for X11 to work we need to run as the same UID as the host + # IMPORTANT: set UIDGID to your host user:group e.g. 1000:1000 + # BUT: always to 0:0 if you are using podman + user: ${UIDGID} + + # network host with a gateway for CA is the most reliable way to + # get X11 forwarding to work - even with ssh->container. + network_mode: host + + configs: + - source: phoebus_config + target: /config + +configs: + phoebus_config: + file: ./config diff --git a/compose/services/phoebus/config/settings.ini b/compose/services/phoebus/config/settings.ini new file mode 100644 index 0000000..c4d462b --- /dev/null +++ b/compose/services/phoebus/config/settings.ini @@ -0,0 +1,4 @@ +# using localhost for channel access to isolate it to the host for development + +# TODO restore this once we have PVA gateway and IOCS running in the CNI +org.phoebus.pv.ca/addr_list=127.0.0.1 diff --git a/ibek-support b/ibek-support index a84418e..c464e40 160000 --- a/ibek-support +++ b/ibek-support @@ -1 +1 @@ -Subproject commit a84418ed7e18306789ed80c2b4c102e07792c63b +Subproject commit c464e4008c89dcc2562d900a35ec5cd528fd9480 diff --git a/ioc/start.sh b/ioc/start.sh index ac912da..926a3db 100755 --- a/ioc/start.sh +++ b/ioc/start.sh @@ -33,7 +33,7 @@ description=' startup script. The file name should always be 'ioc.yaml'. The ioc instance can determine its own name with the following as the first line in 'ioc.yaml' - ioc_name: ""{{ __utils__.get_env('IOC_NAME') }}"" + ioc_name: ""{{ _global.get_env('IOC_NAME') }}"" at the top of the file and in turn "{{ ioc_name }}"" can be used in any of the fields within the file. For example: by default Kubernetes will be @@ -120,7 +120,7 @@ if [ -f ${override} ]; then # 2. ioc.yaml ****************************************************************** elif [ -f ${ibek_src} ]; then - if [[ ${#ibek_yams[@]} > 1 ]]; then + if [[ ${#ibek_yamls[@]} > 1 ]]; then ibek_error "ERROR: Multiple YAML files found in ${CONFIG_DIR}." fi diff --git a/opi/auto-generated/.placeholder b/opi/auto-generated/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt index cf84afb..c459e13 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -ibek==2.0.2 +ibek==3.0.0 # to install direct from github during development in a branch # git+https://github.com/epics-containers/ibek.git@fix-extract-assets