blob: ed5dbc619edbf418d583ee3d6e76956ed6e05b95 [file] [log] [blame]
Anthony Wilson79f697e2018-09-13 13:48:52 -05001#!/bin/sh -e
2
3set -euo pipefail
4
Anthony Wilson3ae0a352018-09-13 14:47:56 -05005OPTS="bmcstate,bootprogress,chassisoff,chassison,chassisstate,hoststate,\
6power,poweroff,poweron,state,status"
Anthony Wilson0f359832018-09-13 14:28:07 -05007
Anthony Wilsonacf54d02018-09-20 15:19:28 -05008USAGE="Usage: obmcutil [-h] [--wait]
Anthony Wilson0f359832018-09-13 14:28:07 -05009 {$OPTS}"
Anthony Wilson79f697e2018-09-13 13:48:52 -050010
11INTERFACE_ROOT=xyz.openbmc_project
12STATE_INTERFACE=$INTERFACE_ROOT.State
13
14OBJECT_ROOT=/xyz/openbmc_project
15STATE_OBJECT=$OBJECT_ROOT/state
16
Anthony Wilsonacf54d02018-09-20 15:19:28 -050017## NOTE: The following global variables are used only in the run_timeout cmd.
18## By declaring these globally instead of passing them through the
19## intermediary functions, which may not be "best practice", the readability
20## and cleanliness of the code should at least be increased.
21
22# The command passed in to be executed (e.g. poweron/off, status, etc.)
23# This will be be used in some instances of error reporting
24G_ORIG_CMD=
25# The state an interface should be in after executing the requested command.
26G_REQUESTED_STATE=
27# The query to run during a poweron/off or chassison/off to check that
28# the requested state (G_REQUESTED_STATE) of the interface has been reached.
29G_QUERY=
30# Wait the set period of time for state transitions to be successful before
31# continuing on with the program or reporting an error if timeout reached.
32G_WAIT=
33
Anthony Wilsonf3f16fa2018-09-13 14:10:52 -050034print_help ()
35{
36 echo "$USAGE"
37 echo ""
38 echo "positional arguments:"
Anthony Wilson0f359832018-09-13 14:28:07 -050039 echo " {$OPTS}"
Anthony Wilsonf3f16fa2018-09-13 14:10:52 -050040 echo ""
41 echo "optional arguments:"
42 echo " -h, --help show this help message and exit"
Anthony Wilsonacf54d02018-09-20 15:19:28 -050043 echo " -w, --wait block until state transition succeeds or fails"
Anthony Wilsonf3f16fa2018-09-13 14:10:52 -050044 exit 0
45}
46
Anthony Wilsonacf54d02018-09-20 15:19:28 -050047run_timeout ()
48{
49 local timeout="$1"; shift
50 local cmd="$@"
51
52 $cmd
53
54 # Run a background query for the transition to the expected state
55 # This will be killed if the transition doesn't succeed within
56 # a timeout period.
57 (
58 while ! grep -q $G_REQUESTED_STATE <<< $(handle_cmd $G_QUERY) ; do
59 sleep 1
60 done
61 ) &
62 child=$!
63
64 # Could be bad if process is killed before 'timeout' occurs if
65 # transition doesn't succeed.
66 trap -- "" SIGTERM
67
68 # Workaround for lack of 'timeout' command.
69 (
70 sleep $timeout
71 kill $child
72 ) > /dev/null 2>&1 &
73
74 if ! wait $child; then
75 echo "Unable to confirm '$G_ORIG_CMD' success" \
76 "within timeout period (${timeout}s)"
77 fi
78}
79
80run_cmd ()
81{
82 local cmd="$@";
83
84 if [ -n "$G_WAIT" ]; then
85 run_timeout $G_WAIT "$cmd"
86 else
87 $cmd
88 fi
89}
90
Anthony Wilson3ae0a352018-09-13 14:47:56 -050091set_property ()
92{
Anthony Wilsonacf54d02018-09-20 15:19:28 -050093 run_cmd busctl set-property "$@"
Anthony Wilson3ae0a352018-09-13 14:47:56 -050094}
95
Anthony Wilson79f697e2018-09-13 13:48:52 -050096get_property ()
97{
Anthony Wilsonacf54d02018-09-20 15:19:28 -050098 G_WAIT=""
99 run_cmd busctl get-property "$@"
Anthony Wilson79f697e2018-09-13 13:48:52 -0500100}
101
102state_query ()
103{
104 local state=$(get_property "$@" | cut -d '"' -f2)
105 printf "%-20s: %s\n" $4 $state
106}
107
Anthony Wilsonea87db42018-09-26 16:06:38 -0500108print_usage_err ()
109{
110 echo "ERROR: $1" >&2
111 echo "$USAGE"
112 exit 1
113}
114
Anthony Wilson79f697e2018-09-13 13:48:52 -0500115handle_cmd ()
116{
117 case "$1" in
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500118 chassisoff)
119 OBJECT=$STATE_OBJECT/chassis0
120 SERVICE=$(mapper get-service $OBJECT)
121 INTERFACE=$STATE_INTERFACE.Chassis
122 PROPERTY=RequestedPowerTransition
123 VALUE=$INTERFACE.Transition.Off
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500124 G_REQUESTED_STATE=$INTERFACE.PowerState.Off
125 G_QUERY="chassisstate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500126 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
127 ;;
128 chassison)
129 OBJECT=$STATE_OBJECT/chassis0
130 SERVICE=$(mapper get-service $OBJECT)
131 INTERFACE=$STATE_INTERFACE.Chassis
132 PROPERTY=RequestedPowerTransition
133 VALUE=$INTERFACE.Transition.On
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500134 G_REQUESTED_STATE=$INTERFACE.PowerState.On
135 G_QUERY="chassisstate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500136 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
137 ;;
138 poweroff)
139 OBJECT=$STATE_OBJECT/host0
140 SERVICE=$(mapper get-service $OBJECT)
141 INTERFACE=$STATE_INTERFACE.Host
142 PROPERTY=RequestedHostTransition
143 VALUE=$INTERFACE.Transition.Off
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500144 G_REQUESTED_STATE=$INTERFACE.HostState.Off
145 G_QUERY="hoststate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500146 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
147 ;;
148 poweron)
149 OBJECT=$STATE_OBJECT/host0
150 SERVICE=$(mapper get-service $OBJECT)
151 INTERFACE=$STATE_INTERFACE.Host
152 PROPERTY=RequestedHostTransition
153 VALUE=$INTERFACE.Transition.On
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500154 G_REQUESTED_STATE=$INTERFACE.HostState.Running
155 G_QUERY="hoststate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500156 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
157 ;;
Anthony Wilson79f697e2018-09-13 13:48:52 -0500158 bmcstate)
159 OBJECT=$STATE_OBJECT/bmc0
160 SERVICE=$(mapper get-service $OBJECT)
161 INTERFACE=$STATE_INTERFACE.BMC
162 PROPERTY=CurrentBMCState
163 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
164 ;;
165 chassisstate)
166 OBJECT=$STATE_OBJECT/chassis0
167 SERVICE=$(mapper get-service $OBJECT)
168 INTERFACE=$STATE_INTERFACE.Chassis
169 PROPERTY=CurrentPowerState
170 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
171 ;;
172 hoststate)
173 OBJECT=$STATE_OBJECT/host0
174 SERVICE=$(mapper get-service $OBJECT)
175 INTERFACE=$STATE_INTERFACE.Host
176 PROPERTY=CurrentHostState
177 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
178 ;;
179 state|status)
180 for query in bmcstate chassisstate hoststate
181 do
182 handle_cmd $query
183 done
184 ;;
Anthony Wilson50c5f882018-09-13 14:19:37 -0500185 bootprogress)
186 OBJECT=$STATE_OBJECT/host0
187 SERVICE=$(mapper get-service $OBJECT)
188 INTERFACE=$STATE_INTERFACE.Boot.Progress
189 PROPERTY=BootProgress
190 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
191 ;;
Anthony Wilson0f359832018-09-13 14:28:07 -0500192 power)
193 OBJECT=/org/openbmc/control/power0
194 SERVICE=$(mapper get-service $OBJECT)
195 INTERFACE=org.openbmc.control.Power
196 for property in pgood state pgood_timeout
197 do
198 # get_property can potentially return several
199 # different formats of values, so we do the parsing outside
200 # of get_property depending on the query. These queries
201 # return 'i VALUE' formatted strings.
202 STATE=$(get_property $SERVICE $OBJECT $INTERFACE $property \
203 | sed 's/i[ ^I]*//')
204 printf "%s = %s\n" $property $STATE
205 done
206 ;;
Anthony Wilson79f697e2018-09-13 13:48:52 -0500207 *)
Anthony Wilsonea87db42018-09-26 16:06:38 -0500208 print_usage_err "Invalid command '$1'"
Anthony Wilson79f697e2018-09-13 13:48:52 -0500209 ;;
210 esac
211}
212
Anthony Wilsonea87db42018-09-26 16:06:38 -0500213for arg in "$@"; do
214 case $arg in
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500215 -w|--wait)
216 G_WAIT=30
217 continue
218 ;;
Anthony Wilsonea87db42018-09-26 16:06:38 -0500219 -h|--help)
220 print_help
221 ;;
222 -*)
223 print_usage_err "Unknown option: $arg"
224 ;;
225 *)
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500226 G_ORIG_CMD=$arg
Anthony Wilsonea87db42018-09-26 16:06:38 -0500227 handle_cmd $arg
228 break
229 ;;
230 esac
231done