blob: 788170ea5de93c2c10408c7c8645767b30b1b66c [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
Andrew Geisslerdeb6bb42020-05-14 13:44:57 -0500227# helper function to check for boot block errors and notify user
228check_and_warn_boot_block()
229{
230 blockingErrors=$(check_boot_block_errors)
231 if ! [ -z "$blockingErrors" ]; then
232 echo !!!!!!!!!!
233 echo "WARNING! System has blocking errors that will prevent boot"
234 echo "$blockingErrors"
235 echo !!!!!!!!!!
236 fi
237}
238
Anthony Wilson79f697e2018-09-13 13:48:52 -0500239handle_cmd ()
240{
241 case "$1" in
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500242 chassisoff)
243 OBJECT=$STATE_OBJECT/chassis0
244 SERVICE=$(mapper get-service $OBJECT)
245 INTERFACE=$STATE_INTERFACE.Chassis
246 PROPERTY=RequestedPowerTransition
247 VALUE=$INTERFACE.Transition.Off
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500248 G_REQUESTED_STATE=$INTERFACE.PowerState.Off
249 G_QUERY="chassisstate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500250 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
251 ;;
252 chassison)
Andrew Geisslerdeb6bb42020-05-14 13:44:57 -0500253 check_and_warn_boot_block
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500254 OBJECT=$STATE_OBJECT/chassis0
255 SERVICE=$(mapper get-service $OBJECT)
256 INTERFACE=$STATE_INTERFACE.Chassis
257 PROPERTY=RequestedPowerTransition
258 VALUE=$INTERFACE.Transition.On
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500259 G_REQUESTED_STATE=$INTERFACE.PowerState.On
260 G_QUERY="chassisstate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500261 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
262 ;;
263 poweroff)
264 OBJECT=$STATE_OBJECT/host0
265 SERVICE=$(mapper get-service $OBJECT)
266 INTERFACE=$STATE_INTERFACE.Host
267 PROPERTY=RequestedHostTransition
268 VALUE=$INTERFACE.Transition.Off
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500269 G_REQUESTED_STATE=$INTERFACE.HostState.Off
270 G_QUERY="hoststate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500271 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
272 ;;
273 poweron)
Andrew Geisslerdeb6bb42020-05-14 13:44:57 -0500274 check_and_warn_boot_block
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500275 OBJECT=$STATE_OBJECT/host0
276 SERVICE=$(mapper get-service $OBJECT)
277 INTERFACE=$STATE_INTERFACE.Host
278 PROPERTY=RequestedHostTransition
279 VALUE=$INTERFACE.Transition.On
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500280 G_REQUESTED_STATE=$INTERFACE.HostState.Running
281 G_QUERY="hoststate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500282 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
283 ;;
Anthony Wilson79f697e2018-09-13 13:48:52 -0500284 bmcstate)
285 OBJECT=$STATE_OBJECT/bmc0
286 SERVICE=$(mapper get-service $OBJECT)
287 INTERFACE=$STATE_INTERFACE.BMC
288 PROPERTY=CurrentBMCState
289 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
290 ;;
291 chassisstate)
292 OBJECT=$STATE_OBJECT/chassis0
293 SERVICE=$(mapper get-service $OBJECT)
294 INTERFACE=$STATE_INTERFACE.Chassis
295 PROPERTY=CurrentPowerState
296 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
297 ;;
298 hoststate)
299 OBJECT=$STATE_OBJECT/host0
300 SERVICE=$(mapper get-service $OBJECT)
301 INTERFACE=$STATE_INTERFACE.Host
302 PROPERTY=CurrentHostState
303 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
304 ;;
Alexander Filippov86cffd92019-04-03 16:29:57 +0300305 osstate)
306 OBJECT=$STATE_OBJECT/host0
307 SERVICE=$(mapper get-service $OBJECT)
308 INTERFACE=$STATE_INTERFACE.OperatingSystem.Status
309 PROPERTY=OperatingSystemState
310 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
311 ;;
Anthony Wilson79f697e2018-09-13 13:48:52 -0500312 state|status)
Alexander Filippov86cffd92019-04-03 16:29:57 +0300313 for query in bmcstate chassisstate hoststate bootprogress osstate
Anthony Wilson79f697e2018-09-13 13:48:52 -0500314 do
315 handle_cmd $query
316 done
Andrew Geisslerdeb6bb42020-05-14 13:44:57 -0500317 check_and_warn_boot_block
Anthony Wilson79f697e2018-09-13 13:48:52 -0500318 ;;
Anthony Wilson50c5f882018-09-13 14:19:37 -0500319 bootprogress)
320 OBJECT=$STATE_OBJECT/host0
321 SERVICE=$(mapper get-service $OBJECT)
322 INTERFACE=$STATE_INTERFACE.Boot.Progress
323 PROPERTY=BootProgress
324 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
325 ;;
Anthony Wilson0f359832018-09-13 14:28:07 -0500326 power)
327 OBJECT=/org/openbmc/control/power0
328 SERVICE=$(mapper get-service $OBJECT)
329 INTERFACE=org.openbmc.control.Power
330 for property in pgood state pgood_timeout
331 do
332 # get_property can potentially return several
333 # different formats of values, so we do the parsing outside
334 # of get_property depending on the query. These queries
335 # return 'i VALUE' formatted strings.
336 STATE=$(get_property $SERVICE $OBJECT $INTERFACE $property \
337 | sed 's/i[ ^I]*//')
338 printf "%s = %s\n" $property $STATE
339 done
340 ;;
Anthony Wilson189cf242018-10-23 01:18:21 -0500341 chassiskill)
342 /usr/libexec/chassiskill
343 ;;
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600344 hostrebootoff)
Vishwanatha Subbanna6d3a2c52019-10-24 07:21:30 -0500345 OBJECT=$CONTROL_OBJECT/host0/auto_reboot
346 SERVICE=$(mapper get-service $OBJECT)
347 INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy
348 PROPERTY=AutoReboot
349 VALUE=false
350 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "b" $VALUE
351 ;;
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600352 hostrebooton)
Vishwanatha Subbanna6d3a2c52019-10-24 07:21:30 -0500353 OBJECT=$CONTROL_OBJECT/host0/auto_reboot
354 SERVICE=$(mapper get-service $OBJECT)
355 INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy
356 PROPERTY=AutoReboot
357 VALUE=true
358 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "b" $VALUE
359 ;;
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600360 bmcrebootoff)
361 disable_bmc_reboot
362 ;;
363 bmcrebooton)
364 enable_bmc_reboot
365 ;;
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500366 recoveryoff)
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600367 handle_cmd hostrebootoff
368 handle_cmd bmcrebootoff
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500369 mask_systemd_target $HOST_TIMEOUT_TARGET
Vishwanatha Subbanna84b3b292019-11-04 05:43:19 -0600370 mask_systemd_target $HOST_CRASH_TARGET
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500371 ;;
372 recoveryon)
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600373 handle_cmd hostrebooton
374 handle_cmd bmcrebooton
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500375 unmask_systemd_target $HOST_TIMEOUT_TARGET
Vishwanatha Subbanna84b3b292019-11-04 05:43:19 -0600376 unmask_systemd_target $HOST_CRASH_TARGET
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500377 ;;
Andrew Geissler3b7b5612020-05-14 10:45:29 -0500378 listbootblock)
379 blockingErrors=$(check_boot_block_errors)
380 if [ -z "$blockingErrors" ]; then
381 echo "No blocking errors present"
382 else
383 echo "$blockingErrors"
384 fi
385 ;;
Anthony Wilson79f697e2018-09-13 13:48:52 -0500386 *)
Anthony Wilsonea87db42018-09-26 16:06:38 -0500387 print_usage_err "Invalid command '$1'"
Anthony Wilson79f697e2018-09-13 13:48:52 -0500388 ;;
389 esac
390}
391
Anthony Wilsonea87db42018-09-26 16:06:38 -0500392for arg in "$@"; do
393 case $arg in
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500394 -w|--wait)
395 G_WAIT=30
396 continue
397 ;;
Anthony Wilsonea87db42018-09-26 16:06:38 -0500398 -h|--help)
399 print_help
400 ;;
Andrew Jeffery60c3ac82019-10-02 09:29:29 +0930401 -v|--verbose)
402 G_VERBOSE=y
403 ;;
Anthony Wilsonea87db42018-09-26 16:06:38 -0500404 -*)
405 print_usage_err "Unknown option: $arg"
406 ;;
407 *)
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500408 G_ORIG_CMD=$arg
Anthony Wilsonea87db42018-09-26 16:06:38 -0500409 handle_cmd $arg
410 break
411 ;;
412 esac
413done