#
# Copyright 2013, Cumulus Networks Inc.
#
# Functions used by cl-service-support
#
MODULES=("system" "network" "switchd")
system=("pkg" "config" "logs" "hwinfo" "misc" "btrfs" "vers" "systemd" "memory_use")
network=("kernel" "quagga" "clag" "ptm" "sfp" "sfphex")
switchd=("bcm" "debug" "stack" "mlx")
MODULES_DISABLED_DEFAULT=("switchd.stack")

detect_arch()
{
	current_arch=($(uname -m | awk ' { print $1 } '))
	echo ${current_arch}
}

is_valid_module()
{
	module_arg=$1

	for module in ${MODULES[*]};
	do
		[ $module == $module_arg ] && return 1

		submodule_arr=${module}[@]
		for submodule in ${!submodule_arr};
		do
			[ "$module.$submodule" == $module_arg ] && return 1
		done
	done
	return 0
}

is_module_enabled()
{
	modulename=$1

	# First check in the disabled list
	for w in ${MODULES_DISABLED[@]};
	do
		[ "$w" == "$modulename" ] && return 0
	done

	if [ ${#MODULES_ENABLED[@]} -ne 0 ]; then
		for w in ${MODULES_ENABLED[@]};
		do
			[ "$w" == "$modulename" ] && return 1
		done

		# If modulename is a submodule, check if the
		# module is enabled
		m=($(echo $modulename | cut -d "." -f1- --output-delimiter=" " 2>/dev/null))
		if [ ${#m[@]} == 2 ]; then
			for w in ${MODULES_ENABLED[@]};
			do
				[ "$w" == "${m[0]}" ] && return 1
			done
		fi
	fi

	# Lastly check if the module is disabled by default
	for w in ${MODULES_DISABLED_DEFAULT[@]};
	do
		[ "$w" == "$modulename" ] && return 0
	done

	# If no specific modules were enabled,
	# assume everything is enabled
	[ ${#MODULES_ENABLED[@]} -eq 0 ] && return 1

	return 0
}

exec_cmd() {
    # args:
    # exec_cmd <outputfile> <cmd> <cmd_args>

    cmdout_file=$1
    shift

    cmd=$1
    shift

    [ $VERBOSE -eq 1 ] && echo "$cmd $@ &>> $cmdout_file"

    echo "# $cmd $@">> $cmdout_file 2>/dev/null
    $cmd "$@" &>> $cmdout_file

    return $?
}

func_switchd() {
	# Do nothing. Default commands can be added here
	return
}

func_switchd.debug() {
	debug_state_orig=0
	switchd_dbg_ctrl="/cumulus/switchd/ctrl/debug"
	switchd_dbg_dir="/cumulus/switchd/debug"

	if [ -e "${switchd_dbg_dir}/bond" ]; then
		debug_state_orig=1
	elif [ -e "$switchd_dbg_ctrl" ]; then
		sudo sh -c "echo 1 >$switchd_dbg_ctrl" &>/dev/null
		[ $? -ne 0 ] && return
	else
		return
	fi

	# ACL Dump
	exec_cmd $LOGDIR/switchd.debug.acl cat ${switchd_dbg_dir}/acl

	# Bond Dump
	switchd_dbg_bond_debug="${switchd_dbg_dir}/bond"
	exec_cmd $LOGDIR/switchd.debug.bond.info cat ${switchd_dbg_bond_debug}/info
	exec_cmd $LOGDIR/switchd.debug.bond.sw_bonds cat ${switchd_dbg_bond_debug}/sw_bonds 

	# Bridge Dump
	switchd_dbg_bridge_debug="${switchd_dbg_dir}/bridge"
	exec_cmd $LOGDIR/switchd.debug.bridge.info cat ${switchd_dbg_bridge_debug}/info

	# Vlan Dump
	switchd_dbg_vlan_debug="${switchd_dbg_dir}/vlan"
	exec_cmd $LOGDIR/switchd.debug.vlan.info cat ${switchd_dbg_vlan_debug}/info

	# Port Dump
	switchd_dbg_misc_debug="${switchd_dbg_dir}/misc"
	exec_cmd $LOGDIR/switchd.debug.misc.ports cat ${switchd_dbg_misc_debug}/ports

        # VXLAN Dump
	switchd_dbg_vxlan_debug="${switchd_dbg_dir}/vxlan"
	exec_cmd $LOGDIR/switchd.debug.vxlan.info cat ${switchd_dbg_vxlan_debug}/info

	# Knet Dump
	switchd_dbg_knet_debug="${switchd_dbg_dir}/knet"
	exec_cmd $LOGDIR/switchd.debug.knet.info cat ${switchd_dbg_knet_debug}/info

	[ $debug_state_orig == 0 ] && sudo sh -c "echo 1 >$switchd_dbg_ctrl" &>/dev/null
}

func_switchd.stack() {
	#dump switchd thread stacks.
	# This was normally invoked from the heartbeat miss in 2.5, but can't
	# work in 3.0 with systemd.  The function is left in case somebody wants
	# to manually invoke it.
	/bin/ps -C switchd -L -o lwp --no-headers | while read p; do exec_cmd $LOGDIR/switchd.stack.1 /bin/cat /proc/$p/stack; done
	sleep 0.1
	/bin/ps -C switchd -L -o lwp --no-headers | while read p; do exec_cmd $LOGDIR/switchd.stack.2 /bin/cat /proc/$p/stack; done
	sleep 0.1
	/bin/ps -C switchd -L -o lwp --no-headers | while read p; do exec_cmd $LOGDIR/switchd.stack.3 /bin/cat /proc/$p/stack; done
}

func_switchd.bcm() {
	[ -e /usr/lib/cumulus/bcmcmd ] || return
	exec_cmd $LOGDIR/l3.defip.show /usr/lib/cumulus/bcmcmd "l3 defip show"
	[ $? -ne 0 ] && return

	exec_cmd $LOGDIR/l3.l3table.show /usr/lib/cumulus/bcmcmd "l3 l3table show"
	exec_cmd $LOGDIR/l3.ip6route.show /usr/lib/cumulus/bcmcmd "l3 ip6route show"
	exec_cmd $LOGDIR/l3.ip6host.show /usr/lib/cumulus/bcmcmd "l3 ip6host show"
	exec_cmd $LOGDIR/l3.egress.show /usr/lib/cumulus/bcmcmd "l3 egress show"
	exec_cmd $LOGDIR/l3.multipath.show /usr/lib/cumulus/bcmcmd "l3 multipath show"
	exec_cmd $LOGDIR/l3.intf.show /usr/lib/cumulus/bcmcmd "l3 intf show"
	exec_cmd $LOGDIR/portstat /usr/lib/cumulus/bcmcmd "portstat"
	exec_cmd $LOGDIR/port.all /usr/lib/cumulus/bcmcmd "port all"
	exec_cmd $LOGDIR/soc /usr/lib/cumulus/bcmcmd "soc"
	exec_cmd $LOGDIR/show.counters /usr/lib/cumulus/bcmcmd "show counters"
	exec_cmd $LOGDIR/show.statistics /usr/lib/cumulus/bcmcmd "show statistics"
	exec_cmd $LOGDIR/show.errors /usr/lib/cumulus/bcmcmd "show errors"
	exec_cmd $LOGDIR/show.interrupts /usr/lib/cumulus/bcmcmd "show interrupts"
	exec_cmd $LOGDIR/show.params /usr/lib/cumulus/bcmcmd "show params"
	exec_cmd $LOGDIR/show.errors /usr/lib/cumulus/bcmcmd "show errors"
	exec_cmd $LOGDIR/l2.show /usr/lib/cumulus/bcmcmd "l2 show"
	exec_cmd $LOGDIR/vlan.show /usr/lib/cumulus/bcmcmd "vlan show"
	exec_cmd $LOGDIR/vlan_xlate.show /usr/lib/cumulus/bcmcmd "vlan translate show"
	exec_cmd $LOGDIR/vlan_xlate_egr.show /usr/lib/cumulus/bcmcmd "vlan translate egress show"
	exec_cmd $LOGDIR/stg.show /usr/lib/cumulus/bcmcmd "stg show"
	exec_cmd $LOGDIR/trunk.show /usr/lib/cumulus/bcmcmd "trunk show"
	exec_cmd $LOGDIR/fp.show /usr/lib/cumulus/bcmcmd "fp show"
	exec_cmd $LOGDIR/mcast.show /usr/lib/cumulus/bcmcmd "multicast show"
	exec_cmd $LOGDIR/cl-route-check.show /usr/cumulus/bin/cl-route-check -V
}

func_switchd.mlx() {
	[ -e /usr/bin/sx_api_dbg_generate_dump.py ] || return
	exec_cmd /dev/null /usr/bin/sx_api_dbg_generate_dump.py "/var/log/sdk_debug_dump.log"
	/usr/lib/cumulus/mlxcmd l2 fdb show table > $LOGDIR/l2.show
	/usr/lib/cumulus/mlxcmd l2 fdb mcshow table > $LOGDIR/l2mc.show
	/usr/lib/cumulus/mlxcmd l3 route > $LOGDIR/l3.route.show
	/usr/lib/cumulus/mlxcmd l3 route6 > $LOGDIR/l3.route6.show
	/usr/lib/cumulus/mlxcmd l3 neighbor > $LOGDIR/l3.neigh.show
	/usr/lib/cumulus/mlxcmd l3 neighbor6 > $LOGDIR/l3.neigh6.show
	/usr/lib/cumulus/mlxcmd l3 ecmp_table > $LOGDIR/l3.ecmp.show
	/usr/lib/cumulus/mlxcmd ports show ids > $LOGDIR/port.ids.show
	/usr/lib/cumulus/mlxcmd ports info > $LOGDIR/port.info.show
	/usr/lib/cumulus/mlxcmd vlan ids > $LOGDIR/vlan.show
}

func_network() {
	exec_cmd $LOGDIR/lldpctl lldpcli show neighbors details hidden
	return
}

func_network.kernel() {
	exec_cmd $LOGDIR/ip.link ip -d -s link
	exec_cmd $LOGDIR/ip.addr ip addr
	exec_cmd $LOGDIR/ip.rule ip rule
	exec_cmd $LOGDIR/ip6.rule ip -6 rule
	exec_cmd $LOGDIR/ip.route ip route show table all
	exec_cmd $LOGDIR/ip.neigh ip neigh
        exec_cmd $LOGDIR/ip6.route ip -6 route show table all
        exec_cmd $LOGDIR/ip6.neigh ip -6 neigh
	exec_cmd $LOGDIR/ip.mroute ip mroute
	exec_cmd $LOGDIR/ip6.mroute ip -6 mroute
	exec_cmd $LOGDIR/ip.ntable ip ntable show
	exec_cmd $LOGDIR/netstat-i netstat -i
	exec_cmd $LOGDIR/cl-acltool.list /usr/cumulus/bin/cl-acltool -L all
	exec_cmd $LOGDIR/brctl.show brctl show
	exec_cmd $LOGDIR/stp.show brctl stpshowall
	exec_cmd $LOGDIR/mstp.show mstpctl showall
	exec_cmd $LOGDIR/bridge.fdb bridge -s fdb show
	exec_cmd $LOGDIR/bridge.mdb bridge -d -s mdb show
	exec_cmd $LOGDIR/bridge.link bridge -d link
	exec_cmd $LOGDIR/bridge.vlan bridge vlan
	exec_cmd $LOGDIR/vrf.tasks vrf task ls

	# ethtool data
	#
	for i in `ls -v --indicator-style=none /sys/class/net/`; do
		exec_cmd $LOGDIR/ethtool.link ethtool $i
		exec_cmd $LOGDIR/ethtool.stats echo -n $i ": "
		exec_cmd $LOGDIR/ethtool.stats ethtool -S $i
	done
	return
}

func_network.sfp() {
        for i in `ls -v --indicator-style=none /sys/class/net/ | egrep -v '^(bonding_masters|lo)$'`; do
                if [[ $i =~ ^(swp[0-9]+(s[0-3])?$|eth) ]] ; then
                        exec_cmd $LOGDIR/ethtool.module ethtool -m $i
                fi
        done
        return
}

func_network.sfphex() {
        local platform=`platform-detect 2>/dev/null`
        if [ $platform != "dell,s6000_s1220" ] ; then
                for i in `ls -v --indicator-style=none /sys/class/net/ | egrep -v '^(bonding_masters|lo)$'`; do
                        if [[ $i =~ ^(swp[0-9]+(s[0-3])?$|eth) ]] ; then
                                exec_cmd $LOGDIR/ethtool.module-hex ethtool -m $i hex on
                        fi
                done
        fi
        return
}

func_network.quagga() {
        exec_cmd $LOGDIR/ospf vtysh -c "show ip ospf"
        exec_cmd $LOGDIR/ospf.neighbor vtysh -c "show ip ospf neighbor"
        exec_cmd $LOGDIR/ospf.interface vtysh -c "show ip ospf interface"
        exec_cmd $LOGDIR/ospf.database vtysh -c "show ip ospf database"
        exec_cmd $LOGDIR/ospf.borderrouters vtysh -c "show ip ospf border-routers"
        exec_cmd $LOGDIR/ospf.database.router vtysh -c "show ip ospf database router"
        exec_cmd $LOGDIR/ospf.show_running vtysh -c "show running ospfd"

        exec_cmd $LOGDIR/ospf6 vtysh -c "show ipv6 ospf6"
        exec_cmd $LOGDIR/ospf6.neighbor vtysh -c "show ipv6 ospf6 neighbor"
        exec_cmd $LOGDIR/ospf6.interface vtysh -c "show ipv6 ospf6 interface"
        exec_cmd $LOGDIR/ospf6.database vtysh -c "show ipv6 ospf6 database"
        exec_cmd $LOGDIR/ospf6.redistribute vtysh -c "show ipv6 ospf6 redistribute"
        exec_cmd $LOGDIR/ospf6.spf.tree vtysh -c "show ipv6 ospf6 spf tree"
        exec_cmd $LOGDIR/ospf6.database.router vtysh -c "show ipv6 ospf6 database router"
        exec_cmd $LOGDIR/ospf6.show_running vtysh -c "show running ospf6d"

        exec_cmd $LOGDIR/bgp.summary vtysh -c "show ip bgp vrf all summary"
        exec_cmd $LOGDIR/bgp.neighbors vtysh -c "show ip bgp vrf all neighbors"
        exec_cmd $LOGDIR/bgp.nexthop vtysh -c "show ip bgp vrf all nexthop"
        exec_cmd $LOGDIR/bgp.update_group vtysh -c "show ip bgp vrf all update-group"
        exec_cmd $LOGDIR/bgp.route vtysh -c "show ip bgp vrf all"
        exec_cmd $LOGDIR/bgp.show_running vtysh -c "show running bgpd"

        exec_cmd $LOGDIR/bgp.ipv6_summary vtysh -c "show bgp vrf all summary"
        exec_cmd $LOGDIR/bgp.ipv6_update_group vtysh -c "show bgp vrf all update-group"
        exec_cmd $LOGDIR/bgp.ipv6_route vtysh -c "show bgp vrf all"

        exec_cmd $LOGDIR/quagga.show_running vtysh -c "show running-config"

        exec_cmd $LOGDIR/zebra.vrf vtysh -c "show vrf"
        exec_cmd $LOGDIR/zebra.intf vtysh -c "show interface vrf all"
        exec_cmd $LOGDIR/zebra.nht vtysh -c "show ip nht vrf all"
        exec_cmd $LOGDIR/zebra.ipv6_nht vtysh -c "show ipv6 nht vrf all"
        exec_cmd $LOGDIR/zebra.route vtysh -c "show ip route vrf all"
        exec_cmd $LOGDIR/zebra.ipv6_route vtysh -c "show ipv6 route vrf all"
        exec_cmd $LOGDIR/zebra.client vtysh -c "show zebra client summary"

        [ $SECURE -eq 0 ] && exec_cmd /dev/null cp -f /root/.history_quagga $LOGDIR/vtysh.history
        [ $SECURE -eq 0 ] && exec_cmd /dev/null cp -f /home/cumulus/.history_quagga $LOGDIR/cumulus.vtysh.history

	return
}

func_network.clag() {
	exec_cmd $LOGDIR/clag.status clagctl -v
	exec_cmd $LOGDIR/clag.params clagctl params


	return
}

func_network.ptm() {
	exec_cmd $LOGDIR/ptmctl.detail ptmctl -d
	exec_cmd $LOGDIR/ptmctl.bfd ptmctl -b -d

	return
}

func_system() {
	# Intentionally empty, we let the system submodules handle gathering things
	# the main reason for this is that if system is specified all submodules
	# are enabled, even when specific submodules are specified on the cmdline
	return
}

func_system.vers() {
	# Capture general system version information
	test -x /usr/bin/lsb_release && \
		exec_cmd $LOGDIR/lsb_release /usr/bin/lsb_release -a

	current_arch=$(detect_arch)

	# Grab bootloader information
	if [[ "${current_arch}" == "ppc" ]] ;
		then exec_cmd $LOGDIR/fw_printenv fw_printenv
	fi

	if [[ "${current_arch}" == "x86_64" ]]; then
		exec_cmd $LOGDIR/grub-editenv grub-editenv list
		exec_cmd $LOGDIR/lvdisplay lvdisplay
		exec_cmd /dev/null cp -f /boot/grub/grub.cfg $LOGDIR/
		exec_cmd /dev/null cp -f /etc/fstab $LOGDIR/
		exec_cmd $LOGDIR/onie-version /usr/lib/cumulus/onie/onie-version
	fi

    exec_cmd /dev/null cp -f /boot/config-$(uname -r) $LOGDIR/

    exec_cmd $LOGDIR/dmidecode dmidecode
    exec_cmd $LOGDIR/bios bios_version
    exec_cmd $LOGDIR/cpld cpld_version

	# onie data
	#
	if [[ "${current_arch}" == "ppc" ]] ; then
		ONIE_DIR=/mnt/root-rw/onie
	fi
	if [[ "${current_arch}" == "x86_64" ]] ; then
		ONIE_DIR=/boot/onie
	fi
	if [ -d "$ONIE_DIR" ]; then
		tar -C $ONIE_DIR --exclude=onie-installer -cf $LOGDIR/onie.tar . > /dev/null 2>&1
	fi
}

func_system.hwinfo() {
	exec_cmd $LOGDIR/platform.detect platform-detect
	exec_cmd $LOGDIR/decode-syseeprom /usr/cumulus/bin/decode-syseeprom
	exec_cmd $LOGDIR/sensors sensors
	exec_cmd $LOGDIR/smonctl smonctl -v
	exec_cmd $LOGDIR/smonctl_json smonctl -j
	exec_cmd $LOGDIR/pwmd pwmd -d
	exec_cmd $LOGDIR/ledmgrd ledmgrd -d
	exec_cmd $LOGDIR/ledmgrd_json ledmgrd -j
	exec_cmd $LOGDIR/lspci lspci -vvv -xxx
	exec_cmd $LOGDIR/switchmode switchmode
	exec_cmd $LOGDIR/poe_diag poectl --diag-info --verbose
	exec_cmd $LOGDIR/poe_sys poectl -s --verbose
}

func_system.misc() {
	mkdir -p $TARDIR/proc
	cp -r /proc/buddyinfo /proc/cmdline /proc/consoles /proc/cpuinfo /proc/devices /proc/diskstats /proc/interrupts /proc/iomem /proc/ioports /proc/kallsyms /proc/loadavg /proc/locks /proc/meminfo /proc/misc /proc/modules /proc/self/mounts /proc/mtd /proc/self/net /proc/pagetypeinfo /proc/partitions /proc/softirqs /proc/stat /proc/swaps /proc/sysvipc /proc/timer_list /proc/uptime /proc/version /proc/vmallocinfo /proc/vmstat /proc/zoneinfo $TARDIR/proc/
	[ -f /proc/linux-kernel-bde ] && cp -r /proc/*-bde $TARDIR/proc
	[ -f /proc/dma ] && cp -r /proc/dma $TARDIR/proc
	for procdir in /proc/bcm /proc/mlx_sx; do
	   [ -d ${procdir} ] && cp -r ${procdir} $TARDIR/proc
	done
	chmod -R +w $TARDIR/proc/

	exec_cmd $LOGDIR/sysctl sysctl -a
	exec_cmd $LOGDIR/uptime uptime
	exec_cmd $LOGDIR/mount mount
	exec_cmd $LOGDIR/df df
	exec_cmd $LOGDIR/parted-list parted --list
	exec_cmd $LOGDIR/blkid blkid
	exec_cmd $LOGDIR/tree-persist tree /mnt/persist/
	exec_cmd $LOGDIR/ifquery ifquery -a
	# capture history of command failures and heartbeat timeouts, if any
	exec_cmd /dev/null cp -a /run/failure.* /run/watchdog.* ${LOGDIR}
	exec_cmd /dev/null cp -f /var/lib/cumulus/porttab $LOGDIR/
	exec_cmd /dev/null cp -f /var/lib/cumulus/phytab $LOGDIR/
        exec_cmd /dev/null cp -r -f /var/lib/cumulus/ztp $LOGDIR/

	# sysfs data - need to avoid arglist too long with lots of interfaces, so
    # do multiple # finds, sort, and put into a file, so order is the same as
    # shell expansion "/sys/class/net/*/*"
    # The find redirect to /dev/null is because some entries in /sys/class/net
    # aren't symlinks to directories, and we want to silently omit those.
    # Put the original full path back into the file list
    # Because gnu tar has issues with /sys files, compress it, to trim down all
    # the padding that gnu tar adds (even though the overall archive gets compressed,
    # this helps when it's extracted, and for the temporary filesystem use during
    # the cl-support).
    syslist=/tmp/syslist$$
    (netdir=/sys/class/net; cd $netdir && for f in *
        do find $f/*  -type f 2>/dev/null; done | sed "s,^,${netdir}/," |
        sort -o $syslist)
	tar czf $LOGDIR/sys.tar -T $syslist > /dev/null 2>&1
    rm -f $syslist

	# cron data
	#
	tar cf $LOGDIR/cron.tar `find /var/spool/cron/ -type f` >/dev/null 2>&1
}

func_system.btrfs() {
	# Info related to BTRFS file system and snapshots
	local logroot="$LOGDIR/btrfs"
	mkdir -p "$logroot"

	# BTRFS mount points and options
	exec_cmd "$logroot/mount-points" findmnt --type btrfs --kernel --list

	# BTRFS device info
	exec_cmd "$logroot/filesystem-df" btrfs filesystem df -h /
	exec_cmd "$logroot/filesystem-show" btrfs filesystem show
	exec_cmd "$logroot/device-stats" btrfs device stats /

	# BTRFS subvolume general info
	exec_cmd "$logroot/subvolume-default"   btrfs subvolume get-default /
	exec_cmd "$logroot/subvolume-list"      btrfs subvolume list -p -t /
	exec_cmd "$logroot/subvolume-list-ro"   btrfs subvolume list -p -t -r /
	exec_cmd "$logroot/subvolume-list-dnyc" btrfs subvolume list -p -t -d /

	# BTRFS per-subvolume detailed info
	for v in $(btrfs subvol list -t / | grep '@' | awk '{print $4}' | sed -e 's/^@$/\//' -e 's/@//') ; do
		p="$(echo $v | sed -e 's^/^-^g')"
		exec_cmd "$logroot/subvolume-show${p}" btrfs subvol show "$v"
	done

	# Snapper snapshot info
	if which snapper > /dev/null 2>&1 ; then
		exec_cmd "$logroot/snapper-list-configs" snapper list-configs
		exec_cmd "$logroot/snapper-root-config"  snapper --config root get-config
		exec_cmd "$logroot/snapper-root-list"    snapper --config root list
	fi
}

func_system.pkg() {
	# packages
	#
	exec_cmd $LOGDIR/dpkg.installed dpkg -l


	# XXX: debsums is a cpu hog plus takes a long time
	# This does not seem to be like a thing we want to collect
	# at every support
	#exec_cmd $LOGDIR/dpkg.sums debsums
}

func_system.config() {
	# XXX: /etc is captured by testing if this module is enabled
	# and then taring the /etc/* directory

	# Add any additional things to be captured by this module here
	return
}

func_system.logs() {
	# XXX: logs are captured by testing if this module is enabled
	# and then taring the /var/log/* directory

	# Add any additional things to be captured by this module here

	# Capture any kernel logs that exist in the kernel's internal
	# log ring buffer that have not made it to disk yet.
	exec_cmd $LOGDIR/dmesg dmesg
	return
}

func_system.systemd() {
	# Capture systemd information that may help debug problems

	exec_cmd $LOGDIR/cl-service-summary cl-service-summary
	exec_cmd $LOGDIR/systemd.failed systemctl -l --no-pager --failed
	exec_cmd $LOGDIR/systemd.status systemctl -l --no-pager status
	exec_cmd $LOGDIR/systemd.units systemctl -l --no-pager list-units
	exec_cmd $LOGDIR/systemd.unitfiles systemctl -l --no-pager list-unit-files
	exec_cmd $LOGDIR/systemd.journal journalctl -l --no-pager
}

func_system.memory_use() {
	exec_cmd $LOGDIR/ps.aux ps aux
	exec_cmd $LOGDIR/free free -l -m
	exec_cmd $LOGDIR/slabtop slabtop -o
	exec_cmd $LOGDIR/vmstat vmstat 1 5
	exec_cmd $LOGDIR/vmstat.m vmstat -m
	exec_cmd $LOGDIR/vmstat.s vmstat -s
}

s6000_get_cpld_versions()
{
    local cplds=(`ls /sys/bus/i2c/drivers/dummy | grep 3`)
    for cpld in ${cplds[@]}; do
        bus=`echo $cpld | cut -d '-' -f1`
        addr=`echo $cpld | cut -d '-' -f2`
        case $addr in
            0031) ver=0x`i2cget -f -y $bus 0x$addr 0 | cut -c 4`
            echo system_cpld=$ver ;;
            0032) ver=0x`i2cget -f -y $bus 0x$addr 1 | cut -c 4`
            echo master_cpld=$ver ;;
            0033) ver=0x`i2cget -f -y $bus 0x$addr 0xa | cut -c 4`
            echo slave_cpld=$ver ;;
        esac
    done
}

s4810_get_cpld_versions()
{
    ver=`cut -d ':' -f2 \
        /sys/devices/ffe05000.localbus/ffdf0000.cpld/board_revision`
    echo cpld_version=$ver
}

s4000_get_cpld_versions()
{
    local cplds=(`ls /sys/bus/i2c/drivers/dummy | grep 3`) 
    for cpld in ${cplds[@]}; do
        bus=`echo $cpld | cut -d '-' -f1`
        addr=`echo $cpld | cut -d '-' -f2`
        case $addr in
            0031) ver=0x`i2cget -f -y $bus 0x$addr 0 | cut -c 4`
                  echo system_cpld=$ver ;;
            0032) ver=0x`i2cget -f -y $bus 0x$addr 1 | cut -c 4`
                  echo master_cpld=$ver ;;
            0033) ver=0x`i2cget -f -y $bus 0x$addr 0 | cut -c 4`
                  echo slave_cpld=$ver ;;
        esac
    done
}

# Check for /sys/devices files for cpld versions; not all platforms
get_cpld_versions()
{
    files=$(find /sys/devices -type f | egrep -i cpld'.*(version|revision)')
    if [ ! "$files" ]; then
        dirs=$(find /sys/devices -type d -iname \*cpld\*)
        if [ "$dirs" ]; then
            files=$(find $dirs -type f | egrep -i cpld'.*(version|revision)')
        fi
    fi
    if [ "$files" ]; then
        grep -H . $files | sed -e 's,.*/,,' -e 's/,//g' -e 's/: */=/g'
    # else no /sys cpld versions on this platform.
    fi
}

bios_version()
{
    dmidecode 2>/dev/null | sed -n '/^BIOS.In/,/^$/{
        /Vendor/p
        /Version/p
        /Date/p
        /Revision/p
    }'
}

cpld_version()
{
    local platform=`platform-detect 2>/dev/null`
    case $platform in 
    dell,s4000_c2338) s4000_get_cpld_versions ;;
    dell,s6000_s1220) s6000_get_cpld_versions ;;
    dni,et-7448bf) s4810_get_cpld_versions ;;
    *) get_cpld_versions ;;
    esac
}
