1#!/bin/bash 2 3# Define constants 4SERVICE="xyz.openbmc_project.FanSensor" 5FUNCTIONAL_INTERFACE="xyz.openbmc_project.State.Decorator.OperationalStatus" 6AVAILABILITY_INTERFACE="xyz.openbmc_project.State.Decorator.Availability" 7 8# D-Bus paths of fan rotors 9FAN_PATHS=( 10 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN0_TACH_INLET_SPEED_RPM" 11 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN0_TACH_OUTLET_SPEED_RPM" 12 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN1_TACH_INLET_SPEED_RPM" 13 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN1_TACH_OUTLET_SPEED_RPM" 14 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN2_TACH_INLET_SPEED_RPM" 15 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN2_TACH_OUTLET_SPEED_RPM" 16 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN3_TACH_INLET_SPEED_RPM" 17 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN3_TACH_OUTLET_SPEED_RPM" 18 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN4_TACH_INLET_SPEED_RPM" 19 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN4_TACH_OUTLET_SPEED_RPM" 20 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN5_TACH_INLET_SPEED_RPM" 21 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN5_TACH_OUTLET_SPEED_RPM" 22 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN6_TACH_INLET_SPEED_RPM" 23 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN6_TACH_OUTLET_SPEED_RPM" 24 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN7_TACH_INLET_SPEED_RPM" 25 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN7_TACH_OUTLET_SPEED_RPM" 26 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN8_TACH_INLET_SPEED_RPM" 27 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN8_TACH_OUTLET_SPEED_RPM" 28 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN9_TACH_INLET_SPEED_RPM" 29 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN9_TACH_OUTLET_SPEED_RPM" 30 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN10_TACH_INLET_SPEED_RPM" 31 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN10_TACH_OUTLET_SPEED_RPM" 32 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN11_TACH_INLET_SPEED_RPM" 33 "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN11_TACH_OUTLET_SPEED_RPM" 34) 35 36# Add event log 37add_sel() 38{ 39 MESSAGE="$*" 40 41 busctl call \ 42 xyz.openbmc_project.Logging /xyz/openbmc_project/logging \ 43 xyz.openbmc_project.Logging.Create Create "ssa{ss}" "$MESSAGE" \ 44 xyz.openbmc_project.Logging.Entry.Level.Error 0 >/dev/null 2>&1 45} 46 47# Check normal fans 48check_normal_fans() { 49 local normal_count=0 50 for path in "${FAN_PATHS[@]}"; do 51 # Get properties with error handling 52 functional=$(busctl get-property "$SERVICE" "$path" "$FUNCTIONAL_INTERFACE" Functional 2>/dev/null | awk '{print $2}') 53 available=$(busctl get-property "$SERVICE" "$path" "$AVAILABILITY_INTERFACE" Available 2>/dev/null | awk '{print $2}') 54 55 # Check if properties were fetched successfully 56 if [[ -z "$functional" || -z "$available" ]]; then 57 continue 58 fi 59 60 # Check for normal fan 61 if [[ "$functional" == "true" && "$available" == "true" ]]; then 62 normal_count=$((normal_count + 1)) 63 fi 64 done 65 echo $normal_count 66} 67 68# Restart fan sensor service 69reload_fan_sensors() { 70 echo "Reloading fan sensors..." 71 if systemctl restart xyz.openbmc_project.fansensor; then 72 echo "Fan sensors reloaded successfully." 73 else 74 echo "Failed to reload fan sensors." >&2 75 fi 76 sleep 30 # Wait for the service to stabilize 77} 78 79# Power off a single slot 80power_off_slot(){ 81 local slot_number=$1 82 local object_path="/xyz/openbmc_project/state/chassis${slot_number}" 83 local service_name="xyz.openbmc_project.State.Chassis${slot_number}" 84 local interface="xyz.openbmc_project.State.Chassis" 85 local property="RequestedPowerTransition" 86 local value="xyz.openbmc_project.State.Chassis.Transition.Off" 87 local ret=0 88 89 echo "AC Powering off slot $slot_number..." 90 91 busctl set-property "$service_name" "$object_path" "$interface" "$property" s "$value" 92 ret=$? 93 94 if [ $ret -eq 0 ]; then 95 echo "Slot $slot_number powered off successfully." 96 else 97 echo "Failed to power off slot $slot_number." >&2 98 return $ret 99 fi 100} 101 102# Power off all slots 103power_off_all_slots() { 104 # Log the event before shutting down 105 local msg="" 106 107 msg="Hosts 1 to 8 are being shut down due to the missing of more than 2 fan rotors." 108 echo "${msg}" 109 add_sel "${msg}" 110 111 for slot in {1..8}; do 112 power_off_slot "$slot" 113 done 114} 115 116# Main logic 117main() { 118 local normal_count=24 119 local normal_rototr_threashold=22 120 # Initial check 121 normal_count=$(check_normal_fans) 122 echo "Initial normal fan count: $normal_count" 123 124 if (( normal_count < normal_rototr_threashold )); then 125 echo "Normal fan count below threshold. Attempting recovery..." 126 normal_count=24 127 reload_fan_sensors 128 129 # Recheck after recovery 130 normal_count=$(check_normal_fans) 131 echo "Post-recovery normal fan count: $normal_count" 132 133 if (( normal_count < normal_rototr_threashold )); then 134 echo "Still > 2 rotors missing after reload the fan sensors. Initiating shutdown." 135 power_off_all_slots 136 else 137 echo "Recovery successful. System is stable." 138 fi 139 else 140 echo "System is stable. No action required." 141 fi 142} 143 144main 145