icmplib==2.1.1 doesn't work in plugin jail
As of HomeAssistant 2021.4.1, the inbuilt ping integration uses icmplib==2.1.1: https://github.com/home-assistant/core/pull/43868/files
Ping in this version of icmplib fails in the HA iocage jail when run as the homeassistant user, but works when run as root. I don't understand the exact problem, but this seems to suggest that there is some type of network permission issue in the jails config.
This can be verified using the jail shell, updating to HA 2021.4.*, then entering the python venv: source /usr/local/share/homeassistant/bin/activate
then running python interactively: python
and pasting the following code:
from functools import lru_cache
from icmplib import SocketPermissionError, ping as icmp_ping
# In python 3.9 and later, this can be converted to just be `cache`
@lru_cache(maxsize=None)
def can_create_raw_socket():
"""Verify we can create a raw socket."""
try:
icmp_ping("127.0.0.1", count=0, timeout=0)
return True
except SocketPermissionError:
return False
print (can_create_raw_socket())
(test code sourced from a similar issue: https://github.com/home-assistant/core/issues/43188)
If you enter the venv as root, this code prints True.
If you su homeassistant before entering the venv, then it returns False.
If you manually roll back the python icmplib to v1.2.2, then it will return True regardless of user.
Sorry, I'm not really sure what I can do. The only immediate work around I can suggest is running Home Assistant as root
From inside the jail, run
service homeassistant stop
sysrc homeassistant_user=root
service homeassistant start
According to https://pypi.org/project/icmplib/ -- Use the library without root privileges...
privileged
When this option is enabled, this library fully manages the exchanges and the structure of ICMP packets. Disable this option if you want to use this function without root privileges and let the kernel handle ICMP headers.
Only available on Unix systems. Ignored on Windows.
- Type: bool
- Default: True
So I added privileged=False to the example
from functools import lru_cache
from icmplib import SocketPermissionError, ping as icmp_ping
# In python 3.9 and later, this can be converted to just be `cache`
@lru_cache(maxsize=None)
def can_create_raw_socket():
"""Verify we can create a raw socket."""
try:
icmp_ping('127.0.0.1', count=3, timeout=1, privileged=False)
return True
except SocketPermissionError:
return False
print (can_create_raw_socket())
However, that results in the following error
Traceback (most recent call last):
File "/usr/local/share/homeassistant/lib/python3.8/site-packages/icmplib/sockets.py", line 88, in __init__
self._sock = self._create_socket(
File "/usr/local/share/homeassistant/lib/python3.8/site-packages/icmplib/sockets.py", line 452, in _create_socket
return socket.socket(
File "/usr/local/lib/python3.8/socket.py", line 231, in __init__
_socket.socket.__init__(self, family, type, proto, fileno)
OSError: [Errno 43] Protocol not supported
Thanks for looking into it so quickly! I think that's good to know about the user work-around. Another work-around I've implemented so far is to not use the built in ping integration in HomeAssistant. I've taken a copy of the ping integration code from a few weeks ago (pre-version change) and modified it to be called old_ping. So now in my config files I have platform: old_ping and that works for now, but possibly not a permanent solution.
For anyone else who wants to do that I'll put the link here: https://github.com/davidlang42/ha-old-ping You can install this by adding a custom integration URL to HACS and installing "Ping (ICMP) at icmplib==1.2.2".