#!/usr/bin/env bash
umask 0027
set -u # treat unset variables as an error

#------------------------------------------------------------------
# Library - x86_64 configuration
#------------------------------------------------------------------
# Script name: "lib_platf_x86_64"
#
#------------------------------------------------------------------

# return if library is already loaded
[[ -n "${LIB_PLATF_x86_64_RELEASE:-}" ]] && return 0

LIB_PLATF_x86_64_RELEASE='loaded'

##########################################################
# Global functions - to be used in other scripts
##########################################################

##########################################################
# Non-global functions - not to be used in other scripts
##########################################################
function __get_platform_x86_64_vendor_details {

    logTrace "<${BASH_SOURCE[0]}:${FUNCNAME[*]}>"

    if [[ -e '/sys/devices/virtual/dmi/id' ]]; then

        # read DATA
        trap '$(shopt -p extglob)' RETURN
        shopt -s extglob    #enable extended pattern matching

        #SYS_VENDOR
        if [[ -r '/sys/devices/virtual/dmi/id/sys_vendor' ]]; then
            # Vendor - IBM, Lenovo, "VMware, Inc.", "Microsoft Corporation" , "Xen" , "Google" , "Cisco Systems Inc", "Amazon EC2"
            local _lib_platf_vendor
            _lib_platf_vendor="$(</sys/devices/virtual/dmi/id/sys_vendor)"
            _lib_platf_vendor=${_lib_platf_vendor//+([[:space:]])/ }
        fi

        #PRODUCT_NAME
        if [[ -r '/sys/devices/virtual/dmi/id/product_name' ]]; then
            # Platform - "x3950 X6 -[6241ZB5]-", "ProLiant DL785 G6",
            #          - "VMware Virtual Platform", "RHEV Hypervisor" , "Virtual Machine" , "Google Compute Engine" , "HVM domU" , "VMware7,1" , "r5.8xlarge"
            local _lib_platf_name
            _lib_platf_name="$(</sys/devices/virtual/dmi/id/product_name)"
            _lib_platf_name=${_lib_platf_name//+([[:space:]])/ }
        fi

        #CHASSIS_ASSET_TAG
        if [[ -r '/sys/devices/virtual/dmi/id/chassis_asset_tag' ]]; then
            local _chassis_asset_tag
            _chassis_asset_tag="$(</sys/devices/virtual/dmi/id/chassis_asset_tag)"
            _chassis_asset_tag=${_chassis_asset_tag//+([[:space:]])/ }
        fi

        # enrich VMware - might be overwritten later on
        if [[ "${_lib_platf_vendor:-}" =~ ^VMware* ]]; then

            if [[ "${_lib_platf_name}" == 'VMware20,1' ]]; then
                LIB_PLATF_VIRT_VM_VERSION='virtualHW 21 or later (>=ESX v8.0u2)'
                _lib_platf_name='VMware UEFI'

            elif [[ "${_lib_platf_name}" == 'VMware7,1' ]]; then
                LIB_PLATF_VIRT_VM_VERSION='virtualHW 14 to 20 (>=ESX v7.0)'
                _lib_platf_name='VMware UEFI'

            elif [[ "${_lib_platf_name}" == 'VMware Virtual Platform' ]]; then
                _lib_platf_name='VMware BIOS'

            fi

            if [[ -x '/usr/bin/vmware-toolbox-cmd' ]]; then
                LIB_PLATF_VIRT_HYPER=$(grep 'version =' <(vmware-toolbox-cmd stat raw txt session version))
                LIB_PLATF_VIRT_HYPER=${LIB_PLATF_VIRT_HYPER//version = /}
            fi

        fi

        if [[ "${_lib_platf_vendor:-}" == 'Xen' ]]; then
            #special Amazon EC2 handling for Xen images

            local _bios_version
            _bios_version="$(</sys/devices/virtual/dmi/id/bios_version)"

            if LIB_FUNC_STRINGCONTAIN "${_bios_version}" 'amazon'; then

                LIB_PLATF_VENDOR='Amazon EC2'
                LIB_PLATF_VIRT_TYPE="${_lib_platf_name}" #HVM domU
                LIB_PLATF_NAME=$(curl -sf -m 10 http://169.254.169.254/latest/meta-data/instance-type)

            fi

        elif [[ "${_lib_platf_name:-}" == 'Google Compute Engine' ]]; then

            LIB_PLATF_VENDOR='Google GCP'
            _lib_platf_name=$(curl -sf -m 10 -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/machine-type)
            #projects/[NUMERIC_PROJECT_ID]/machineTypes/[MACHINE_TYPE]
            LIB_PLATF_NAME=${_lib_platf_name//*machineTypes\//}

        elif [[ "${_chassis_asset_tag:-}" == '7783-7084-3265-9085-8269-3286-77' ]]; then

            LIB_PLATF_VENDOR='Microsoft Azure'
            _lib_platf_name=$(curl -sf -m 10 -H "Metadata:true" --noproxy "*" "http://169.254.169.254/metadata/instance/compute/vmSize?api-version=2020-09-01&format=text")
            [[ "${_lib_platf_name}" =~ ^Standard_* ]] && LIB_PLATF_NAME=${_lib_platf_name}

        elif [[ "${_lib_platf_name:-}" == 'Alibaba Cloud ECS' ]]; then

            LIB_PLATF_VENDOR='Alibaba Cloud ECS'
            LIB_PLATF_NAME=$(curl -sf -m 10 http://100.100.100.200/latest/meta-data/instance/instance-type)

        elif [[ "${_chassis_asset_tag:-}" == 'HUAWEICLOUD' ]]; then

            LIB_PLATF_VENDOR='Huawei Cloud'
            LIB_PLATF_NAME=$(curl -sf -m 10 http://169.254.169.254/latest/meta-data/instance-type)

        elif [[ "${_chassis_asset_tag:-}" == 'HuaweiFusionSphere' ]]; then

            LIB_PLATF_VENDOR='Huawei'
            LIB_PLATF_NAME='FusionSphere'

        elif [[ "${_chassis_asset_tag:-}" == 'ibmcloud' ]]; then

            LIB_PLATF_VENDOR='IBM Cloud VPC'

            _lib_platf_name="$(</sys/devices/virtual/dmi/id/chassis_vendor)"
            #IBM:Cloud Compute Server 1.0:bx2-2x8
            LIB_PLATF_NAME=${_lib_platf_name//*:/}

        elif [[ "${_chassis_asset_tag:-}" == 'IBM SoftLayer' ]]; then

            LIB_PLATF_VENDOR='IBM Cloud Classic'
            LIB_PLATF_NAME='Not available'

        elif [[ "${_chassis_asset_tag:-}" == "SAP CCloud VM" ]]; then

            LIB_PLATF_VENDOR='SAP Converged Cloud'
            LIB_PLATF_NAME=$(curl -sf -m 10  http://169.254.169.254/latest/meta-data/instance-type)

        else

            #all others - Amazon EC2 KVM, Bare-Metal, VMware etc.
            [[ -z "${LIB_PLATF_VENDOR:-}" ]] && LIB_PLATF_VENDOR="${_lib_platf_vendor}"
            [[ -z "${LIB_PLATF_NAME:-}" ]] && LIB_PLATF_NAME="${_lib_platf_name}"

        fi

        [[ -z "${LIB_PLATF_VENDOR:-}" ]] && LIB_PLATF_VENDOR='N/A'
        [[ -z "${LIB_PLATF_NAME:-}" ]] && LIB_PLATF_NAME='N/A'
        readonly LIB_PLATF_VENDOR
        readonly LIB_PLATF_NAME

    fi

}

function __get_platform_x86_64_cpu_details {

    logTrace "<${BASH_SOURCE[0]}:${FUNCNAME[*]}>"

    while read -r line ; do

        logTrace "<${FUNCNAME[0]}> # lscpu:${line}>"

        case ${line} in

        'Architecture:'*)
                            if [[ -z ${LIB_PLATF_ARCHITECTURE:-} ]]; then
                                LIB_PLATF_ARCHITECTURE=$(LIB_FUNC_TRIM_LEFT "${line/Architecture:}")
                                readonly LIB_PLATF_ARCHITECTURE
                            fi
        ;;

        'Thread(s) per core:'*)
                            if [[ -z ${LIB_PLATF_CPU_THREADSPERCORE:-} ]]; then
                                LIB_PLATF_CPU_THREADSPERCORE=$(LIB_FUNC_TRIM_LEFT "${line/Thread(s) per core:}")
                                readonly LIB_PLATF_CPU_THREADSPERCORE
                            fi
        ;;

        'Core(s) per socket:'*)
                            if [[ -z ${LIB_PLATF_CPU_CORESPERSOCKET:-} ]]; then
                                LIB_PLATF_CPU_CORESPERSOCKET=$(LIB_FUNC_TRIM_LEFT "${line/Core(s) per socket:}")
                                readonly LIB_PLATF_CPU_CORESPERSOCKET
                            fi
        ;;

        'Socket(s):'*)
                            if [[ -z ${LIB_PLATF_CPU_SOCKETS:-} ]]; then
                                LIB_PLATF_CPU_SOCKETS=$(LIB_FUNC_TRIM_LEFT "${line/Socket(s):}")
                                readonly LIB_PLATF_CPU_SOCKETS
                            fi
        ;;

        'NUMA node(s):'*)
                            if [[ -z ${LIB_PLATF_CPU_NUMANODES:-} ]]; then
                                LIB_PLATF_CPU_NUMANODES=$(LIB_FUNC_TRIM_LEFT "${line/NUMA node(s):}")
                                readonly LIB_PLATF_CPU_NUMANODES
                            fi
        ;;

        'Vendor ID:'*)
                            #GenuineIntel; AuthenticAMD
                            if [[ -z ${LIB_PLATF_CPU_VENDOR:-} ]]; then
                                LIB_PLATF_CPU_VENDOR=$(LIB_FUNC_TRIM_LEFT "${line/Vendor ID:}")
                                readonly LIB_PLATF_CPU_VENDOR
                            fi
        ;;

        'Model:'*)
                            #on Intel <Model: 63>
                            LIB_PLATF_CPU_MODELID=$(LIB_FUNC_TRIM_LEFT "${line/Model:}")
                            readonly LIB_PLATF_CPU_MODELID
        ;;

        'Model name:'*)
                            #on x64 only
                            #<Intel(R) Xeon(R) CPU E7-8880 v3 @ 2.30GHz>; AMD Opteron 23xx (Gen 3 Class Opteron)
                            if [[ -z ${LIB_PLATF_CPU:-} ]]; then
                                LIB_PLATF_CPU=$(LIB_FUNC_TRIM_LEFT "${line/Model name:}")
                                readonly LIB_PLATF_CPU
                            fi
        ;;

        'Stepping:'*)
                            LIB_PLATF_CPU_STEPID=$(LIB_FUNC_TRIM_LEFT "${line/Stepping:}")
                            readonly LIB_PLATF_CPU_STEPID
        ;;

        # Virtualization information provided by lscpu version >=2.19 and only if virtualized
        # x64:  ( VMware - full ) ; ( KVM - full ) = RHEV ; ( Xen - none ) ; ( Xen - full ) = Amazon EC2

        'Hypervisor vendor:'*)
                            if [[ -z ${LIB_PLATF_VIRT_HYPER:-} ]]; then
                                LIB_PLATF_VIRT_HYPER=$(LIB_FUNC_TRIM_LEFT "${line/Hypervisor vendor:}")
                                readonly LIB_PLATF_VIRT_HYPER
                            fi
        ;;

        'Virtualization type:'*)
                            local _lib_platform_virt_type
                            _lib_platform_virt_type=$(LIB_FUNC_TRIM_LEFT "${line/Virtualization type:}")

                            if [[ -z ${LIB_PLATF_VIRT_TYPE:-} ]]; then
                                LIB_PLATF_VIRT_TYPE=${_lib_platform_virt_type}
                            else
                                LIB_PLATF_VIRT_TYPE="${_lib_platform_virt_type} (${LIB_PLATF_VIRT_TYPE})"
                            fi
                            readonly LIB_PLATF_VIRT_TYPE
        ;;

        'NUMA node0'* )    break ;;

        esac

    done <<< "$(lscpu)"

    if [[ -z ${LIB_PLATF_CPU:-} ]]; then

        LIB_PLATF_CPU=$(grep  'model name' -m 1 /proc/cpuinfo)
        LIB_PLATF_CPU=$(LIB_FUNC_TRIM_LEFT "${LIB_PLATF_CPU/model name[[:blank:]]:}")

        readonly LIB_PLATF_CPU
    fi

}


#============================================================
# LIB MAIN - initialization
#============================================================
function _lib_platf_x86_64_main {

    logTrace "<${BASH_SOURCE[0]}:${FUNCNAME[*]}>"

    __get_platform_x86_64_vendor_details
    __get_platform_x86_64_cpu_details

    #readonly <AnyVariable>
}

#Import libraries
#shellcheck source=./saphana-logger
source "$( cd "${BASH_SOURCE[0]%/*}" && pwd )/saphana-logger" ||
                { echo 'unable to load saphana-logger library' >&2; exit 1; }
#shellcheck source=./saphana-helper-funcs
source "$( cd "${BASH_SOURCE[0]%/*}" && pwd )/saphana-helper-funcs" ||
                { echo 'unable to load saphana-helper-funcs library' >&2; exit 1; }
#LIB LOCAL

#GLOBAL
#don't use declare here ... file is sourced within function, which would restrict visibility

#CALL MAIN
_lib_platf_x86_64_main
