docker: inject /dev/shm size and host devices via HostConfig from env

Heavy NOS containers (e.g. Cisco XRd) need /dev/shm larger than Docker's
64 MB default and host device nodes such as /dev/fuse. Add two opt-in
environment variables, consumed host-side and applied as native Docker
HostConfig keys at create time:

  GNS3_SHM_SIZE (MB)  -> HostConfig.ShmSize (bytes)
  GNS3_DEVICES        -> HostConfig.Devices in `docker run --device` syntax
                         (host[:container[:perm]]; Docker resolves major/minor
                         from the host node itself)

Native HostConfig (rather than remount/mknod inside init.sh) is used so this
works for vendor NOS nodes that skip init.sh (console_type=docker_exec) --
the path XRd must take, since GNS3's init.sh wrapper crashes XRd's glibc
loader. It applies whether or not init.sh runs, needs no schema/API/UI
change (reuses the `environment` field), and only takes effect when the vars
are set, so ordinary nodes keep default Docker behaviour.

GNS3_-prefixed user env vars stay dropped from the container environment
(only consumed here host-side), keeping GNS3-injected vars safe.
This commit is contained in:
YueGuobin committed 2026-08-13 22:39:48 +08:00
1 parent f65d9b17c6
commit 86d30f34b4
2 files changed
+86

No files matched your search

+36
View File
@@ -271,6 +271,42 @@ async def test_create_with_extra_hosts(compute_project, manager):
assert "GNS3_EXTRA_HOSTS=199.199.199.1\ttest\n199.199.199.1\ttest2" in called_kwargs["data"]["Env"]
assert vm._extra_hosts == extra_hosts
@pytest.mark.asyncio
async def test_create_applies_env_host_config(compute_project, manager):
"""
GNS3_SHM_SIZE / GNS3_DEVICES are applied as native Docker HostConfig keys
(ShmSize, Devices) at create time -- not forwarded as container env vars --
so they work even for vendor nodes that skip init.sh. Other GNS3_-prefixed
vars stay dropped from the container environment.
"""
environment = (
"GNS3_SHM_SIZE=1024\n"
"GNS3_DEVICES=/dev/fuse\n"
"GNS3_EVIL=should-be-dropped\n" # GNS3_ -> never forwarded as env
"FOO=bar" # normal var -> forwarded
)
response = {"Id": "e90e34656806", "Warnings": []}
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "ubuntu"}]):
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value=response) as mock:
vm = DockerVM("test", str(uuid.uuid4()), compute_project, manager, "ubuntu", environment=environment)
await vm.create()
data = mock.call_args[1]["data"]
host_config = data["HostConfig"]
assert host_config["ShmSize"] == 1024 * 1024 * 1024
assert host_config["Devices"] == [
{"PathOnHost": "/dev/fuse", "PathInContainer": "/dev/fuse", "CgroupPermissions": "rwm"}
]
env = data["Env"]
assert "FOO=bar" in env
assert not any(
e.startswith(("GNS3_SHM_SIZE=", "GNS3_DEVICES=", "GNS3_EVIL="))
for e in env
), "GNS3_ user vars must not leak into the container environment"
@pytest.mark.asyncio
async def test_create_with_colon_in_project_name(compute_project, manager):