#!/usr/bin/env python3

# SPDX-FileCopyrightText: 2009 Fermi Research Alliance, LLC
# SPDX-License-Identifier: Apache-2.0

# Description:
#  This program creates a glidein factory directory structure
#  based on a configuration file


import os
import shutil
import sys
import tarfile
import traceback

from glideinwms.creation.lib import cgWConsts, cgWCreate, cgWParamDict, factoryXmlConfig

STARTUP_DIR = sys.path[0]
sys.path.append(os.path.join(STARTUP_DIR, "../.."))


################################################################################


def main(conf):
    # print params.__dict__
    glidein_dicts_obj = cgWParamDict.glideinDicts(conf)

    try:
        glidein_dicts_obj.populate()
    except cgWParamDict.UnconfiguredScheddError as e:
        print(e.err_str)
        sys.exit(1)

    glidein_dicts_obj.create_dirs()
    try:
        # save files in dictionaries
        glidein_dicts_obj.save()
        glidein_dicts_obj.set_readonly(True)

        # copy the submit files
        cgWCreate.copy_exe(cgWConsts.STARTUP_FILE, glidein_dicts_obj.main_dicts.work_dir, cgWConsts.WEB_BASE_DIR)
        cgWCreate.copy_exe(cgWConsts.LOCAL_START_WRAPPER, glidein_dicts_obj.main_dicts.work_dir, cgWConsts.WEB_BASE_DIR)

        # augment glidein_startup.sh, appending the utility files/data to glidein_startup_base.sh as tarball:
        # create tarball of files to be later sourced and shared between scripts
        tar_file_list = cgWConsts.STARTUP_FILE_PAYLOAD
        try:
            with tarfile.open("tar_utils.tar.gz", "w:gz", dereference=True) as tar_utils:
                for util_file in tar_file_list:
                    util_file_path = os.path.join(cgWConsts.WEB_BASE_DIR, util_file)
                    tar_utils.add(util_file_path, arcname=os.path.basename(util_file_path))
        except tarfile.TarError as terr:
            print("Unable to pack the startup file payload. TarError: %s" % str(terr))
            sys.exit(1)
        # append the the tarball to glidein_startup.sh
        try:
            with open(os.path.join(glidein_dicts_obj.main_dicts.work_dir, cgWConsts.STARTUP_FILE), "a") as st_file:
                st_file.write("exit 0\n#EOF\n")
                with open("tar_utils.tar.gz", "rb") as tar_utils:
                    shutil.copyfileobj(tar_utils, st_file)
        except OSError as ioe:
            print("Unable to append the payload to the startup file. IOError [%d]: %s" % (ioe.errno, ioe.strerror))
            sys.exit(1)
        os.remove("tar_utils.tar.gz")

        # copy glidein_startup.sh from work dir (the version w/ the utility files) to the stage area for cloud entries
        cgWCreate.copy_exe(
            cgWConsts.STARTUP_FILE, glidein_dicts_obj.main_dicts.stage_dir, glidein_dicts_obj.main_dicts.work_dir, True
        )

        # copy helper executables
        cgWCreate.copy_exe(cgWConsts.UPDATE_PROXY_FILE, glidein_dicts_obj.main_dicts.work_dir, cgWConsts.WEB_BASE_DIR)

        # create the init.d startup file
        cgWCreate.create_initd_startup(
            os.path.join(glidein_dicts_obj.main_dicts.work_dir, cgWConsts.INITD_STARTUP_FILE),
            glidein_dicts_obj.main_dicts.work_dir,
            os.path.realpath(os.path.join(STARTUP_DIR, "..")),
            conf.file,
        )
    except:
        glidein_dicts_obj.delete_dirs()
        raise

    print("Created glidein '%s'" % conf["glidein_name"])
    print("Active entries are:")
    for entry in glidein_dicts_obj.active_sub_list:
        print("  %s" % entry)
    print("Submit files can be found in %s" % glidein_dicts_obj.main_dicts.work_dir)
    print("Log files can be found in %s" % glidein_dicts_obj.main_dicts.log_dir)
    print("Support files are in %s" % glidein_dicts_obj.main_dicts.stage_dir)
    print("Monitoring files are in %s" % glidein_dicts_obj.main_dicts.monitor_dir)


############################################################
#
# S T A R T U P
#
############################################################

if __name__ == "__main__":
    usage = "create_glidein [-writeback yes|no] [-debug] cfg_fname | -help"
    argv = sys.argv
    writeback = "yes"
    debug = False
    while len(argv) > 2:
        if argv[1] == "-writeback":
            writeback = argv[2]
            argv = argv[0:1] + argv[3:]
        elif argv[1] == "-debug":
            debug = True
            argv = argv[0:1] + argv[2:]
        else:
            break

    xml = argv[1]
    conf = factoryXmlConfig.parse(xml)

    if writeback not in ("yes", "no"):
        print(usage)
        print("")
        print("-writeback must be yes or no, found '%s'" % writeback)
        sys.exit(1)

    try:
        main(conf)
    except RuntimeError as e:
        if debug:
            tb = traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])
            print("\n".join(tb))
        print(usage)
        print("")
        print(e)
        sys.exit(1)
