Skip to content
Snippets Groups Projects
Commit 90a71da1 authored by Martin Mareš's avatar Martin Mareš
Browse files

Improve handling of paths

Variables ending in _path contain a Path, those ending in _dir are
strings.
parent e0b1ed0f
No related branches found
No related tags found
No related merge requests found
......@@ -3,5 +3,8 @@
# Where to find container configuration files
container_config_dir = "/etc/shipcat/containers"
# Where to find container roots (can be overridden by container's config)
container_root_dir = "/aux/containers"
# Overall verbosity
verbosity = 0
......@@ -16,7 +16,8 @@ class ConfigError(RuntimeError):
class GlobalConfig:
container_config_dir: Path
container_config_path: Path
container_root_path: Path
verbosity: int
@classmethod
......@@ -39,16 +40,19 @@ class GlobalConfig:
def parse(self, walker: Walker) -> None:
with walker.enter_object() as w:
self.container_config_dir = Path(w['container_config_dir'].as_str())
self.container_config_path = Path(w['container_config_dir'].as_str())
self.container_root_path = Path(w['container_root_dir'].as_str())
self.verbosity = w['verbosity'].as_int(0)
class ContainerConfig:
container: str
root_dir: str
name: str
root_path: Path
data_path: Path
image: str
allowed_users: Set[int]
allowed_groups: Set[int]
global_config: GlobalConfig
# Automatically generated
pid_file: str
......@@ -59,7 +63,7 @@ class ContainerConfig:
if not re.fullmatch(r'[0-9A-Za-z_-]+', name):
raise ConfigError(f'Invalid container name {name}')
path = global_config.container_config_dir / (name + '.toml')
path = global_config.container_config_path / (name + '.toml')
try:
with open(path, 'rb') as f:
root = tomllib.load(f)
......@@ -69,7 +73,8 @@ class ContainerConfig:
raise ConfigError(f'Cannot parse container configuration {path}: {e}')
cc = ContainerConfig()
cc.container = name
cc.name = name
cc.global_config = global_config
try:
cc.parse(Walker(root))
except WalkerError as e:
......@@ -79,6 +84,13 @@ class ContainerConfig:
def parse(self, walker: Walker) -> None:
with walker.enter_object() as w:
rd = w['root_dir']
if rd.is_present():
self.root_path = Path(rd.as_str())
else:
self.root_path = self.global_config.container_root_path / self.name
self.data_path = self.root_path / 'data'
self.root_dir = w['root_dir'].as_str()
self.image = w['image'].as_str()
......@@ -100,5 +112,5 @@ class ContainerConfig:
wu.raise_error(f'Unknown group {name}')
self.allowed_groups.add(grp.gr_gid)
self.pid_file = f'/run/shc/{self.container}.pid'
self.user_name = self.container
self.pid_file = f'/run/shc/{self.name}.pid'
self.user_name = self.name
......@@ -145,7 +145,7 @@ def cmd_init(args: argparse.Namespace) -> None:
progress(f'Using user {cc.user_name}, uid {uid}, subuids {sur.first}+{sur.count}, subgids {sgr.first}+{sgr.count}\n')
root_path = Path(cc.root_dir)
root_path = cc.root_path
progress(f'Container directory {root_path}: ')
if root_path.is_dir():
progress('already exists\n')
......@@ -154,7 +154,7 @@ def cmd_init(args: argparse.Namespace) -> None:
os.chown(root_path, 0, sgr.first)
progress('created\n')
data_path = root_path / 'data'
data_path = cc.data_path
progress(f'Data directory {data_path}: ')
if data_path.is_dir():
progress('already exists\n')
......@@ -173,35 +173,36 @@ def cmd_init(args: argparse.Namespace) -> None:
def service_action(cc: ContainerConfig, action: str) -> None:
run_command(
['systemctl', action, f'shc@{cc.container}.service']
['systemctl', action, f'shc@{cc.name}.service']
)
def cmd_create(args: argparse.Namespace) -> None:
name = args.name
cc = setup_container(args, False)
data_dir = Path(cc.root_dir) / 'data'
ip = socket.gethostbyname(name)
run_command(
['podman', 'pull', cc.image]
)
service_action(cc, 'stop')
create_container(cc)
def create_container(cc: ContainerConfig) -> None:
ip = socket.gethostbyname(cc.name)
run_command(
['podman', 'rm', '-if', name]
['podman', 'rm', '-if', cc.name]
)
run_command(
[
'podman', 'create',
'--name', name,
'--name', cc.name,
'--conmon-pidfile', cc.pid_file,
'--log-driver', 'journald',
'--hostname', name,
'--volume', f'{data_dir}:/data',
'--hostname', cc.name,
'--volume', f'{cc.data_path}:/data',
'--network', 'static',
'--ip', ip,
'--subuidname', cc.user_name,
......@@ -240,7 +241,7 @@ def cmd_shell(args: argparse.Namespace) -> None:
cc = setup_container(args, False)
run_command(
['podman', 'exec', '-it', cc.container, '/bin/bash']
['podman', 'exec', '-it', cc.name, '/bin/bash']
)
......@@ -252,7 +253,7 @@ def cmd_exec(args: argparse.Namespace) -> None:
cmd.append('--tty')
if args.user is not None:
cmd.extend(['--user', args.user])
cmd.append(cc.container)
cmd.append(cc.name)
cmd.extend(args.arg)
run_command(cmd)
......@@ -282,33 +283,36 @@ def cmd_rsync(args: argparse.Namespace) -> None:
cmd = ['podman', 'exec', '-i']
if user is not None:
cmd.extend(['--user', user])
cmd.append(cc.container)
cmd.append(cc.name)
cmd.extend(rsync)
run_command(cmd)
def cmd_list(args: argparse.Namespace) -> None:
for conf in Path(config.container_config_dir).iterdir():
for conf in config.container_config_path.iterdir():
if conf.suffix == '.toml':
cc = ContainerConfig.load(config, conf.stem)
if args.all or check_rights(cc, args.as_user, args.as_groups):
print(cc.container)
print(cc.name)
def main_service_start():
# Service helper for service start, called by root
if len(sys.argv) != 2:
die("Expected arguments: container")
die("Expected arguments: name")
config = load_config()
cc = ContainerConfig.load(config, sys.argv[1])
pid_file = f'/run/shc/{cc.container}.pid'
# Just to be sure
run_command(['podman', 'stop', '--ignore', cc.name])
pid_file = f'/run/shc/{cc.name}.pid'
Path(pid_file).unlink(missing_ok=True)
run_command(['podman', 'start', cc.container])
run_command(['podman', 'start', cc.name])
def main_service_stop():
......@@ -320,7 +324,7 @@ def main_service_stop():
config = load_config()
cc = ContainerConfig.load(config, sys.argv[1])
run_command(['podman', 'stop', '--ignore', cc.container])
run_command(['podman', 'stop', '--ignore', cc.name])
def parse_int_list(s: str) -> List[int]:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment