82 lines
2.4 KiB
Python
82 lines
2.4 KiB
Python
"""Chroot environment preparation."""
|
|
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
from .utils import info, success, warn, run, is_mounted
|
|
|
|
|
|
def prepare_chroot(mount_root: Path | None = None) -> None:
|
|
"""Prepare chroot environment with bind mounts."""
|
|
if mount_root is None:
|
|
mount_root = Path("/mnt/gentoo")
|
|
|
|
info("=== Preparing Chroot Environment ===")
|
|
|
|
# Check if already prepared (idempotency)
|
|
if is_mounted(mount_root / "proc"):
|
|
info("Chroot already prepared (skipping)")
|
|
return
|
|
|
|
# Copy DNS configuration
|
|
info("Copying DNS configuration...")
|
|
resolv_src = Path("/etc/resolv.conf")
|
|
resolv_dst = mount_root / "etc/resolv.conf"
|
|
|
|
if resolv_src.exists():
|
|
# Use --dereference to copy the actual file if it's a symlink
|
|
shutil.copy2(resolv_src.resolve(), resolv_dst)
|
|
success("Copied resolv.conf")
|
|
|
|
# Bind mount pseudo-filesystems
|
|
mounts = [
|
|
("proc", "/proc", ["--rbind"]),
|
|
("sys", "/sys", ["--rbind"]),
|
|
("dev", "/dev", ["--rbind"]),
|
|
("run", "/run", ["--rbind"]),
|
|
]
|
|
|
|
for name, source, flags in mounts:
|
|
target = mount_root / name.lstrip("/")
|
|
target.mkdir(parents=True, exist_ok=True)
|
|
|
|
run("mount", *flags, source, str(target))
|
|
run("mount", "--make-rslave", str(target))
|
|
success(f"Mounted {source}")
|
|
|
|
print()
|
|
success("=== Chroot environment ready ===")
|
|
print()
|
|
info("To enter chroot:")
|
|
print(f" chroot {mount_root} /bin/bash")
|
|
print(" source /etc/profile")
|
|
print(" export PS1=\"(chroot) $PS1\"")
|
|
|
|
|
|
def enter_chroot(mount_root: Path | None = None) -> None:
|
|
"""Enter the chroot environment."""
|
|
if mount_root is None:
|
|
mount_root = Path("/mnt/gentoo")
|
|
|
|
import os
|
|
os.execvp("chroot", ["chroot", str(mount_root), "/bin/bash", "--login"])
|
|
|
|
|
|
def cleanup_chroot(mount_root: Path | None = None) -> None:
|
|
"""Unmount chroot bind mounts."""
|
|
if mount_root is None:
|
|
mount_root = Path("/mnt/gentoo")
|
|
|
|
info("Cleaning up chroot mounts...")
|
|
|
|
# Unmount in reverse order
|
|
for name in ["run", "dev", "sys", "proc"]:
|
|
target = mount_root / name
|
|
result = run("umount", "-R", str(target), check=False)
|
|
if not result.ok:
|
|
# Try lazy unmount as fallback
|
|
warn(f"Normal unmount failed for {target}, trying lazy unmount...")
|
|
run("umount", "-Rl", str(target), check=False)
|
|
|
|
success("Chroot mounts cleaned up.")
|