This document states workflows to develop and deploy IOC on a EPIK8S infrastructure.
Every IOC/application MUST have a GIT repository associated. A project must be created under https://baltig.infn.it/lnf-da-control or a different group like for instance:
https://baltig.infn.it/infn-epics
https://baltig.infn.it/epics-containers
Pay attention to not set the project private otherwise will not be possible to load it into the EPIK8S.
It's highly suggested to use https://code.visualstudio.com/ to handle the project.
It's
also recommended to use a container for development to decouple development of the application from the platform where the application is developed.
It's really simple to use a container please read this guide: https://code.visualstudio.com/docs/devcontainers/containers
Depending on the target beamline (i.e. sparc environ EPIK8s Sparc):
For this kind of IOC it's recommended to use the docker image: baltig.infn.it:4567/epics-containers/epics-py-base since it contains the required packages and will be also the image that will be used to run this kind of softioc.
Here below an example of configuration of the devontainer devcontainer.json
// For format details, see https://containers.dev/implementors/json_reference/
{
"name": "python container",
"image": "baltig.infn.it:4567/epics-containers/epics-py-base",
"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}"
},
"features": {
},
// IMPORTANT for this devcontainer to work with docker EC_REMOTE_USER must be
// set to vscode. For podman it should be left blank.
"remoteUser": "${localEnv:EC_REMOTE_USER}",
"customizations": {
"vscode": {
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"tamasfe.even-better-toml",
"redhat.vscode-yaml",
"ryanluker.vscode-coverage-gutters",
"epicsdeb.vscode-epics",
"ms-python.black-formatter"
]
}
},
// Make sure the files we are mapping into the container exist on the host
// You can place any other outside of the container before-launch commands here
//"initializeCommand": "bash .devcontainer/initializeCommand ${devcontainerId}",
// Hooks the global .bashprofile_dev_container but also can add any other commands
// to run in the container at creation in here
//"postCreateCommand": "bash .devcontainer/postCreateCommand ${devcontainerId}",
//"forwardPorts": [5064, 5065],
"runArgs": [
// Allow the container to access the host X11 display and EPICS CA
//"--net=host",
// Make sure SELinux does not disable with access to host filesystems like tmp
"--security-opt=label=disable"
],
"workspaceMount": "source=${localWorkspaceFolder},target=/app/${localWorkspaceFolderBasename},type=bind",
"workspaceFolder": "/app/${localWorkspaceFolderBasename}",
"mounts": [
// Mount some useful local files from the user's home directory
// By mounting the parent of the workspace we can work on multiple peer projects
"source=${localWorkspaceFolder}/../,target=/repos,type=bind",
// this provides eternal bash history in and out of the container
"source=${localEnv:HOME}/.bash_eternal_history,target=/root/.bash_eternal_history,type=bind",
// this bashrc hooks up the .bashrc_dev_container in the following mount
"source=${localWorkspaceFolder}/.devcontainer/.bashrc,target=/root/.bashrc,type=bind",
// provides a place for you to put your shell customizations for all your dev containers
"source=${localEnv:HOME}/.bashrc_dev_container,target=/root/.bashrc_dev_container,type=bind",
// provides a place to install any packages you want to have across all your dev containers
"source=${localEnv:HOME}/.bashprofile_dev_container,target=/root/.bashprofile_dev_container,type=bind",
// provides the same command line editing experience as your host
"source=${localEnv:HOME}/.inputrc,target=/root/.inputrc,type=bind"
]
} |
A fully functional example:
https://baltig.infn.it/infn-epics/py-ioc-collector
To test the container connection:
docker run -it baltig.infn.it:4567/epics-containers/epics-py-base bash
epics@d916ac2d3987:~$ export EPICS_CA_ADDR_LIST=rdsparcpitaia001.lnf.infn.it ## list of IOCs or gateway
epics@d916ac2d3987:~$ python
Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import epics
>>> epics.caget("SR00RPA01:DVDR")
'Redpitaya' |
SOFT IOC Development SoftIOC in a Linux-like environment
Once your IOC/application named 'mynewioc' is tested and ready to be published on the target EPIK8S.
Identify your target EPIK8S information page (i.e EPIK8s Sparc ) retrieving "GIT Control Source" URL, clone it:
git clone https://baltig.infn.it/lnf-da-control/epik8-<BEAMLINE>.git --recurse-submodules |
you should have a directory like this:
├── README.md ├── config │ ├── applications │ │ ├── flame-state-import │ │ └── icpdastemp01 │ ├── iocs │ │ ├── mrf01 │ │ ├── pitaya │ │ ├── temp01 │ │ └── mynewioc <-- add here your folder or git subproject for configuration │ └── services │ └── cagateway ├── deploy │ ├── Chart.yaml │ ├── templates │ │ └── epik8.yaml │ └── values.yaml <-- add here your IOC to deploy ├─ ... |
Suppose your iocname is mynewioc you should create a folder with the same name. This folder should contain a:
In case mynewioc is a soft IOC this directory should also contain the git submodule that point to your application git repository.
If your mynewioc is a softioc you should have a repository for it. So in the EPIK8S folder config/iocs/mynewioc you must add your repository as submodule:
cd <EPIK8Sfolder/config/iocs> git pull --recurse-submodules ## to update remote changes git submodule update --init ## to update eventually new submodules cd mynewioc ## here add your new submodule git submodule add <your repository_URL> scripts # your softioc repository will be added as scripts git commit -m "your comment Add submodule <submodule_name>" git push origin <your remote branch i.e main/master> |
In your application repository create a bash file named start.sh (bash script) that will be used to start your application.
#!/bin/bash script_dir=$(dirname "$0") cd $script_dir echo "Starting mynewioc : $EPICS_CA_ADDR_LIST" python ./scripts/mynewioc <parameters> -c myconfig.json |
This script will launch ./scripts/mynewioc (remember scripts scripts is the folder name you gave to your submodule in the previous step) and will give some parameters and a configuration myconfig.json file that must be added to the mynewioc.
Once your configuration directory mynewioc is complete. We need to add to the main git repository.
cd <EPIK8Sfolder/config/iocs/mynewioc> chmod a+x start.sh # make start.sh executable git add start.sh myconfig.json scripts git commit -m "my comment" . git push origin |
This way we just added the information needed to start the ioc, but we still instruct ArgoCD to launch the IOC in the EPIK8S target infrastructure.
We should now add and entry into <EPIK8Sfolder/deploy/values.yaml>
We must distinguish IOC types, the configuration is slightly different if the IOC runs inside the cluster or outside.
You must find the iocs section in values.yaml and add your IOC:
- name: "mynewioc"
asset: "https://confluence.infn.it/x/nYD8DQ" ## optional link to the asset
charturl: 'https://baltig.infn.it/epics-containers/ioc-chart.git'
iocprefix: "LEL:DIA" ## iocprefix that can be used in start.sh to change dynamically prefix of different instances
iocroot: ""
securityContext:
privileged: true
runAsUser: 0
dataVolume:
accessMode: 'ReadWriteOnce' ## space and type required to run
size: 8Mi
gitinit: true ## use default beamline repository and as path <config>/iocs/<mynewioc>
|
An simple example took from (https://baltig.infn.it/lnf-da-control/dafne-k8s-ecs/-/tree/main/config/ioc/ioc-dafne-accumulator-orbit?ref_type=heads):
If the application/ioc is generic a more generic approach should be followed decoupling the source and the startup. In this approach the configuration of the IOC resides in a dedicated directory <TARGET ECS>/config/ioc of the target K8s ECS see for instance https://baltig.infn.it/lnf-da-control/dafne-k8s-ecs/-/tree/main/config/ioc
Follow this steps:
git clone https://baltig.infn.it/lnf-da-control/<BEAMLINE>-k8s-ecs.git --recurse-submodules |
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: <myapplicationname>-ioc
namespace: argocd
labels:
rootapp: {{ .Chart.Name }}
rootappver: {{ .Chart.Version | quote }}
beamline: {{ .Values.beamline | quote }}
spec:
project: default
source:
repoURL: 'https://baltig.infn.it/epics-containers/ioc-chart.git'
path: .
targetRevision: HEAD
helm:
values: |
image: baltig.infn.it:4567/epics-containers/epics-py-base
beamline: {{ .Values.beamline | quote }}
replicaCount: {{ .Values.consoleReplica }}
configCA:
existingConfigMap: {{ .Values.configCA.configName | quote}}
address_list: {{ .Values.configCA.gatewayName }} ## override with gateway
gitRepoConfig:
url: 'http://<your repo url>'
path: '<path to reach your app and conf... usually just .>'
branch: 'main'
init: 'true'
start: '/epics/ioc/config/start.sh'
destination:
server: 'https://kubernetes.default.svc'
namespace: {{ .Values.namespace | quote }}
syncPolicy:
automated:
prune: true # Optional: Automatically remove resources not specified in Helm chart
selfHeal: true |
address_list, so that it can be found from interface and servicesInstall Phoebus: Phoebus Setup.
If you want to develop the OPI for your IOC however each K8S ECS installation has in its GIT Control Source project a directory opi (that is a git subproject with other subproject) that contain a Launcher.bob and a start.sh, this setup is intended to start the main control interface of a given beamline.
If you are developing an gui interface that must be integrated in the control a OPI Development Workflow must be followed.