summaryrefslogtreecommitdiffstats
path: root/core/modules/hardware-stats/data/opt/openslx/scripts/systemd-gather_hw_info
diff options
context:
space:
mode:
Diffstat (limited to 'core/modules/hardware-stats/data/opt/openslx/scripts/systemd-gather_hw_info')
-rwxr-xr-xcore/modules/hardware-stats/data/opt/openslx/scripts/systemd-gather_hw_info308
1 files changed, 308 insertions, 0 deletions
diff --git a/core/modules/hardware-stats/data/opt/openslx/scripts/systemd-gather_hw_info b/core/modules/hardware-stats/data/opt/openslx/scripts/systemd-gather_hw_info
new file mode 100755
index 00000000..cdeb6d63
--- /dev/null
+++ b/core/modules/hardware-stats/data/opt/openslx/scripts/systemd-gather_hw_info
@@ -0,0 +1,308 @@
+#!/bin/bash
+# Use bash since ash can only do math on 32bit numbers, which is not sufficient for ID44 calculations
+# also for negative length to ${x:0:-1}
+
+# This script gathers information about the hardware and configuration and reports it back to the server
+
+. /opt/openslx/config
+
+export LANG=C.UTF-8
+export LC_ALL=C.UTF-8
+
+declare -rg REPORTFILE="/run/hwreport"
+declare -rg jsonfile="/run/hwreport.json"
+
+# new json-based reporting, run first in background and wait at the end of script
+# This is only supported by Sat3.11, released 12-2023, so keep creating the old format
+# too below this call, until we don't support 3.10 anymore.
+if ! python3 /opt/openslx/hardware-stats/collect_hw_info_json.py -p > "$jsonfile"; then
+ echo -n "" > "$jsonfile"
+fi &
+
+tmpmask="/tmp/hwreport-$$."
+
+mktemp() {
+ local FILE=
+ if [ -x /bin/mktemp ]; then
+ FILE=$( /bin/mktemp "${tmpmask}XXXXXXXX" )
+ fi
+ if [ -z "$FILE" ] && [ -x /opt/openslx/bin/mktemp ]; then
+ FILE=$( /opt/openslx/bin/mktemp "${tmpmask}XXXXXXXX" )
+ fi
+ if [ -z "$FILE" ]; then
+ FILE="${tmpmask}$RANDOM$RANDOM$$"
+ fi
+ echo "$FILE"
+}
+
+# Run on exit
+cleanup_exit() {
+ wait
+ rm -f -- "$tmpmask"* # no space!
+ exit 0
+}
+
+slxfdisk() {
+ local binary RET
+ for binary in "/opt/openslx/sbin/fdisk -u" "busybox fdisk -u" "fdisk"; do
+ $binary "$@"
+ RET=$?
+ [ "$RET" = "127" ] && continue # command not found
+ [ "$RET" = "1" ] && [ "${binary%% *}" = "busybox" ] && continue # maybe applet not found
+ return $RET
+ done
+ return 127
+}
+
+################################################################################
+# 1) Get MAC Address used for booting
+#
+MAC="${SLX_PXE_MAC}"
+if [ -z "$MAC" ]; then
+ # get MAC from sysfs
+ MAC="$(cat /sys/class/net/${SLX_PXE_NETIF:-br0}/address)"
+fi
+if [ -z "$MAC" ]; then
+ BOOTIF="$(grep -Po '(?<=BOOTIF=)[0-9a-f\-:]+' /proc/cmdline)"
+ [ "${#BOOTIF}" -eq "20" ] && MAC="${BOOTIF:3}"
+fi
+if [ -z "$MAC" ]; then
+ echo "Getting MAC from /proc/cmdline failed, using 'ip a'..."
+ _mac="$(ip a | grep -A 1 ': br0' | grep -o 'ether ..:..:..:..:..:..' | cut -d' ' -f2)"
+ [ "$_mac" -eq 17 ] && MAC="$_mac"
+fi
+if [ -z "$MAC" ]; then
+ MAC="88-77-66-55-44-33"
+fi
+# always uppercase and dash-separated
+MAC="${MAC^^}"
+MAC="${MAC//:/-}"
+echo "Determined MAC=$MAC"
+
+################################################################################
+# 2) Number of real and virtual CPU cores
+# Virtual, cheap way
+VCORES=$(grep '^processor\s' /proc/cpuinfo | sort -u | wc -l)
+# Real cores
+CPUCORES=$(cat /sys/devices/system/cpu/cpu*/topology/thread_siblings_list | sort -u | wc -l)
+CPUSOCKETS=$(grep '^physical id' /proc/cpuinfo | sort -u | wc -l)
+# Fallback 1...
+if [ -z "$CPUCORES" ] || [ "$CPUCORES" = "0" ]; then
+ for c in $(dmidecode -t 4 | grep 'Core Enabled' | awk -F ':' '{print $2}'); do
+ CPUCORES=$(( $CPUCORES + $c ))
+ done
+fi
+# Fallback 2...
+if [ -z "$CPUCORES" ] || [ "$CPUCORES" = "0" ]; then
+ CPUCORES=$(grep -E -e '^core id\s*:' -e '^physical id\s*:' /proc/cpuinfo | xargs -l2 echo | sort -u | wc -l)
+fi
+echo "$CPUCORES real cores, $VCORES with HT"
+
+################################################################################
+# 3) CPU model name
+#
+CPUMODEL=$(grep -m1 '^model name\s*:' /proc/cpuinfo | sed 's/^model name\s*:\s*//;s/\s\s*/ /g;s/^ //;s/ $//')
+echo "$CPUMODEL"
+
+################################################################################
+# 4) RAM
+#
+RAM=$(grep -m1 '^MemTotal:' /proc/meminfo | awk '{print $2}')
+RAM=$(( $RAM / 1024 ))
+if [ -z "$RAM" ] || [ "$RAM" -lt 500 ]; then
+ # Fallback to dmidecode
+ RAM=0
+ for c in $(dmidecode -t 17 | grep -o 'Size:.*MB$' | awk '{print $2}'); do
+ RAM=$(( $RAM + $c ))
+ done
+fi
+echo "$RAM MB RAM"
+
+################################################################################
+# 5) 64bit virtualization support
+#
+VT="UNSUPPORTED"
+CPU_VENDOR=$( grep -m1 '^vendor_id\s*:' /proc/cpuinfo | awk '{print $3}' )
+VIRTTYPE=$(grep -m1 '^flags\s*:' /proc/cpuinfo | grep -wo -e svm -e vmx)
+[ -n "$CPU_VENDOR" ] && modprobe msr
+echo "CPUID: $CPU_VENDOR"
+
+if [ "$CPU_VENDOR" = "GenuineIntel" ]; then
+ BIT1="$( rdmsr --bitfield 0:0 0x3a 2>/dev/null || echo "fail" )"
+ BIT2="$( rdmsr --bitfield 2:2 0x3a 2>/dev/null || echo "fail" )"
+ if [ "$BIT1" = "fail" ] || [ "$BIT2" = "fail" ]; then
+ VT="UNKNOWN"
+ elif [ "$BIT1" = "1" ] && [ "$BIT2" = "0" ]; then
+ VT="DISABLED"
+ elif [ "$VIRTTYPE" = "vmx" ]; then
+ VT="ENABLED"
+ fi
+elif [ "$CPU_VENDOR" = "AuthenticAMD" ]; then
+ BIT="$( rdmsr --bitfield 4:4 0xc0010114 2>/dev/null || echo "fail" )"
+ if [ "$BIT" = "fail" ]; then
+ VT="UNKNOWN"
+ elif [ "$BIT" = "1" ]; then
+ VT="DISABLED"
+ elif [ "$VIRTTYPE" = "svm" ]; then
+ VT="ENABLED"
+ fi
+fi
+echo "KVM support is $VT"
+
+################################################################################
+# 6) ID44 partition size
+#
+ID44=0
+if ! slx-tools fs_path_isvolatile "/tmp/virt" ; then
+ ID44_SPACE=($(slx-tools fs_path_space "/tmp/virt"))
+ [ -n "${ID44_SPACE[1]}" ] && ID44="$(( ${ID44_SPACE[1]} / 1024 ))"
+
+ if [ "$ID44" -eq 0 ]; then
+ # Fallback to old way to detect it
+ # Try df first, make sure device starts with /dev
+ read -r df_dev df_size df_used df_avail df_usepercent df_mountpoint df_crap < <(df -P /tmp/virt | grep ' /tmp/virt$')
+ if [ -n "${df_size}" ] && [ "${df_dev:0:5}" = "/dev/" ]; then
+ # df reports kbytes, convert to MB
+ ID44=$(( df_size / 1024 ))
+ fi
+ if [ "$ID44" = 0 ]; then
+ # slxfdisk fallback
+ for c in $(slxfdisk -l | grep -E '[0-9]+[\-\+MG]?\s+44\s+' | awk '{print $1}'); do
+ val=$(blockdev --getsize64 "$c")
+ [ -z "$val" ] && continue
+ [ "$val" -gt "$ID44" ] && ID44=$val
+ done
+ # blockdev reports bytes, convert to MB
+ ID44=$(( $ID44 / 1058576 )) # we'd rather underreport
+ fi
+ fi
+fi
+echo "Scratch space: $ID44 MB"
+
+################################################################################
+# 7) check smart values
+#
+FDISK=$(mktemp)
+declare -a DISKS
+shopt -s extglob
+for disk in /dev/disk/by-path/!(*-part*|*-usb-*); do
+ [ -L "$disk" ] || continue
+ disk="$( readlink -f "$disk" )"
+ DISKS+=("$disk")
+ slxfdisk -l "$disk" | sed -r 's/\s+[0-9]+,[0-9]+,[0-9]+/ /g;/^\// s/\s[0-9]+\.?[0-9]+[MGT]\s/ /;s/^Units: /Units =foo= /' | awk '{if ($1 !~ /^[0-9]+$/ || $5 ~ /^[0-9a-f]{4}/) { print $0 } else { $5 = "0700 " $5; print $0 }}' # Work around busybox YET AGAIN changing something in an incompatible way
+done > "$FDISK"
+shopt -u extglob
+[ -z "$SLX_SMARTCTL_MIN_REALLOC" ] && SLX_SMARTCTL_MIN_REALLOC=0
+BADSECTORS=0
+if which smartctl; then
+ ALLSMART=$(mktemp)
+ FILE=$(mktemp)
+ [ -z "$FILE" ] && FILE="/tmp/smartctl.$$.$RANDOM.$RANDOM"
+ for dev in "${DISKS[@]}"; do
+ smartctl -i -H -A -f "brief" "${dev%n[0-9]}" > "$FILE"
+ # Exit code might be nonzero to indicate fail status, or because some (but not all) ATA commands
+ # failed. So instead, see if we at least got basic device information and go on if so.
+ grep -q -E -e '^Device Model:' -e '^\s*5\s.+\s.+\s.+\s[0-9]' -e '^Model Number:' "$FILE" || continue
+ echo "NEXTHDD=$dev" >> "$ALLSMART"
+ cat "$FILE" >> "$ALLSMART"
+ # parse
+ OVERALL=$(grep -o "test result: .*$" "$FILE" | cut -c 14-)
+ [ "x$OVERALL" = "xPASSED" ] && OVERALL=""
+ REALLOC=$(grep "^ *5 " "$FILE" | awk '{print $8}')
+ PENDING=$(grep "^ *197 " "$FILE" | awk '{print $8}')
+ SPINRETRY_VAL=$(grep "^ *10 " "$FILE" | awk '{print $4}')
+ SPINRETRY_THR=$(grep "^ *10 " "$FILE" | awk '{print $6}')
+ [ -n "$OVERALL" ] && BADSECTORS=$(( $BADSECTORS + 100 ))
+ if [ -n "$REALLOC" ] && [ "$REALLOC" -gt "0" ]; then
+ BADSECTORS=$(( $BADSECTORS + $REALLOC ))
+ fi
+ if [ -n "$PENDING" ] && [ "$PENDING" -gt "5" ]; then
+ BADSECTORS=$(( $BADSECTORS + $PENDING ))
+ fi
+ if [ -n "$SPINRETRY_VAL" ] && [ "$SPINRETRY_VAL" -le "$SPINRETRY_THR" ]; then
+ BADSECTORS=$(( $BADSECTORS + 100 ))
+ fi
+ done
+ rm -f -- "$FILE"
+fi
+echo "SMART: $OVERALL - $REALLOC reallocated, $PENDING pending"
+
+################################################################################
+# 8) Read system model and manufacturer
+#
+dmidec() {
+ local RETVAL=$(dmidecode "$@" 2>/dev/null | grep -v '^#' | grep -v '^Invalid' | sed 's/\s\s*/ /g;s/^ //;s/ $//')
+ case "$RETVAL" in
+ ""|*"Product Name"*|*"be filled"*|"unknown"|*"efault string"*|*"efault String"*|*"product name"*|*"anufacturer"*|*"ystem model"*)
+ RETVAL="Unknown"
+ ;;
+ esac
+ echo "$RETVAL"
+}
+
+bashesc () {
+ sed s/\'/\'\"\'\"\'/g <<< $*
+}
+
+HW_MODEL=$(dmidec -q -s system-product-name)
+HW_MANUF=$(dmidec -q -s system-manufacturer)
+# Try fallback to baseboard
+if [ "$HW_MODEL" = "Unknown" ]; then
+ HW_MODEL=$(dmidec -q -s baseboard-product-name)
+ HW_MANUF=$(dmidec -q -s baseboard-manufacturer)
+fi
+
+HW_MANUF=$(bashesc "$HW_MANUF")
+HW_MODEL=$(bashesc "$HW_MODEL")
+
+################################################################################
+# Save raw data to report file
+#
+cat > "$REPORTFILE" <<-EOF
+############################### CPU #####################################
+Sockets: $CPUSOCKETS
+Real cores: $CPUCORES
+Virtual cores: $VCORES
+######################## Partition tables ###############################
+EOF
+cat "$FDISK" >> "$REPORTFILE"
+cat >> "$REPORTFILE" <<-EOF
+############################ PCI ID #####################################
+EOF
+lspci -n -m >> "$REPORTFILE"
+cat >> "$REPORTFILE" <<-EOF
+########################## dmidecode ####################################
+EOF
+dmidecode >> "$REPORTFILE"
+if [ -n "$ALLSMART" ] && [ -s "$ALLSMART" ]; then
+ cat >> "$REPORTFILE" <<-EOF
+ ########################### smartctl ####################################
+ EOF
+ cat "$ALLSMART" >> "$REPORTFILE"
+fi
+cat >> "$REPORTFILE" <<-EOF
+#########################
+EOF
+echo "Created report file"
+
+[ -n "$ALLSMART" ] && rm -f -- "$ALLSMART"
+
+################################################################################
+# Save information to local file for later use
+#
+cat > "/run/hwinfo" <<HORST
+HW_KVM='${VT}'
+HW_ID44='${ID44}'
+HW_MAC='${MAC}'
+HW_MBRAM='${RAM}'
+HW_HDDCOUNT='${#DISKS[@]}'
+HW_BADSECTORS='${BADSECTORS}'
+HW_MANUF='${HW_MANUF}'
+HW_MODEL='${HW_MODEL}'
+HW_CPUMODEL='${CPUMODEL}'
+HW_SOCKETS='${CPUSOCKETS}'
+HW_CORES='${CPUCORES}'
+HW_THREADS='${VCORES}'
+HORST
+
+cleanup_exit