blob: 64945b65cc0f29bf1993c47955b1edc124a1df2c [file] [log] [blame]
Anthony Wilson79f697e2018-09-13 13:48:52 -05001#!/bin/sh -e
2
3set -euo pipefail
4
Anthony Wilson189cf242018-10-23 01:18:21 -05005OPTS="bmcstate,bootprogress,chassiskill,chassisoff,chassison,chassisstate,hoststate,\
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -05006osstate,power,poweroff,poweron,state,status,rebootoff,rebooton,recoveryoff,recoveryon"
Anthony Wilson0f359832018-09-13 14:28:07 -05007
Andrew Jeffery60c3ac82019-10-02 09:29:29 +09308USAGE="Usage: obmcutil [-h] [--wait] [--verbose]
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
Vishwanatha Subbanna6d3a2c52019-10-24 07:21:30 -050013CONTROL_INTERFACE=$INTERFACE_ROOT.Control
Anthony Wilson79f697e2018-09-13 13:48:52 -050014
15OBJECT_ROOT=/xyz/openbmc_project
16STATE_OBJECT=$OBJECT_ROOT/state
Vishwanatha Subbanna6d3a2c52019-10-24 07:21:30 -050017CONTROL_OBJECT=$OBJECT_ROOT/control
Anthony Wilson79f697e2018-09-13 13:48:52 -050018
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -050019HOST_TIMEOUT_TARGET=obmc-host-timeout@0.target
20
Anthony Wilsonacf54d02018-09-20 15:19:28 -050021## NOTE: The following global variables are used only in the run_timeout cmd.
22## By declaring these globally instead of passing them through the
23## intermediary functions, which may not be "best practice", the readability
24## and cleanliness of the code should at least be increased.
25
26# The command passed in to be executed (e.g. poweron/off, status, etc.)
27# This will be be used in some instances of error reporting
28G_ORIG_CMD=
29# The state an interface should be in after executing the requested command.
30G_REQUESTED_STATE=
31# The query to run during a poweron/off or chassison/off to check that
32# the requested state (G_REQUESTED_STATE) of the interface has been reached.
33G_QUERY=
34# Wait the set period of time for state transitions to be successful before
35# continuing on with the program or reporting an error if timeout reached.
36G_WAIT=
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093037# Print the journal to the console
38G_VERBOSE=
Anthony Wilsonacf54d02018-09-20 15:19:28 -050039
Anthony Wilsonf3f16fa2018-09-13 14:10:52 -050040print_help ()
41{
42 echo "$USAGE"
43 echo ""
44 echo "positional arguments:"
Anthony Wilson0f359832018-09-13 14:28:07 -050045 echo " {$OPTS}"
Anthony Wilsonf3f16fa2018-09-13 14:10:52 -050046 echo ""
Vishwanatha Subbanna6d3a2c52019-10-24 07:21:30 -050047 echo "Examples:"
48 echo ""
49 echo "obmcutil rebootoff Disable auto reboot from Quiesce state"
50 echo "obmcutil rebooton Enable auto reboot from Quiesce state"
51 echo ""
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -050052 echo "obmcutil recoveryoff Disable boot watchdog timeout handling and"
53 echo " disable auto reboot from Quiesce state"
54 echo "obmcutil recoveryon Enable boot watchdog timeout handling and"
55 echo " enable auto reboot from Quiesce state"
56 echo ""
Anthony Wilsonf3f16fa2018-09-13 14:10:52 -050057 echo "optional arguments:"
58 echo " -h, --help show this help message and exit"
Anthony Wilsonacf54d02018-09-20 15:19:28 -050059 echo " -w, --wait block until state transition succeeds or fails"
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093060 echo " -v, --verbose print the journal to stdout if --wait is supplied"
Anthony Wilsonf3f16fa2018-09-13 14:10:52 -050061 exit 0
62}
63
Anthony Wilsonacf54d02018-09-20 15:19:28 -050064run_timeout ()
65{
66 local timeout="$1"; shift
67 local cmd="$@"
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093068 local verbose_child=
69
Andrew Jeffery2869a922019-10-18 14:42:34 +103070 if [ -n "$G_VERBOSE" ]; then
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093071 journalctl -f &
72 verbose_child=$!
73 fi
Anthony Wilsonacf54d02018-09-20 15:19:28 -050074
75 $cmd
76
77 # Run a background query for the transition to the expected state
78 # This will be killed if the transition doesn't succeed within
79 # a timeout period.
80 (
81 while ! grep -q $G_REQUESTED_STATE <<< $(handle_cmd $G_QUERY) ; do
82 sleep 1
83 done
84 ) &
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093085 wait_child=$!
Anthony Wilsonacf54d02018-09-20 15:19:28 -050086
87 # Could be bad if process is killed before 'timeout' occurs if
88 # transition doesn't succeed.
89 trap -- "" SIGTERM
90
91 # Workaround for lack of 'timeout' command.
92 (
93 sleep $timeout
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093094 kill $wait_child
Anthony Wilsonacf54d02018-09-20 15:19:28 -050095 ) > /dev/null 2>&1 &
96
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093097 if ! wait $wait_child; then
Anthony Wilsonacf54d02018-09-20 15:19:28 -050098 echo "Unable to confirm '$G_ORIG_CMD' success" \
99 "within timeout period (${timeout}s)"
100 fi
Andrew Jeffery60c3ac82019-10-02 09:29:29 +0930101
102 if [ -n $verbose_child ]; then
103 kill $verbose_child
104 fi
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500105}
106
107run_cmd ()
108{
109 local cmd="$@";
110
111 if [ -n "$G_WAIT" ]; then
112 run_timeout $G_WAIT "$cmd"
113 else
114 $cmd
115 fi
116}
117
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500118set_property ()
119{
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500120 run_cmd busctl set-property "$@"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500121}
122
Anthony Wilson79f697e2018-09-13 13:48:52 -0500123get_property ()
124{
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500125 G_WAIT=""
126 run_cmd busctl get-property "$@"
Anthony Wilson79f697e2018-09-13 13:48:52 -0500127}
128
129state_query ()
130{
131 local state=$(get_property "$@" | cut -d '"' -f2)
132 printf "%-20s: %s\n" $4 $state
133}
134
Anthony Wilsonea87db42018-09-26 16:06:38 -0500135print_usage_err ()
136{
137 echo "ERROR: $1" >&2
138 echo "$USAGE"
139 exit 1
140}
141
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500142mask_systemd_target ()
143{
144 target="$@"
145 systemctl mask $target
146}
147
148unmask_systemd_target ()
149{
150 target="$@"
151 systemctl unmask $target
152}
153
Anthony Wilson79f697e2018-09-13 13:48:52 -0500154handle_cmd ()
155{
156 case "$1" in
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500157 chassisoff)
158 OBJECT=$STATE_OBJECT/chassis0
159 SERVICE=$(mapper get-service $OBJECT)
160 INTERFACE=$STATE_INTERFACE.Chassis
161 PROPERTY=RequestedPowerTransition
162 VALUE=$INTERFACE.Transition.Off
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500163 G_REQUESTED_STATE=$INTERFACE.PowerState.Off
164 G_QUERY="chassisstate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500165 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
166 ;;
167 chassison)
168 OBJECT=$STATE_OBJECT/chassis0
169 SERVICE=$(mapper get-service $OBJECT)
170 INTERFACE=$STATE_INTERFACE.Chassis
171 PROPERTY=RequestedPowerTransition
172 VALUE=$INTERFACE.Transition.On
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500173 G_REQUESTED_STATE=$INTERFACE.PowerState.On
174 G_QUERY="chassisstate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500175 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
176 ;;
177 poweroff)
178 OBJECT=$STATE_OBJECT/host0
179 SERVICE=$(mapper get-service $OBJECT)
180 INTERFACE=$STATE_INTERFACE.Host
181 PROPERTY=RequestedHostTransition
182 VALUE=$INTERFACE.Transition.Off
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500183 G_REQUESTED_STATE=$INTERFACE.HostState.Off
184 G_QUERY="hoststate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500185 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
186 ;;
187 poweron)
188 OBJECT=$STATE_OBJECT/host0
189 SERVICE=$(mapper get-service $OBJECT)
190 INTERFACE=$STATE_INTERFACE.Host
191 PROPERTY=RequestedHostTransition
192 VALUE=$INTERFACE.Transition.On
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500193 G_REQUESTED_STATE=$INTERFACE.HostState.Running
194 G_QUERY="hoststate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500195 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
196 ;;
Anthony Wilson79f697e2018-09-13 13:48:52 -0500197 bmcstate)
198 OBJECT=$STATE_OBJECT/bmc0
199 SERVICE=$(mapper get-service $OBJECT)
200 INTERFACE=$STATE_INTERFACE.BMC
201 PROPERTY=CurrentBMCState
202 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
203 ;;
204 chassisstate)
205 OBJECT=$STATE_OBJECT/chassis0
206 SERVICE=$(mapper get-service $OBJECT)
207 INTERFACE=$STATE_INTERFACE.Chassis
208 PROPERTY=CurrentPowerState
209 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
210 ;;
211 hoststate)
212 OBJECT=$STATE_OBJECT/host0
213 SERVICE=$(mapper get-service $OBJECT)
214 INTERFACE=$STATE_INTERFACE.Host
215 PROPERTY=CurrentHostState
216 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
217 ;;
Alexander Filippov86cffd92019-04-03 16:29:57 +0300218 osstate)
219 OBJECT=$STATE_OBJECT/host0
220 SERVICE=$(mapper get-service $OBJECT)
221 INTERFACE=$STATE_INTERFACE.OperatingSystem.Status
222 PROPERTY=OperatingSystemState
223 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
224 ;;
Anthony Wilson79f697e2018-09-13 13:48:52 -0500225 state|status)
Alexander Filippov86cffd92019-04-03 16:29:57 +0300226 for query in bmcstate chassisstate hoststate bootprogress osstate
Anthony Wilson79f697e2018-09-13 13:48:52 -0500227 do
228 handle_cmd $query
229 done
230 ;;
Anthony Wilson50c5f882018-09-13 14:19:37 -0500231 bootprogress)
232 OBJECT=$STATE_OBJECT/host0
233 SERVICE=$(mapper get-service $OBJECT)
234 INTERFACE=$STATE_INTERFACE.Boot.Progress
235 PROPERTY=BootProgress
236 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
237 ;;
Anthony Wilson0f359832018-09-13 14:28:07 -0500238 power)
239 OBJECT=/org/openbmc/control/power0
240 SERVICE=$(mapper get-service $OBJECT)
241 INTERFACE=org.openbmc.control.Power
242 for property in pgood state pgood_timeout
243 do
244 # get_property can potentially return several
245 # different formats of values, so we do the parsing outside
246 # of get_property depending on the query. These queries
247 # return 'i VALUE' formatted strings.
248 STATE=$(get_property $SERVICE $OBJECT $INTERFACE $property \
249 | sed 's/i[ ^I]*//')
250 printf "%s = %s\n" $property $STATE
251 done
252 ;;
Anthony Wilson189cf242018-10-23 01:18:21 -0500253 chassiskill)
254 /usr/libexec/chassiskill
255 ;;
Vishwanatha Subbanna6d3a2c52019-10-24 07:21:30 -0500256 rebootoff)
257 OBJECT=$CONTROL_OBJECT/host0/auto_reboot
258 SERVICE=$(mapper get-service $OBJECT)
259 INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy
260 PROPERTY=AutoReboot
261 VALUE=false
262 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "b" $VALUE
263 ;;
264 rebooton)
265 OBJECT=$CONTROL_OBJECT/host0/auto_reboot
266 SERVICE=$(mapper get-service $OBJECT)
267 INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy
268 PROPERTY=AutoReboot
269 VALUE=true
270 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "b" $VALUE
271 ;;
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500272 recoveryoff)
273 handle_cmd rebootoff
274 mask_systemd_target $HOST_TIMEOUT_TARGET
275 ;;
276 recoveryon)
277 handle_cmd rebooton
278 unmask_systemd_target $HOST_TIMEOUT_TARGET
279 ;;
Anthony Wilson79f697e2018-09-13 13:48:52 -0500280 *)
Anthony Wilsonea87db42018-09-26 16:06:38 -0500281 print_usage_err "Invalid command '$1'"
Anthony Wilson79f697e2018-09-13 13:48:52 -0500282 ;;
283 esac
284}
285
Anthony Wilsonea87db42018-09-26 16:06:38 -0500286for arg in "$@"; do
287 case $arg in
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500288 -w|--wait)
289 G_WAIT=30
290 continue
291 ;;
Anthony Wilsonea87db42018-09-26 16:06:38 -0500292 -h|--help)
293 print_help
294 ;;
Andrew Jeffery60c3ac82019-10-02 09:29:29 +0930295 -v|--verbose)
296 G_VERBOSE=y
297 ;;
Anthony Wilsonea87db42018-09-26 16:06:38 -0500298 -*)
299 print_usage_err "Unknown option: $arg"
300 ;;
301 *)
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500302 G_ORIG_CMD=$arg
Anthony Wilsonea87db42018-09-26 16:06:38 -0500303 handle_cmd $arg
304 break
305 ;;
306 esac
307done