...
https://baltig.infn.it/infn-epics
httpshtps://baltig.infn.it/epics-containers
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
docker run --network=host -v .:/epics/ioc/config -it baltig.infn.it:4567/epics-containers/infn-epics-ioc |
IBEK support and "IBEKisation step"
To allow an easy portability of a IOC (in particular IOC that can run inside containers) once an IOC or support is ready and tested, the next step is the DiamonLightSsource "ibekization". This steps in few words allows to instantiate a general st.cmd with support through a simple YAML file.
1- Add a new support in infn-epics-ioc
Once your IOC has its own GIT project, clone the infn-epics-ioc project that is the project the build the container with all IOC supports for infn.
...
This project contains the following layout:
infn-epics-ioc directory tree
| Anchor | ||||
|---|---|---|---|---|
|
| Code Block | ||||
|---|---|---|---|---|
| ||||
├── Dockerfile <-- 2 file where to add the new support this file will create the docker image ├── Dockerfile.all ├── Dockerfile.base ├── LICENSE ├── README.md ├── build ├── build-base ├── epics-support-template-infn <-- JNJA2 templates for not ibekizable supports ├── ibek-support <-- DLS base ibek-support ├── ibek-support-infn <-- 1 INFN specific ibek supports ADD NEW support HERE ├── ibek-templates <-- 3 JNJA2 templates to generalize, make sophisticated templates and allow parameters to be given |
To add a support:
├── tests <-- 4 test directory
|
2- Create support directory
Suppose your new support is named <mynewsupportname>
create add a directory in ibek-support-infn/<mynewsupportname> this directory must contain two files (:
- mynewsupportname.ibek.support.yaml
- mynewsupportname.install.yml
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
ibek-support-infn │ ├── mynewsupportname │ │ ├── mynewsupportname.ibek.support.yaml <== here the st.cmd yaml translation instruction │ │ ├── mynewsupportname.install.yml <== here the instruction to install │ ├── Tektronix_MSO58LP │ │ ├── Tektronix_MSO58LP.ibek.support.yaml │ │ └── Tektronix_MSO58LP.install.yml |
3- Create the install support file mynewsupportname.install.yml
mynewsupportname.install.yml
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
# yaml-language-server: $schema=../../ibek-support/_scripts/support_install_variables.json module: mynewsupportname ## your git project name version: devel ## your reversion/tag # this module uses modbus so requires none of its own libs/dbds organization: https://github.com/infn-epics/ ## your git organization name dbds: ## here the dbds used by your ioc/support - asyn.dbd - stream.dbd - calc.dbd - asSupport.dbd - sscan.dbd - <mynewsupportname>.dbd libs: #here - asyn - stream - calc - autosave - sscan <mynewsupportname>Support -## <mynewsupportname>Support ## if you have support libs protocol_files: - db/<mynewsupportname>.proto ## if you have protocols file |
4- Create the support file mynewsupportname.ibek.support.yml
mynewsupportname.ibek.support.yaml
Here you have to instruct how the yaml expand in the st.cmd of your IOC. For example:
| Code Block | ||||
|---|---|---|---|---|
| ||||
# yaml-language-server: $schema=https://github.com/epics-containers/ibek/releases/download/3.1.2/ibek.support.schema.json module: caenelsmynewsupportname entity_models: - name: histarmycontroller description: |- ThisCreate willa create an instance of CAENELS HiStar PSmy controller parameters: Pname: type: strid description: Device Prefix|- R: The name of the type:controller str and its Asyn Port Name description: Device Suffix P: type: str description: |- Device PV Prefix IP: type: str description: |- IP address of the Power Supplyethernet2serial default: 127.0.0.1 ## localhost TCPPORT: type: int description: |- TCP PORTPort of the Power Supplyethernet2serial default: 100014001 rangeASYNPRIO: type: int description: |- ASYN PRIORITY, CurrentDefault channels: range0 default: 30 0 OMAXAUTOCONNECT: type: int description: |- OutputAsyn auto MAXconnect default: 0 : Auto connection IMAX: 1: no type:Auto intconnection descriptiondefault: |-0 NOPRECESSESOS: Current MAX defaulttype: 0 int pre_init: - valuedescription: |- drvAsynIPPortConfigure("{{R}}_ASYN", "{{IP}}:{{TCPPORT}}", 0,0,0)ASYN noProcessEos, Default : 0 epicsEnvSet "STREAM_PROTOCOL_PATH", "/epics/support/configure/protocol/" https://epics.anl.gov/tech-talk/2020/msg01705.php databases: - filedefault: caenels-hs.db0 argsTPG_UNDERRANGE_ALARM_SEVERITY_A1: type: P:enum description: |- R: PORT: '{{R}}_ASYN' underrange severity A1 RANGEvalues: '{{range}}' ## unimag interface overlayMINOR: - fileMAJOR: unimag-histar.db argsNO_ALARM: default: MINOR P: R: TPG_UNDERRANGE_ALARM_SEVERITY_A2: - name: fastps descriptiontype: |-enum This will create an instance of CAENELS FASTPS description: |- parameters: underrange severity P:A2 typevalues: str description: Device PrefixMINOR: R MAJOR: typeNO_ALARM: str descriptiondefault: Device SuffixMINOR IPTPG_UNDERRANGE_ALARM_SEVERITY_B1: type: strenum description: |- IP address ofunderrange theseverity Power Supply defaultvalues: 127.0.0.1 ## localhost TCPPORTMINOR: type: int description: |-MAJOR: TCP PORT of the Power SupplyNO_ALARM: default: 10001MINOR rangeITPG_UNDERRANGE_ALARM_SEVERITY_B2: type: intenum description: |- Currentunderrange channelsseverity range defaultvalues: 30 rangeV: MINOR: type: int description: |-MAJOR: Voltage channels rangeNO_ALARM: default: 20MINOR OMAX: type: intpre_init: - descriptionvalue: |- drvAsynIPPortConfigure("{{name}}", "{{IP}}:{{TCPPORT}}", 0, Output0, MAX0) default: 0 epicsEnvSet "STREAM_PROTOCOL_PATH", "/epics/support/configure/protocol/ IMAXdatabases: - typefile: int<mymodule1>.db descriptionargs: |- CurrentP: MAX default PORT: 0 '{{name}}' pre_init: - value: |TPG_UNDERRANGE_ALARM_SEVERITY_A1: drvAsynIPPortConfigure("{{R}}_ASYN", "{{IP}}:{{TCPPORT}}", 0,0,0)TPG_UNDERRANGE_ALARM_SEVERITY_A2: epicsEnvSet "STREAM_PROTOCOL_PATH", "/epics/support/configure/protocol/" TPG_UNDERRANGE_ALARM_SEVERITY_B1: databases: - file: fastps.dbTPG_UNDERRANGE_ALARM_SEVERITY_B2: args: - name: mychannel Pdescription: |- Template database for Ra channel parameters: controller: PORT type: '{{R}}_ASYN'object description: |- RANGEI: '{{rangeI}}' a reference to RANGEV: '{{rangeV}}' the controller name: ## unimag interfacetype: overlaystr - filedescription: unimag|-fastps.db args: channel prefix Pchannel: type: R: enum description: |- Channel values: A1: A2: B1: B2: TPG_UNDERRANGE_ALARM_SEVERITY: type: enum description: |- underrange severity values: MINOR: MAJOR: NO_ALARM: default: MINOR databases: - file: $(MYMODULENAME)/mydb2.template args: P: '{{controller.P}}' NAME: '{{name}}' CHAN: '{{channel}}' PORT: '{{controller.name}}' TPG_UNDERRANGE_ALARM_SEVERITY: |
5- Add the new support to the container
Edit Dockerfile and add two lines for mynewsupportname
| Code Block | ||||
|---|---|---|---|---|
| ||||
.....
COPY ibek-support-infn/motorMicos motorMicos/
RUN ansible.sh motorMicos
COPY ibek-support-infn/cagateway cagateway
RUN ansible.sh cagateway
COPY ibek-support-infn/mynewsupportname mynewsupportname ## NEW support
RUN ansible.sh mynewsupportname ##
|
6- Build the container inside VScode
CTRL(or Command)+Shift+P (Rebuild Container or open directory in container)
If the build succeed your support has been re-compiled successfully, otherwise check the errors.
7- Create/update a JNJA2 template that use your new support
Your new support to be instantiated needs a YAML that parametrize the values that you defined in your support so for instance for your support a valid YAML could be:
| Code Block | ||||
|---|---|---|---|---|
| ||||
iocname: mynewioc
description: test
entities:
- type: mynewsupportname.mycontroller
name: MYCONTROLLER
P: "MYBEAMLINE:TEST"
IP: "192.168.1.1"
TCPPORT: 4001
- type: mynewsupportname.mychannel
controller: MYCONTROLLER
name: "PIPPO"
channel: A1
|
Normally a particular module/IOC is re-used multiple time and may include many different types/cases instead to have many YAMLs to configure each of them a single JNJA2 template is written yaml.j2 JNJA2 is a powerful preprocess language that may be applied to any form of text to perform substitutions, logic and flow, it's used in many contextes to create templates.
So the previous YAML can be templated to be used by EPIK8S. In particular the yaml (deploy/values.yaml) that describes your EPIK8s beamline will initialize your template.
| Code Block | ||||
|---|---|---|---|---|
| ||||
iocname: {{iocname}}
description: Templated test
entities:
- type: {{devtype}}.controller
name: MYCONTROLLER
P: "{{iocprefix}}"
IP: {{server}}
TCPPORT: {{[port}}
{%- for t in devices %}
- type: {{devtype}}.channel
controller: MYCONTROLLER
name: "{{ t.name }}"
channel: {{ t.channel }}
{%- endfor %}
|
8- Test your support with template
copy or update ibek-templates/templates directory
Once your have prepared your mynewsupportname.yaml.j2 place in a suitable directory inside ibek-templates/templates see infn epics ioc directory tree. For example if mynewsupportname belongs to the VAC subsystem an updated or new entry must be created into ibek-templates/templates/vac.
If it is an update the content of your mynewsupportname.yaml.j2 must be added to an existing template file adding for instance a new model of VAC of an existing template. If the support is completely new and for instance represent the first of a series of support a new directory can be created and the support file mynewsupportname.yaml.j2 copied in such directory.
Suppose the mynewsupportname is a completely new file.
update your deploy/values.yaml beamline description file
Copy your current epik8s beamline file deploy/values.yaml file in the tests directory see infn epics ioc directory tree. Add in some point of the ioc list your new ioc like that:
| Code Block | ||||
|---|---|---|---|---|
| ||||
- name: "caenelsfast"
asset: "https://confluence.infn.it/x/nYD8DQ"
charturl: 'https://baltig.infn.it/epics-containers/ioc-chart.git'
.....
- name: "mynewIOCNAME" ## replace parameter iocname
asset: "https://confluence.infn.it/x/nYD8DQ"
charturl: 'https://baltig.infn.it/epics-containers/ioc-chart.git'
iocprefix: "SPARC:MAG:HZ" ### replace parameter iocprefix
iocparam:
- name: "server" ### replace generic parameter server
value: "192.168.197.102"
- name: "port" ### replacegeneric parameter port
value: "4001"
autosync: false ## restart automatically on changes
devtype: "mynewsupportname" ### a template file may contain different device types
devgroup: mag
opi: "mynewsupportname"
template: "mynewsupportname" ## or the name of the directory or file where your new template is
networks:
- name: "control"
annotation: "sparc-magnets"
devices: ## device list parameters that will be replaced in your template
- name: "GUN01"
channel: "6"
- name: "AC1SOL01"
channel: "7"
- name: "AC1SOL02"
channel: "8"
|
test using epik8s-run
Inside the container terminal launch the utility epik8s-run that execute things as the EPIK8s will do:
| Code Block | ||||
|---|---|---|---|---|
| ||||
rm /epics/ioc/config/* ## remove previous configs
epik8s-run tests/values.yaml mynewIOCNAME --native
|
This utility will take from your beamline values the ioc instance mynewIOCNAME will create a yaml using the template you wrote and will call the ibek utility to generate an ioc instance following the ibek support that you did.
So it tests a lot of things together and probably some error will be detected, even if most of typo errors can be avoided using vscode yaml schema.
Once the IOC starts everything can be committed step 9.
It's possible to check the yaml result of instantiation in /epics/ioc/config the yaml has the name like the template without .j2.
| Code Block | ||||
|---|---|---|---|---|
| ||||
rm /epics/ioc/config/* ## remove previous configs
## the following will perform replacement and start the ioc
epik8s-run tests/values.yaml mynewIOCNAME --native
## check yaml
more /epics/ioc/config/mynewsupportname.yaml
## the resulting st.cmd after ibek instantiation of mynewsupportname.yaml can be found in
more /epics/runtime/st.cmd
|
Chek Intermediate files generated
/epics/ioc/config/<mynewsupportname>.yaml resulting YAML after j2 replacement with parameters given from IBEK beamline/deploy/values.yaml
/epics/runtime/st.cmd resulting st.cmd after ibek replacement using the support mynewsupportname
| Code Block | ||||
|---|---|---|---|---|
| ||||
more /epics/ioc/config/mynewsupportname.yaml
more /epics/runtime/st.cmd
|
9- Commit, Tag to create a new image
ibek-infn-support and ibek-templates are git subproject so to add your new support you should go in the directories:
| Code Block | ||||
|---|---|---|---|---|
| ||||
cd ibek-infn-support
git status
git add <mynewsupportname>
git commit -m "my first beautiful ibek support" .
git checkout main
git merge <hash/branch>
git push origin
cd ..
cd ibek-templates/templates
git add <mynewsupportdircontent>
git commit -m "my first beautiful ibek template" .
git checkout main
git merge <hash/branch>
git push origin
## now commit and push the epics-infn-ioc main project
cd ../../
git commit -m "my first beautiful support" .
git checkout main
git merge <hash/branch>
git push origin
## to create a new image a tag must be created
## list tags
git tag
git tag <last tag + 1 in minor or +1 in bump release (something temporary) <tag>b xx
git push origin <tagname created> |
Release tags convention
The ufficial tags should have the following format : v<year>.<month>.<day> the test tags or fix during a day must have the suffix <bincremental number>
Deploy on the target EPIK8S
...