Skip to content

Commit

Permalink
daemon: initial experimental support for podman-compose in podman nod…
Browse files Browse the repository at this point in the history
…es from scripts
  • Loading branch information
bharnden committed Oct 16, 2023
1 parent 2a37070 commit a86fa3a
Showing 1 changed file with 61 additions and 36 deletions.
97 changes: 61 additions & 36 deletions daemon/core/nodes/podman.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
from dataclasses import dataclass, field
from pathlib import Path
from tempfile import NamedTemporaryFile
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Optional

from mako.template import Template

from core.emulator.distributed import DistributedServer
from core.errors import CoreCommandError, CoreError
Expand All @@ -17,6 +19,7 @@
from core.emulator.session import Session

PODMAN: str = "podman"
PODMAN_COMPOSE: str = "podman-compose"


@dataclass
Expand All @@ -32,6 +35,10 @@ class PodmanOptions(CoreNodeOptions):
unique is True for node unique volume naming
delete is True for deleting volume mount during shutdown
"""
compose: str = None
"""
Path to a compose file, if one should be used for this node.
"""


@dataclass
Expand Down Expand Up @@ -76,6 +83,7 @@ def __init__(
self.image: str = options.image
self.binds: list[tuple[str, str]] = options.binds
self.volumes: dict[str, VolumeMount] = {}
self.compose: Optional[str] = options.compose
for src, dst, unique, delete in options.volumes:
src_name = self._unique_name(src) if unique else src
self.volumes[src] = VolumeMount(src_name, dst, unique, delete)
Expand Down Expand Up @@ -135,39 +143,53 @@ def startup(self) -> None:
raise CoreError(f"starting node({self.name}) that is already up")
# create node directory
self.makenodedir()
# setup commands for creating bind/volume mounts
binds = ""
for src, dst in self.binds:
binds += f"--mount type=bind,source={src},target={dst} "
volumes = ""
for volume in self.volumes.values():
volumes += (
f"--mount type=volume," f"source={volume.src},target={volume.dst} "
)
# normalize hostname
hostname = self.name.replace("_", "-")
# create container and retrieve the created containers PID
self.host_cmd(
f"{PODMAN} run -td --init --net=none --hostname {hostname} "
f"--name {self.name} --sysctl net.ipv6.conf.all.disable_ipv6=0 "
f"{binds} {volumes} "
f"--privileged {self.image} tail -f /dev/null"
)
# retrieve pid and process environment for use in nsenter commands
self.pid = self.host_cmd(
f"{PODMAN} inspect -f '{{{{.State.Pid}}}}' {self.name}"
)
# setup symlinks for bind and volume mounts within
for src, dst in self.binds:
link_path = self.host_path(Path(dst), True)
self.host_cmd(f"ln -s {src} {link_path}")
for volume in self.volumes.values():
volume.path = self.host_cmd(
f"{PODMAN} volume inspect -f '{{{{.Mountpoint}}}}' {volume.src}"
if self.compose:
data = self.host_cmd(f"cat {self.compose}")
template = Template(data)
rendered = template.render_unicode(node=self, hostname=hostname)
compose_path = self.directory / "docker-compose.yml"
rendered = "\\n".join(rendered.splitlines())
self.host_cmd(f"printf '{rendered}' >> {compose_path}", shell=True)
self.host_cmd(f"{PODMAN_COMPOSE} up -d", cwd=self.directory)
self.pid = self.host_cmd(
f"{PODMAN} inspect -f '{{{{.State.Pid}}}}' {self.name}"
)
else:
# setup commands for creating bind/volume mounts
binds = ""
for src, dst in self.binds:
binds += f"--mount type=bind,source={src},target={dst} "
volumes = ""
for volume in self.volumes.values():
volumes += (
f"--mount type=volume,"
f"source={volume.src},target={volume.dst} "
)
# normalize hostname
hostname = self.name.replace("_", "-")
# create container and retrieve the created containers PID
self.host_cmd(
f"{PODMAN} run -td --init --net=none --hostname {hostname} "
f"--name {self.name} --sysctl net.ipv6.conf.all.disable_ipv6=0 "
f"{binds} {volumes} "
f"--privileged {self.image} tail -f /dev/null"
)
# retrieve pid and process environment for use in nsenter commands
self.pid = self.host_cmd(
f"{PODMAN} inspect -f '{{{{.State.Pid}}}}' {self.name}"
)
link_path = self.host_path(Path(volume.dst), True)
self.host_cmd(f"ln -s {volume.path} {link_path}")
logger.debug("node(%s) pid: %s", self.name, self.pid)
# setup symlinks for bind and volume mounts within
for src, dst in self.binds:
link_path = self.host_path(Path(dst), True)
self.host_cmd(f"ln -s {src} {link_path}")
for volume in self.volumes.values():
volume.path = self.host_cmd(
f"{PODMAN} volume inspect -f '{{{{.Mountpoint}}}}' {volume.src}"
)
link_path = self.host_path(Path(volume.dst), True)
self.host_cmd(f"ln -s {volume.path} {link_path}")
logger.debug("node(%s) pid: %s", self.name, self.pid)
self.up = True

def shutdown(self) -> None:
Expand All @@ -181,10 +203,13 @@ def shutdown(self) -> None:
return
with self.lock:
self.ifaces.clear()
self.host_cmd(f"{PODMAN} rm -f {self.name}")
for volume in self.volumes.values():
if volume.delete:
self.host_cmd(f"{PODMAN} volume rm {volume.src}")
if self.compose:
self.host_cmd(f"{PODMAN_COMPOSE} down -t 0", cwd=self.directory)
else:
self.host_cmd(f"{PODMAN} rm -f {self.name}")
for volume in self.volumes.values():
if volume.delete:
self.host_cmd(f"{PODMAN} volume rm {volume.src}")
self.up = False

def termcmdstring(self, sh: str = "/bin/sh") -> str:
Expand Down

0 comments on commit a86fa3a

Please sign in to comment.