{"config":{"separator":"[\\s\\-_,:!=\\[\\]()\\\\\"`/]+|\\.(?!\\d)"},"items":[{"location":"","level":1,"title":"Overview","text":"
Documentation for the SLS 2.0 High Level Applications Framework
","path":["Overview"],"tags":[]},{"location":"developer/ansible/","level":1,"title":"Ansible","text":"","path":["Developer","Ansible"],"tags":[]},{"location":"developer/ansible/#running-a-playbook-manually","level":2,"title":"Running a playbook manually","text":"Set vars on command line:
ansible-playbook ansible/playbooks/add-new-service.yml \\\n -i ansible/hosts.yml \\\n --extra-vars=\"repo_root=${{ github.workspace }} agebd_env=dev service_name_lower=<service dir name>\" \\\n -v\n","path":["Developer","Ansible"],"tags":[]},{"location":"developer/ansible/#install-an-ioc","level":3,"title":"Install an IOC","text":"ansible-playbook ansible/playbooks/ioc-install.yml \\\n -i ansible/hosts.yml \\\n --extra-vars=\"agebd_env=dev branch_name=feature/add-service-playground service_name_lower=playground ioc_port=50003\" \\\n -v\n","path":["Developer","Ansible"],"tags":[]},{"location":"developer/ansible/#start-an-ioc","level":3,"title":"Start an IOC","text":"ansible-playbook ansible/playbooks/ioc-start.yml \\\n -i ansible/hosts.yml \\\n --extra-vars=\"service_name_lower=playground ioc_port=50003\" \\\n -v\n","path":["Developer","Ansible"],"tags":[]},{"location":"developer/ansible/#restart-an-ioc","level":3,"title":"Restart an IOC","text":"ansible-playbook ansible/playbooks/ioc-restart.yml \\\n -i ansible/hosts.yml \\\n --extra-vars=\"agebd_env=dev branch_name=feature/add-service-playground service_name_lower=playground\" \\\n -v\n","path":["Developer","Ansible"],"tags":[]},{"location":"developer/caget/","level":1,"title":"Using caget to check the values of PVs","text":"ssh sls-lc\n On sls-lc or sls-vserv-bd-hla01-dev:
ca office network\nexport EPICS_CA_ADDR_LIST=\"129.129.130.255 129.129.131.255 129.129.137.255 129.129.158.255 129.129.217.255 129.129.150.255 129.129.152.255 sls-cagw.psi.ch:5062\"\ncaget AGEBD-PLAYGROUND-DEV:AO\n","path":["Developer","Using caget to check the values of PVs"],"tags":[]},{"location":"developer/cicd_runner/","level":1,"title":"CI/CD Runner","text":"","path":["Developer","CI/CD Runner"],"tags":[]},{"location":"developer/cicd_runner/#hosts","level":2,"title":"Hosts","text":"sls-vserv-bd-01(-dev)ioc install ...?)sls-vserv-bd-hla01(-dev)Resources:
Register the runner: (by default the name is the machine name sls-vserv-bd-hla01-dev.psi.ch)
sudo su svcusr-sls2hla\nmkdir ~/gitea-runner\ncd ~/gitea-runner\n/usr/local/bin/act_runner register --instance https://gitea.psi.ch/ --labels hla-dev --token <token> --no-interactive\n Note, if you use a systemd service with a config file as in the example below, the labels will be read from that file.
This generates a .runner file.
Set up deployment dirs (not directly related to the gitea cicd runner setup)
mkdir /sls/bd/hla\nchmod 755 /sls/bd/hla\n...\n Install Node -- required for actions like repo checkout
mkdir ~/.local/bin\n\ncd /tmp\ncurl -LO https://nodejs.org/dist/v20.11.1/node-v20.11.1-linux-x64.tar.xz\ntar -xf node-v20.11.1-linux-x64.tar.xz --strip-components=2 -C ~/.local/bin/ node-v20.11.1-linux-x64/bin/\nrm node-v20.11.1-linux-x64.tar.xz\n","path":["Developer","CI/CD Runner"],"tags":[]},{"location":"developer/cicd_runner/#manually-run-the-runner","level":2,"title":"Manually run the runner","text":"sudo su svcusr-sls2hla\n/usr/local/bin/act_runner daemon\n","path":["Developer","CI/CD Runner"],"tags":[]},{"location":"developer/cicd_runner/#run-the-runner-as-a-systemd-service","level":2,"title":"Run the runner as a systemd service","text":"Edit the service file /etc/systemd/system/act_runner.service:
[Unit]\nConditionPathExists=/etc/act_runner/config.yaml\nDescription=Gitea Actions runner\nDocumentation=https://gitea.com/gitea/act_runner\nAfter=podman.socket\nRequires=podman.socket\n\n[Service]\nUser=svcusr-sls2hla\nWorkingDirectory=/home/svcusr-sls2hla/gitea-runner\nEnvironment=\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/svcusr-sls2hla/.local/bin\"\nExecStart=/usr/local/bin/act_runner daemon --config /etc/act_runner/config.yaml\nExecReload=/bin/kill -s HUP $MAINPID\nTimeoutSec=0\nRestartSec=10\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n As your own user (not svcusr-sls2hla; need access to sudo):
# 1. Install Podman\nsudo dnf install -y podman\n\n# 2. Enable and start the system-wide Podman socket\nsudo systemctl enable --now podman.socket\n\n# 3. Create the symlink so the Gitea runner finds Podman at the expected Docker path\nsudo ln -s /run/podman/podman.sock /var/run/docker.sock\n\n# 4. Create podman group\nsudo groupadd podman\n\n# 5. Add service user to this new group\nsudo usermod -aG podman svcusr-sls2hla\n Configure podman socket:
sudo systemctl edit podman.socket\n add this to the file: [Socket]\nSocketMode=0660\nSocketGroup=podman\n Created uv cache dir, for UV_CACHE_DIR:
sudo mkdir -m 777 /var/cache/uv\n Change the location of the act cache and working directory (uv .venvs are built here, take up lots of space)
sudo mkdir -m 777 /var/lib/act_runner/cache\nsudo mkdir -m 777 /var/lib/act_runner/work\n and edit /etc/act_runner/config.yaml
cache:\n dir: \"/var/lib/act_runner/cache\"\nhost:\n # The parent directory of a job's working directory.\n # If it's empty, $HOME/.cache/act/ will be used.\n workdir_parent: \"/var/lib/act_runner/work\"\n Configure the runner labels: (edit /etc/act_runner/config.yaml)
runner:\n labels:\n - \"hla-dev\"\n Enable and restart:
# Enable act_runner\nsudo systemctl enable --now act_runner\n\n# Reload configurations\nsudo systemctl daemon-reload\n\n# Restart the socket so it applies the new group owner\nsudo systemctl restart podman.socket\n\n# Fire up the runner\nsudo systemctl restart act_runner.service\n","path":["Developer","CI/CD Runner"],"tags":[]},{"location":"developer/cicd_runner/#check-logs-of-systemd-service","level":3,"title":"Check logs of systemd service","text":"sudo su svcusr-sls2hla\njournalctl -u act_runner.service -n 20\n Should show
Jul 24 10:05:30 sls-vserv-bd-hla01-dev.psi.ch act_runner[3662214]: time=\"2026-07-24T10:05:30+02:00\" level=info msg=\"Starting runner daemon\"\nJul 24 10:05:30 sls-vserv-bd-hla01-dev.psi.ch act_runner[3662214]: time=\"2026-07-24T10:05:30+02:00\" level=info msg=\"labels updated to: [hla-dev:host]\"\nJul 24 10:05:30 sls-vserv-bd-hla01-dev.psi.ch act_runner[3662214]: time=\"2026-07-24T10:05:30+02:00\" level=info msg=\"runner: sls-vserv-bd-hla01-dev.psi.ch, with version: v2.0.0, with labels: [hla-dev], declare successfully\"\n...\n","path":["Developer","CI/CD Runner"],"tags":[]},{"location":"developer/cicd_runner/#user","level":2,"title":"User","text":"The gitea actions run as user svcusr-sls2hla
I created an ssh key on sls-vserv-bd-hla01-dev (where the runner runs), and added the public key to my gitea profile ssh keys. That way the svcusr can clone the repos I can clone.
ssh -J sls-lc -X labrec_b@sls-vserv-bd-hla01-dev.psi.ch\n also works?:
ssh hla-dev\n Macro substitution
caqtdm -m'TESTAGEBDALH=AGEBD-ALH' A_BD_ServiceManager.ui\n caqtdm does not exists when using svcusr-sls2hla
Check which network a host lives in, e.g. for sls-lca:
ping sls-lca.psi.ch\n","path":["Developer","Hosts overview"],"tags":[]},{"location":"developer/hosts/#machine-net-prod","level":3,"title":"Machine Net (prod)","text":"dev)","text":"TODO
","path":["Developer","HLA Framework BD"],"tags":[]},{"location":"developer/systemd-service/","level":1,"title":"Systemd Service","text":"","path":["Developer","Systemd Service"],"tags":[]},{"location":"developer/systemd-service/#check-all-logs","level":2,"title":"Check all logs","text":"sudo su svcusr-sls2hla\njournalctl --user -u AGEBD-SERVICE-MASTER.service\n","path":["Developer","Systemd Service"],"tags":[]},{"location":"developer/ioc/ioc/","level":1,"title":"IOC","text":"The following instructions explain the basics of starting and managing IOCs on the IOC host.
sls-vserv-bd-01(-dev)
Start up an IOC shell:
iocsh AGEBD-CPCL-MASTER_main.subs\n or:
ioc shell AGEBD-CPCL-MASTER-DEV\n then you can run commands to interact with EPICS.
List available PVs:
> dbl\n Exit:
Ctrl + d\n","path":["Developer","Ioc","IOC"],"tags":[]},{"location":"developer/ioc/ioc/#install","level":2,"title":"Install","text":"For existing IOCs, a login to the IOC and a restart via ctrl+x is sufficient.
On sls-lc*
ioc install -V --ioc AGEBD-CPCL-PLAYGROUND --clean\nioc shell AGEBD-CPCL-PLAYGROUND\nctrl+x\n For the initial install, additionally, the shellbox on the ioc host must be restarted.
sudo shellbox reload # new ioc installed\n Result: on ioc host, e.g. sls-vserv-bd-01-dev
vim /etc/shellbox/<port-number>\n","path":["Developer","Ioc","IOC"],"tags":[]},{"location":"developer/ioc/ioc/#local-tests","level":3,"title":"Local Tests","text":"iocsh AGEBD-CPCL-PLAYGROUND_main.subs\n using template file:
iocsh PLAYGROUND.template DEVICE=TEST\n","path":["Developer","Ioc","IOC"],"tags":[]},{"location":"developer/ioc/ioc/#delete","level":2,"title":"\"Delete\"","text":"There is no way to really delete an IOC through the ioc cli.
What you can do: ssh sls-lc* and delete the entry from /ioc/hosts/sls-vserv-bd-01(-dev)/shellbox.conf
On BD host sls-vserv-bd-01(-dev)
sudo shellbox reload # new ioc installed\nsudo shellbox status # status of all iocs on server\nsudo shellbox stop 50045 # stop ioc\nsudo shellbox start 50045 # start ioc\nsudo shellbox log 50045 -f # log file (tail)\nexit # exit ssh\n","path":["Developer","Ioc","IOC"],"tags":[]},{"location":"developer/python/epics/","level":1,"title":"EPICS","text":"Where is EPICS Base (https://gitea.psi.ch/epics) installed?
echo $EPICS\n Host architecture that EPICS Base runs on:
echo $EPICS_HOST_ARCH\n Which channel access lib is being used in python?
[sls-vserv-bd-hla01-dev ~]$ which python\n/bin/python\n[sls-vserv-bd-hla01-dev playground]$ python3 -c \"import ctypes; import epics.ca; print(epics.ca.find_libca())\"\n/usr/local/epics/base-7.0.9/lib/RHEL9-x86_64/libca.so\n[sls-vserv-bd-hla01-dev ~]$ source /opt/gfa/python-3.10/latest/bin/activate\n(base) [sls-vserv-bd-hla01-dev ~]$ which python\n/opt/gfa/python-3.10/20220602/bin/python\n(base) [sls-vserv-bd-hla01-dev ~]$ python3 -c \"import ctypes; import epics.ca; print(epics.ca.find_libca())\"\n/opt/gfa/python-3.10/20220602/epics/lib/linux-x86_64/libca.so\n How does the conda env configure which EPICS to use?
(base) [sls-vserv-bd-hla01-dev ~]$ cat /opt/gfa/python-3.10/20220602/etc/conda/activate.d/epics-base_activate.sh\nexport EPICS_BASE=\"/opt/gfa/python-3.10/20220602/epics\"\nexport EPICS_HOST_ARCH=\"linux-x86_64\"\nexport EPICS_BASE_HOST_BIN=\"/opt/gfa/python-3.10/20220602/epics/bin/linux-x86_64\"\nexport EPICS_BASE_VERSION=\"7.0.5.0\"\nexport PATH=$EPICS_BASE_HOST_BIN:$PATH\n How does the conda env configure which EPICS python uses?
(base) [sls-vserv-bd-hla01-dev ~]$ cat /opt/gfa/python-3.10/20220602/etc/conda/activate.d/pyepics_activate.sh\nexport PYEPICS_LIBCA=\"${EPICS_BASE}/lib/${EPICS_HOST_ARCH}/libca.so\"\n Example reading from a PV:
[sls-vserv-bd-hla01-dev ~]$ /bin/python\nPython 3.9.25 (main, Apr 17 2026, 00:00:00)\n[GCC 11.5.0 20240719 (Red Hat 11.5.0-14)] on linux\nType \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n>>> from epics import PV\n>>> pv = PV(\"AGEBD-PLAYGROUND-DEV:AO\")\n>>> pv.get()\n5.0\n>>>\n","path":["Developer","Python","EPICS"],"tags":[]},{"location":"developer/python/epics/#system-python-installed-packages","level":2,"title":"System python installed packages","text":"/bin/python -m pip list -v\n","path":["Developer","Python","EPICS"],"tags":[]},{"location":"developer/python/epics/#systemd-services","level":2,"title":"Systemd Services","text":"When ssh-ing into a machine, /etc/profile.d/* automatically gets sourced.
When running a systemd service, this does not happen.
That's why we need to source /etc/profile.d/cas_12_epics.sh in our startup script to make sure that EPICS is configured properly.
See: - docs: https://linux.psi.ch/documentation/services/gitea/gitea-packages/#pypi-package-registry - example: https://gitea.psi.ch/sls/OM
","path":["Developer","Python","Python packaging"],"tags":[]},{"location":"developer/python/pixi/","level":1,"title":"Pixi","text":"","path":["Developer","Python","Pixi"],"tags":[]},{"location":"developer/python/pixi/#install","level":2,"title":"Install","text":"curl -fsSL https://pixi.sh/install.sh | sh\n installs in ${HOME}/.pixi/bin
Install the uv package manager
","path":["User","Adding a new service"],"tags":[]},{"location":"user/add-new-service/#cli-command-line-interface","level":2,"title":"CLI (Command-Line Interface)","text":"We have our own cli called agebd.
To use the cli, first clone this repo. Then:
cd cli\nuv sync\nsource .venv/bin/activate\nagebd --help\n","path":["User","Adding a new service"],"tags":[]},{"location":"user/add-new-service/#adding-a-new-service_1","level":3,"title":"Adding a new service","text":"agebd service add --help\n","path":["User","Adding a new service"],"tags":[]},{"location":"user/add-new-service/#environments","level":2,"title":"Environments","text":"The services are deployed to 2 environments:
Environment Network Host Deploy path on hostprod machine sls-vserv-bd-hla01 /sls/bd/hla/prod/ dev office sls-vserv-bd-hla01-dev /sls/bd/hla/dev/","path":["User","Adding a new service"],"tags":[]},{"location":"user/add-new-service/#process-variables-pvs","level":3,"title":"Process Variables (PVs)","text":"We distinguish between
prod vs dev PVs You create them, see (# TODO: docs...)
prod and dev PVs automatically get created.
In your code, you only use the prod name of a PV. The framework will automatically use the dev name/PV when a service runs in the dev environment.
The framework will use the same PV in prod and dev, i.e. there is no dev PV. However, in dev you can only read from the PV, whereas in prod you can also write to it.
prod PV(\"AGEBD-MYSERVICE:MYPVNAME\") read&write PV(\"AGEOP-SOME-SERVICE:SOME-PVNAME\") read&write dev PV(\"AGEBD-MYSERVICE-DEV:MYPVNAME\") read&write PV(\"AGEOP-SOME-SERVICE:SOME-PVNAME\") readonly","path":["User","Adding a new service"],"tags":[]},{"location":"user/add-new-service/#python","level":3,"title":"Python","text":"For python services there are 3 environments. The python environment is set through the env variable AGEBD_ENV.
AGEBD_ENV=prod uses prod PVs AGEBD_ENV=dev uses dev PVs AGEBD_ENV=local uses fake/mock python objects as PVs, no access to real PVs","path":["User","Adding a new service"],"tags":[]},{"location":"user/gui/","level":1,"title":"GUI","text":"","path":["User","GUI"],"tags":[]},{"location":"user/gui/#launch","level":2,"title":"Launch","text":"cd <repo-root>\n In prod:
./bin/sls_hla_launch_gui.sh qt/A_BD_InjectionGuard.ui\n In dev:
./bin/sls_hla_launch_gui.sh qt/A_BD_InjectionGuard.ui dev\n If you need to pass another macro variable in dev, you will need to set AGEBD_ENV_SUFFIX explicitely:
./bin/sls_hla_launch_gui.sh qt/A_BD_Tune.ui dev -macro \"AGEBD_ENV_SUFFIX=-DEV, OTHER_ENV_VAR=HEYHEY\"\n","path":["User","GUI"],"tags":[]},{"location":"user/ioc/iocs_overview/","level":1,"title":"Overview of IOCs for Beam Dynamics","text":"The ports are configured in the service registry
IOC NAME Description AGEBD-CPCL-MASTER IOC providing PVs for the service master application and IOC enabling to monitor the health status of BD High Level Application Services with the alarm handler ALH AGEBD-CPCL-ALH IOC enabling to monitor the health status of BD High Level Application Services with the alarm handler ALH AGEBD-CPCL-TUNE IOC providing PVs for the tune measurement AGEBD-CPCL-SCRUBBING IOC providing PVs for the vacuum scrubbing service AGEBD-CPCL-NTURNS IOC providing PVs for the DBPM3 stage0 and stage1 nr. of turns calculation service AGEBD-CPCL-TIMING IOC providing PVs for working around limitations of the SLS 2.0 timing system AGEBD-CPCL-INJECTIONGUARD IOC providing PVs for the injection guard application AGEBD-CPCL-POSTMORTEMLOG IOC providing PVs for the post mortem elog service application AGEBD-CPCL-TUNEBUMP IOC providing PVs for the tune bump service application AGEBD-CPCL-PLOTS IOC providing Buffers of PVs for plots AGEBD-CPCL-ORBITBUMP IOC providing PVs for orbit bumps for the beamlines AGEBD-CPCL-TAUBPM IOC providing PVs for the lifetime measurement AGEBD-CPCL-TOPUPTOOL IOC providing PVs for the top up tool AGEBD-CPCL-TUNEFBX IOC providing PVs for the top up tool","path":["User","Ioc","Overview of IOCs for Beam Dynamics"],"tags":[]},{"location":"user/ioc/iocs_overview/#todo","level":1,"title":"TODO:","text":"IOC NAME Description AGEBD-CPCL-PARAMS IOC providing PVs for machine parameters AGEBD-CPCL-PARAMS IOC providing PVs for PCT base lifetime measurement AGEBD-CPCL-SHIFTTOOL AGEBD-CPCL-DBPM3CURR AGEBD-CPCL-DBPM3 IOC providing PVs for the DBPM3 stage2 average current calculation service","path":["User","Ioc","Overview of IOCs for Beam Dynamics"],"tags":[]}]}