#!/usr/bin/python3

# Copyright (c) 2021 SUSE LLC
#
# This software is licensed to you under the GNU General Public License,
# version 2 (GPLv2). There is NO WARRANTY for this software, express or
# implied, including the implied warranties of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
# along with this software; if not, see
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.

# Initial creator of the script: Enno Gotthold <egotthold@suse.de>

import os
import socket

import yaml
import argparse
from configparser import ConfigParser
from shutil import copyfile

parser = argparse.ArgumentParser(description='Setup Cobbler for Uyuni.')
parser.add_argument('--cobbler-config-directory', '-c', dest='cobbler_config_directory', default="/etc/cobbler/",
                    help='The directory where "settings" and "modules.conf" are in.')
parser.add_argument('--apache2-config-directory', '-a', dest='httpd_config_directory', default="/etc/apache2/conf.d",
                    help='The directory where the Apache config file "cobbler.conf" is in.')

COBBLER_CONFIG_DIRECTORY = "/etc/cobbler/"
COBBLER_CONFIG_FILES = ["modules.conf", "settings"]
HTTPD_CONFIG_DIRECTORY = "/etc/apache2/conf.d/"
COBBLER_HTTP_CONFIG = "cobbler.conf"


def backup_file(file_path: str):
    """
    Copies the file and adds a suffix ".backup" to it.
    
    :param file_path: The full path to the file which should be backed up.
    :raises FileNotFoundError: In case the path specified was not existing.
    """
    copyfile(file_path, "%s.backup" % file_path)


def manipulate_cobbler_settings(config_dir: str, settings_yaml: str):
    """
    Manipulate the main Cobbler configuration file which is in YAML format. This function backs the original
    configuration up and writes a new one with the required changes to the disk.
    
    :param config_dir: The directory of Cobbler where the config files are.
    :param settings_yaml: The name of the main YAML file of Cobbler.
    """
    full_path = os.path.join(config_dir, settings_yaml)
    backup_file(full_path)
    with open(full_path) as settings_file:
        filecontent = yaml.safe_load(settings_file.read())
    filecontent["server"] = socket.getfqdn()
    filecontent["next_server"] = socket.getfqdn()
    filecontent["pxe_just_once"] = True
    filecontent["redhat_management_server"] = socket.getfqdn()
    yaml_dump = yaml.safe_dump(filecontent)
    with open(full_path, "w") as settings_file:
        settings_file.write(yaml_dump)


def manipulate_cobbler_modules(config_dir: str, modules_ini: str):
    """
    Manipulates the authentication of Cobbler to use the SUMA/Uyuni Server directly.
    
    :param config_dir: The directory of Cobbler where the config files are.
    :param modules_ini: The name of the configuration in INI style for the modules Cobbler uses at runtime.
    """
    full_path = os.path.join(config_dir, modules_ini)
    backup_file(full_path)
    # Read Ini File
    cp = ConfigParser()
    cp.read(full_path)
    # Modify Authentication to Spacewalk module
    cp["authentication"]["module"] = "authentication.spacewalk"
    # Write Ini File
    with open(full_path, "w") as modules_conf:
        cp.write(modules_conf)


def remove_virtual_host(conf_directory: str, conf_file: str):
    """
    Replaces all occurrences of lines with "VirtualHost" with an empty one.
    
    :param conf_directory: The directory where the Apache2 configuration files are.
    :param conf_file: The file to edit.
    """
    full_path = os.path.join(conf_directory, conf_file)
    backup_file(full_path)
    with open(full_path, "r") as http_config:
        http_lines = http_config.readlines()
        for i in range(0, len(http_lines)):
            if "VirtualHost" in http_lines[i]:
                http_lines[i] = ""
    with open (full_path, 'w') as http_config_update:
        http_config_update.writelines(http_lines)


def sanitize_args(args):
    global COBBLER_CONFIG_DIRECTORY
    COBBLER_CONFIG_DIRECTORY = os.path.join(args.cobbler_config_directory, '')
    global HTTPD_CONFIG_DIRECTORY
    HTTPD_CONFIG_DIRECTORY = os.path.join(args.httpd_config_directory, '')


def main():
    """
    Main entrypoint for the script to get Cobbler in the correct state for SUMA.
    """
    args = parser.parse_args()
    sanitize_args(args)
    manipulate_cobbler_settings(COBBLER_CONFIG_DIRECTORY, COBBLER_CONFIG_FILES[1])
    manipulate_cobbler_modules(COBBLER_CONFIG_DIRECTORY, COBBLER_CONFIG_FILES[0])
    remove_virtual_host(HTTPD_CONFIG_DIRECTORY, COBBLER_HTTP_CONFIG)


if __name__ == "__main__":
    # execute only if run as a script
    main()
