I have a couple of udev rules in a container that trigger when a USB storage device is inserted or removed (with a Raspberry Pi). The rules trigger correctly, and the relevant scripts are run.
Within the scripts, I want to call the Balena Supervisor API using curl, to restart an adjacent service. This call is not working.
I determined that the BALENA* environment variables are unavailable in the udev environment, and I fixed that (by caching them in files)
The curl command runs correctly when called from a terminal in the container
Presumably there is some other udev limitation that I’m not aware of? I tried adding IPAddressAllow=127.0.0.1 to /lib/systemd/system/udev.service, but that’s not it; perhaps the Balena udev service is configured differently?
Yes, I’ve already done that, as evidenced by the fact that supervisor API call works correctly when run from a terminal in the container.
In the UDEV context the BALENA_* env. vars are not present, but I set them manually using values cached in files by the main container process when it starts.
Hi, thanks for the clarification. So you are running a privileged container with UDEV=1 in the dockerfile and then also have some udev rules that trigger some scripts. I will ping some of my teammates that could have some knowledge of why the environment variables are not present in the udev environment and we will get back to you. For reference this is the script that launches udevd inside a container: https://github.com/balena-io-library/base-images/blob/master/scripts/assets/entry.sh
Thanks,
Zahari
Mostly correct … I’m not expecting the the BALENA_* variables to be present in the UDEV context, so I deal with that manually, and that part works.
However, something is preventing the curl command reaching the supervisor API, presumably some UDEV environment restriction. (Or, it’s just a silly bug on my part, of course).
When it’s run within the script triggered by the UDEV event, I logged the following output from the script:
Fri Oct 11 10:00:58 UTC 2019 : USB device inserted
BALENA_SUPERVISOR_ADDRESS: http://127.0.0.1:48484
BALENA_APP_ID: 1303046
BALENA_SUPERVISOR_API_KEY: bf4d12c92a8e4b7de390ddbb2dead3d01c9f4f2635c4b5eea1f803aaf7d6d5
curl: (7) Couldn't connect to server
Note that the BALENA_* variables are not part of the script’s environment, so I set them manually using values cached in a file by the main container process.
The curl command works fine when executed within the main container process.
I suspect there’s something limiting what can be done within the UDEV context.
As an alternative I got an idea - instead of defining UDEV=1 in your Dockerfile, you may try running from your start script udevd with the same code from the entry script I posted a link to above. Could you try that please and let us know whether it is working for you?
Thanks,
Zahari
For now I’ve decided just to work around this by setting a (file-based) flag in the script triggered by UDEV, with the main container process subsequently acting on the flag and executing the curl command to the supervisor API.
It’s clear that the UDEV context is restricted somehow, but I don’t have the time to experiment my way through finding out how to lift the restrictions.
Thanks for letting us know.
We are glad that the workaround you mentioned worked for you, but could you provide a part of your docker-compose & dockerfile to further investigate this?
And this is the relevant excerpt from the Dockerfile.template for the manager container:
FROM balenalib/%%BALENA_MACHINE_NAME%%:stretch
...
# Copy over the start script
COPY start.sh /.
# Copy over the UDEV rules and scripts
COPY usb-insertion.rules /etc/udev/rules.d/.
COPY udev-trigger-usb-inserted.sh /.
COPY udev-trigger-usb-removed.sh /.
RUN chmod +x /udev-trigger-usb-*
# Enable udevd in this container
ENV UDEV=1
# Entry point is the start script
CMD /bin/bash /start.sh
Hi, it looks like a solid approach for a workaround over the udev context restrictions. Please let us know if you have any further issues or questions.
Thanks,
Zahari