#!/usr/local/bin/cbsd
#v12.0.11
MYARG=""
MYOPTARG="mode"
MYDESC="Collect and/or update system-related information in inventory tables"
ADDHELP="sysinv withount mode=update only collect information and stored in variables\n\
mode=update - collect and update in db\n"

. ${subrdir}/nc.subr
. ${cbsdinit}

# create SQL schema
#${miscdir}/sqlcli ${dbdir}/local.sqlite DROP TABLE IF EXISTS local
#/usr/local/bin/cbsd ${miscdir}/updatesql ${dbdir}/inv.${nodename}.sqlite ${distdir}/share/local-local.schema local
sysinv_get_info_hostname()
{
	case "${platform}" in
		Linux)
			hostname=$( ${SYSCTL_CMD} -n kernel.hostname 2>/dev/null )
			;;
		*)
			hostname=$( ${SYSCTL_CMD} -n kern.hostname 2>/dev/null )
			;;
	esac
	[ -z "${hostname}" ] && hostname="unknown"
}

sysinv_get_info_hostarch()
{
	hostarch=$( ${UNAME_CMD} -m 2>/dev/null )
	[ "${hostarch}" = "x86_64" ] && hostarch="amd64"
	[ -z "${hostarch}" ] && hostarch="unknown"
}

sysinv_get_info_osrelease()
{
	case "${platform}" in
		Linux)
			osrelease=$( lsb_release -cs 2>/dev/null )
			;;
		*)
			osrelease=$( ${SYSCTL_CMD} -n kern.osrelease 2>/dev/null )
			;;
	esac
	[ -z "${osrelease}" ] && osrelease="unknown"
}

sysinv_get_info_cpumodel()
{
	case "${platform}" in
		Linux)
			cpumodel=$( ${GREP_CMD} "^model name" /proc/cpuinfo | ${HEAD_CMD} -n1 | ${AWK_CMD} '{ for (i=4; i<=NF; i++) printf("%s ",$i) }END{ print"" }' )
			;;
		*)
			cpumodel=$( ${SYSCTL_CMD} -n hw.model 2>/dev/null )
			;;
	esac
	[ -z "${cpumodel}" ] && cpumodel="unknown"
}

sysinv_get_info_ncpu()
{
	case "${platform}" in
		Linux)
			ncpu=$( ${GREP_CMD} -E "^vendor_id" /proc/cpuinfo | ${WC_CMD} -l )
			;;
		*)
			ncpu=$( ${SYSCTL_CMD} -n hw.ncpu 2>/dev/null )
			;;
	esac
	[ -z "${ncpu}" ] && ncpu="0"
}

sysinv_get_info_cpufreq()
{
	case "${platform}" in
		Linux)
			cpufreq=0
			;;
		*)
			cpufreq=$( ${SYSCTL_CMD} -n dev.cpu.0.freq 2>/dev/null )
			;;
	esac
	[ -z "${cpufreq}" ] && cpufreq="0"
}

sysinv_get_info_kernhz()
{
	case "${platform}" in
		Linux)
			kernhz=$( getconf CLK_TCK )
			;;
		*)
			kernhz=$( ${SYSCTL_CMD} -n kern.hz 2>/dev/null )
			;;
	esac
	[ -z "${kernhz}" ] && kernhz="0"
}

sysinv_get_info_sched()
{
	case "${platform}" in
		Linux)
			sched="unknown"
			;;
		*)
			sched=$( ${SYSCTL_CMD} -n kern.sched.name 2>/dev/null )
			;;
	esac
	[ -z "${sched}" ] && sched="unknown"
}

sysinv_get_info_eventtimer()
{
	case "${platform}" in
		Linux)
			eventtimer="unknown"
			;;
		*)
			eventtimer=$( ${SYSCTL_CMD} -n kern.eventtimer.choice 2>/dev/null )
			;;
	esac

	[ -z "${eventtimer}" ] && eventtimer="unknown"
}

sysinv_get_info_disks()
{
	local _disks

	case "${platform}" in
		Linux)
			 _disks=$( lsblk -n --raw |grep -E " disk" | awk '{printf $1" "}' )
			disks=
			for i in ${_disks}; do
				if [ -n "${disks}" ]; then
					disks="${disks} ${i}"
				else
					disks="${i}"
				fi
			done
			;;
		*)
			disks=$( ${SYSCTL_CMD} -n kern.disks 2>/dev/null )
			;;
	esac
	[ -z "${disks}" ] && disks="unknown"
}

sysinv_get_info_nodenamefile()
{
	[ -r "${nodenamefile}" ] && nodename=$( ${CAT_CMD} ${nodenamefile} | ${AWK_CMD} '{printf $1}' )
	[ -z "${nodenamefile}" ] && nodenamefile="unknown"
}

sysinv_get_info_vimage_feature()
{
	case "${platform}" in
		Linux)
			vimage_feature=0
			;;
		*)
			_ret=$( ${SYSCTL_CMD} -n kern.features.vimage 2>/dev/null )
			if [ -z "${_ret}" ]; then
				vimage_feature=0
			else
				vimage_feature=1
			fi
			;;
	esac
}

sysinv_get_info_racct()
{
	case "${platform}" in
		Linux)
			racct=0
			;;
		*)
			_ret=$( ${SYSCTL_CMD} -n kern.features.racct 2>/dev/null )
			if [ -z "${_ret}" ]; then
				racct=0
			else
				racct=1
		fi
	esac
}

sysinv_get_info_physmem()
{
	local _realmem

	. ${subrdir}/xen.subr

	if is_xen_dom0; then
		_realmem=$( ${XL_CMD} info total_memory 2>/dev/null )			# in MB by default
		[ -n "${_realmem}" ] && _realmem=$(( _realmem * 1024 * 1024 ))		# ->KB -> Bytes
	else
		case "${platform}" in
			Linux)
				_realmem=$( ${GREP_CMD} MemTotal /proc/meminfo | ${AWK_CMD} '{printf $2}' )
				if [ -n "${_realmem}" ]; then
					_realmem=$(( _realmem * 1024 ))          # ->KB -> Bytes
				fi
				;;
			*)
				_realmem=$( ${SYSCTL_CMD} -n hw.physmem 2>/dev/null )
				;;
		esac
	fi

	if [ -z "${_realmem}" ]; then
		physmem=0
	else
		physmem="${_realmem}"
	fi
}

sysinv_get_info_freemem()
{
	local _realmem _page_size _active_count _wire_count _active_size _wire_size _freemem

	. ${subrdir}/xen.subr

	if is_xen_dom0; then
		_freemem=$( ${XL_CMD} info free_memory 2>/dev/null )			# in MB by default
		[ -n "${_freemem}" ] && _freemem=$(( _freemem * 1024 * 1024 ))		# ->KB -> Bytes
	else
		sysinv_get_info_physmem		# get physmem
		_realmem="${physmem}"
		case "${platform}" in
			Linux)
				_realmem=$( ${GREP_CMD} MemTotal /proc/meminfo | ${AWK_CMD} '{printf $2}' )
				if [ -n "${_realmem}" ]; then
					_realmem=$(( _realmem * 1024 ))          # ->KB -> Bytes
				fi
				_freemem=$( ${GREP_CMD} MemFree /proc/meminfo | ${AWK_CMD} '{printf $2}' )
				if [ -n "${_freemem}" ]; then
					_freemem=$(( _freemem * 1024 ))          # ->KB -> Bytes
				fi
				;;
			*)
				_realmem=$( ${SYSCTL_CMD} -n hw.physmem 2>/dev/null )
				_page_size=$( ${SYSCTL_CMD} -n vm.stats.vm.v_page_size )
				_active_count=$( ${SYSCTL_CMD} -n vm.stats.vm.v_active_count )
				_wire_count=$( ${SYSCTL_CMD} -n vm.stats.vm.v_wire_count )
				_active_size=$(( _page_size * _active_count ))
				_wire_size=$(( _page_size * _wire_count ))
				_freemem=$(( _realmem - _active_size - _wire_size ))
		esac
	fi

	if [ -n "${_freemem}" ]; then
		freemem="${_freemem}"
	else
		freemem=0
	fi

	return 0
}

sysinv_get_info_memtype()
{
	local _dmidecode

	_dmidecode=$( which dmidecode )

	if [ -n "${_dmidecode}" ]; then
		memtype=$( ${_dmidecode} -t memory | ${GREP_CMD} -A20 "Memory Device" | ${GREP_CMD} -B20 "^Handle" | ${GREP_CMD} -E "Type:|Speed:" | ${CUT_CMD} -d : -f 2 | ${XARGS_CMD} )
	else
		memtype=""
	fi
}

sysinv_get_info_nics()
{
	nics=""
	local _tmp

	case "${platform}" in
		Linux)
			for i in $( ${LS_CMD} /sys/class/net ); do
				if [ -n "${nics}" ]; then
					nic=s"${nics} ${i}"
				else
					nics="${i}"
				fi
			done
		;;
		*)
			for i in $( ${IFCONFIG_CMD} -l ); do
				case "${i%%[0-9]*}" in
					ipfw|ppp|sl|lp|faith|fwe|fwip|plip|pfsync|pflog|tun|vboxnet|lo)
						continue
						;;
				esac
				nics="${nics} ${i}"
			done
			;;
	esac
	[ -n "${nics}" ] && nics=$( echo ${nics} | ${TR_CMD} " " "," )
}

# NEW
sysinv_get_info_la()
{
	case "${platform}" in
		Linux)
			la=$( ${CAT_CMD} /proc/loadavg | ${AWK_CMD} '{printf $1" "$2" "$3"\n"}' )
			;;
		*)
			la=$( ${SYSCTL_CMD} -qn vm.loadavg | ${TR_CMD} -d "{}" | ${AWK_CMD} '{printf $1" "$2" "$3"\n"}' )
			;;
	esac
	[ -z "${la}" ] && la="0 0 0"
}

sysinv_get_info_is_virtual()
{
	local _tmp=

	local smbios=

	case "${platform}" in
		Linux)
			_tmp=$( ${GREP_CMD} hypervisor /proc/cpuinfo )
			if [ -n "${_tmp}" ]; then
				smbios="virtual"
			else
				smbios="physical"
			fi
			;;
		*)
			smbios=$( ${KENV_CMD} smbios.system.product )
			;;
	esac

	case "${smbios}" in
		VirtualBox*)
			is_virtual="virtualbox"
			;;
		VMware*)
			is_virtual="vmware"
			;;
		Parallels*)
			is_virtual="parallels"
			;;
		KVM*)
			is_virtual="kvm"
			;;
		"Virtual Machine")
			is_virtual="hyperv"
			;;
		"RHEV Hypervisor")
			is_virtual="redhat_ev"
			;;
		"oVirt Node")
			is_virtual="ovirt"
			;;
		"HVM domU")
			is_virtual="xen_hardware"
			;;
		Bochs*)
			is_virtual="bochs"
			;;
		BHYVE)
			is_virtual="bhyve"
			;;
		*)
			is_virtual="physical"
			;;
	esac
}

sysinv_get_info_cbsdver()
{
	cbsdver=$( /usr/local/bin/cbsd version )
}

collect_info()
{
	cbsdver=${myversion}
	platform=$( ${UNAME_CMD} -s )

	# Overwrite $platform to HardenedBSD if we have /usr/sbin/hbsd-update:
	[ -e "/usr/sbin/hbsd-update" ] && platform="HardenedBSD"

	for i in hostname hostarch osrelease cpumodel ncpu cpufreq kernhz sched eventtimer disks nodenamefile vimage_feature racct physmem freemem memtype nics la is_virtual cbsdver; do
		sysinv_get_info_${i}
	done
}

## MAIN
collect_info

if [ "${mode}" = "update" ]; then
	[ ! -h "${dbdir}/local.sqlite" ] && err 1 "${N1_COLOR}No inventory symlink. Run ${N2_COLOR}cbsd initenv${N1_COLOR} first${N0_COLOR}"
	. ${initenv}
	update_hwinfo
	env sqlcolnames="1" ${miscdir}/sqlcli ${dbdir}/local.sqlite "SELECT * FROM local" | ${XARGS_CMD} /usr/local/cbsd/misc/cbsdsysrc -qf ${inventory} > /dev/null
	${CHMOD_CMD} 0640 ${inventory} && ${CHOWN_CMD} ${cbsduser}:${cbsduser} ${inventory}
fi

# don't use exit here: included from initenv
#exit 0
