1#!/bin/bash -e
2
3FAN_STATUS_UNKNOWN="Unknown"
4FAN_STATUS_NORMAL="Normal"
5FAN_STATUS_ABNORMAL="Abnormal"
6FAN_FAIL_REASON=""
7
8create_log()
9{
10    local service="xyz.openbmc_project.Logging"
11    local object_path="/xyz/openbmc_project/logging"
12    local interface="xyz.openbmc_project.Logging.Create"
13    local message="Fan status abnormal: $FAN_FAIL_REASON"
14    local severity="xyz.openbmc_project.Logging.Entry.Level.Error"
15    local arg="CALLOUT_INVENTORY_PATH"
16    local value="/xyz/openbmc_project/inventory/fan"
17
18    echo "Creating log: $message"
19    busctl call "$service" "$object_path" "$interface" Create "ssa{ss}" "$message" "$severity" 1 "$arg" "$value"
20}
21
22resolve_log()
23{
24    local service="xyz.openbmc_project.ObjectMapper"
25    local object_path="/xyz/openbmc_project/inventory/fan/fault"
26    local interface="xyz.openbmc_project.Association"
27    local property="endpoints"
28
29    mapfile -t -d " " endpoint_array < <(busctl get-property "$service" "$object_path" "$interface" "$property" | tr -d '"\n')
30
31    for ((i = 2; i < ${#endpoint_array[@]}; i++)); do
32        endpoint="${endpoint_array[$i]}"
33        busctl set-property xyz.openbmc_project.Logging "$endpoint" xyz.openbmc_project.Logging.Entry Resolved b true
34    done
35}
36
37check_fcb_fan_status()
38{
39    local fcb_num=$1
40
41    local service="xyz.openbmc_project.FanSensor"
42    local interface="xyz.openbmc_project.Sensor.Threshold.Critical"
43    local property_list=("CriticalAlarmHigh" "CriticalAlarmLow")
44    local in_out=("IL" "OL")
45
46    for index in {0..7}
47    do
48        local fan_number=$((((fcb_num - 1) * 4) + (index / 2) + 1))
49        local io_index=$((index % 2))
50        local sensor_name="FCB_${fcb_num}_FAN_${fan_number}_TACH_${in_out[$io_index]}_SPEED_RPM"
51        local object_path="/xyz/openbmc_project/sensors/fan_tach/$sensor_name"
52
53        for property in "${property_list[@]}"; do
54            tach_alarm=$(busctl get-property "$service" "$object_path" "$interface" "$property" | cut -d ' ' -f2)
55            if [ "$tach_alarm" = "true" ]; then
56                echo "$FAN_STATUS_ABNORMAL|$sensor_name $property alarm"
57                return 0
58            fi
59        done
60
61        # Check FCB whether is AC off
62        local operation_interface="xyz.openbmc_project.State.Decorator.OperationalStatus"
63        functional=$(busctl get-property "$service" "$object_path" "$operation_interface" Functional | awk '{print $NF}')
64        if [ "$functional" = "false" ]; then
65            echo "$FAN_STATUS_ABNORMAL|FCB$fcb_num is not functional. The AC may be off."
66            return 0
67        fi
68    done
69
70    echo "$FAN_STATUS_NORMAL|"
71    return 0
72}
73
74pre_status=$FAN_STATUS_UNKNOWN
75
76while true
77do
78    fan_status=$FAN_STATUS_NORMAL
79    FAN_FAIL_REASON=""
80
81    # FCB1 ~ FCB6
82    for i in {1..6}
83    do
84        # Check the presence of each FCB
85        presence=$(busctl get-property xyz.openbmc_project.Inventory.Manager \
86            /xyz/openbmc_project/inventory/system/board/Minerva_CMM/FCB_"${i}" \
87            xyz.openbmc_project.Inventory.Item Present | awk '{print $NF}')
88
89        if [ "$presence" != "true" ]; then
90            fan_status=$FAN_STATUS_ABNORMAL
91            FAN_FAIL_REASON="FCB$i not present"
92            break
93        else
94            # Check each sensor on the FCB whether alert critical alarm
95            result=$(check_fcb_fan_status "$i")
96            fan_status=$(echo "$result" | cut -d '|' -f1)
97            FAN_FAIL_REASON=$(echo "$result" | cut -d '|' -f2)
98            if [ "$fan_status" = "$FAN_STATUS_ABNORMAL" ]; then
99                break
100            fi
101        fi
102    done
103
104    if [ "$fan_status" = "$FAN_STATUS_ABNORMAL" ] && [ "$pre_status" != "$FAN_STATUS_ABNORMAL" ]; then
105        create_log
106        pre_status="$FAN_STATUS_ABNORMAL"
107    elif [ "$fan_status" = "$FAN_STATUS_NORMAL" ] && [ "$pre_status" != "$FAN_STATUS_NORMAL" ]; then
108        resolve_log
109        pre_status="$FAN_STATUS_NORMAL"
110    fi
111    sleep 1
112done
113