Container Virtualization for PANDA DCS

Usefull links:

Docker Container

The PANDA DCS Software will be distributed and maintained using Docker containers. All containers have been tested extensively under Debian 9-11.
The gateway and IOC containers were also tested under Windows 10 (only connection to network devices!)

For a deeper look in the docker build process, you might have a look at the build repository https://panda-repo.gsi.de/f.feldbauer/epics-docker.

Images

epics-ioc

The epics-ioc image is based on a minimal Debian Bullseye image and contains the complete EPICS installation including the following device support modules:
  • asyn
  • autosave
  • calc
  • modbus
  • devSnmp
  • StreamDevice
  • drvAsynI2C (only tags with `-sbc`)
  • devGpio (only tags with `-sbc`)
  • iocStats

The image is available for amd64, aarch64 and arm/v7

Usage

Default run command (standalone):
docker run -dit -v <LOCAL_DIR>:/config --name <NAME_OF_CONTAINER> [OPTIONS] paluma.ruhr-uni-bochum.de/epics/ioc <IOC_STARTUP_SCRIPT>

The epics-ioc image works with Volumes. With volumes you can mount a local directory from your host system into the Docker container (see `-v` option).
You need a directory on your host containing the IOC startup script, and substitution files which is mounted at `/config`
An IOC startup script looks like this
#!/epics/ioc/bin/linux-<ARCH>/epicsIoc

epicsEnvSet( "STREAM_PROTOCOL_PATH", "/epics/ioc/protocols/" )

## Register all support components
dbLoadDatabase( "/epics/ioc/dbd/epicsIoc.dbd", 0, 0 )
epicsIoc_registerRecordDeviceDriver( pdbbase )

## Load device drivers
[...]

## Load record instances
[...]

iocInit()

The preinstalled database files provided with this Docker image are located at `/epics/databases` within the container's filesystem. A list of all available database and protocol files can be found on the PANDA Gitlab server.

To run commands within the IOC container use
docker attach <CONTAINER_ID/NAME>

and you should see the EPICS IOC command prompt.
To detach from the container again use `CTRL+p CTRL+q`

OPTIONS:

  • Add a host device to the container:
    --device <DEVICENAME>[:<NAME_INSIDE_CONTAINER>]
    # e.g. --device /dev/ttyS0      ## add serial port0 to container
    # e.g. --device /dev/gpiochip0  ## add gpio interface to container (this is mandatory for the `-sbc` tagged images)
  • Add user inside container to a group:
    --group-add $(getent group | grep <GROUPNAME> | cut -d ":" -f 3)
    # e.g. --group-add $(getent group | grep gpio | cut -d ":" -f 3)  ## add the user inside the container to the host's gpio group
  • Connect to ethernet devices:
    Works without any additional settings
  • Connect to CAN bus devices:
    --network host
  • Access PVs from remote:
    • -p 5064-5065:5064-5065 -p 5064-5065:5064-5065/udp # for CA
    • --network host # for PVaccess
  • Access remote PVs:
    • -e EPICS_CA_AUTO_ADDR_LIST=no -e EPICS_CA_ADDR_LIST=<LIST OF IP ADDRESSES> # for CA
      UDP broadcasts are not forwarded by Docker's default network (bridge). Setting `EPICS_CA_ADDR_LIST` to the broadcast address (e.g. `192.168.0.255`) does not work.
      Alternatively use `--network host`
    • --network host # for PVaccess

Tags

  • 2.0.0, 2, latest
    based on epics-base 7.0.6.1, asyn 4.42 with FTDI support, autosave 5.10.2, calc 3.7.4, modbus 3.2, devSnmp 1.1.0.2, StreamDevice 2.8.22, iocStats 3.1.16, devThmpLedPulser 1.0.0
  • 2.0.0-sbc, 1-sbc, latest-sbc
    based on epics-base 7.0.6.1, asyn 4.42 with FTDI support, autosave 5.10.2, calc 3.7.4, modbus 3.2, devSnmp 1.1.0.2, StreamDevice 2.8.22, drvAsynI2C 1.0.3, devGpio 2.0.0, iocStats 3.1.16, devThmpLedPulser 1.0.0

ca-gateway

Docker Image providing the Channel Access gateway.

The image is available for amd64, aarch64 and arm/v7

Usage

Default run command (PC with two NICs required):
docker run -d --network host -v <LOCAL_DIR>:/config paluma.ruhr-uni-bochum.de/epics/ca-gateway /gateway -cip <CLIENT IP> -sip <SERVER IP> -pvlist <PVLIST_FILE> -access <ACCESS_FILE>

The ca-gateway image works with Volumes. With volumes you can mount a local directory from your host system into the Docker container (see `-v` option).
You need a directory on your host containing the gateway configuration (access file and pvlist) which is mounted at `/config`

The CLIENT IP is the broadcast address of the network with the IOCs, the SERVER IP is the local IP address of the network to the supervisory layer.

Tags

  • 2.1.3.0, 2, latest

phoebus

The phoebus image provides the Phoebus GUI toolchain, to create, edit and run OPIs.

Usage

Default run command (standalone)

docker run --network host -e DISPLAY=$DISPLAY --device /dev/dri -v <LOCAL_DIR>:/config -v /tmp/.X11-unix:/tmp/.X11-unix paluma.ruhr-uni-bochum.de/epics/phoebus -settings <CONFIG_FILE>

On the host system a user with `UID=1000` has to exists with read/write access to the X server of the host system.

The phoebus image works with Volumes. With volumes you can mount a local directory from your host system into the Docker container (see `-v` option).
You need a directory on your host containing the display files and custom configuration settings which is mounted at `/config`

Tags

  • 4.6.9, 4, latest

archive-engine

The archive-engine image provides the Phoebus RDB archiver.

Usage

Default run command (standalone):

docker run -d -v <LOCAL_DIR>:/config -p 4812 paluma.ruhr-uni-bochum.de/epics/archive-engine -engine <ENGINE> -settings <CONFIG_FILE>

The archive-engine image works with Volumes. With volumes you can mount a local directory from your host system into the Docker container (see `-v` option).
You need a directory on your host containing custom configuration settings and engine-configuration file(s) which is mounted at `/config`

When the container is started for the first time, any `*.xml` files present in `/config` are imported as new engines into the archiver configuration (using `-replace_engine -steal_channels`). The basename of the xml-files is used as engine name.

The CA address list must be configured manually in settings file (or use `--network host`).

Tags

  • 4.6.9, 4, latest

sncseq base image

This is a base image to create Docker images for sequencer programs and cannot be used directly. The Sequencer programs are collected at our PANDA Gitlab server

The image is available for amd64, aarch64 and arm/v7

Examples of using the epics-ioc

Hameg HMP4040 LV Power Supply

  1. Install Docker (refer to the links at the top of this page!)
  2. Create a directory, where you will store the needed configuration files for our IOC (e.g. `${HOME}/hameg_demo`)
  3. Now create a file called "hameg_demo.sub" inside this newly created directory with the following content to get access to all for channels of this device
    file "/epics/ioc/databases/hmp4040.db"
    {
      pattern { CHAN, PORT }
        { 0, hmp_1 }
        { 1, hmp_1 }
        { 2, hmp_1 }
        { 3, hmp_1 }
    }
  4. The HMP4040 has two interfaces for remote control: USB and Ethernet. I will discuss both
    1. USB:
      1. Connect the HMP4040 to our PC via USB. Under linux, the device will show up under `/dev/ttyAMA0` or similar.
      2. Now we need a startup script for our EPICS IOC, which opens the serial interface and configures it so we can talk to the HMP4040. The default settings of the HMP4040 is 8N1 at 9600baud.
        Create a file "hameg_demo.cmd" within the directory we created at the beginning:
        #!/epics/ioc/bin/linux-x86_64/epicsIoc
        
        epicsEnvSet( "STREAM_PROTOCOL_PATH", "/epics/ioc/protocols/" )
        
        ## Register all support components
        dbLoadDatabase( "/epics/ioc/dbd/epicsIoc.dbd", 0, 0 )
        epicsIoc_registerRecordDeviceDriver( pdbbase )
        
        ## Connect to R&S HMP4040 with HO732 via usb-serial interface
        drvAsynSerialPortConfigure( "hmp_1", "/dev/ttyS0", 0, 0, 0 )
        asynSetOption( "hmp_1", 0, "baud", "9600" )
        asynSetOption( "hmp_1", 0, "bits", "8" )
        asynSetOption( "hmp_1", 0, "parity", "none" )
        asynSetOption( "hmp_1", 0, "stop", "1" )
        asynSetOption( "hmp_1", 0, "clocal", "Y" )
        asynSetOption( "hmp_1", 0, "crtscts", "N" )
        asynSetOption( "hmp_1", 0, "ixon", "N" )
        asynSetOption( "hmp_1", 0, "ixoff", "N" )
        asynSetOption( "hmp_1", 0, "ixany", "N" )
        
        ## Load record instances
        dbLoadTemplate ( "/config/hameg_demo.sub" )
        
        iocInit()
      3. Note in the file above: the first parameter of `drvAsynSerialPortConfigure` is an internal name for the newly created device handle. This has to be the same name we used in our "hameg_demo.sub" as value for the PORT macro.
        This startup script now creates a handle for the serial port at "/dev/ttyAMA0", configures this port and afterwards loads all needed records via the substitution file we created in the beginning.
      4. Now start the docker container to run your IOC:
        docker run -dit --name hamer-demo -v ${HOME}/hameg_demo:/config --device /dev/ttyS0 paluma.ruhr-uni-bochum.de/epics/ioc:latest /config/hameg_demo.cmd
    2. Ethernet:
      1. Connect the HMP4040 to our PC via Ethernet cable. You need a DHCP server and need to get the IP address assigned to the HMP4040 (e.g. 192.168.0.5)
      2. Now we need a startup script for our EPICS IOC, which opens a TCP/IP port to the HMP4040.
        Create a file "hameg_demo.cmd" within the directory we created at the beginning:
        #!/epics/ioc/bin/linux-x86_64/epicsIoc
        
        epicsEnvSet( "STREAM_PROTOCOL_PATH", "/epics/ioc/protocols/" )
        
        ## Register all support components
        dbLoadDatabase( "/epics/ioc/dbd/epicsIoc.dbd", 0, 0 )
        epicsIoc_registerRecordDeviceDriver( pdbbase )
        
        ## Connect to R&S HMP4040 with HO732 via ethernet
        drvAsynIPPortConfigure( "hmp_1", "192.168.0.5:5025 TCP", 0, 0, 0 )
        
        ## Load record instances
        dbLoadTemplate ( "/config/hameg_demo.sub" )
        
        iocInit()
      3. Note in the file above: the first parameter of `drvAsynIPPortConfigure` is an internal name for the newly created device handle. This has to be the same name we used in our "hameg_demo.sub" as value for the PORT macro.
      4. This startup script now creates a TCP/IP connection to the HMP4040 and loads all needed records via the substitution file we created in the beginning.
      5. Now start the docker container to run your IOC:
        docker run -dit --name hamer-demo -v ${HOME}/hameg_demo:/config paluma.ruhr-uni-bochum.de/epics/ioc:latest /config/hameg_demo.cmd

Wiener PL5xx and Wiener MPOD LV power supplies (SNMP)

  1. Install Docker (refer to the links at the top of this page!)
  2. Create a directory, where you will store the needed configuration files for our IOC
  3. Connect the Wiener MPOD (or PL5xx) via ethernet to your PC and look up the IP address of the device (e.g. 192.168.0.5)
  4. Now create a file called "wiener_demo.sub" inside this newly created directory with the following content to get access to channels 'u0' and 'u1' of this device. The macro CRATE is either the hostname or the IP address of the MPOD crate.
    file "/epics/ioc/databases/WienerPL500.db"
    {
      pattern { H, N, CRATE, CH }
        { LMD, MUPIX:LV:P0:H1, 192.168.0.5, u0 }
        { LMD, MUPIX:LV:P0:H2, 192.168.0.5, u1 }
    }
  5. Now create the startup script for the IOC
    #!/epics/ioc/bin/linux-x86_64/epicsIoc
    
    epicsEnvSet( "STREAM_PROTOCOL_PATH", "/epics/ioc/protocols/" )
    epicsEnvSet( "WCR",  "guru WIENER-CRATE-MIB::" )
    
    ## Register all support components
    dbLoadDatabase( "/epics/ioc/dbd/epicsIoc.dbd", 0, 0 )
    epicsIoc_registerRecordDeviceDriver( pdbbase )
    
    dbLoadTemplate ("/config/wienerpl_demo.sub" )
    
    iocInit()
  6. Now start the docker container to run your IOC:
    docker run -dit -v ${HOME}/wiener_demo:/config --name snmp-demo paluma.ruhr-uni-bochum.de/epics/ioc:latest /config/wiener_demo.cmd
-- PeterZumbruch - 12 Nov 2019
-- FlorianFeldbauer - 01 Jul 2022
Topic revision: r25 - 2022-08-23, UdoKurilla
Copyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Panda Wiki Send feedback | Imprint | Privacy Policy (in German)