#!/bin/sh

set -e
#set -x

PRODUCT_NAME=$(dmidecode -t 1 | grep "Product Name" | sed -e "s/[ \t]*Product Name:[ ]*//"  -e "s/,//g")

# Use flock to avoid launching the agent twice at once
LOCKDIR=/var/run/lock
LOCKFILE=${LOCKDIR}/$(basename ${0})
if [ "${1}" = "--nolock" ] ; then
	shift
else
	echo "===> Claming lock for $0 in ${LOCKFILE}"
	if ! flock -w 120 -x ${LOCKFILE} $0 --nolock $@ ; then
		exit 1
	fi
	exit 0
fi

# We need the server to report to, otherwise this agent is useless
if [ -r /etc/oci/pxe-server-ip ] ; then
	PXE_SERVER_IP=$(cat /etc/oci/pxe-server-ip)
else
	echo "No /etc/oci/pxe-server-ip: refusing to start."
	exit 1
fi

# Check if the OCI server has port 80 open before doing anything
if netcat -z ${PXE_SERVER_IP} 80 ; then
	echo -n ""
else
	echo "Port 80 is not open on host ${PXE_SERVER_IP}: refusing to start."
	exit 1
fi

# Get a device name in the order proposed by /dev/disk/oci-sort
# instead of /dev/sdX. If the device isn't listed in /dev/disk/oci-sort
# this function just return the device name as found in /dev.
get_oci_sort_devname () {
	local devname
	devname=${1}
	# Attempt to find the "real" device name from /dev/disk/oci-sort
	if [ -d /dev/disk/oci-sort ] ; then
		for symlink in $(ls /dev/disk/oci-sort) ; do
			if [ ""$(basename $(realpath /dev/disk/oci-sort/${symlink})) = "${devname}" ] ; then
				RET=${symlink}
				return
			fi
		done
	fi
	RET=${devname}
	return
}

###################################
### START OF HARDWARD DISCOVERY ###
###################################
### Get all disks:

echo "===> Fetching block devices with lsblk"

TMPFILE=$(mktemp -t openstack-cluster-installer-agent.XXXXXX)
lsblk -b -l -d -J --exclude 2,7,11 -o +TRAN,MODEL  >${TMPFILE}
TMPFILE2=$(mktemp -t openstack-cluster-installer-agent.XXXXXX)
if [ "$(cat ${TMPFILE} | wc -l)" = "0" ] ; then
	# No disk present
	echo '{
   "blockdevices": [
   ],
' >${TMPFILE2}
else
	echo '{
   "blockdevices": [' >>$TMPFILE2
	FIRST=yes
	# Remove iscsi disks (probably cinder volume mounted on a compute node)
	# and any USB device (probably from the KVM over IP of the hardware IPMI)
	if [ "${PRODUCT_NAME}" = "DSS 1510" ] || [ "${PRODUCT_NAME}" = "DSS1510" ] || [ "${PRODUCT_NAME}" = "PowerEdge R420" ] || [ "${PRODUCT_NAME}" = "PowerEdge R440" ] ; then
		USB_FILTER='.tran != "iscsi"'
	else
		USB_FILTER='(.tran != "iscsi") and (.tran != "usb")'
	fi
	for devname in $(cat ${TMPFILE} | jq -r ".[\"blockdevices\"][] | select(${USB_FILTER}) | . [\"name\"]") ; do
		get_oci_sort_devname ${devname}
		reported_devname=${RET}
		devsize=$(cat ${TMPFILE} | jq -r '.["blockdevices"][] | select(.name == "'${devname}'") | . ["size"]')
		devmodel=$(cat ${TMPFILE} | jq -r '.["blockdevices"][] | select(.name == "'${devname}'") | . ["model"]')
		if [ "${FIRST}" = "yes" ] ; then
			FIRST=no
		else
			echo ',' >>$TMPFILE2
		fi
		echo -n '      { "name": "'${reported_devname}'", "realdev": "'${devname}'", "size": "'${devsize}'", "model": "'${devmodel}'" }' >>$TMPFILE2
	done
	echo '
   ],' >>$TMPFILE2
fi

# Do we have hardware RAID (to configure with megacli) ?
LSPCI_OUT=$(lspci | grep -i MegaRAID | head -n 1)
if lshw -class storage -json 2>/dev/null | jq -r '.[]["id"]' | grep -q raid && echo "${LSPCI_OUT}" | grep -q MegaRAID; then
	if [ -x ""$(which megacli) ] ; then
		echo "===> Fetching MegaRAID block devices"
		ENCLOSURE=$(megacli -EncInfo -aALL -NoLog | awk '/Device ID/ {print $4}')
		PHYSDEVS=""
		for SLOT_NUM in $(megacli -pdlist -a0 -NoLog | grep "Slot Number:" | cut -d':' -f2 | awk '{print $1}') ; do
			MODEL=$(megacli -pdInfo -PhysDrv[${ENCLOSURE}:${SLOT_NUM}] -aall | grep "Inquiry Data:" | sed 's/Inquiry Data: //' | awk '{print substr($0,21,40)}' | sed -e 's/[ ]*$//' -e 's/^[ ]*//')
			SERIAL=$(megacli -pdInfo -PhysDrv[${ENCLOSURE}:${SLOT_NUM}] -aall | grep "Inquiry Data:" | sed 's/Inquiry Data: //' | awk '{print substr($0,0,21)}' | sed -e 's/[ ]*$//' -e 's/^[ ]*//')

			SECTOR_NUM_HEX=$(megacli -pdInfo -PhysDrv[${ENCLOSURE}:${SLOT_NUM}] -aall | grep "Non Coerced Size:" | sed 's/Non Coerced Size: //' | cut -d'[' -f2 | cut -d' ' -f1)
			SECTOR_NUM=$(printf "%d" ${SECTOR_NUM_HEX})
			SECTOR_SIZE=$(megacli -pdInfo -PhysDrv[${ENCLOSURE}:${SLOT_NUM}] -aall | grep "^Sector Size:" | sed 's/Sector Size://' | awk '{print $1}')
			if [ "${SECTOR_SIZE}" = 0 ] ; then
				SECTOR_SIZE=512
			fi
			SIZE=$(( ${SECTOR_NUM} * ${SECTOR_SIZE}))

			FULL_STATE=$(megacli -PDInfo -PhysDrv [${ENCLOSURE}:${SLOT_NUM}] -aALL -NoLog | grep -E '^Firmware state: ' | sed 's/Firmware state: //')
			STATE=$(echo ${FULL_STATE} | cut -d, -f1)
			SPUN=$(echo ${FULL_STATE} | cut -d, -f2 | awk '{$1=$1;print}')
			HDD_SPEC='{
		"slot": "'${SLOT_NUM}'",
		"model": "'${MODEL}'",
		"serial": "'${SERIAL}'",
		"size": "'${SIZE}'",
		"state": "'${STATE}'"
	}'
			if [ -n "${PHYSDEVS}" ] ; then
				PHYSDEVS="${PHYSDEVS},\n"
			fi
			PHYSDEVS="${PHYSDEVS}${HDD_SPEC}"
		done
		echo '   "phys-blockdevices": [
		'${PHYSDEVS}'
	   ],' >>${TMPFILE2}
	fi
fi

echo -n "===> Fetching network device information: "

### Get all interface names
echo '   "interfaces": [' >>${TMPFILE2}
for i in $(ip link show | grep -v '^ ' | grep -v 'lo:' | cut -d' ' -f2 | cut -d: -f1 | grep -v vlan | grep -v -E 'bond|.*@.*|qvb.*|qvo.*|vxlan.*|tap.*|qbr.*|qr.*|sg-.*|ha-.*|ovs.*|qg-.*|sg-.*|fg-.*|ovs-system|br-ex|br-int|br-tun|vlan.*|usb.*|docker0|kube-ipvs0|nodelocaldns|idrac|cali.*@if\d|enx.*') ; do
	echo -n "$i "
	MAC_ADDR=$(ip link show dev $i | grep 'link/ether' | awk '{print $2}')
	NET_FIRMWARE_VERSION=$(ethtool -i $i | grep firmware-version: | awk -F"[, ]" '{print $2}')
	if [ -z "${NET_FIRMWARE_VERSION}" ] ; then
		NET_FIRMWARE_VERSION=$(ethtool -i $i | grep -E '^version:' | sed -e 's/^version: //' | awk '{print $1}')
	fi
	NET_DRIVER_NAME=$(ethtool -i $i | grep driver | sed -e 's/driver: //' | awk '{print $1}')
	LSHW_SPEED=$(lshw -class network -json 2>/dev/null | jq '.[] | select(.serial == "'${MAC_ADDR}'") | .capacity' | head -n 1)
	if [ -n "${LSHW_SPEED}" ] ; then
		ETH_SPEED=$(( ${LSHW_SPEED} / 1000000 ))
	else
		# If we can't find a speed, let's report it as 100 MBits/s
		ETH_SPEED=100
	fi

        # Find the neighbors using lldpcli
	if lldpcli -f json show neighbors | jq -r '.[]["interface"] | keys[]' | grep -q $i ; then
		TMPFILE_LLDP=$(mktemp -t openstack-cluster-installer-agent.XXXXXX)
		lldpcli -f json show neighbors | jq -r '.[]["interface"] | "\(.'${i}')"' | grep -v null >${TMPFILE_LLDP}
		SWITCHPORT_NAME=$(cat ${TMPFILE_LLDP} | jq -r '.["port"]["id"]["value"]')
		SWITCH_HOSTNAME=$(cat ${TMPFILE_LLDP} | jq -r '.["chassis"] | keys[]')
		rm -f ${TMPFILE_LLDP}
	elif lldpcli -f json show neighbors | jq -r '.[]["interface"][] | keys[]' | grep -q $i ; then
                TMPFILE_LLDP=$(mktemp -t openstack-cluster-installer-agent.XXXXXX)
                lldpcli -f json show neighbors | jq -r '.[]["interface"][] | "\(.'${i}')"' | grep -v null >${TMPFILE_LLDP}
                SWITCHPORT_NAME=$(cat ${TMPFILE_LLDP} | jq -r '.["port"]["id"]["value"]')
                SWITCH_HOSTNAME=$(cat ${TMPFILE_LLDP} | jq -r '.["chassis"] | keys[]')
                rm -f ${TMPFILE_LLDP}
        else
                SWITCHPORT_NAME='unknown'
                SWITCH_HOSTNAME='unknown'
        fi
        echo '      {"name": "'${i}'", "macaddr": "'${MAC_ADDR}'", "max_speed": "'${ETH_SPEED}'", "switchport_name": "'${SWITCHPORT_NAME}'", "switch_hostname": "'${SWITCH_HOSTNAME}'", "firmware_version": "'${NET_FIRMWARE_VERSION}'", "driver": "'${NET_DRIVER_NAME}'" },' >>${TMPFILE2}
done
echo ""
NMU_LINES=$(cat ${TMPFILE2} | wc -l)
sed -i ${NMU_LINES}'s/,$//' ${TMPFILE2}
# End the section
echo '   ],' >>${TMPFILE2}

echo "===> Fetching baseboard info with dmidecode"

### Chassis serial number, product name, BIOS version, IPMI version, IPMI ip
SYSTEM_MANUFACTURER=$(dmidecode -s system-manufacturer)

case $SYSTEM_MANUFACTURER in
	"HPE"|"Dell"|"Dell Inc."|"Acer"|"LinuxKVM"|"OpenStack Nova"|"GIGABYTE")
		SYSTEM_SERIAL=$(dmidecode -s system-serial-number)
	;;
	"LENOVO"|"Lenovo")
		SYSTEM_SERIAL=$(dmidecode -s chassis-serial-number)
	;;
	# Supermicro is stupid, dmidecode -s system-serial-number
	# will always return 1234567890
	"Supermicro")
		SYSTEM_SERIAL=$(dmidecode -s baseboard-serial-number)
	;;
	# Fallback for all other (possibly broken?) motherboards.
	# Please contribute as you see issues.
	*)
		SYSTEM_SERIAL=$(dmidecode -s baseboard-serial-number)
		if [ -z "${SYSTEM_SERIAL}" ] ; then
			SYSTEM_SERIAL=$(dmidecode -s system-serial-number)
		fi
	;;
esac

PRODUCT_NAME=$(dmidecode -t 1 | grep "Product Name" | sed -e "s/[ \t]*Product Name:[ ]*//"  -e "s/,//g")
BIOS_VENDOR=$(dmidecode -s bios-vendor)
case ${BIOS_VENDOR} in
"GIGABYTE"|"HPE")
	BIOS_VERSION=$(dmidecode -s bios-revision)
;;
*)
	BIOS_VERSION=$(dmidecode -s bios-version)
;;
esac

echo "===> Fetching CPU info"
CPU_VENDOR=$(lscpu | grep "^Vendor ID:" | sed 's/Vendor ID:[ ]*//')
CPU_THREADS=$(lscpu | grep '^CPU(s):' | sed 's/CPU(s):[ ]*//')
CPU_CORE_PER_SOCKET=$(lscpu | grep '^Core(s) per socket:' | sed 's/Core(s) per socket:[ ]*//')
CPU_SOCKETS=$(lscpu | grep '^Socket(s):' | sed 's/Socket(s):[ ]*//')
CPU_MODEL_NAME=$(lscpu | grep '^Model name:' | sed 's/Model name:[ ]*//')
CPU_MHZ=$(lscpu | grep '^CPU MHz:' | sed 's/CPU MHz:[ ]*//')

echo "===> Fetching storage controllers"
TMPSTRAGE_CTRL=$(mktemp -t openstack-cluster-installer-agent_storage_ctrl.XXXXXX)
lshw -class storage -json 2>/dev/null >${TMPSTRAGE_CTRL}
echo '   "blkdev_ctrl": [' >>${TMPFILE2}
START=""
for store_ctrl_handle in $(cat ${TMPSTRAGE_CTRL} | jq -r '.[]["handle"]') ; do
	store_ctrl_id=$(cat ${TMPSTRAGE_CTRL} | jq -r  '.[] | select(.handle == "'${store_ctrl_handle}'") | .id')
	if cat ${TMPSTRAGE_CTRL} | jq -r  '.[] | select(.handle == "'${store_ctrl_handle}'")' | grep -q vendor ; then
		VENDOR=$(cat ${TMPSTRAGE_CTRL}| jq -r '.[] | select(.handle == "'${store_ctrl_handle}'") | .["vendor"]' | sed -e 's/,//' | head -n 1)
	else
		VENDOR="none"
	fi
	if cat ${TMPSTRAGE_CTRL} | jq -r  '.[] | select(.handle == "'${store_ctrl_handle}'")' | grep -q product ; then
		PRODUCT=$(cat ${TMPSTRAGE_CTRL}| jq -r '.[] | select(.handle == "'${store_ctrl_handle}'") | .["product"]' | sed -e 's/,//' | head -n 1)
	else
		PRODUCT="none"
	fi
	if [ "${store_ctrl_id}" = "nvme" ] ; then
		CTRL_TYPE="nvme"
		LOGICAL_NAME=$(cat ${TMPSTRAGE_CTRL} | jq -r  '.[] | select(.handle == "'${store_ctrl_handle}'") | .logicalname')
		BLKCTRL_FIRMWARE_VERSION=$(smartctl -a ${LOGICAL_NAME} | grep "Firmware Version:" | sed 's/Firmware Version://' | awk '{print $1}')
	elif [ "${PRODUCT}" = "MegaRAID 12GSAS/PCIe Secure SAS39xx" ] ; then
		CTRL_TYPE="LSI-raid"
		BLKCTRL_FIRMWARE_VERSION="0.0.0"
	elif echo "${PRODUCT}" | grep -q -E 'MegaRAID' ; then
		CTRL_TYPE="LSI-raid"
		BLKCTRL_FIRMWARE_VERSION=$(megacli -Version -Ctrl -aall | grep "Fw Package Build :" | sed -e 's/Fw Package Build : //')
	elif [ "${PRODUCT}" = "Smart Storage PQI SAS" ] || [ ""$(cat ${TMPSTRAGE_CTRL} | jq -r  '.[] | select(.handle == "'${store_ctrl_handle}'") | .["configuration"]["driver"]' | head -n 1) = "smartpqi" -a "${PRODUCT}" = "Adaptec" ] ; then
			CTRL_TYPE="SSA"
			PRODUCT="Smart Storage PQI SAS"
			SSA_SLOT_NUMBER=$(ssacli controller all show | head -n 2 | tail -n 1 | sed -r 's/.*(Slot [0-9]+).*/\1/' | sed 's/Slot //')
			BLKCTRL_FIRMWARE_VERSION=$(ssacli controller slot=${SSA_SLOT_NUMBER} show | grep "Firmware Version" | sed -e 's/   Firmware Version: //')
	else
		case "${PRODUCT}" in
		# r740xd with PERC H330-mini
		"SAS3008 PCI-Express Fusion-MPT SAS-3")
			CTRL_TYPE="LSI-noraid"
			BLKCTRL_FIRMWARE_VERSION=$(perccli show J | jq -r '.["Controllers"][]["Response Data"]["StoreLib IR3 Version"]')
		;;
		"Lewisburg SATA Controller [AHCI mode]")
			CTRL_TYPE="HP-JBOD"
			BLKCTRL_FIRMWARE_VERSION="0.0.0"
		;;
		*)
			CTRL_TYPE="none"
			BLKCTRL_FIRMWARE_VERSION="0.0.0"
		;;
		esac
	fi

	if [ -z "${store_ctrl_id}" ] ; then
		store_ctrl_id=None
	fi

	echo ${START}'      {"hwid": "'${store_ctrl_id}'", "vendor": "'${VENDOR}'", "product": "'${PRODUCT}'", "ctrl_type": "'${CTRL_TYPE}'", "firmware_version": "'${BLKCTRL_FIRMWARE_VERSION}'" }' >>${TMPFILE2}
	START=","
done
echo '   ],' >>${TMPFILE2}
rm -f ${TMPSTRAGE_CTRL}

echo "===> Fetching IPMI address and firmware versions"

IPMI_FIRMWARE_VERSION=$(ipmitool mc info | grep "Firmware Revision" | awk '{print $4}')
IPMI_DETECTED_IP=$(ipmitool lan print 1 | grep -E "IP Address[ ]*:" | sed 's/IP Address[ \t:]*//')

# Find out if we're on a Dell iDRAC system
LIFECYCLE_VERSION=0.0.0
# Due to some bugs on these old hardware, "ipmitool sdr elist mcloc" can simply hang,
# so we avoid doing it and just double-guess the iDRAC model based on the product-name.
# This is also much faster this way.
if [ "${PRODUCT_NAME}" = "PowerEdge R610" ] || [ "${PRODUCT_NAME}" = "PowerEdge R410" ] ; then
	IPMI_TYPE="iDRAC6"
elif [ "${PRODUCT_NAME}" = "PowerEdge R620" ] || [ "${PRODUCT_NAME}" = "PowerEdge R420" ] ; then
	IPMI_TYPE="iDRAC7"
elif [ "${PRODUCT_NAME}" = "PowerEdge R630" ] || [ "${PRODUCT_NAME}" = "PowerEdge R430" ] ; then
	IPMI_TYPE="iDRAC8"
elif [ "${PRODUCT_NAME}" = "PowerEdge R640" ] || [ "${PRODUCT_NAME}" = "PowerEdge R440" ] ; then
	IPMI_TYPE="iDRAC9"
else
	IPMI_TYPE=$(ipmitool sdr elist mcloc | awk '{print $1}')
fi
case "${IPMI_TYPE}" in
"iDRAC6")
	if [ -x /usr/bin/racadm ] ; then
		LIFECYCLE_VERSION=$(racadm getversion | grep "USC Version" | cut -d= -f2 | awk '{print $1}')
	fi
;;
"iDRAC7"|"iDRAC8"|"iDRAC9")
	if [ -x /usr/bin/racadm ] ; then
		LIFECYCLE_VERSION=$(racadm getversion | grep "Lifecycle Controller Version" | cut -d= -f2 | awk '{print $1}')
	fi
;;
"GPX")
	LIFECYCLE_VERSION=0.0.0
;;
*)
	LIFECYCLE_VERSION=0.0.0
;;
esac

echo "===> Checking for firmware upgrades"

# Check if we need to upgrade the BIOS and IPMI
UPGRADE_CONFIG=/etc/oci/oci-firmware-upgrade-config.json
if [ -r ${UPGRADE_CONFIG} ] ; then
	# Spaces in product names are annoying, so we convert them to underscore
	PRODUCT_LIST=$(cat ${UPGRADE_CONFIG} | jq -r '. | keys[]' | sed 's/ /_/g' | tr '\n' ' ')
	for PRODUCT_NAME_TARGET in ${PRODUCT_LIST} ; do
		# If the current server type matches one of the product names listed in oci-firmware-upgrade-config.json
		if [ "${PRODUCT_NAME_TARGET}" = "$(echo ${PRODUCT_NAME} | sed 's/ /_/g')" ] ; then
			# Check if we have an upgrade for the BIOS
			BIOS_TARGET_VERSION=$(cat ${UPGRADE_CONFIG} | jq -r '.["'"${PRODUCT_NAME}"'"]["BIOS"]["version"]')
			if [ "${BIOS_TARGET_VERSION}" != "null" ] && dpkg --compare-versions "${BIOS_VERSION}" lt "${BIOS_TARGET_VERSION}" ; then
				SCRIPT_NAME=$(cat ${UPGRADE_CONFIG} | jq -r '.["'"${PRODUCT_NAME}"'"]["BIOS"]["script"]')
				if [ -x "${SCRIPT_NAME}" ] ; then
					BIOS_UPGRADE_SCRIPT=${SCRIPT_NAME}
					BIOS_UPGRADE_VERSION=${BIOS_TARGET_VERSION}
				fi
			fi
			# Check if we have an upgrade for IPMI
			IPMI_TARGET_VERSION=$(cat ${UPGRADE_CONFIG} | jq -r '.["'"${PRODUCT_NAME}"'"]["IPMI"]["version"]')
			if [ "${IPMI_TARGET_VERSION}" != "null" ] && dpkg --compare-versions "${IPMI_FIRMWARE_VERSION}" lt "${IPMI_TARGET_VERSION}" ; then
				SCRIPT_NAME=$(cat ${UPGRADE_CONFIG} | jq -r '.["'"${PRODUCT_NAME}"'"]["IPMI"]["script"]')
				if [ -x "${SCRIPT_NAME}" ] ; then
					IPMI_UPGRADE_SCRIPT=${SCRIPT_NAME}
					IPMI_UPGRADE_VERSION=${IPMI_TARGET_VERSION}
				fi
			fi
			LIFECYCLE_TARGET_VERSION=$(cat ${UPGRADE_CONFIG} | jq -r '.["'"${PRODUCT_NAME}"'"]["Lifecycle"]["version"]')
			if [ "${LIFECYCLE_TARGET_VERSION}" != "null" ] && [ "${LIFECYCLE_VERSION}" != "0.0.0" ] && dpkg --compare-versions "${LIFECYCLE_VERSION}" lt "${LIFECYCLE_TARGET_VERSION}" ; then
				SCRIPT_NAME=$(cat ${UPGRADE_CONFIG} | jq -r '.["'"${PRODUCT_NAME}"'"]["Lifecycle"]["script"]')
				if [ -x "${SCRIPT_NAME}" ] ; then
					LIFECYCLE_UPGRADE_SCRIPT=${SCRIPT_NAME}
					LIFECYCLE_UPGRADE_VERSION=${LIFECYCLE_TARGET_VERSION}
				fi
			fi
		fi
	done
fi

if [ -n "${IPMI_UPGRADE_VERSION}" ] ; then
	IPMI_FIRMWARE_VERSION="${IPMI_FIRMWARE_VERSION}->${IPMI_UPGRADE_VERSION}"
else
	if [ -n "${LIFECYCLE_UPGRADE_VERSION}" ] ; then
		LIFECYCLE_VERSION="${LIFECYCLE_VERSION}->${LIFECYCLE_UPGRADE_VERSION}"
	else
		if [ -n "${BIOS_UPGRADE_VERSION}" ] ; then
			BIOS_VERSION="${BIOS_VERSION}->${BIOS_UPGRADE_VERSION}"
		fi
	fi
fi

if [ -d /dev/disk/oci-sort ] ; then
	USE_OCI_SORT_DEV=yes
else
	USE_OCI_SORT_DEV=no
fi

SECURE_BOOT="no"
if [ -d /sys/firmware/efi ] ; then
	BOOT_UEFI="yes"
	if [ -x /usr/bin/mokutil ] ; then
		SECB=$(mokutil --sb-state)
		if [ "${SECB}" = "SecureBoot enabled" ] ; then
			SECURE_BOOT="yes"
		fi
	fi
else
	BOOT_UEFI="no"
fi

echo '   "machine": [' >>${TMPFILE2}
echo '      {"serial": "'${SYSTEM_SERIAL}'", "system_manufacturer": "'${SYSTEM_MANUFACTURER}'", "productname": "'${PRODUCT_NAME}'", "bios_version": "'${BIOS_VERSION}'", "dell_lifecycle_version": "'${LIFECYCLE_VERSION}'", "ipmi_firmware_version": "'${IPMI_FIRMWARE_VERSION}'", "ipmi_detected_ip": "'${IPMI_DETECTED_IP}'", "ladvd_report": "none", "use_oci_sort_dev":"'${USE_OCI_SORT_DEV}'", "cpu_vendor": "'${CPU_VENDOR}'", "cpu_threads": "'${CPU_THREADS}'", "cpu_core_per_socket": "'${CPU_CORE_PER_SOCKET}'", "cpu_sockets": "'${CPU_SOCKETS}'", "cpu_model_name": "'${CPU_MODEL_NAME}'", "cpu_mhz": "'${CPU_MHZ}'", "boot_uefi": "'${BOOT_UEFI}'", "secure_boot": "'${SECURE_BOOT}'"}' >>${TMPFILE2}
echo '   ],' >>${TMPFILE2}

### Get total amount of RAM
TOTAL_RAM=$(dmidecode -t memory |  awk '/Size: [0-9]/ {tmp=$2 ; if($3 == "GB") { tmp = $2 * 1024 }; t+=tmp;} END { print t}')
RAM_TYPE=$(dmidecode -t 17 | grep Type | head -n 1 | awk '{print $2}')
RAM_SPEED=$(dmidecode -t 17 | grep Speed | head -n 1 | awk '{print $2}')
RAM_MANUFACTURER=$(dmidecode -t 17 | grep Manufacturer | head -n 1 | awk '{print $2}')
echo '   "memory": [' >>${TMPFILE2}
	echo '      {"size": "'${TOTAL_RAM}'", "type": "'${RAM_TYPE}'", "speed": "'${RAM_SPEED}'", "manufacturer": "'${RAM_MANUFACTURER}'" }' >>${TMPFILE2}
echo '   ]' >>${TMPFILE2}
echo '}' >>${TMPFILE2}

echo "===> Will send this report to provisionning server:"
cat ${TMPFILE2}

echo "===> Calling curl (web server output):"
curl -s --header "Content-Type: application/json" -d @${TMPFILE2} http://${PXE_SERVER_IP}/oci/report.php

rm ${TMPFILE}

#############################################
### Process BIOS and IPMI firmware update ###
#############################################
if [ -x "${IPMI_UPGRADE_SCRIPT}" ] ; then
	${IPMI_UPGRADE_SCRIPT}
	exit 0
fi
if [ -x "${LIFECYCLE_UPGRADE_SCRIPT}" ] ; then
	${LIFECYCLE_UPGRADE_SCRIPT}
	exit 0
fi
if [ -x "${BIOS_UPGRADE_SCRIPT}" ] ; then
	${BIOS_UPGRADE_SCRIPT}
	exit 0
fi

if [ -r ${UPGRADE_CONFIG} ] ; then
	echo "===> Checking for block device controller upgrades"
	cat ${TMPFILE2} | jq -r '.["blkdev_ctrl"][]["product"]' | while read -r SERVER_IN_LIVE_FIRMWARE ; do
		cat /etc/oci/oci-firmware-upgrade-config.json  | jq -r '.["generic"]["block_device_controller"] | keys[]' | while read -r KNOWN_FIRMWARE ; do
			if [ "${SERVER_IN_LIVE_FIRMWARE}" = "${KNOWN_FIRMWARE}" ] ; then
				SERVER_IN_LIVE_FW_VERSION=$(cat ${TMPFILE2} | jq -r '.["blkdev_ctrl"][] | select(.product == "'"${SERVER_IN_LIVE_FIRMWARE}"'") | .firmware_version')
				KNOWN_FW_VERSION=$(cat /etc/oci/oci-firmware-upgrade-config.json | jq -r '.["generic"]["block_device_controller"]["'"${SERVER_IN_LIVE_FIRMWARE}"'"]["version"]')
				KNOWN_FW_SCRIPT=$(cat /etc/oci/oci-firmware-upgrade-config.json | jq -r '.["generic"]["block_device_controller"]["'"${SERVER_IN_LIVE_FIRMWARE}"'"]["script"]')
				if [ -x "${KNOWN_FW_SCRIPT}" ] && dpkg --compare-versions "${SERVER_IN_LIVE_FW_VERSION}" lt "${KNOWN_FW_VERSION}" ; then
					echo "Found to be needing upgrade: $SERVER_IN_LIVE_FIRMWARE"
					echo  "Version in server: ${SERVER_IN_LIVE_FW_VERSION} to be upgraded to: ${KNOWN_FW_VERSION}"
					echo "Script path: ${KNOWN_FW_SCRIPT}"
					${KNOWN_FW_SCRIPT}
					exit 0
				fi
			fi
		done
	done
fi

rm ${TMPFILE2}
echo "-> Done"
