summaryrefslogblamecommitdiffstats
path: root/core/modules/hardware-stats/data/opt/openslx/scripts/systemd-hardware_stats
blob: cdeb6d63cb4845e8a464d6cd27c3bf09f39a628f (plain) (tree)
1
2
3
4
5
6
7
8
9
10






                                                                                                        
 

                     
 










                                                                                       
 
          

                                   
                                                          

                                                                 
                                                                      

                               
                                                 
          


                    




                                        

 
            
                        
                                                                                 
                            
                      
                                                                  
                                                                                                        




                           
                                                                                
                                     










                                                                     
                                                                     

                                                                                              
  

                               
  



                                     
 

                                                                                


                                                             
                                                                                            
                                                                 







                                                                                      
                                                                                                                    
  
                                            
 


                                                                                
                                                                                                             
                
 


                                                                                
                                                             







                                                                                 
                  
 


                                                                                
                
                                                                          
                                                                        

                                    
 



                                                                        
                            
                                                         
                             

                                          
          

                                                                             

                                    
                                   
                             

                                          

          
                         
 


                                                                                
      

                                                           

                                                                          
                                  

                                                                 
                                                                                                                                     





                                                                             
                                                                                                          







                                                                             
  
                              
 


                                                                                
               
                
                
                                                    


                                       
                                                                                                                                                                                                                                                                                                                  
               
                
                                                                




                                                                 
                                    
                                                                      

                                                                                                                
                                                                                                                    





                                                                          
                                                                    





                                                                         


                                                                    





                                                                                             
                                                               
 


                                                                                
          

                                                                                                                        
                                                                                                                                                 
                                        

                          
                      
 
 



                                    

                                            
                           


                                                       

  

                               
 


                                                                                
                          
                                                                         
                          
                        
                      

                                                                         

                             

                                                                         

                            

                                                                         
                          
                                                 
                                   

                                                                                 
                                        
  
                           

                         
                          


                                          


                                                                                


                           
               
                 

                             

                      
                         
                          



                      
            
#!/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