179f697e0SAnthony Wilson#!/bin/sh -e
279f697e0SAnthony Wilson
379f697e0SAnthony Wilsonset -euo pipefail
479f697e0SAnthony Wilson
5189cf248SAnthony WilsonOPTS="bmcstate,bootprogress,chassiskill,chassisoff,chassison,chassisstate,hoststate,\
67a787dd7SVishwanatha Subbannaosstate,power,poweroff,poweron,state,status,rebootoff,rebooton,recoveryoff,recoveryon"
70f35983dSAnthony Wilson
860c3ac8cSAndrew JefferyUSAGE="Usage: obmcutil [-h] [--wait] [--verbose]
90f35983dSAnthony Wilson                {$OPTS}"
1079f697e0SAnthony Wilson
1179f697e0SAnthony WilsonINTERFACE_ROOT=xyz.openbmc_project
1279f697e0SAnthony WilsonSTATE_INTERFACE=$INTERFACE_ROOT.State
136d3a2c54SVishwanatha SubbannaCONTROL_INTERFACE=$INTERFACE_ROOT.Control
1479f697e0SAnthony Wilson
1579f697e0SAnthony WilsonOBJECT_ROOT=/xyz/openbmc_project
1679f697e0SAnthony WilsonSTATE_OBJECT=$OBJECT_ROOT/state
176d3a2c54SVishwanatha SubbannaCONTROL_OBJECT=$OBJECT_ROOT/control
1879f697e0SAnthony Wilson
197a787dd7SVishwanatha SubbannaHOST_TIMEOUT_TARGET=obmc-host-timeout@0.target
20*84b3b29eSVishwanatha SubbannaHOST_CRASH_TARGET=obmc-host-crash@0.target
217a787dd7SVishwanatha Subbanna
22acf54d08SAnthony Wilson## NOTE: The following global variables are used only in the run_timeout cmd.
23acf54d08SAnthony Wilson## By declaring these globally instead of passing them through the
24acf54d08SAnthony Wilson## intermediary functions, which may not be "best practice", the readability
25acf54d08SAnthony Wilson## and cleanliness of the code should at least be increased.
26acf54d08SAnthony Wilson
27acf54d08SAnthony Wilson# The command passed in to be executed (e.g. poweron/off, status, etc.)
28acf54d08SAnthony Wilson# This will be be used in some instances of error reporting
29acf54d08SAnthony WilsonG_ORIG_CMD=
30acf54d08SAnthony Wilson# The state an interface should be in after executing the requested command.
31acf54d08SAnthony WilsonG_REQUESTED_STATE=
32acf54d08SAnthony Wilson# The query to run during a poweron/off or chassison/off to check that
33acf54d08SAnthony Wilson# the requested state (G_REQUESTED_STATE) of the interface has been reached.
34acf54d08SAnthony WilsonG_QUERY=
35acf54d08SAnthony Wilson# Wait the set period of time for state transitions to be successful before
36acf54d08SAnthony Wilson# continuing on with the program or reporting an error if timeout reached.
37acf54d08SAnthony WilsonG_WAIT=
3860c3ac8cSAndrew Jeffery# Print the journal to the console
3960c3ac8cSAndrew JefferyG_VERBOSE=
40acf54d08SAnthony Wilson
41f3f16fa9SAnthony Wilsonprint_help ()
42f3f16fa9SAnthony Wilson{
43f3f16fa9SAnthony Wilson    echo "$USAGE"
44f3f16fa9SAnthony Wilson    echo ""
45f3f16fa9SAnthony Wilson    echo "positional arguments:"
460f35983dSAnthony Wilson    echo "  {$OPTS}"
47f3f16fa9SAnthony Wilson    echo ""
486d3a2c54SVishwanatha Subbanna    echo "Examples:"
496d3a2c54SVishwanatha Subbanna    echo ""
506d3a2c54SVishwanatha Subbanna    echo "obmcutil rebootoff    Disable auto reboot from Quiesce state"
516d3a2c54SVishwanatha Subbanna    echo "obmcutil rebooton     Enable auto reboot from Quiesce state"
526d3a2c54SVishwanatha Subbanna    echo ""
53*84b3b29eSVishwanatha Subbanna    echo "obmcutil recoveryoff  Disable handling boot watchdog timeout and host crash"
54*84b3b29eSVishwanatha Subbanna    echo "                      Also, disable auto reboot from Quiesce state"
55*84b3b29eSVishwanatha Subbanna    echo "obmcutil recoveryon   Enable handling boot watchdog timeout and host crash"
56*84b3b29eSVishwanatha Subbanna    echo "                      Also, enable auto reboot from Quiesce state"
577a787dd7SVishwanatha Subbanna    echo ""
58f3f16fa9SAnthony Wilson    echo "optional arguments:"
59f3f16fa9SAnthony Wilson    echo "  -h, --help          show this help message and exit"
60acf54d08SAnthony Wilson    echo "  -w, --wait          block until state transition succeeds or fails"
6160c3ac8cSAndrew Jeffery    echo "  -v, --verbose       print the journal to stdout if --wait is supplied"
62f3f16fa9SAnthony Wilson    exit 0
63f3f16fa9SAnthony Wilson}
64f3f16fa9SAnthony Wilson
65acf54d08SAnthony Wilsonrun_timeout ()
66acf54d08SAnthony Wilson{
67acf54d08SAnthony Wilson    local timeout="$1"; shift
68acf54d08SAnthony Wilson    local cmd="$@"
6960c3ac8cSAndrew Jeffery    local verbose_child=
7060c3ac8cSAndrew Jeffery
712869a926SAndrew Jeffery    if [ -n "$G_VERBOSE" ]; then
7260c3ac8cSAndrew Jeffery        journalctl -f &
7360c3ac8cSAndrew Jeffery        verbose_child=$!
7460c3ac8cSAndrew Jeffery    fi
75acf54d08SAnthony Wilson
76acf54d08SAnthony Wilson    $cmd
77acf54d08SAnthony Wilson
78acf54d08SAnthony Wilson    # Run a background query for the transition to the expected state
79acf54d08SAnthony Wilson    # This will be killed if the transition doesn't succeed within
80acf54d08SAnthony Wilson    # a timeout period.
81acf54d08SAnthony Wilson    (
82acf54d08SAnthony Wilson        while ! grep -q $G_REQUESTED_STATE <<< $(handle_cmd $G_QUERY) ; do
83acf54d08SAnthony Wilson            sleep 1
84acf54d08SAnthony Wilson        done
85acf54d08SAnthony Wilson    ) &
8660c3ac8cSAndrew Jeffery    wait_child=$!
87acf54d08SAnthony Wilson
88acf54d08SAnthony Wilson    # Could be bad if process is killed before 'timeout' occurs if
89acf54d08SAnthony Wilson    # transition doesn't succeed.
90acf54d08SAnthony Wilson    trap -- "" SIGTERM
91acf54d08SAnthony Wilson
92acf54d08SAnthony Wilson    # Workaround for lack of 'timeout' command.
93acf54d08SAnthony Wilson    (
94acf54d08SAnthony Wilson        sleep $timeout
9560c3ac8cSAndrew Jeffery        kill $wait_child
96acf54d08SAnthony Wilson    ) > /dev/null 2>&1 &
97acf54d08SAnthony Wilson
9860c3ac8cSAndrew Jeffery    if ! wait $wait_child; then
99acf54d08SAnthony Wilson        echo "Unable to confirm '$G_ORIG_CMD' success" \
100acf54d08SAnthony Wilson        "within timeout period (${timeout}s)"
101acf54d08SAnthony Wilson    fi
10260c3ac8cSAndrew Jeffery
10360c3ac8cSAndrew Jeffery    if [ -n $verbose_child ]; then
10460c3ac8cSAndrew Jeffery        kill $verbose_child
10560c3ac8cSAndrew Jeffery    fi
106acf54d08SAnthony Wilson}
107acf54d08SAnthony Wilson
108acf54d08SAnthony Wilsonrun_cmd ()
109acf54d08SAnthony Wilson{
110acf54d08SAnthony Wilson    local cmd="$@";
111acf54d08SAnthony Wilson
112acf54d08SAnthony Wilson    if [ -n "$G_WAIT" ]; then
113acf54d08SAnthony Wilson        run_timeout $G_WAIT "$cmd"
114acf54d08SAnthony Wilson    else
115acf54d08SAnthony Wilson        $cmd
116acf54d08SAnthony Wilson    fi
117acf54d08SAnthony Wilson}
118acf54d08SAnthony Wilson
1193ae0a354SAnthony Wilsonset_property ()
1203ae0a354SAnthony Wilson{
121acf54d08SAnthony Wilson    run_cmd busctl set-property "$@"
1223ae0a354SAnthony Wilson}
1233ae0a354SAnthony Wilson
12479f697e0SAnthony Wilsonget_property ()
12579f697e0SAnthony Wilson{
126acf54d08SAnthony Wilson    G_WAIT=""
127acf54d08SAnthony Wilson    run_cmd busctl get-property "$@"
12879f697e0SAnthony Wilson}
12979f697e0SAnthony Wilson
13079f697e0SAnthony Wilsonstate_query ()
13179f697e0SAnthony Wilson{
13279f697e0SAnthony Wilson    local state=$(get_property "$@" | cut -d '"' -f2)
13379f697e0SAnthony Wilson    printf "%-20s: %s\n" $4 $state
13479f697e0SAnthony Wilson}
13579f697e0SAnthony Wilson
136ea87db40SAnthony Wilsonprint_usage_err ()
137ea87db40SAnthony Wilson{
138ea87db40SAnthony Wilson    echo "ERROR: $1" >&2
139ea87db40SAnthony Wilson    echo "$USAGE"
140ea87db40SAnthony Wilson    exit 1
141ea87db40SAnthony Wilson}
142ea87db40SAnthony Wilson
1437a787dd7SVishwanatha Subbannamask_systemd_target ()
1447a787dd7SVishwanatha Subbanna{
1457a787dd7SVishwanatha Subbanna    target="$@"
1467a787dd7SVishwanatha Subbanna    systemctl mask $target
1477a787dd7SVishwanatha Subbanna}
1487a787dd7SVishwanatha Subbanna
1497a787dd7SVishwanatha Subbannaunmask_systemd_target ()
1507a787dd7SVishwanatha Subbanna{
1517a787dd7SVishwanatha Subbanna    target="$@"
1527a787dd7SVishwanatha Subbanna    systemctl unmask $target
1537a787dd7SVishwanatha Subbanna}
1547a787dd7SVishwanatha Subbanna
15579f697e0SAnthony Wilsonhandle_cmd ()
15679f697e0SAnthony Wilson{
15779f697e0SAnthony Wilson    case "$1" in
1583ae0a354SAnthony Wilson        chassisoff)
1593ae0a354SAnthony Wilson            OBJECT=$STATE_OBJECT/chassis0
1603ae0a354SAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
1613ae0a354SAnthony Wilson            INTERFACE=$STATE_INTERFACE.Chassis
1623ae0a354SAnthony Wilson            PROPERTY=RequestedPowerTransition
1633ae0a354SAnthony Wilson            VALUE=$INTERFACE.Transition.Off
164acf54d08SAnthony Wilson            G_REQUESTED_STATE=$INTERFACE.PowerState.Off
165acf54d08SAnthony Wilson            G_QUERY="chassisstate"
1663ae0a354SAnthony Wilson            set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
1673ae0a354SAnthony Wilson            ;;
1683ae0a354SAnthony Wilson        chassison)
1693ae0a354SAnthony Wilson            OBJECT=$STATE_OBJECT/chassis0
1703ae0a354SAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
1713ae0a354SAnthony Wilson            INTERFACE=$STATE_INTERFACE.Chassis
1723ae0a354SAnthony Wilson            PROPERTY=RequestedPowerTransition
1733ae0a354SAnthony Wilson            VALUE=$INTERFACE.Transition.On
174acf54d08SAnthony Wilson            G_REQUESTED_STATE=$INTERFACE.PowerState.On
175acf54d08SAnthony Wilson            G_QUERY="chassisstate"
1763ae0a354SAnthony Wilson            set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
1773ae0a354SAnthony Wilson            ;;
1783ae0a354SAnthony Wilson        poweroff)
1793ae0a354SAnthony Wilson            OBJECT=$STATE_OBJECT/host0
1803ae0a354SAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
1813ae0a354SAnthony Wilson            INTERFACE=$STATE_INTERFACE.Host
1823ae0a354SAnthony Wilson            PROPERTY=RequestedHostTransition
1833ae0a354SAnthony Wilson            VALUE=$INTERFACE.Transition.Off
184acf54d08SAnthony Wilson            G_REQUESTED_STATE=$INTERFACE.HostState.Off
185acf54d08SAnthony Wilson            G_QUERY="hoststate"
1863ae0a354SAnthony Wilson            set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
1873ae0a354SAnthony Wilson            ;;
1883ae0a354SAnthony Wilson        poweron)
1893ae0a354SAnthony Wilson            OBJECT=$STATE_OBJECT/host0
1903ae0a354SAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
1913ae0a354SAnthony Wilson            INTERFACE=$STATE_INTERFACE.Host
1923ae0a354SAnthony Wilson            PROPERTY=RequestedHostTransition
1933ae0a354SAnthony Wilson            VALUE=$INTERFACE.Transition.On
194acf54d08SAnthony Wilson            G_REQUESTED_STATE=$INTERFACE.HostState.Running
195acf54d08SAnthony Wilson            G_QUERY="hoststate"
1963ae0a354SAnthony Wilson            set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
1973ae0a354SAnthony Wilson            ;;
19879f697e0SAnthony Wilson        bmcstate)
19979f697e0SAnthony Wilson            OBJECT=$STATE_OBJECT/bmc0
20079f697e0SAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
20179f697e0SAnthony Wilson            INTERFACE=$STATE_INTERFACE.BMC
20279f697e0SAnthony Wilson            PROPERTY=CurrentBMCState
20379f697e0SAnthony Wilson            state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
20479f697e0SAnthony Wilson            ;;
20579f697e0SAnthony Wilson        chassisstate)
20679f697e0SAnthony Wilson            OBJECT=$STATE_OBJECT/chassis0
20779f697e0SAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
20879f697e0SAnthony Wilson            INTERFACE=$STATE_INTERFACE.Chassis
20979f697e0SAnthony Wilson            PROPERTY=CurrentPowerState
21079f697e0SAnthony Wilson            state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
21179f697e0SAnthony Wilson            ;;
21279f697e0SAnthony Wilson        hoststate)
21379f697e0SAnthony Wilson            OBJECT=$STATE_OBJECT/host0
21479f697e0SAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
21579f697e0SAnthony Wilson            INTERFACE=$STATE_INTERFACE.Host
21679f697e0SAnthony Wilson            PROPERTY=CurrentHostState
21779f697e0SAnthony Wilson            state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
21879f697e0SAnthony Wilson            ;;
21986cffd9cSAlexander Filippov        osstate)
22086cffd9cSAlexander Filippov            OBJECT=$STATE_OBJECT/host0
22186cffd9cSAlexander Filippov            SERVICE=$(mapper get-service $OBJECT)
22286cffd9cSAlexander Filippov            INTERFACE=$STATE_INTERFACE.OperatingSystem.Status
22386cffd9cSAlexander Filippov            PROPERTY=OperatingSystemState
22486cffd9cSAlexander Filippov            state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
22586cffd9cSAlexander Filippov            ;;
22679f697e0SAnthony Wilson        state|status)
22786cffd9cSAlexander Filippov            for query in bmcstate chassisstate hoststate bootprogress osstate
22879f697e0SAnthony Wilson            do
22979f697e0SAnthony Wilson                handle_cmd $query
23079f697e0SAnthony Wilson            done
23179f697e0SAnthony Wilson            ;;
23250c5f88dSAnthony Wilson        bootprogress)
23350c5f88dSAnthony Wilson            OBJECT=$STATE_OBJECT/host0
23450c5f88dSAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
23550c5f88dSAnthony Wilson            INTERFACE=$STATE_INTERFACE.Boot.Progress
23650c5f88dSAnthony Wilson            PROPERTY=BootProgress
23750c5f88dSAnthony Wilson            state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
23850c5f88dSAnthony Wilson            ;;
2390f35983dSAnthony Wilson        power)
2400f35983dSAnthony Wilson            OBJECT=/org/openbmc/control/power0
2410f35983dSAnthony Wilson            SERVICE=$(mapper get-service $OBJECT)
2420f35983dSAnthony Wilson            INTERFACE=org.openbmc.control.Power
2430f35983dSAnthony Wilson            for property in pgood state pgood_timeout
2440f35983dSAnthony Wilson            do
2450f35983dSAnthony Wilson                # get_property can potentially return several
2460f35983dSAnthony Wilson                # different formats of values, so we do the parsing outside
2470f35983dSAnthony Wilson                # of get_property depending on the query. These queries
2480f35983dSAnthony Wilson                # return 'i VALUE' formatted strings.
2490f35983dSAnthony Wilson                STATE=$(get_property $SERVICE $OBJECT $INTERFACE $property \
2500f35983dSAnthony Wilson                    | sed 's/i[ ^I]*//')
2510f35983dSAnthony Wilson                printf "%s = %s\n" $property $STATE
2520f35983dSAnthony Wilson            done
2530f35983dSAnthony Wilson            ;;
254189cf248SAnthony Wilson        chassiskill)
255189cf248SAnthony Wilson            /usr/libexec/chassiskill
256189cf248SAnthony Wilson            ;;
2576d3a2c54SVishwanatha Subbanna        rebootoff)
2586d3a2c54SVishwanatha Subbanna            OBJECT=$CONTROL_OBJECT/host0/auto_reboot
2596d3a2c54SVishwanatha Subbanna            SERVICE=$(mapper get-service $OBJECT)
2606d3a2c54SVishwanatha Subbanna            INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy
2616d3a2c54SVishwanatha Subbanna            PROPERTY=AutoReboot
2626d3a2c54SVishwanatha Subbanna            VALUE=false
2636d3a2c54SVishwanatha Subbanna            set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "b" $VALUE
2646d3a2c54SVishwanatha Subbanna            ;;
2656d3a2c54SVishwanatha Subbanna        rebooton)
2666d3a2c54SVishwanatha Subbanna            OBJECT=$CONTROL_OBJECT/host0/auto_reboot
2676d3a2c54SVishwanatha Subbanna            SERVICE=$(mapper get-service $OBJECT)
2686d3a2c54SVishwanatha Subbanna            INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy
2696d3a2c54SVishwanatha Subbanna            PROPERTY=AutoReboot
2706d3a2c54SVishwanatha Subbanna            VALUE=true
2716d3a2c54SVishwanatha Subbanna            set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "b" $VALUE
2726d3a2c54SVishwanatha Subbanna            ;;
2737a787dd7SVishwanatha Subbanna        recoveryoff)
2747a787dd7SVishwanatha Subbanna            handle_cmd rebootoff
2757a787dd7SVishwanatha Subbanna            mask_systemd_target $HOST_TIMEOUT_TARGET
276*84b3b29eSVishwanatha Subbanna            mask_systemd_target $HOST_CRASH_TARGET
2777a787dd7SVishwanatha Subbanna            ;;
2787a787dd7SVishwanatha Subbanna        recoveryon)
2797a787dd7SVishwanatha Subbanna            handle_cmd rebooton
2807a787dd7SVishwanatha Subbanna            unmask_systemd_target $HOST_TIMEOUT_TARGET
281*84b3b29eSVishwanatha Subbanna            unmask_systemd_target $HOST_CRASH_TARGET
2827a787dd7SVishwanatha Subbanna            ;;
28379f697e0SAnthony Wilson        *)
284ea87db40SAnthony Wilson            print_usage_err "Invalid command '$1'"
28579f697e0SAnthony Wilson            ;;
28679f697e0SAnthony Wilson    esac
28779f697e0SAnthony Wilson}
28879f697e0SAnthony Wilson
289ea87db40SAnthony Wilsonfor arg in "$@"; do
290ea87db40SAnthony Wilson    case $arg in
291acf54d08SAnthony Wilson        -w|--wait)
292acf54d08SAnthony Wilson            G_WAIT=30
293acf54d08SAnthony Wilson            continue
294acf54d08SAnthony Wilson            ;;
295ea87db40SAnthony Wilson        -h|--help)
296ea87db40SAnthony Wilson            print_help
297ea87db40SAnthony Wilson            ;;
29860c3ac8cSAndrew Jeffery        -v|--verbose)
29960c3ac8cSAndrew Jeffery            G_VERBOSE=y
30060c3ac8cSAndrew Jeffery            ;;
301ea87db40SAnthony Wilson        -*)
302ea87db40SAnthony Wilson            print_usage_err "Unknown option: $arg"
303ea87db40SAnthony Wilson            ;;
304ea87db40SAnthony Wilson        *)
305acf54d08SAnthony Wilson            G_ORIG_CMD=$arg
306ea87db40SAnthony Wilson            handle_cmd $arg
307ea87db40SAnthony Wilson            break
308ea87db40SAnthony Wilson            ;;
309ea87db40SAnthony Wilson    esac
310ea87db40SAnthony Wilsondone
311