# Directory where this plugin.sh file is
TOBIKO_PLUGIN_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)

# NOTE(slaweq): Tobiko requires admin endpoint for keystone to be enabled,
# creation of such endpoint was disabled by default with:
# https://github.com/openstack/devstack/commit/b538b3267cec11f0b345ce101607bbd36ada8f32
# so let's enable it always when Tobiko is installed
KEYSTONE_ADMIN_ENDPOINT=True

TOX_MIN_VERSION="4.13"
if [ "$REQUIREMENTS_BRANCH" == "stable/2023.2" ]; then
    TOX_MIN_VERSION="4.5.1"
elif [[ "$REQUIREMENTS_BRANCH" == "stable/2023.1" ]] || [[ "$REQUIREMENTS_BRANCH" == "stable/zed" ]]; then
    TOX_MIN_VERSION="3.28"
fi

function install_tobiko_deps {
    install_python3
    git_clone "${TOBIKO_REPO}" "${TOBIKO_DIR}" "${TOBIKO_VERSION}"
    install_bindep "${TOBIKO_DIR}/bindep.txt" test
    pip_install "tox>=${TOX_MIN_VERSION}"
}


function configure_libguestfs_tools {
    local target_path
    if is_ubuntu; then
        target_path=/boot/vmlinuz-`uname -r`
        if ! dpkg-statoverride --list "${target_path}"; then
            sudo dpkg-statoverride --update --add root root 0644 \
                "${target_path}"
        fi
    fi
}


function configure_tobiko {
    # Ensure any user can write to log file
    local log_dir
    log_dir=$(dirname ${TOBIKO_LOG_FILE})
    if ! [ -d "${log_dir}" ]; then
        sudo mkdir -p "${log_dir}"
    fi
    if ! [ -w "${TOBIKO_LOG_FILE}" ]; then
        sudo touch "${TOBIKO_LOG_FILE}"
        sudo chmod ugo+rw "${TOBIKO_LOG_FILE}"
    fi

    # Write configuration to a new temporary file
    local tobiko_conf_file
    tobiko_conf_file=$(mktemp)
    if [ -f "${TOBIKO_CONF_FILE}" ]; then
        # Start from existing tobiko.conf file
        cp "${TOBIKO_CONF_FILE}" "${tobiko_conf_file}"
    fi

    configure_tobiko_default "${tobiko_conf_file}"
    configure_tobiko_cirros "${tobiko_conf_file}"
    configure_tobiko_glance "${tobiko_conf_file}"
    configure_tobiko_keystone "${tobiko_conf_file}"
    configure_tobiko_nova "${tobiko_conf_file}"
    configure_tobiko_neutron "${tobiko_conf_file}"
    configure_tobiko_ssh "${tobiko_conf_file}"
    configure_tobiko_tripleo "${tobiko_conf_file}"
    configure_tobiko_octavia "${tobiko_conf_file}"

    echo_summary "Apply changes to actual ${TOBIKO_CONF_FILE} file."
    sudo mkdir -p $(dirname "${TOBIKO_CONF_FILE}")
    sudo mv "${tobiko_conf_file}" "${TOBIKO_CONF_FILE}"
    sudo chmod ugo+r "${TOBIKO_CONF_FILE}"

    echo "${TOBIKO_CONF_FILE} file content:"
    echo --------------------------------
    cat "${TOBIKO_CONF_FILE}"
    echo --------------------------------
}


function configure_tobiko_cirros {
    echo_summary "Write [cirros] section to ${TOBIKO_CONF_FILE}"
    local tobiko_conf_file=$1

    iniset_nonempty "${tobiko_conf_file}" cirros name \
        "${TOBIKO_CIRROS_IMAGE_NAME}"
    iniset_nonempty "${tobiko_conf_file}" cirros url \
        "${TOBIKO_CIRROS_IMAGE_URL}"
    iniset_nonempty "${tobiko_conf_file}" cirros file \
        "${TOBIKO_CIRROS_IMAGE_FILE}"
    iniset_nonempty "${tobiko_conf_file}" cirros username \
        "${TOBIKO_CIRROS_USERNAME}"
    iniset_nonempty "${tobiko_conf_file}" cirros password \
        "${TOBIKO_CIRROS_PASSWORD}"
}


function configure_tobiko_default {
    echo_summary "Write [DEFAULT] section to ${TOBIKO_CONF_FILE}"
    local tobiko_conf_file=$1

    setup_logging "${tobiko_conf_file}"
    iniset ${tobiko_conf_file} DEFAULT debug "${TOBIKO_DEBUG}"
    iniset ${tobiko_conf_file} DEFAULT log_dir $(dirname "${TOBIKO_LOG_FILE}")
    iniset ${tobiko_conf_file} DEFAULT log_file \
        $(basename "${TOBIKO_LOG_FILE}")
}


function configure_tobiko_glance {
    echo_summary "Write [glance] section to ${TOBIKO_CONF_FILE}"
    local tobiko_conf_file=$1

    iniset_nonempty "${tobiko_conf_file}" glance image_dir \
        "${TOBIKO_GLANCE_IMAGE_DIR}"

    ensure_boot_files_permissions
}


function ensure_boot_files_permissions {
    if [ -f /boot/vmlinuz ]; then
        sudo chmod ugo+r /boot/vmlinuz
    fi
}


function configure_tobiko_keystone {
    echo_summary "Write [keystone] section to ${TOBIKO_CONF_FILE}"
    local tobiko_conf_file=$1

    local api_version=${IDENTITY_API_VERSION}
    if [ "${api_version}" == '2' ]; then
        local auth_url=${KEYSTONE_AUTH_URI/v2.0}
    else
        local auth_url=${KEYSTONE_AUTH_URI_V3:-${KEYSTONE_AUTH_URI/v3}}
    fi

    local project_id
    project_id=$(get_or_create_project \
        "${TOBIKO_KEYSTONE_PROJECT_NAME}" \
        "${TOBIKO_KEYSTONE_PROJECT_DOMAIN_NAME}")

    local user_id
    user_id=$(get_or_create_user \
        "${TOBIKO_KEYSTONE_USERNAME}" \
        "${TOBIKO_KEYSTONE_PASSWORD}" \
        "${TOBIKO_KEYSTONE_USER_DOMAIN_NAME}")

    local user_project_role_id
    user_project_role_id=$(get_or_add_user_project_role \
        "${TOBIKO_KEYSTONE_USER_ROLE}" \
        "${user_id}" \
        "${project_id}")

    local user_domain_role_id
    user_domain_role_id=$(get_or_add_user_domain_role \
        "${TOBIKO_KEYSTONE_USER_ROLE}" \
        "${user_id}" \
        "${TOBIKO_KEYSTONE_USER_DOMAIN_NAME}")

    iniset "${tobiko_conf_file}" keystone cloud_name \
        "${TOBIKO_KEYSTONE_CLOUD_NAME}"
    iniset "${tobiko_conf_file}" keystone api_version "${api_version}"
    iniset "${tobiko_conf_file}" keystone auth_url "${auth_url}"
    iniset "${tobiko_conf_file}" keystone username \
        "${TOBIKO_KEYSTONE_USERNAME}"
    iniset "${tobiko_conf_file}" keystone password \
        "${TOBIKO_KEYSTONE_PASSWORD}"
    iniset "${tobiko_conf_file}" keystone project_name \
        "${TOBIKO_KEYSTONE_PROJECT_NAME}"

    if [ "${api_version}" != '2' ]; then
        iniset "${tobiko_conf_file}" keystone domain_name \
            "${TOBIKO_KEYSTONE_DOMAIN_NAME}"
        iniset "${tobiko_conf_file}" keystone user_domain_name \
            "${TOBIKO_KEYSTONE_USER_DOMAIN_NAME}"
        iniset "${tobiko_conf_file}" keystone project_domain_name \
            "${TOBIKO_KEYSTONE_PROJECT_DOMAIN_NAME}"
        iniset "${tobiko_conf_file}" keystone trust_id \
            "${TOBIKO_KEYSTONE_TRUST_ID}"
    fi
}


function configure_tobiko_nova {
    echo_summary "Write [nova] section to ${TOBIKO_CONF_FILE}"
    local tobiko_conf_file=$1

    (
        cd $(dirname "${tobiko_conf_file}")
        configure_key_file "${tobiko_conf_file}" nova key_file \
            "${TOBIKO_NOVA_KEY_FILE}"
    )
}


function configure_tobiko_neutron {
    echo_summary "Write [neutron] section to ${TOBIKO_CONF_FILE}"
    local tobiko_conf_file=$1

    iniset_nonempty "${tobiko_conf_file}" neutron external_network \
        "${TOBIKO_NEUTRON_EXTERNAL_NETWORK}"
    iniset_nonempty "${tobiko_conf_file}" neutron floating_network \
        "${TOBIKO_NEUTRON_FLOATING_NETWORK}"
    iniset_nonempty "${tobiko_conf_file}" neutron ipv4_dns_nameservers \
        "${TOBIKO_NEUTRON_IPV4_DNS_NAMESERVERS}"
    iniset_nonempty "${tobiko_conf_file}" neutron ipv6_dns_nameservers \
        "${TOBIKO_NEUTRON_IPV6_DNS_NAMESERVERS}"
}


function configure_tobiko_ssh {
    echo_summary "Write [ssh] section to ${TOBIKO_CONF_FILE}"
    local tobiko_conf_file=$1

    (
        cd $(dirname "${tobiko_conf_file}")
        configure_key_file "${tobiko_conf_file}" ssh key_file \
            "${TOBIKO_SSH_KEY_FILE}"
    )
}


function configure_tobiko_tripleo {
    echo_summary "Write [tripleo] section to ${TOBIKO_CONF_FILE}"
    local tobiko_conf_file=$1

    # Ensure Tobiko will skip looking for the undercloud node
    iniset "${tobiko_conf_file}" tripleo undercloud_ssh_hostname ""
}


function configure_tobiko_octavia {
    echo_summary "Write [octavia] section to ${TOBIKO_CONF_FILE}"
    local tobiko_conf_file=$1

    # Ensure Tobiko will skip looking for the undercloud node
    iniset_nonempty "${tobiko_conf_file}" octavia check_timeout \
        "${TOBIKO_OCTAVIA_CHECK_TIMEOUT}"
}


function configure_key_file {
    local tobiko_conf_file=$1

    ensure_key_file "${key_file}"
    iniset_nonempty "$@"
}


function ensure_key_file {
    local key_file=${1:-~/.ssh/id_rsa}
    # Ensure key file exists
    if ! [ -r "${key_file}" ]; then
        mkdir -p $(dirname "${key_file}")
        ssh-keygen -f "${key_file}" -N ""
    fi

    # Ensure Tobiko can SSH localhost using key file
    local pub_key
    pub_key=$(cat "${key_file}.pub")
    if ! grep "${pub_key}" ~/.ssh/authorized_keys; then
        cat "${key_file}.pub" >> ~/.ssh/authorized_keys
    fi
    chmod 600 "${key_file}" "${key_file}.pub" ~/.ssh/authorized_keys
}


function iniset_nonempty {
    # Calls iniset only when option value is not an empty string
    if [ -n "$4" ]; then
        iniset "$@"
    fi
}


if [[ "$1" == "stack" ]]; then
    case "$2" in
        install)
            echo_summary "Installing Tobiko dependencies"
            install_tobiko_deps
            configure_libguestfs_tools
            ;;
        test-config)
            echo_summary "Configuring Tobiko test cases"
            configure_tobiko
            ;;
    esac
fi