Source code for cobbler.cobblerd.setup

"""
Module for setting up Cobbler daemon configuration files, directories, and templates.

This module provides functions to copy resource files, template configuration files, and create required directory
structures for Cobbler's operation. It supports setup for Apache, Nginx, systemd, logrotate, manpages, and other
components based on distribution options and installation scope.
"""

import pathlib
import shutil
from typing import TYPE_CHECKING, List

try:
    from importlib.resources import files  # type: ignore
except ImportError:
    from importlib_resources import files  # type: ignore

if TYPE_CHECKING:
    from cobbler.cobblerd.distro_options import DistroOptions

    try:
        from importlib.abc import Traversable
    except ImportError:
        from importlib_resources.abc import Traversable  # type: ignore


[docs] def get_path_no_root(path: pathlib.Path) -> pathlib.Path: """ Strip the leading slash in case one exists. """ my_path = str(path) if my_path.startswith("/"): return pathlib.Path(my_path[1:]) return path
[docs] def get_prefixed_path(path: pathlib.Path, prefix: pathlib.Path) -> pathlib.Path: """ Prefix the given path with a prefix. """ return prefix / get_path_no_root(path)
[docs] def template_file(path: pathlib.Path, context: "DistroOptions"): """ This method takes a file and templates it with the magic "@@name@@" syntax. """ file_content = path.read_text(encoding="UTF-8") dict_context = context.to_context() for key, value in dict_context.items(): file_content = file_content.replace(f"@@{key}@@", value) path.write_text(file_content, encoding="UTF-8")
[docs] def copy_file(src: "Traversable", dst: pathlib.Path) -> None: """ Copies a file from the resource files to the destination path. :param src: The source file in the resource files. :param dst: The destination path where the file should be copied. """ dst.write_text(src.read_text(encoding="UTF-8"), encoding="UTF-8")
[docs] def copy_directory(src: "Traversable", dst: pathlib.Path) -> None: """ Copies a directory from the resource files to the destination path. :param src: The source directory in the resource files. :param dst: The destination path where the directory should be copied. """ for file in src.iterdir(): if file.is_dir(): new_dst = dst / file.name new_dst.mkdir(parents=True, exist_ok=True) copy_directory(file, new_dst) else: copy_file(file, dst / file.name)
[docs] def setup_cobblerd_manpages( base_path: pathlib.Path, resource_files: "Traversable", ) -> None: """ Use the embedded manpages and install them into the system. """ man_directory = base_path man5_files = resource_files.joinpath("man").joinpath("man5") if man5_files.is_dir(): man5_directory = man_directory / "man5" man5_directory.mkdir(parents=True, exist_ok=True) copy_directory(man5_files, man5_directory) man8_files = resource_files.joinpath("man").joinpath("man8") if man8_files.is_dir(): man8_directory = man_directory / "man8" man8_directory.mkdir(parents=True, exist_ok=True) copy_directory(man8_files, man8_directory)
[docs] def setup_cobblerd_logrotate( base_path: pathlib.Path, resource_files: "Traversable" ) -> None: """ Use the embedded logrotate configuration and install it into the system. """ logrotate_config_file = ( resource_files.joinpath("config").joinpath("rotate").joinpath("cobblerd_rotate") ) logrotate_config_directory = base_path / "etc" / "logrotate.d" logrotate_config_directory.mkdir(parents=True, exist_ok=True) copy_file(logrotate_config_file, logrotate_config_directory / "cobblerd")
[docs] def setup_cobblerd_systemd( base_path: pathlib.Path, resource_files: "Traversable" ) -> None: """ Use the embedded systemd service file and install it into the system. """ # FIXME: Template systemd http service dependency # FIXME: Cobblerd Binary Path systemd_service_files = resource_files.joinpath("config").joinpath("service") systemd_service_directory = base_path systemd_service_directory.mkdir(parents=True, exist_ok=True) copy_directory(systemd_service_files, systemd_service_directory)
[docs] def setup_cobblerd_apache( base_path: pathlib.Path, resource_files: "Traversable" ) -> None: """ Use the embedded Apache configuration and install it into the system. """ apache_config_files = resource_files.joinpath("config").joinpath("apache") apache_config_directory = base_path apache_config_directory.mkdir(parents=True, exist_ok=True) copy_directory(apache_config_files, apache_config_directory)
[docs] def setup_cobblerd_nginx( base_path: pathlib.Path, resource_files: "Traversable" ) -> None: """ Use the embedded Nginx configuration and install it into the system. """ nginx_config_files = resource_files.joinpath("config").joinpath("nginx") nginx_config_directory = base_path / "etc" / "nginx" / "cobbler" nginx_config_directory.mkdir(parents=True, exist_ok=True) copy_directory(nginx_config_files, nginx_config_directory)
[docs] def setup_cobblerd_log_directories(base_path: pathlib.Path, apache_user: str) -> None: """ Create all the directories needed for logging in the Cobbler daemon. """ log_path = base_path / "cobbler" log_path.mkdir(parents=True, exist_ok=True) (log_path / "kicklog").mkdir(parents=True, exist_ok=True) (log_path / "sysyslog").mkdir(parents=True, exist_ok=True) (log_path / "anamon").mkdir(parents=True, exist_ok=True) (log_path / "tasks").mkdir(parents=True, exist_ok=True) (base_path / apache_user / "cobbler").mkdir(parents=True, exist_ok=True)
[docs] def setup_cobblerd( base_path: pathlib.Path, distro_options: "DistroOptions", scope: List[str] ) -> None: """ Setup all required directories and files for the Cobbler daemon. """ # Directories # Create /etc/cobbler etc_path = get_prefixed_path(distro_options.etcpath, base_path) etc_path.mkdir(parents=True, exist_ok=True) # Create /var/lib/cobbler var_path = get_prefixed_path(distro_options.libpath, base_path) var_path.mkdir(parents=True, exist_ok=True) (var_path / "loaders").mkdir(parents=True, exist_ok=True) # Create /var/log/cobbler logpath = get_prefixed_path(distro_options.logpath, base_path) setup_cobblerd_log_directories(logpath, distro_options.httpd_user) # Files resource_files: "Traversable" = files("cobbler.data") # type: ignore[reportAssignmentType] # Core cobbler_config: "Traversable" = resource_files.joinpath("config").joinpath( "cobbler" ) copy_directory(cobbler_config, etc_path) # Autoinstall Content autoinstall_templates_path = var_path / "templates" autoinstall_templates_path.mkdir(parents=True, exist_ok=True) # Move distro_signatures.json to /var/lib/cobbler signatures_filename = "distro_signatures.json" old_signatures_path = etc_path / signatures_filename if old_signatures_path.exists(): # Can't use rename because may be cross-device shutil.move(old_signatures_path, (var_path / signatures_filename)) # Create Apache & Nginx config webconfigpath = get_prefixed_path(distro_options.webconfig, base_path) if "apache" in scope or "full" in scope: setup_cobblerd_apache(webconfigpath, resource_files) if "nginx" in scope or "full" in scope: setup_cobblerd_nginx(base_path, resource_files) # Create logrotate config setup_cobblerd_logrotate(base_path, resource_files) # Create rsync config rsync_config_files: "Traversable" = resource_files.joinpath("config").joinpath( "rsync" ) copy_directory(rsync_config_files, etc_path) # Create systemd service file systemdpath = get_prefixed_path(distro_options.systemd_dir, base_path) if "systemd" in scope or "full" in scope: setup_cobblerd_systemd(systemdpath, resource_files) # Create Man Pages if "man" in scope or "full" in scope: manpath = get_prefixed_path(distro_options.docpath, base_path) setup_cobblerd_manpages(manpath, resource_files) # Web Root Files web_root_misc_files: "Traversable" = resource_files.joinpath("misc") web_root_misc_directory = var_path / "misc" web_root_misc_directory.mkdir(parents=True, exist_ok=True) copy_directory(web_root_misc_files, web_root_misc_directory) # TFTP Root Files # TODO: Copy GRUB files into TFTP-root # Now template all files that need it configure_files = [ (etc_path / "settings.yaml"), (webconfigpath / "cobbler.conf"), base_path / pathlib.Path("etc/nginx/cobbler.conf"), base_path / pathlib.Path("etc/systemd/system/cobblerd.service"), ] for file in configure_files: if file.exists(): template_file(file, distro_options)