214 lines
6.0 KiB
Python
214 lines
6.0 KiB
Python
"""Service packages installation and OpenRC configuration."""
|
|
|
|
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
from .utils import info, success, error, run, emerge
|
|
|
|
|
|
# Packages to emerge for system services
|
|
SERVICE_PACKAGES = [
|
|
# System essentials
|
|
"app-admin/sysklogd",
|
|
"sys-process/cronie",
|
|
# Network
|
|
"net-misc/networkmanager",
|
|
"net-misc/chrony",
|
|
"net-firewall/iptables",
|
|
# Bluetooth
|
|
"net-wireless/bluez",
|
|
"net-wireless/blueman",
|
|
# Desktop services
|
|
"sys-fs/udisks",
|
|
"sys-power/power-profiles-daemon",
|
|
"sys-auth/rtkit",
|
|
# Display manager
|
|
"x11-misc/sddm",
|
|
"gui-libs/display-manager-init",
|
|
# Containers
|
|
"app-containers/podman",
|
|
"app-containers/podman-compose",
|
|
"app-containers/podman-tui",
|
|
# Backup
|
|
"app-backup/snapper",
|
|
]
|
|
|
|
# OpenRC boot runlevel services
|
|
BOOT_SERVICES = [
|
|
"dbus",
|
|
"elogind",
|
|
"dmcrypt",
|
|
]
|
|
|
|
# OpenRC default runlevel services
|
|
DEFAULT_SERVICES = [
|
|
"sysklogd",
|
|
"sshd",
|
|
"NetworkManager",
|
|
"chronyd",
|
|
"cronie",
|
|
"power-profiles-daemon",
|
|
"display-manager",
|
|
"bluetooth",
|
|
"iptables",
|
|
"ip6tables",
|
|
]
|
|
|
|
|
|
def emerge_services() -> None:
|
|
"""Emerge service packages."""
|
|
info("=== Emerging Service Packages ===")
|
|
|
|
print()
|
|
info("Packages to install:")
|
|
for pkg in SERVICE_PACKAGES:
|
|
print(f" - {pkg}")
|
|
print()
|
|
|
|
emerge(*SERVICE_PACKAGES)
|
|
|
|
success("Service packages installed.")
|
|
|
|
|
|
def configure_display_manager() -> None:
|
|
"""Configure SDDM as the display manager."""
|
|
info("=== Configuring Display Manager ===")
|
|
|
|
dm_conf = Path("/etc/conf.d/display-manager")
|
|
|
|
if dm_conf.exists():
|
|
content = dm_conf.read_text()
|
|
|
|
# Check if already configured correctly (idempotency)
|
|
if 'DISPLAYMANAGER="sddm"' in content:
|
|
info("SDDM already configured as display manager")
|
|
return
|
|
|
|
# Update existing config
|
|
lines = content.split("\n")
|
|
new_lines = []
|
|
found = False
|
|
|
|
for line in lines:
|
|
if line.startswith("DISPLAYMANAGER="):
|
|
new_lines.append('DISPLAYMANAGER="sddm"')
|
|
found = True
|
|
else:
|
|
new_lines.append(line)
|
|
|
|
if not found:
|
|
new_lines.append('DISPLAYMANAGER="sddm"')
|
|
|
|
dm_conf.write_text("\n".join(new_lines))
|
|
else:
|
|
dm_conf.write_text('DISPLAYMANAGER="sddm"\n')
|
|
|
|
success("SDDM configured as display manager.")
|
|
|
|
|
|
def copy_system_configs(source_dir: Path) -> None:
|
|
"""Copy system configuration files."""
|
|
info("=== Copying System Configuration ===")
|
|
|
|
# conf.d/ -> /etc/conf.d/
|
|
conf_d_src = source_dir / "conf.d"
|
|
if conf_d_src.is_dir():
|
|
conf_d_dst = Path("/etc/conf.d")
|
|
for f in conf_d_src.iterdir():
|
|
if f.is_file():
|
|
shutil.copy2(f, conf_d_dst / f.name)
|
|
success(f"Copied conf.d/{f.name}")
|
|
|
|
# iptables/ -> /etc/iptables/ (for reference)
|
|
# Also copy to /var/lib/iptables/ and /var/lib/ip6tables/ (OpenRC locations)
|
|
iptables_src = source_dir / "iptables"
|
|
if iptables_src.is_dir():
|
|
# Copy to /etc/iptables for reference
|
|
iptables_etc = Path("/etc/iptables")
|
|
iptables_etc.mkdir(parents=True, exist_ok=True)
|
|
for f in iptables_src.iterdir():
|
|
if f.is_file():
|
|
shutil.copy2(f, iptables_etc / f.name)
|
|
success(f"Copied iptables/{f.name}")
|
|
|
|
# Copy to OpenRC service locations
|
|
iptables_var = Path("/var/lib/iptables")
|
|
ip6tables_var = Path("/var/lib/ip6tables")
|
|
iptables_var.mkdir(parents=True, exist_ok=True)
|
|
ip6tables_var.mkdir(parents=True, exist_ok=True)
|
|
|
|
rules_v4 = iptables_src / "iptables.rules"
|
|
rules_v6 = iptables_src / "ip6tables.rules"
|
|
|
|
if rules_v4.exists():
|
|
shutil.copy2(rules_v4, iptables_var / "rules-save")
|
|
success("Installed iptables rules to /var/lib/iptables/rules-save")
|
|
|
|
if rules_v6.exists():
|
|
shutil.copy2(rules_v6, ip6tables_var / "rules-save")
|
|
success("Installed ip6tables rules to /var/lib/ip6tables/rules-save")
|
|
|
|
# udev/ -> /etc/udev/rules.d/
|
|
udev_src = source_dir / "udev"
|
|
if udev_src.is_dir():
|
|
udev_dst = Path("/etc/udev/rules.d")
|
|
udev_dst.mkdir(parents=True, exist_ok=True)
|
|
for f in udev_src.iterdir():
|
|
if f.is_file():
|
|
shutil.copy2(f, udev_dst / f.name)
|
|
success(f"Copied udev/{f.name}")
|
|
|
|
|
|
def setup_openrc_services() -> None:
|
|
"""Add services to OpenRC runlevels."""
|
|
info("=== Configuring OpenRC Services ===")
|
|
|
|
# Boot runlevel
|
|
info("Adding boot runlevel services...")
|
|
for service in BOOT_SERVICES:
|
|
result = run("rc-update", "add", service, "boot", check=False)
|
|
if result.ok:
|
|
success(f" Added {service} to boot")
|
|
else:
|
|
error(f" Warning: Could not add {service} (may already exist)")
|
|
|
|
# Default runlevel
|
|
info("Adding default runlevel services...")
|
|
for service in DEFAULT_SERVICES:
|
|
result = run("rc-update", "add", service, "default", check=False)
|
|
if result.ok:
|
|
success(f" Added {service} to default")
|
|
else:
|
|
error(f" Warning: Could not add {service} (may already exist)")
|
|
|
|
print()
|
|
info("Current runlevel configuration:")
|
|
run("rc-update", "show")
|
|
|
|
|
|
def setup_services(source_dir: Path | None = None) -> None:
|
|
"""Full services setup workflow."""
|
|
if source_dir is None:
|
|
# Assume config files are in /root/gentoo or similar
|
|
# This should be passed from setup.py
|
|
source_dir = Path("/root/gentoo")
|
|
|
|
emerge_services()
|
|
print()
|
|
configure_display_manager()
|
|
print()
|
|
copy_system_configs(source_dir)
|
|
print()
|
|
setup_openrc_services()
|
|
|
|
print()
|
|
success("=== Services Setup Complete ===")
|
|
print()
|
|
info("Next steps:")
|
|
print(" 1. Install kernel: emerge gentoo-kernel-bin (or gentoo-kernel)")
|
|
print(" 2. Configure bootloader")
|
|
print(" 3. Set root password: passwd")
|
|
print(" 4. Create user account")
|
|
print(" 5. Reboot and test")
|