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:
Blake Harnden 2023-06-12 16:30:02 -07:00
parent e60b0f0de1
commit c76bc2ee8a

View file

@ -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}")