Skip to content

Commit

Permalink
add guard container
Browse files Browse the repository at this point in the history
  • Loading branch information
zoumingzhe committed Sep 26, 2024
1 parent 207f69c commit a48e42a
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 10 deletions.
6 changes: 4 additions & 2 deletions casm/cmds/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
from xarg import commands
from xarg import run_command

from ..utils import __url_home__
from ..utils import __project__
from ..utils import __url_home__
from ..utils import __version__
from ..utils import assemble_file
from .modify import add_cmd_modify
from .podman import add_cmd_guard
from .podman import add_cmd_system
from .podman import add_cmd_systemd
from .podman_compose import add_cmd_down
Expand Down Expand Up @@ -48,7 +49,8 @@ def add_cmd(_arg: argp):
@run_command(add_cmd, add_cmd_pull, add_cmd_up, add_cmd_down,
add_cmd_start, add_cmd_stop, add_cmd_restart,
add_cmd_pause, add_cmd_unpause, add_cmd_exec, add_cmd_logs,
add_cmd_system, add_cmd_systemd, add_cmd_services, add_cmd_modify)
add_cmd_system, add_cmd_systemd, add_cmd_guard,
add_cmd_services, add_cmd_modify)
def run_cmd(cmds: commands) -> int:
instance: str = DEF_INSTANCE
if isinstance(cmds.args.instance, list):
Expand Down
6 changes: 4 additions & 2 deletions casm/cmds/podman/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@

from ...utils import __url_home__
from ...utils import __version__
from .container import add_cmd_container
from .guard import add_cmd_guard # noqa:F401
from .system import add_cmd_system
from .systemd import add_cmd_systemd
from .systemd import add_cmd_systemd # noqa:F401


@add_command("cman")
def add_cmd(_arg: argp):
pass


@run_command(add_cmd, add_cmd_system)
@run_command(add_cmd, add_cmd_container, add_cmd_system)
def run_cmd(cmds: commands) -> int:
return 0

Expand Down
28 changes: 28 additions & 0 deletions casm/cmds/podman/container.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# coding:utf-8

from xarg import add_command
from xarg import argp
from xarg import commands
from xarg import run_command

from ...utils import podman_container


@add_command("guard", help="Guard podman container")
def add_cmd_container_guard(_arg: argp):
pass


@run_command(add_cmd_container_guard)
def run_cmd_container_guard(cmds: commands) -> int:
return 0


@add_command("container", help="Manage podman containers")
def add_cmd_container(_arg: argp):
pass


@run_command(add_cmd_container, add_cmd_container_guard)
def run_cmd_container(cmds: commands) -> int:
return 0
44 changes: 44 additions & 0 deletions casm/cmds/podman/guard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# coding:utf-8

from typing import List

from xarg import add_command
from xarg import argp
from xarg import commands
from xarg import run_command

from ...utils import assemble_file
from ...utils import podman_container
from ..service import add_pos_services


@add_command("generate", help="Generate container guard crontab")
def add_cmd_guard_generate(_arg: argp):
add_pos_services(_arg)


@run_command(add_cmd_guard_generate)
def run_cmd_guard_generate(cmds: commands) -> int:
assemble: assemble_file = cmds.args.assemble_file
assert isinstance(assemble, assemble_file)
services: List[str] = cmds.args.services
for service in assemble.template.services:
cmds.logger.debug(f"{service.title}: {service.container_name}")
if len(services) > 0 and service.title not in services:
continue
container_name = assemble.safe_substitute(service.container_name)
cmds.logger.info(f"generate container {container_name} guard")
podman_container(container_name).generate_guard_task()
return 0


@add_command("guard", help="Manage containers guard")
def add_cmd_guard(_arg: argp):
pass


@run_command(add_cmd_guard, add_cmd_guard_generate)
def run_cmd_guard(cmds: commands) -> int:
return 0


4 changes: 2 additions & 2 deletions casm/cmds/podman/systemd.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from ..service import add_pos_services


@add_command("enable", help="Enable systemd for containers")
@add_command("enable", help="Enable systemd unit for containers")
def add_cmd_enable(_arg: argp):
_arg.add_argument("--restart-policy", dest="restart_policy",
type=str, nargs=1, metavar="STR", default=["on-failure"],
Expand All @@ -37,7 +37,7 @@ def run_cmd_enable(cmds: commands) -> int:
return 0


@add_command("disable", help="Disable systemd for containers")
@add_command("disable", help="Disable systemd unit for containers")
def add_cmd_disable(_arg: argp):
add_pos_services(_arg)

Expand Down
57 changes: 53 additions & 4 deletions casm/utils/podman.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# coding:utf-8

import getpass
import os
import shutil
from typing import Any
Expand Down Expand Up @@ -95,7 +96,7 @@ def __init__(self, container: Container):
self.__container: Container = container
self.__info: Dict[str, Any] = container.inspect()
self.__state: Optional[podman_container_inspect.state_struct] = None
self.__host_config: Optional[podman_container_inspect.host_config_struct] = None # noqa: E501
self.__host_config: Optional[podman_container_inspect.host_config_struct] = None # noqa:E501

@property
def container(self) -> Container:
Expand Down Expand Up @@ -130,7 +131,7 @@ def State(self) -> state_struct:
@property
def HostConfig(self) -> host_config_struct:
if self.__host_config is None:
self.__host_config = self.host_config_struct(self.info["HostConfig"]) # noqa: E501
self.__host_config = self.host_config_struct(self.info["HostConfig"]) # noqa:E501
return self.__host_config


Expand Down Expand Up @@ -168,9 +169,44 @@ def inspect(self) -> podman_container_inspect:
def service_unit(self) -> str:
return f"container-{self.container_name}.service"

@property
def healthy(self) -> bool:
inspect = self.inspect()

def __restarting() -> bool:
return inspect.State.Restarting

def __running() -> bool:
return inspect.State.Status == "running" and\
inspect.State.Running and\
not inspect.State.Paused and\
not inspect.State.OOMKilled and\
not inspect.State.Dead

def __healthy() -> bool:
health = inspect.State.Health
return health is None or health.Status == "healthy"

return __restarting() or __running() and __healthy()

def stop(self) -> int:
return os.system(f"podman container stop {self.container_name}")

def start(self) -> int:
return os.system(f"podman container start {self.container_name}")

def restart(self) -> int:
return os.system(f"podman container restart {self.container_name}")

def stop_service(self) -> int:
return os.system(f"systemctl stop {self.service_unit}")

def start_service(self) -> int:
return os.system(f"systemctl start {self.service_unit}")

def restart_service(self) -> int:
return os.system(f"systemctl restart {self.service_unit}")

def generate_service(self, restart_policy: str = "on-failure",
restart_sect: Optional[int] = None,
start_timeout: Optional[int] = None,
Expand All @@ -187,8 +223,8 @@ def generate_service(self, restart_policy: str = "on-failure",
raise FileNotFoundError("podman command not found")

container_inspect: podman_container_inspect = self.inspect()
mounts: List[Optional[str]] = [mountpoint(bind.split(":")[0]) for bind in # noqa: E501
container_inspect.HostConfig.Binds if bind.startswith("/")] # noqa: E501
mounts: List[Optional[str]] = [mountpoint(bind.split(":")[0]) for bind in # noqa:E501
container_inspect.HostConfig.Binds if bind.startswith("/")] # noqa:E501
mountpoints: List[str] = ["/run/containers/storage"]
mountpoints.extend([m for m in mounts if isinstance(m, str)])
content: str = f"""
Expand Down Expand Up @@ -237,6 +273,19 @@ def disable_service(self) -> int:
systemd_service.delete_unit(unit=self.service_unit)
return 0

def generate_guard_task(self, interval: int = 3) -> int:
container_name: str = self.container_name
with open(f"/etc/cron.d/guard-{container_name}.sh", "w") as hdl:
username: str = getpass.getuser()
hdl.write(f"PATH={os.environ['PATH']}\n")
hdl.write(f"*/{interval} * * * * {username} cman guard ${container_name}\n") # noqa:E501
return 0

def guard(self) -> bool:
def __restart() -> bool:
return self.restart_service() == 0 or self.restart() == 0
return True if self.healthy else __restart()


class podman_cmd:
'''Execute podman command
Expand Down

0 comments on commit a48e42a

Please sign in to comment.