Skip to content

Commit d88bca4

Browse files
committed
update Create Generic IOC
1 parent 71e5725 commit d88bca4

File tree

1 file changed

+82
-88
lines changed

1 file changed

+82
-88
lines changed

docs/tutorials/generic_ioc.md

Lines changed: 82 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ StreamDevice/install.sh 2.8.26
158158

159159
This uses ibek-support 'recipes' to pull the two support modules from GitHub and builds them in our devcontainer. Now any IOC instances we run in the devcontainer will be able to use these support modules.
160160

161+
Having run the above commands you could look in **/epics/support** to see the additional built support modules.
162+
161163
Next, make sure that the next build of our `ioc-lakeshore340` container image will have the same support built in by updating the Dockerfile as follows:
162164

163165
```dockerfile
@@ -186,13 +188,9 @@ order to do so we must first add a recipe for it to `ibek-support`.
186188
The `ibek-support` submodule is used to share information about how to build
187189
and use support modules. It contains three kinds of files:
188190
189-
1. install.sh - These are used to fetch and build support modules. They are
190-
run from the Dockerfile as described above.
191-
2. IBEK support module `definitions`: These are used to help IOCs build their
192-
iocShell boot scripts and EPICS Database from YAML descriptions.
193-
3. PVI definitions: These are used to add structure to the set of PV's a
194-
device exposes. This structure allows us to auto-generate engineering
195-
screens for the device. See <https://github.com/epics-containers/pvi>.
191+
1. install.sh - These are used to fetch and build support modules. They are run from the Dockerfile as described above.
192+
2. IBEK support YAML: These are used to help IOCs build their iocShell boot scripts and EPICS Database from YAML descriptions. These are the files that contribute to the schema used when making an ioc.yaml instance file for this Generic IOC.
193+
3. PVI definitions: These are used to add structure to the set of PV's a device exposes. This structure allows us to auto-generate engineering screens for the device. See <https://github.com/epics-containers/pvi>.
196194

197195
`ibek-support` is curated for security reasons, therefore we need to work with
198196
a fork of it so we can add our own recipe for lakeshore340. If you make changes
@@ -219,13 +217,14 @@ cd ..
219217

220218
We are using the `tutorial-KEEP` branch which is a snapshot of the `ibek-support` state
221219
appropriate for this tutorial. Normally you would use the `main` branch and
222-
then create your own branch off of that to work in.
220+
then create your own branch off of that to work in, therefore you could skip the `git checkout tutorial-KEEP` line and instead do `git checkout -b my-new-feature-branch; git push -u origin my-new-feature-branch`.
223221

224222
:::{note}
225223
IMPORTANT: we used an *HTTPS* URL for the `ibek-support` submodule, not
226224
a *SSH* URL. This is because other clones of `ioc-lakeshore340` will not
227-
be guaranteed to have the required SSH keys. HTTPS is fine for reading, but
228-
to write you need SSH. Therefore add the following to your `~/.gitconfig`:
225+
be guaranteed to have the required SSH keys (i.e. when CI is running).
226+
227+
HTTPS is fine for reading, but to write you need SSH. Therefore add the following to your `~/.gitconfig`:
229228

230229
```
231230
[url "ssh://[email protected]/"]
@@ -244,31 +243,31 @@ a particular commit (until updated with `git pull`) see
244243

245244
The first file we will create is the `install.sh` script for lakeshore340. This is a simple script that fetches the support module from GitHub and builds it.
246245

247-
These scripts draw heavily on the `ibek` tool to do tasks that most support modules require. They are also are as close to identical as possible for simple support modules.
246+
These scripts draw heavily on the `ibek` tool to do common tasks that most support modules require. They are also are as close to identical as possible for simple support modules. `ibek` commands allow us to have a simple, consistent structure for all support module's `install.sh` scripts.
248247
249248
IMPORTANT points to note are:
250249
251250
- Although we are using `ibek` we are really just automating what an EPICS engineer would do manually. This is very much using the vanilla EPICS build system that comes with EPICS base, along with the vanilla Make and Config files that come with each support module. These steps are:-
252251
253252
- make sure we have the necessary system dependencies installed
254-
- fetch a version of the support module from GitHub
253+
- fetch a version of the support module from GitHub or other source
255254
- add a RELEASE.local to enable dependency resolution
256255
- optionally add CONFIG_SITE.local to apply settings for the build environment
257256
- run make to build the support module
258-
- take a note of the dbds and libs that we build so that we can use them
259-
to make our IOC instance later
257+
- take a note of the dbds and libs that we build so that we can link them in to our Generic IOC build later
260258
261259
- This is a bash script so although we encourage a very standard structure,
262260
you can do anything you like. For example this support module has to
263261
compile a 3rd party library before it can build the support module itself.
264-
[ADAravis install.sh](https://github.com/gilesknap/ibek-support/blob/46fd9394f6bf07da97ab7971e6b3f09a623a42f6/ADAravis/install.sh#L17-L44)
262+
[ADAravis install.sh](https://github.com/gilesknap/ibek-support/blob/72eaec2cfd9b2f51f20b7b2b34eeab7c0f51a0cd/ADAravis/install.sh#L17-L44)
265263
266264
To make your lakeshore340 install.sh script:
267265
268266
```bash
269267
cd /workspaces/ioc-lakeshore340/ibek-support
270268
mkdir lakeshore340
271-
cp iocStats/install.sh lakeshore340/install.sh
269+
# use the relatively simple calc install.sh as a template
270+
cp calc/install.sh lakeshore340/install.sh
272271
code lakeshore340/install.sh
273272
```
274273
@@ -278,21 +277,21 @@ The changes required for any support module you care to build would be:
278277
279278
- change the NAME variable to match the name of the support module
280279
281-
- add in `ibek support apt-install` lines for any system dependencies.
282-
These can be for the developer stage or the runtime stage or both.
280+
- add in `ibek support apt-install` lines for any build time system dependencies. Also add `ibek support add-runtime-packages` for any runtime dependencies (runs apt-get install in the runtime stage).
283281
284-
- change the `ibek support add-*` lines to declare the libs and DBDs
285-
that this module will publish.
282+
- change the `ibek support add-*` lines to declare the libs and DBDs that this module will publish. For this StreamDevice module we don't need to add any libs or DBDs.
286283

287-
- add extra release macros for RELEASE.local (the RELEASE macro for
288-
the current support module is added automatically). Or add
289-
CONFIG entries for CONFIG_SITE.local as required.
290-
None of these were required for lakeshore340. To see how to use these
291-
functions see
284+
- add extra release macros for RELEASE.local (the RELEASE macro for the current support module is added automatically). Or add CONFIG entries for CONFIG_SITE.local as required. None of these were required for lakeshore340. To see how to use these functions see
292285

293286
- ibek support add-release-macro --help
294287
- ibek support add-to-config-site --help
295288

289+
- occasionally we will use `sed` to modify files in the support module. In particular it is sometimes beneficial to comment out some of the lines in the root Makefile in order to skip over test and documentation building. This is done in the script below for the lakeshore340 documentation. Note that the sed command is idempotent, so it is safe to run the script more than once.
290+
291+
- To see all commands for assisting in building support modules see **ibek support --help**
292+
293+
- NOTE: all of the ibek support commands are idempotent. Therefore it is safe to run install.sh more than once. This is an advantage of using ibek instead of hand coding the build process.
294+
296295
```bash
297296
#!/bin/bash
298297
@@ -305,18 +304,18 @@ FOLDER=$(dirname $(readlink -f $0))
305304
# log output and abort on failure
306305
set -xe
307306
308-
# doxygen is used in documentation build for the developer stage
309-
ibek support apt-install doxygen
310-
311307
# get the source and fix up the configure/RELEASE files
312308
ibek support git-clone ${NAME} ${VERSION} --org https://github.com/DiamondLightSource/
313-
314309
ibek support register ${NAME}
315310
316311
# declare the libs and DBDs that are required in ioc/iocApp/src/Makefile
317-
# None required for a stream device ------------------------------------
318-
#ibek support add-libs
319-
#ibek support add-dbds
312+
# NONE required for StreamDevice
313+
# ibek support add-libs
314+
# ibek support add-dbds
315+
316+
# comment out the documentation from the Makefile - idempotent because it searches
317+
# for lines not starting with # and inserts a # at the start of the line.
318+
sed -i -E 's/(^[^#].*documentation)/# \1/' ${SUPPORT}/${NAME}/Makefile
320319
321320
# global config settings
322321
${FOLDER}/../_global/install.sh
@@ -325,6 +324,8 @@ ${FOLDER}/../_global/install.sh
325324
ibek support compile ${NAME}
326325
# prepare *.bob, *.pvi, *.ibek.support.yaml for access outside the container.
327326
ibek support generate-links ${FOLDER}
327+
328+
328329
```
329330

330331
Having made these changes you can now test the script by running it:
@@ -354,43 +355,43 @@ an iocShell startup script and an EPICS Database. You can supply hand
354355
crafted `st.cmd` and `ioc.subst` files for this purpose. The Generic IOC
355356
we have made above is already capable of using such files.
356357

357-
For this exercise we will use the full capabilities of `ibek` to generate
358-
these files from a YAML description of the IOC instance. To do this we need
359-
to create a YAML file that describes what the instance YAML is allowed to
360-
make.
358+
For this exercise we will use the full capabilities of `ibek` to generate these files from a YAML description of the IOC instance. To do this we need to create a Support YAML file that describes what the instance YAML is allowed to make.
361359

362-
TODO: a detailed description of the YAML files' structure and purpose should
360+
The advantage of using YAML to describe your instances is that there is a considerable amount of validation that can be done on the YAML file to ensure that it is correct. Checking is done at the time of writing the YAML file, using a schema aware editor. More extensive checks are done in the CI of your services project when you push your IOC instance definition changes. Also, much of the complexity of using a given support module can be managed in a single place by the author of the YAML file.
361+
362+
**TODO**: a detailed description of the YAML files' structure and purpose should
363363
be included in the `ibek` documentation and linked here.
364364
The current version of this is here
365365
[entities](https://epics-containers.github.io/ibek/main/developer/explanations/entities.html)
366-
but it is rather out of date.
366+
but it is currently out of date.
367367
368-
To create an `ibek` support YAML file we need to provide a list of `definitions` .
369-
Each `definition` gives:
368+
To create an `ibek` support YAML file we need to provide a list of `entity_models` .
369+
Each `entity_model` gives:
370370
371-
- a name and description for the `definition`
371+
- a name and description for the `entity_model`
372372
373-
- a list of arguments that an
374-
instance of this `definition` may supply, with each having:
373+
- a list of parameters that an instance of this type of `entity` may supply, with each having:
375374
376375
- a type (string, integer, float, boolean, enum)
377376
- a name
378377
- a description
379378
- optionally a default value
380379
381-
- A list of database templates to instantiate for each instance of this `definition`
380+
- A list of database templates to instantiate for each instance of this `entity`
382381
\- including values for the Macros in the template
383382
384383
- A list of iocShell command line entries to add before or after `iocInit`
385384
386385
In all of the fields Jinja templating can be used to combine the values of
387386
arguments into the final output. At its simplest this is just the name of
388-
an argument in double curly braces e.g. `{{argument_name}}`. But, it can
387+
an argument in double curly braces e.g. `{{parameter_name}}`. But, it can
389388
also be used to do more complex things as a Python interpreter is evaluating
390389
the text inside the curly braces and that interpreter has the values of
391-
all the `definition` arguments available in its context.
390+
all the `entity` arguments available in its context.
392391
See <https://jinja.palletsprojects.com/en/3.0.x/templates/>
393392
393+
**TODO**: `ibek` also needs detailed documentation of the interfaces available to the Jinja interpreter. This is to include order of evaluation, what is available in the context, etc.
394+
394395
:::{note}
395396
IMPORTANT: the file created below MUST have the suffix `.ibek.support.yaml`.
396397
This means it is a support yaml file for `ibek`. This is important because
@@ -412,68 +413,64 @@ contents:
412413
413414
module: lakeshore340
414415
415-
defs:
416+
entity_models:
416417
- name: lakeshore340
417418
description: |-
418419
Lakeshore 340 Temperature Controller
419420
Notes: The temperatures in Kelvin are archived once every 10 secs.
420-
args:
421-
- type: str
422-
name: P
421+
parameters:
422+
P:
423+
type: str
423424
description: |-
424425
Prefix for PV name
425426
426-
- type: str
427-
name: PORT
427+
PORT:
428+
type: str
428429
description: |-
429430
Bus/Port Address (eg. ASYN Port).
430431
431-
- type: int
432-
name: ADDR
432+
ADDR:
433+
type: int
433434
description: |-
434435
Address on the bus
435436
default: 0
436437
437-
- type: int
438-
name: SCAN
438+
SCAN:
439+
type: int
439440
description: |-
440441
SCAN rate for non-temperature/voltage parameters.
441442
default: 5
442443
443-
- type: int
444-
name: TEMPSCAN
444+
TEMPSCAN:
445+
type: int
445446
description: |-
446447
SCAN rate for the temperature/voltage readings
447448
default: 5
448449
449-
- type: id
450-
name: name
450+
name:
451+
type: id
451452
description: |-
452453
Object and gui association name
453454
454-
- type: int
455-
name: LOOP
455+
LOOP:
456+
type: int
456457
description: |-
457458
Which heater PID loop to control (Default = 1)
458459
default: 1
459460
460-
databases:
461-
- file: $(LAKESHORE340)/db/lakeshore340.template
462-
args:
463-
name:
464-
SCAN:
465-
P:
466-
TEMPSCAN:
467-
PORT:
468-
LOOP:
469-
ADDR:
470-
471461
pre_init:
472462
- value: |
473463
epicsEnvSet "STREAM_PROTOCOL_PATH", "$(LAKESHORE340)/lakeshore340App/protocol/"
464+
465+
databases:
466+
- file: $(LAKESHORE340)/db/lakeshore340.template
467+
# use a regex to say that we want all the parameters in the template
468+
# this is equivalent to {P: '{{P}}', PORT: '{{PORT}}', ADDR: '{{ADDR}}', SCAN: '{{SCAN}}', TEMPSCAN: '{{TEMPSCAN}}', name: '{{name}}', LOOP: '{{LOOP}}'}
469+
args:
470+
.*:
474471
```
475472
476-
This file declares a list of arguments, one for each of the database template
473+
This file declares a list of parameters, one for each of the database template
477474
macros that it needs to substitute. It then declares that we need to instantiate
478475
the `lakeshore340.template` database template and passes all of the arguments
479476
verbatim to the template.
@@ -515,7 +512,7 @@ When a Generic IOC is built, each support module will register its support YAML
515512

516513
This registration process happens as part of the `install.sh` script for the support module. It is done by the `ibek support generate-links` command.
517514

518-
Here we just need to go ahead and re-run our `install.sh` script to register the lakeshore340 support YAML that we just created:
515+
Here we just need to go ahead and re-run our `install.sh` script to register the lakeshore340 support YAML that we just created. Because the ibek support commands are idempotent it is safe to run the `install.sh` script more than once.
519516

520517
```bash
521518
cd /workspaces/ioc-lakeshore340/ibek-support
@@ -573,11 +570,15 @@ Add the following contents to the new yaml file:
573570
```yaml
574571
# yaml-language-server: $schema=/tmp/ibek.ioc.schema.json
575572
576-
ioc_name: "{{ __utils__.get_env('IOC_NAME') }}"
573+
ioc_name: "{{ _global.get_env('IOC_NAME') }}"
577574
578-
description: auto-generated by https://github.com/epics-containers/builder2ibek
575+
description: example IOC for testing lakeshore340
579576
580577
entities:
578+
- type: epics.EpicsEnvSet
579+
name: EPICS_TZ
580+
value: GMT0BST
581+
581582
- type: devIocStats.iocAdminSoft
582583
IOC: "{{ ioc_name | upper }}"
583584
@@ -595,9 +596,9 @@ entities:
595596
name: lakeshore
596597
```
597598

598-
The above YAML file declares an IOC instance that has the following 3
599-
`entities` (which is what we call instances of `definitions` in `ibek`):
599+
The above YAML file declares an IOC instance that has the following 4 `entities` (which is what we call instances of `entity_models` in `ibek`):
600600

601+
- A EpicsEnvSet entity that sets the timezone for the IOC (because the compiled IOC is Generic - all instances need to set the timezone).
601602
- A devIocStats object that will supply monitoring PVs
602603
- An asyn IP port that will be used to talk to the simulator
603604
- A lakeshore340 object that will talk to the simulator via the asyn port
@@ -671,14 +672,7 @@ you can:
671672
672673
For the final step we will get the Generic IOC container image published to GHCR. This means committing all our changes and pushing them up to GitHub so that the Continuous Integration system can build the container image and publish it.
673674
674-
Before we do that we need to make sure our changes we have manually made inside the developer container will be applied at container build time. There is one thing we have done that is not yet added to the Dockerfile. That is the building of the lakeshore support module itself. Therefore we need to add the following lines to the Dockerfile just after the install of the `asyn` and `StreamDevice` support modules:
675-
676-
```dockerfile
677-
COPY ibek-support/lakeshore340/ lakeshore340/
678-
RUN lakeshore340/install.sh 2-6-2
679-
```
680-
681-
These commands will do the same install we did manually above. They rely on our new additions to the `ibek-support` submodule which shows that it is important to commit the submodule changes first before we push ioc-lakeshore340 repository to GitHub.
675+
Before we do that we need to make sure our changes we have manually made inside the developer container will be applied at container build time.
682676
683677
Perform the following commands to commit and push the changes:
684678
@@ -690,7 +684,7 @@ git commit -m "add lakeshore340 support module"
690684
git push -u origin my-lakeshore-branch
691685
692686
# now we can push up the ioc-lakeshore340 repository
693-
cd /workspaces/ioc-lakeshore340
687+
cd ..
694688
git add .
695689
git commit -m "add lakeshore340 support module and dependencies"
696690
# we are pushing to the main branch here - which is OK for a tutorial

0 commit comments

Comments
 (0)