blob: 81fba8f847246008df5df000b61f79c610463ee1 [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 Subbannaa65d30d2019-11-13 01:26:12 -06006osstate,power,poweroff,poweron,state,status,hostrebootoff,hostrebooton,recoveryoff,recoveryon,\
Andrew Geissler3b7b5612020-05-14 10:45:29 -05007bmcrebootoff, bmcrebooton, listbootblock"
Anthony Wilson0f359832018-09-13 14:28:07 -05008
Andrew Jeffery60c3ac82019-10-02 09:29:29 +09309USAGE="Usage: obmcutil [-h] [--wait] [--verbose]
Anthony Wilson0f359832018-09-13 14:28:07 -050010 {$OPTS}"
Anthony Wilson79f697e2018-09-13 13:48:52 -050011
12INTERFACE_ROOT=xyz.openbmc_project
13STATE_INTERFACE=$INTERFACE_ROOT.State
Vishwanatha Subbanna6d3a2c52019-10-24 07:21:30 -050014CONTROL_INTERFACE=$INTERFACE_ROOT.Control
Anthony Wilson79f697e2018-09-13 13:48:52 -050015
16OBJECT_ROOT=/xyz/openbmc_project
17STATE_OBJECT=$OBJECT_ROOT/state
Vishwanatha Subbanna6d3a2c52019-10-24 07:21:30 -050018CONTROL_OBJECT=$OBJECT_ROOT/control
Anthony Wilson79f697e2018-09-13 13:48:52 -050019
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -050020HOST_TIMEOUT_TARGET=obmc-host-timeout@0.target
Vishwanatha Subbanna84b3b292019-11-04 05:43:19 -060021HOST_CRASH_TARGET=obmc-host-crash@0.target
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -050022
Anthony Wilsonacf54d02018-09-20 15:19:28 -050023## NOTE: The following global variables are used only in the run_timeout cmd.
24## By declaring these globally instead of passing them through the
25## intermediary functions, which may not be "best practice", the readability
26## and cleanliness of the code should at least be increased.
27
28# The command passed in to be executed (e.g. poweron/off, status, etc.)
29# This will be be used in some instances of error reporting
30G_ORIG_CMD=
31# The state an interface should be in after executing the requested command.
32G_REQUESTED_STATE=
33# The query to run during a poweron/off or chassison/off to check that
34# the requested state (G_REQUESTED_STATE) of the interface has been reached.
35G_QUERY=
36# Wait the set period of time for state transitions to be successful before
37# continuing on with the program or reporting an error if timeout reached.
38G_WAIT=
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093039# Print the journal to the console
40G_VERBOSE=
Anthony Wilsonacf54d02018-09-20 15:19:28 -050041
Anthony Wilsonf3f16fa2018-09-13 14:10:52 -050042print_help ()
43{
44 echo "$USAGE"
45 echo ""
46 echo "positional arguments:"
Anthony Wilson0f359832018-09-13 14:28:07 -050047 echo " {$OPTS}"
Anthony Wilsonf3f16fa2018-09-13 14:10:52 -050048 echo ""
Vishwanatha Subbanna6d3a2c52019-10-24 07:21:30 -050049 echo "Examples:"
50 echo ""
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -060051 echo "obmcutil hostrebootoff Disable auto reboot of Host from Quiesce state"
52 echo "obmcutil hostrebooton Enable auto reboot of Host from Quiesce state"
Vishwanatha Subbanna6d3a2c52019-10-24 07:21:30 -050053 echo ""
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -060054 echo "obmcutil bmcrebootoff Disable reboot of BMC"
55 echo "obmcutil bmcrebooton Enable reboot of BMC"
56 echo ""
57 echo "obmcutil recoveryoff Disable handling boot watchdog timeout and host crash"
58 echo " Also, disable BMC and Host auto reboots"
59 echo ""
60 echo "obmcutil recoveryon Enable handling boot watchdog timeout and host crash"
61 echo " Also, enable BMC and Host auto reboots"
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -050062 echo ""
Andrew Geissler3b7b5612020-05-14 10:45:29 -050063 echo "obmcutil listbootblock Check for and list any errors blocking the boot"
64 echo " of the system"
65 echo ""
Anthony Wilsonf3f16fa2018-09-13 14:10:52 -050066 echo "optional arguments:"
67 echo " -h, --help show this help message and exit"
Anthony Wilsonacf54d02018-09-20 15:19:28 -050068 echo " -w, --wait block until state transition succeeds or fails"
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093069 echo " -v, --verbose print the journal to stdout if --wait is supplied"
Anthony Wilsonf3f16fa2018-09-13 14:10:52 -050070 exit 0
71}
72
Anthony Wilsonacf54d02018-09-20 15:19:28 -050073run_timeout ()
74{
75 local timeout="$1"; shift
76 local cmd="$@"
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093077 local verbose_child=
78
Andrew Jeffery2869a922019-10-18 14:42:34 +103079 if [ -n "$G_VERBOSE" ]; then
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093080 journalctl -f &
81 verbose_child=$!
82 fi
Anthony Wilsonacf54d02018-09-20 15:19:28 -050083
84 $cmd
85
86 # Run a background query for the transition to the expected state
87 # This will be killed if the transition doesn't succeed within
88 # a timeout period.
89 (
90 while ! grep -q $G_REQUESTED_STATE <<< $(handle_cmd $G_QUERY) ; do
91 sleep 1
92 done
93 ) &
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093094 wait_child=$!
Anthony Wilsonacf54d02018-09-20 15:19:28 -050095
96 # Could be bad if process is killed before 'timeout' occurs if
97 # transition doesn't succeed.
98 trap -- "" SIGTERM
99
100 # Workaround for lack of 'timeout' command.
101 (
102 sleep $timeout
Andrew Jeffery60c3ac82019-10-02 09:29:29 +0930103 kill $wait_child
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500104 ) > /dev/null 2>&1 &
105
Andrew Jeffery60c3ac82019-10-02 09:29:29 +0930106 if ! wait $wait_child; then
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500107 echo "Unable to confirm '$G_ORIG_CMD' success" \
108 "within timeout period (${timeout}s)"
109 fi
Andrew Jeffery60c3ac82019-10-02 09:29:29 +0930110
Andrew Jeffery8be70292019-11-01 08:56:49 +1030111 if [ -n "$verbose_child" ]; then
Andrew Jeffery60c3ac82019-10-02 09:29:29 +0930112 kill $verbose_child
113 fi
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500114}
115
116run_cmd ()
117{
118 local cmd="$@";
119
120 if [ -n "$G_WAIT" ]; then
121 run_timeout $G_WAIT "$cmd"
122 else
123 $cmd
124 fi
125}
126
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500127set_property ()
128{
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500129 run_cmd busctl set-property "$@"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500130}
131
Anthony Wilson79f697e2018-09-13 13:48:52 -0500132get_property ()
133{
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500134 G_WAIT=""
135 run_cmd busctl get-property "$@"
Anthony Wilson79f697e2018-09-13 13:48:52 -0500136}
137
138state_query ()
139{
140 local state=$(get_property "$@" | cut -d '"' -f2)
141 printf "%-20s: %s\n" $4 $state
142}
143
Anthony Wilsonea87db42018-09-26 16:06:38 -0500144print_usage_err ()
145{
146 echo "ERROR: $1" >&2
147 echo "$USAGE"
148 exit 1
149}
150
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500151mask_systemd_target ()
152{
153 target="$@"
154 systemctl mask $target
155}
156
157unmask_systemd_target ()
158{
159 target="$@"
160 systemctl unmask $target
161}
162
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600163disable_bmc_reboot ()
164{
165 dir="/run/systemd/system/"
166 file="reboot-guard.conf"
167 units=("reboot" "poweroff" "halt")
168
169 for unit in "${units[@]}"; do
170 mkdir -p ${dir}${unit}.target.d
171 echo -e "[Unit]\nRefuseManualStart=yes" >> ${dir}${unit}.target.d/${file}
172 done
173}
174
175enable_bmc_reboot ()
176{
177 dir="/run/systemd/system/"
178 file="reboot-guard.conf"
179 units=("reboot" "poweroff" "halt")
180
181 for unit in "${units[@]}"; do
182 rm -rf ${dir}${unit}.target.d/${file}
183 rm -rf ${dir}${unit}.target.d
184 done
185}
186
Andrew Geissler3b7b5612020-05-14 10:45:29 -0500187# will write blocking errors to stdout
188check_boot_block_errors ()
189{
190 # array of boot block objects
191 blockArray=()
192
193 # Look for any objects under logging that implement the
194 # xyz.openbmc_project.Logging.ErrorBlocksTransition
195 subtree="$(busctl call xyz.openbmc_project.ObjectMapper \
196 /xyz/openbmc_project/object_mapper \
197 xyz.openbmc_project.ObjectMapper \
198 GetSubTree sias "/xyz/openbmc_project/logging/" 0 1 \
199 xyz.openbmc_project.Logging.ErrorBlocksTransition)"
200
201 # remove quotation marks
202 subtree="$(echo $subtree | sed 's/\"//g')"
203
204 for entry in $subtree; do
205 if [[ ${entry} =~ "xyz/openbmc_project/logging/block"* ]]; then
206 blockArray+=( $entry )
207 fi
208 done
209
210 # now find associated error log for each boot block error
211 for berror in "${blockArray[@]}"; do
212 assocs="$(busctl call xyz.openbmc_project.Logging $berror \
213 org.freedesktop.DBus.Properties Get \
214 ss xyz.openbmc_project.Association.Definitions Associations)"
215
216 # remove quotation marks
217 assocs="$(echo $assocs | sed 's/\"//g')"
218
219 for entry in $assocs; do
220 if [[ ${entry} =~ "xyz/openbmc_project/logging/entry"* ]]; then
221 echo "Blocking Error: $entry"
222 fi
223 done
224 done
225}
226
Anthony Wilson79f697e2018-09-13 13:48:52 -0500227handle_cmd ()
228{
229 case "$1" in
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500230 chassisoff)
231 OBJECT=$STATE_OBJECT/chassis0
232 SERVICE=$(mapper get-service $OBJECT)
233 INTERFACE=$STATE_INTERFACE.Chassis
234 PROPERTY=RequestedPowerTransition
235 VALUE=$INTERFACE.Transition.Off
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500236 G_REQUESTED_STATE=$INTERFACE.PowerState.Off
237 G_QUERY="chassisstate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500238 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
239 ;;
240 chassison)
241 OBJECT=$STATE_OBJECT/chassis0
242 SERVICE=$(mapper get-service $OBJECT)
243 INTERFACE=$STATE_INTERFACE.Chassis
244 PROPERTY=RequestedPowerTransition
245 VALUE=$INTERFACE.Transition.On
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500246 G_REQUESTED_STATE=$INTERFACE.PowerState.On
247 G_QUERY="chassisstate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500248 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
249 ;;
250 poweroff)
251 OBJECT=$STATE_OBJECT/host0
252 SERVICE=$(mapper get-service $OBJECT)
253 INTERFACE=$STATE_INTERFACE.Host
254 PROPERTY=RequestedHostTransition
255 VALUE=$INTERFACE.Transition.Off
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500256 G_REQUESTED_STATE=$INTERFACE.HostState.Off
257 G_QUERY="hoststate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500258 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
259 ;;
260 poweron)
261 OBJECT=$STATE_OBJECT/host0
262 SERVICE=$(mapper get-service $OBJECT)
263 INTERFACE=$STATE_INTERFACE.Host
264 PROPERTY=RequestedHostTransition
265 VALUE=$INTERFACE.Transition.On
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500266 G_REQUESTED_STATE=$INTERFACE.HostState.Running
267 G_QUERY="hoststate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500268 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
269 ;;
Anthony Wilson79f697e2018-09-13 13:48:52 -0500270 bmcstate)
271 OBJECT=$STATE_OBJECT/bmc0
272 SERVICE=$(mapper get-service $OBJECT)
273 INTERFACE=$STATE_INTERFACE.BMC
274 PROPERTY=CurrentBMCState
275 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
276 ;;
277 chassisstate)
278 OBJECT=$STATE_OBJECT/chassis0
279 SERVICE=$(mapper get-service $OBJECT)
280 INTERFACE=$STATE_INTERFACE.Chassis
281 PROPERTY=CurrentPowerState
282 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
283 ;;
284 hoststate)
285 OBJECT=$STATE_OBJECT/host0
286 SERVICE=$(mapper get-service $OBJECT)
287 INTERFACE=$STATE_INTERFACE.Host
288 PROPERTY=CurrentHostState
289 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
290 ;;
Alexander Filippov86cffd92019-04-03 16:29:57 +0300291 osstate)
292 OBJECT=$STATE_OBJECT/host0
293 SERVICE=$(mapper get-service $OBJECT)
294 INTERFACE=$STATE_INTERFACE.OperatingSystem.Status
295 PROPERTY=OperatingSystemState
296 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
297 ;;
Anthony Wilson79f697e2018-09-13 13:48:52 -0500298 state|status)
Alexander Filippov86cffd92019-04-03 16:29:57 +0300299 for query in bmcstate chassisstate hoststate bootprogress osstate
Anthony Wilson79f697e2018-09-13 13:48:52 -0500300 do
301 handle_cmd $query
302 done
303 ;;
Anthony Wilson50c5f882018-09-13 14:19:37 -0500304 bootprogress)
305 OBJECT=$STATE_OBJECT/host0
306 SERVICE=$(mapper get-service $OBJECT)
307 INTERFACE=$STATE_INTERFACE.Boot.Progress
308 PROPERTY=BootProgress
309 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
310 ;;
Anthony Wilson0f359832018-09-13 14:28:07 -0500311 power)
312 OBJECT=/org/openbmc/control/power0
313 SERVICE=$(mapper get-service $OBJECT)
314 INTERFACE=org.openbmc.control.Power
315 for property in pgood state pgood_timeout
316 do
317 # get_property can potentially return several
318 # different formats of values, so we do the parsing outside
319 # of get_property depending on the query. These queries
320 # return 'i VALUE' formatted strings.
321 STATE=$(get_property $SERVICE $OBJECT $INTERFACE $property \
322 | sed 's/i[ ^I]*//')
323 printf "%s = %s\n" $property $STATE
324 done
325 ;;
Anthony Wilson189cf242018-10-23 01:18:21 -0500326 chassiskill)
327 /usr/libexec/chassiskill
328 ;;
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600329 hostrebootoff)
Vishwanatha Subbanna6d3a2c52019-10-24 07:21:30 -0500330 OBJECT=$CONTROL_OBJECT/host0/auto_reboot
331 SERVICE=$(mapper get-service $OBJECT)
332 INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy
333 PROPERTY=AutoReboot
334 VALUE=false
335 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "b" $VALUE
336 ;;
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600337 hostrebooton)
Vishwanatha Subbanna6d3a2c52019-10-24 07:21:30 -0500338 OBJECT=$CONTROL_OBJECT/host0/auto_reboot
339 SERVICE=$(mapper get-service $OBJECT)
340 INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy
341 PROPERTY=AutoReboot
342 VALUE=true
343 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "b" $VALUE
344 ;;
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600345 bmcrebootoff)
346 disable_bmc_reboot
347 ;;
348 bmcrebooton)
349 enable_bmc_reboot
350 ;;
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500351 recoveryoff)
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600352 handle_cmd hostrebootoff
353 handle_cmd bmcrebootoff
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500354 mask_systemd_target $HOST_TIMEOUT_TARGET
Vishwanatha Subbanna84b3b292019-11-04 05:43:19 -0600355 mask_systemd_target $HOST_CRASH_TARGET
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500356 ;;
357 recoveryon)
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600358 handle_cmd hostrebooton
359 handle_cmd bmcrebooton
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500360 unmask_systemd_target $HOST_TIMEOUT_TARGET
Vishwanatha Subbanna84b3b292019-11-04 05:43:19 -0600361 unmask_systemd_target $HOST_CRASH_TARGET
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500362 ;;
Andrew Geissler3b7b5612020-05-14 10:45:29 -0500363 listbootblock)
364 blockingErrors=$(check_boot_block_errors)
365 if [ -z "$blockingErrors" ]; then
366 echo "No blocking errors present"
367 else
368 echo "$blockingErrors"
369 fi
370 ;;
Anthony Wilson79f697e2018-09-13 13:48:52 -0500371 *)
Anthony Wilsonea87db42018-09-26 16:06:38 -0500372 print_usage_err "Invalid command '$1'"
Anthony Wilson79f697e2018-09-13 13:48:52 -0500373 ;;
374 esac
375}
376
Anthony Wilsonea87db42018-09-26 16:06:38 -0500377for arg in "$@"; do
378 case $arg in
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500379 -w|--wait)
380 G_WAIT=30
381 continue
382 ;;
Anthony Wilsonea87db42018-09-26 16:06:38 -0500383 -h|--help)
384 print_help
385 ;;
Andrew Jeffery60c3ac82019-10-02 09:29:29 +0930386 -v|--verbose)
387 G_VERBOSE=y
388 ;;
Anthony Wilsonea87db42018-09-26 16:06:38 -0500389 -*)
390 print_usage_err "Unknown option: $arg"
391 ;;
392 *)
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500393 G_ORIG_CMD=$arg
Anthony Wilsonea87db42018-09-26 16:06:38 -0500394 handle_cmd $arg
395 break
396 ;;
397 esac
398done