daemon: updates for docker nodes to read and use the environ file for the launched process for all nsenter commands
This commit is contained in:
parent
e60b0f0de1
commit
c76bc2ee8a
1 changed files with 32 additions and 1 deletions
|
@ -6,6 +6,7 @@ from pathlib import Path
|
||||||
from tempfile import NamedTemporaryFile
|
from tempfile import NamedTemporaryFile
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from core import utils
|
||||||
from core.emulator.distributed import DistributedServer
|
from core.emulator.distributed import DistributedServer
|
||||||
from core.errors import CoreCommandError, CoreError
|
from core.errors import CoreCommandError, CoreError
|
||||||
from core.executables import BASH
|
from core.executables import BASH
|
||||||
|
@ -76,6 +77,7 @@ class DockerNode(CoreNode):
|
||||||
self.image: str = options.image
|
self.image: str = options.image
|
||||||
self.binds: list[tuple[str, str]] = options.binds
|
self.binds: list[tuple[str, str]] = options.binds
|
||||||
self.volumes: dict[str, DockerVolume] = {}
|
self.volumes: dict[str, DockerVolume] = {}
|
||||||
|
self.env: dict[str, str] = {}
|
||||||
for src, dst, unique, delete in options.volumes:
|
for src, dst, unique, delete in options.volumes:
|
||||||
src_name = self._unique_name(src) if unique else src
|
src_name = self._unique_name(src) if unique else src
|
||||||
self.volumes[src] = DockerVolume(src_name, dst, unique, delete)
|
self.volumes[src] = DockerVolume(src_name, dst, unique, delete)
|
||||||
|
@ -99,7 +101,24 @@ class DockerNode(CoreNode):
|
||||||
"""
|
"""
|
||||||
if shell:
|
if shell:
|
||||||
args = f"{BASH} -c {shlex.quote(args)}"
|
args = f"{BASH} -c {shlex.quote(args)}"
|
||||||
return f"nsenter -t {self.pid} -m -u -i -p -n {args}"
|
return f"nsenter -t {self.pid} -m -u -i -p -n -- {args}"
|
||||||
|
|
||||||
|
def cmd(self, args: str, wait: bool = True, shell: bool = False) -> str:
|
||||||
|
"""
|
||||||
|
Runs a command that is used to configure and setup the network within a
|
||||||
|
node.
|
||||||
|
|
||||||
|
:param args: command to run
|
||||||
|
:param wait: True to wait for status, False otherwise
|
||||||
|
:param shell: True to use shell, False otherwise
|
||||||
|
:return: combined stdout and stderr
|
||||||
|
:raises CoreCommandError: when a non-zero exit status occurs
|
||||||
|
"""
|
||||||
|
args = self.create_cmd(args, shell)
|
||||||
|
if self.server is None:
|
||||||
|
return utils.cmd(args, wait=wait, shell=shell, env=self.env)
|
||||||
|
else:
|
||||||
|
return self.server.remote_cmd(args, wait=wait, env=self.env)
|
||||||
|
|
||||||
def _unique_name(self, name: str) -> str:
|
def _unique_name(self, name: str) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -133,7 +152,9 @@ class DockerNode(CoreNode):
|
||||||
with self.lock:
|
with self.lock:
|
||||||
if self.up:
|
if self.up:
|
||||||
raise CoreError(f"starting node({self.name}) that is already up")
|
raise CoreError(f"starting node({self.name}) that is already up")
|
||||||
|
# create node directory
|
||||||
self.makenodedir()
|
self.makenodedir()
|
||||||
|
# setup commands for creating bind/volume mounts
|
||||||
binds = ""
|
binds = ""
|
||||||
for src, dst in self.binds:
|
for src, dst in self.binds:
|
||||||
binds += f"--mount type=bind,source={src},target={dst} "
|
binds += f"--mount type=bind,source={src},target={dst} "
|
||||||
|
@ -142,16 +163,26 @@ class DockerNode(CoreNode):
|
||||||
volumes += (
|
volumes += (
|
||||||
f"--mount type=volume," f"source={volume.src},target={volume.dst} "
|
f"--mount type=volume," f"source={volume.src},target={volume.dst} "
|
||||||
)
|
)
|
||||||
|
# normalize hostname
|
||||||
hostname = self.name.replace("_", "-")
|
hostname = self.name.replace("_", "-")
|
||||||
|
# create container and retrieve the created containers PID
|
||||||
self.host_cmd(
|
self.host_cmd(
|
||||||
f"{DOCKER} run -td --init --net=none --hostname {hostname} "
|
f"{DOCKER} run -td --init --net=none --hostname {hostname} "
|
||||||
f"--name {self.name} --sysctl net.ipv6.conf.all.disable_ipv6=0 "
|
f"--name {self.name} --sysctl net.ipv6.conf.all.disable_ipv6=0 "
|
||||||
f"{binds} {volumes} "
|
f"{binds} {volumes} "
|
||||||
f"--privileged {self.image} tail -f /dev/null"
|
f"--privileged {self.image} tail -f /dev/null"
|
||||||
)
|
)
|
||||||
|
# retrieve pid and process environment for use in nsenter commands
|
||||||
self.pid = self.host_cmd(
|
self.pid = self.host_cmd(
|
||||||
f"{DOCKER} inspect -f '{{{{.State.Pid}}}}' {self.name}"
|
f"{DOCKER} inspect -f '{{{{.State.Pid}}}}' {self.name}"
|
||||||
)
|
)
|
||||||
|
output = self.host_cmd(f"cat /proc/{self.pid}/environ")
|
||||||
|
for line in output.split("\x00"):
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
key, value = line.split("=")
|
||||||
|
self.env[key] = value
|
||||||
|
# setup symlinks for bind and volume mounts within
|
||||||
for src, dst in self.binds:
|
for src, dst in self.binds:
|
||||||
link_path = self.host_path(Path(dst), True)
|
link_path = self.host_path(Path(dst), True)
|
||||||
self.host_cmd(f"ln -s {src} {link_path}")
|
self.host_cmd(f"ln -s {src} {link_path}")
|
||||||
|
|
Loading…
Reference in a new issue