Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new xsos v1 branch: split all modules into separate files #159

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions modules/BIOS
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#!/bin/bash

BIOS() {
# Local vars:
local dmidecode_input

if [[ -z $1 ]]; then
dmidecode_input=$(dmidecode 2>/dev/null)
elif [[ -f $1 ]]; then
dmidecode_input=$(<"$1")
elif [[ -r $1/dmidecode ]]; then
dmidecode_input=$(<"$1/dmidecode")
elif [[ -r $1/sos_commands/kernel.dmidecode ]]; then
dmidecode_input=$(<"$1/sos_commands/kernel.dmidecode")
fi

# If bad dmidecode input, return
if head -n3 <<<"$dmidecode_input" | egrep -qs 'No such file or directory|No SMBIOS nor DMI entry point found'; then
echo -e "${c[Warn2]}Warning:${c[Warn1]} dmidecode input invalid; skipping bios check${c[0]}" >&2
echo -en $XSOS_HEADING_SEPARATOR >&2
return 1
fi

echo -e "${c[H1]}DMIDECODE${c[0]}"

# Prints "<BIOS Vendor>, <BIOS Version>, <BIOS Release Date>"
echo -e "${c[H2]} BIOS:${c[0]}"
gawk 'BEGIN { RS="\nHandle" } /BIOS Information/' <<<"$dmidecode_input" |
gawk -F: -vH3="${c[H3]}" -vH2="${c[H2]}" -vH0="${c[0]}" -vH_IMP="${c[Imp]}" '
/Vendor:/ { Vendor = $2; gsub(/ */, " ", Vendor) }
/Version:/ { Version = $2; gsub(/ */, " ", Version) }
/Release Date:/ { RelDate = $2; gsub(/ */, " ", RelDate) }
/BIOS Revision:/ { BiosRev = $2; gsub(/ */, " ", BiosRev) }
/Firmware Revision:/ { FirmRev = $2; gsub(/ */, " ", FirmRev) }
END {
printf " %sVend:%s%s\n", H3, H0, Vendor
printf " %sVers:%s%s\n", H3, H0, Version
printf " %sDate:%s%s\n", H3, H0, RelDate
printf " %sBIOS Rev:%s%s\n", H3, H0, BiosRev
printf " %sFW Rev:%s %s\n", H3, H0, FirmRev
}
'
# Prints <SYSTEM Manufacturer>, <SYSTEM Product Name>, <SYSTEM Version>, <SYSTEM Serial Number>, <SYSTEM UUID>
echo -e "${c[H2]} System:${c[0]}"
gawk 'BEGIN { RS="\nHandle" } /System Information/' <<<"$dmidecode_input" |
gawk -F: -vH3="${c[H3]}" -vH2="${c[H2]}" -vH0="${c[0]}" -vH_IMP="${c[Imp]}" '
/Manufacturer:/ { Mfr = $2; gsub(/ */, " ", Mfr) }
/Product Name:/ { Product = $2; gsub(/ */, " ", Product) }
/Version:/ { Version = $2; gsub(/ */, " ", Version) }
/Serial Number:/{ Serial = $2 }
/UUID:/ { UUID = $2 }
END {
printf " %sMfr:%s %s\n", H3, H0, Mfr
printf " %sProd:%s%s\n", H3, H0, Product
printf " %sVers:%s%s\n", H3, H0, Version
printf " %sSer:%s %s\n", H3, H0, Serial
printf " %sUUID:%s%s\n", H3, H0, UUID
}
'
# Prints <CPU Manufacturer>, <CPU Family>, <CPU Current Speed>, <CPU Version>
# Prints "<N> of <N> CPU sockets populated, <N> cores/<N> threads per CPU"
# Prints "<N> total cores, <N> total threads"
echo -e "${c[H2]} CPU:${c[0]}"
gawk 'BEGIN { RS="\nHandle" } /Processor Information/' <<<"$dmidecode_input" |
gawk -F: -vH3="${c[H3]}" -vH2="${c[H2]}" -vH0="${c[0]}" -vH_IMP="${c[Imp]}" '
/Status:/ { SumSockets ++; if ($2 ~ /Populated/) PopulatedSockets ++ }
/Core Count:/ { SumCores += $2; CoresPerCpu = $2 }
/Thread Count:/ { SumThreads += $2; ThreadsPerCpu = $2 }
/Manufacturer:/ { if ($2 ~ /^ *$/) next; Mfr = $2; gsub(/ */, " ", Mfr) }
/Family:/ { if ($2 ~ /^ *$|Other/) next; Family = $2; gsub(/ */, " ", Family) }
/Current Speed:/{ if ($2 ~ /^ *$|Unknown/) next; CpuFreq = $2; gsub(/ */, " ", CpuFreq) }
/Version:/ { if ($2 ~ /^ *$/) next; Version = $2; gsub(/ */, " ", Version) }
END {
printf " %s%d of %d CPU sockets populated, %d cores/%d threads per CPU\n",
H_IMP, PopulatedSockets, SumSockets, CoresPerCpu, ThreadsPerCpu
printf " %d total cores, %d total threads\n", SumCores, SumThreads, H0
printf " %sMfr:%s %s\n", H3, H0, Mfr
printf " %sFam:%s %s\n", H3, H0, Family
printf " %sFreq:%s%s\n", H3, H0, CpuFreq
printf " %sVers:%s%s\n", H3, H0, Version
}
'
# Prints "<N> MB (<N> GB) total"
# Prints "<N> of <N> DIMMs populated (max capacity <N>)"
echo -e "${c[H2]} Memory:${c[0]}"
gawk 'BEGIN { RS="\nHandle" } /Physical Memory Array|Memory Device/' <<<"$dmidecode_input" |
gawk -vH3="${c[H3]}" -vH2="${c[H2]}" -vH0="${c[0]}" -vH_IMP="${c[Imp]}" '
/Size:/ { NumDimmSlots ++; if ($2 ~ /^[0-9]/) { NumDimms ++; SumRam+=$2 } }
/Maximum Capacity:/ { MaxRam = $3" "$4 }
END {
printf " %d MB (%.0f GB) total\n", SumRam, SumRam/1024
printf " %d of %d DIMMs populated (system max capacity %s)\n",
NumDimms, NumDimmSlots, MaxRam
}
'
echo -en $XSOS_HEADING_SEPARATOR
}
146 changes: 146 additions & 0 deletions modules/BONDING
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#!/bin/bash

BONDING() {
# Local vars:
local files netscriptsdir bond_input f mode bonding_opts active slaves slave s

# If passed a file (i.e. xsos --G <file>), use that
if [[ -f $1 ]]; then
files=($1)
# If localhost or sosreport, use that
else
files=("$1"/proc/net/bonding/*)
if [[ ! -r ${files[0]} ]]; then
echo -e "${c[Warn2]}Warning:${c[Warn1]} '/proc/net/bonding/' files unreadable; skipping bonding check${c[0]}" >&2
echo -en $XSOS_HEADING_SEPARATOR >&2
return
fi
[[ -d "$1"/etc/sysconfig/network-scripts ]] && netscriptsdir="$1"/etc/sysconfig/network-scripts
fi

__transform_mode() {
# Could be vastly improved by using bashV4 associative array, but KISS for rhel5 peeps
if grep -q "load balancing (round-robin)" <<<"$1"; then
mode="0 (balance-rr)"

elif grep -q "fault-tolerance (active-backup)" <<<"$1"; then
mode="1 (active-backup)"

elif grep -q "load balancing (xor)" <<<"$1"; then
mode="2 (balance-xor)"

elif grep -q "fault-tolerance (broadcast)" <<<"$1"; then
mode="3 (broadcast)"

elif grep -q "IEEE 802.3ad Dynamic link aggregation" <<<"$1"; then
mode="4 (802.3ad)"

elif grep -q "transmit load balancing" <<<"$1"; then
mode="5 (balance-tlb)"

elif grep -q "adaptive load balancing" <<<"$1"; then
mode="6 (balance-alb)"

else
mode="unrecognized: $1"
fi
}

if [[ $XSOS_SCRUB_MACADDR == y ]]; then
__scrub_mac() { sed -r 's/[0-9abcdef]/⣿/g' ; }
else
__scrub_mac() { cat ; }
fi

echo -e "${c[H1]}BONDING${c[0]}"

# The bracket here is like using parens to make a subshell -- allows to capture all stdout
{
# Header info ("❚" is used later by `column` to columnize the output)
echo " Device❚Mode❚ifcfg-File BONDING_OPTS❚Partner MAC Addr❚Slaves (*=active; [n]=AggID)"
echo " ========❚=================❚========================❚==================❚==============================="

f=0; for bond_input in ${files[@]}; do

echo -n " ${bond_input##*/}❚"

__transform_mode "$(gawk -F: '/Bonding Mode/ {printf $2}' $bond_input | sed -e 's/^ //')"
echo -n "$mode❚"

bonding_opts=$(gawk '/^BONDING_OPTS=/' "$netscriptsdir/ifcfg-${bond_input##*/}" 2>/dev/null | tail -n1 | sed s/BONDING_OPTS=// | tr -d \"\')
[[ -z $bonding_opts ]] && bonding_opts=-
echo -n "$bonding_opts❚"

if [[ ${mode::1} == 4 ]]; then
active_agg_info=$(gawk 'BEGIN{RS="\n\n"} /Active Aggregator Info:/ {print}' $bond_input)
partner_mac=$(gawk '/Partner Mac Address:/ {print $4}' <<<"$active_agg_info" | __scrub_mac)
echo -n "${partner_mac:--}❚"
active=$(gawk '/Aggregator ID:/ {print $3}' <<<"$active_agg_info")
else
echo -n "-❚"
active=$(gawk '/Active Slave/ {printf $4}' $bond_input)
fi

slaves=( $(gawk '/^Slave Interface:/ {print $3}' $bond_input) )

[[ ${#slaves[@]} -eq 0 ]] && echo "[None]"

s=0; until [[ $s -eq ${#slaves[@]} ]]; do
if [[ ${mode::1} == 4 ]]; then
agg_id=$(gawk 'BEGIN{RS="\n\n"} /Slave Interface: '"${slaves[s]}/" $bond_input | gawk '/Aggregator ID:/ {print $3}')
fi
# First line
if [[ $s -eq 0 ]]; then
if [[ ${mode::1} == 4 ]]; then
if [[ $active == $agg_id ]]; then
echo -n "* [$agg_id] ${slaves[s]}"
else
echo -n " [$agg_id] ${slaves[s]}"
fi
elif [[ $active == ${slaves[s]} ]]; then
echo -n "* ${slaves[s]}"
else
echo -n " ${slaves[s]}"
fi
# Not first line
else
if [[ ${mode::1} == 4 ]]; then
if [[ $active == $agg_id ]]; then
echo -n " ❚ ❚ ❚ ❚* [$agg_id] ${slaves[s]}"
else
echo -n " ❚ ❚ ❚ ❚ [$agg_id] ${slaves[s]}"
fi
elif [[ $active == ${slaves[s]} ]]; then
echo -n " ❚ ❚ ❚ ❚* ${slaves[s]}"
else
echo -n " ❚ ❚ ❚ ❚ ${slaves[s]}"
fi
fi

gawk 'BEGIN { RS="\n\n" } /Slave Interface: '${slaves[s]}'\>/' $bond_input |
gawk '/Permanent HW addr/ {printf " (%s)", $4}' | __scrub_mac
s=$((s+1))
echo
done
f=$((f+1))
[[ $f -lt ${#files[@]} ]] && echo " ❚ ❚ ❚ ❚- - - - - - - - - - - - - - - -"
done
} |
column -ts❚ |

# And then we need to do some color funness!
# This colorizes the first 2 lines with the H2 color and the interfaces with H3
gawk -vH0="${c[0]}" -vH2="${c[H2]}" -vH3="${c[H3]}" '
{
if (NR <= 2) print H2 $0 H0
else printf gensub(/(^ [[:graph:]]+ )/, H3"\\1"H0, 1)"\n"
}' |
gawk -vU="${c[Up]}" -vH0="${c[0]}" -vgrey="${c[DGREY]}" '
{
if (NR <= 2) print
else if ($1 == "-") print grey $0 H0
else printf gensub(/( \*.*)/, U"\\1"H0, 1)"\n"
}'

echo -en $XSOS_HEADING_SEPARATOR
}
51 changes: 51 additions & 0 deletions modules/CHECK_GRUB.helper
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/bash

CHECK_GRUB() {
# Local vars:
local grubcfg default

# Other vars that we want to be global, so no local here and no local in modules that call them:
## bad_grubcfg default_missing grub_kernel grub_cmdline

# Find the grub config file
if [[ -f $1/boot/grub/grub.conf ]]; then
# Set grubcfg for grub1
grubcfg=$1/boot/grub/grub.conf
elif [[ -f $1/boot/grub2/grub.cfg ]]; then
# Set grubcfg for rhel grub2
grubcfg=$1/boot/grub2/grub.cfg
elif [[ -f $1/boot/grub/grub.cfg ]]; then
# Set grubcfg for debian grub2
grubcfg=$1/boot/grub/grub.cfg
else
# Else, we have nothing
bad_grubcfg="${c[Warn1]}unknown (no grub config file)${c[0]}"
return 1
fi

# Check for read permission
if [[ ! -r $grubcfg ]]; then
# Set a message for later and stop here
bad_grubcfg="${c[Warn1]}unknown (no read permission on ${grubcfg##*/})${c[0]}"
return 1
fi

case "${grubcfg##*/}" in
grub.conf)
# If we have grub.conf, use that
default=$(gawk -F= '/^default=/{print$2}' "$grubcfg" 2>/dev/null)
[[ -z $default ]] && {
default=0; default_missing="${c[Warn1]}(Warning: grub.conf lacks \"default=\"; showing title 0)${c[0]}"
}
# Get the full kernel line for the default title statement
grub_cmdline=$(gawk /^title/,G "$grubcfg" | egrep -v '^#|^ *#' | sed '1!s/^title.*/\n&/' | gawk -vDEFAULT=$((default+1)) -vRS="\n\n" 'NR==DEFAULT' | grep -o '/vmlinuz-.*')
;;
grub.cfg)
# Otherwise, if we have a grub2 config (grub.cfg), use that
default=$(gawk -F\" '/^set default=/{print$2}' "$grubcfg")
grub_cmdline=$(gawk '/^menuentry.*{/,/^}/' "$grubcfg" | gawk -vRS="\n}\n" -vDEFAULT="$((default+1))" 'NR==DEFAULT' | grep -o '/vmlinuz-.*')
esac

grub_kernel=$(gawk {print\$1} <<<"${grub_cmdline#/vmlinuz-}" 2>/dev/null)
grub_cmdline=$(cut -d' ' -f2- <<<"$grub_cmdline")
}
90 changes: 90 additions & 0 deletions modules/CHECK_TAINTED.helper
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/bin/bash

CHECK_TAINTED() {
# Local vars:
local quote sys_tainted_status sys_kernel_version taint_states taintbit taintval indent t

[[ $1 == --quote ]] && quote=1 || quote=

sys_tainted_status=$(<"$2/proc/sys/kernel/tainted")
sys_kernel_version=$(<"$2/proc/sys/kernel/osrelease")

if [[ -n $quote ]]; then
echo -en "\"$sys_tainted_status\"${c[0]}"
else
echo -en "$sys_tainted_status${c[0]}"
fi

if [[ $sys_tainted_status == 0 ]]; then
echo " (kernel untainted)"
return
else
echo " (see https://access.redhat.com/solutions/40594)"
fi

case $3 in
H0) indent= ;;
H1) indent=$XSOS_INDENT_H1 ;;
H2) indent=$XSOS_INDENT_H2 ;;
H3) indent=$XSOS_INDENT_H3
esac

# See /usr/share/doc/kernel-doc*/Documentation/sysctl/kernel.txt
# kernel source: linux/kernel/panic.c
# kernel source: include/linux/kernel.h
# https://access.redhat.com/solutions/40594

t[0]="PROPRIETARY_MODULE: Proprietary module has been loaded"
t[1]="FORCED_MODULE: Module has been forcibly loaded"
t[2]="UNSAFE_SMP: SMP with CPUs not designed for SMP"
t[3]="FORCED_RMMOD: User forced a module unload"
t[4]="MACHINE_CHECK: System experienced a machine check exception"
t[5]="BAD_PAGE: System has hit bad_page"
if grep -qs '^2\.6\.18-.*el5' <<<"$sys_kernel_version"; then
t[6]="UNSIGNED_MODULE: Unsigned module has been loaded (RHEL5-specific)"
else
t[6]="USER: Userspace-defined naughtiness (RHEL6+)"
fi
t[7]="DIE: Kernel has oopsed before"
t[8]="OVERRIDDEN_ACPI_TABLE: ACPI table overridden"
t[9]="WARN: Taint on warning"
t[10]="CRAP: Modules from drivers/staging are loaded"
t[11]="FIRMWARE_WORKAROUND: Working around severe firmware bug"
t[12]="OOT_MODULE: Out-of-tree module has been loaded"
t[13]="UNSIGNED_MODULE: Unsigned module has been loaded"
t[14]="SOFTLOCKUP: A soft lockup has previously occurred"
t[15]="LIVEPATCH: Kernel has been live patched"
t[16]="16: undefined"
t[17]="17: undefined"
t[18]="18: undefined"
t[19]="19: undefined"
t[20]="20: undefined"
t[21]="21: undefined"
t[22]="22: undefined"
t[23]="23: undefined"
t[24]="24: undefined"
t[25]="25: undefined"
t[26]="26: undefined"
t[27]="BIT_BY_ZOMBIE: Kernel booted with OMGZOMBIES param"
t[28]="HARDWARE_UNSUPPORTED: Hardware is unsupported"
t[29]="TECH_PREVIEW: Technology Preview code is loaded"
t[30]="RESERVED30: undefined"
t[31]="RESERVED31: undefined"

taint_states=$(
for taintbit in $(sed 's, ,\n,g' <<<"${!t[@]}" | tac); do
taintval=$((2**taintbit))
if [[ $sys_tainted_status -gt $taintval ]]; then
echo $taintbit
sys_tainted_status=$((sys_tainted_status-taintval))
elif [[ $sys_tainted_status == $taintval ]]; then
echo $taintbit
break
fi
done
)

for taintbit in $(tac <<<"$taint_states"); do
printf "$indent%2s ${t[$taintbit]}\n" $taintbit
done
}
Loading