docker: warn about low inotify/file-max and missing FUSE at connect

Add a read-only _check_host_readiness() that runs once after the Docker
daemon connection is established. It reads /proc/sys inotify/file-max
limits and /proc/filesystems (for FUSE), and logs a warning with the exact
commands to fix when they are too low for heavy containers -- XRd wants
~4000 inotify instances per node against a stock default of 128.

The server runs unprivileged (only the setuid ubridge helper has root), so
it can only check, not set; the warning tells the admin exactly what to
raise once. Stays silent when the limits are already sufficient.
This commit is contained in:
YueGuobin committed 2026-08-13 22:39:48 +08:00
1 parent 86d30f34b4
commit 2bee34031c
2 files changed
+106

No files matched your search

+51
View File
@@ -364,3 +364,54 @@ async def test_install_busybox_no_executables():
dst_dir = Docker.resources_path()
await Docker.install_busybox(dst_dir)
assert str(e.value) == "No busybox executable could be found, please install busybox (apt install busybox-static on Debian/Ubuntu) and make sure it is in your PATH"
@pytest.mark.asyncio
async def test_check_host_readiness_warns_when_low(caplog):
import logging
from io import StringIO
docker = Docker()
files = {
"/proc/sys/fs/inotify/max_user_instances": "128",
"/proc/sys/fs/inotify/max_user_watches": "8192",
"/proc/sys/fs/file-max": "100000",
"/proc/filesystems": "nodev ext4\nnodev tmpfs\n",
}
def fake_open(path, *args, **kwargs):
return StringIO(files[path])
with patch("builtins.open", side_effect=fake_open):
with caplog.at_level(logging.WARNING, logger="gns3server.compute.docker"):
docker._check_host_readiness()
message = " ".join(r.message for r in caplog.records)
assert "max_user_instances=128" in message
assert "sudo sysctl -w" in message
assert "modprobe fuse" in message # FUSE missing -> warned
@pytest.mark.asyncio
async def test_check_host_readiness_silent_when_ok(caplog):
import logging
from io import StringIO
docker = Docker()
files = {
"/proc/sys/fs/inotify/max_user_instances": "64000",
"/proc/sys/fs/inotify/max_user_watches": "524288",
"/proc/sys/fs/file-max": "1000000",
"/proc/filesystems": "nodev ext4\nnodev fuse\n",
}
def fake_open(path, *args, **kwargs):
return StringIO(files[path])
with patch("builtins.open", side_effect=fake_open):
with caplog.at_level(logging.WARNING, logger="gns3server.compute.docker"):
docker._check_host_readiness()
assert not [r for r in caplog.records if r.levelno == logging.WARNING]