blob: 0afa678c0a41d9baff0d45691e03c53c4f364c4c [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,\
7bmcrebootoff, bmcrebooton"
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 ""
Anthony Wilsonf3f16fa2018-09-13 14:10:52 -050063 echo "optional arguments:"
64 echo " -h, --help show this help message and exit"
Anthony Wilsonacf54d02018-09-20 15:19:28 -050065 echo " -w, --wait block until state transition succeeds or fails"
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093066 echo " -v, --verbose print the journal to stdout if --wait is supplied"
Anthony Wilsonf3f16fa2018-09-13 14:10:52 -050067 exit 0
68}
69
Anthony Wilsonacf54d02018-09-20 15:19:28 -050070run_timeout ()
71{
72 local timeout="$1"; shift
73 local cmd="$@"
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093074 local verbose_child=
75
Andrew Jeffery2869a922019-10-18 14:42:34 +103076 if [ -n "$G_VERBOSE" ]; then
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093077 journalctl -f &
78 verbose_child=$!
79 fi
Anthony Wilsonacf54d02018-09-20 15:19:28 -050080
81 $cmd
82
83 # Run a background query for the transition to the expected state
84 # This will be killed if the transition doesn't succeed within
85 # a timeout period.
86 (
87 while ! grep -q $G_REQUESTED_STATE <<< $(handle_cmd $G_QUERY) ; do
88 sleep 1
89 done
90 ) &
Andrew Jeffery60c3ac82019-10-02 09:29:29 +093091 wait_child=$!
Anthony Wilsonacf54d02018-09-20 15:19:28 -050092
93 # Could be bad if process is killed before 'timeout' occurs if
94 # transition doesn't succeed.
95 trap -- "" SIGTERM
96
97 # Workaround for lack of 'timeout' command.
98 (
99 sleep $timeout
Andrew Jeffery60c3ac82019-10-02 09:29:29 +0930100 kill $wait_child
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500101 ) > /dev/null 2>&1 &
102
Andrew Jeffery60c3ac82019-10-02 09:29:29 +0930103 if ! wait $wait_child; then
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500104 echo "Unable to confirm '$G_ORIG_CMD' success" \
105 "within timeout period (${timeout}s)"
106 fi
Andrew Jeffery60c3ac82019-10-02 09:29:29 +0930107
Andrew Jeffery8be70292019-11-01 08:56:49 +1030108 if [ -n "$verbose_child" ]; then
Andrew Jeffery60c3ac82019-10-02 09:29:29 +0930109 kill $verbose_child
110 fi
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500111}
112
113run_cmd ()
114{
115 local cmd="$@";
116
117 if [ -n "$G_WAIT" ]; then
118 run_timeout $G_WAIT "$cmd"
119 else
120 $cmd
121 fi
122}
123
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500124set_property ()
125{
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500126 run_cmd busctl set-property "$@"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500127}
128
Anthony Wilson79f697e2018-09-13 13:48:52 -0500129get_property ()
130{
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500131 G_WAIT=""
132 run_cmd busctl get-property "$@"
Anthony Wilson79f697e2018-09-13 13:48:52 -0500133}
134
135state_query ()
136{
137 local state=$(get_property "$@" | cut -d '"' -f2)
138 printf "%-20s: %s\n" $4 $state
139}
140
Anthony Wilsonea87db42018-09-26 16:06:38 -0500141print_usage_err ()
142{
143 echo "ERROR: $1" >&2
144 echo "$USAGE"
145 exit 1
146}
147
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500148mask_systemd_target ()
149{
150 target="$@"
151 systemctl mask $target
152}
153
154unmask_systemd_target ()
155{
156 target="$@"
157 systemctl unmask $target
158}
159
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600160disable_bmc_reboot ()
161{
162 dir="/run/systemd/system/"
163 file="reboot-guard.conf"
164 units=("reboot" "poweroff" "halt")
165
166 for unit in "${units[@]}"; do
167 mkdir -p ${dir}${unit}.target.d
168 echo -e "[Unit]\nRefuseManualStart=yes" >> ${dir}${unit}.target.d/${file}
169 done
170}
171
172enable_bmc_reboot ()
173{
174 dir="/run/systemd/system/"
175 file="reboot-guard.conf"
176 units=("reboot" "poweroff" "halt")
177
178 for unit in "${units[@]}"; do
179 rm -rf ${dir}${unit}.target.d/${file}
180 rm -rf ${dir}${unit}.target.d
181 done
182}
183
Anthony Wilson79f697e2018-09-13 13:48:52 -0500184handle_cmd ()
185{
186 case "$1" in
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500187 chassisoff)
188 OBJECT=$STATE_OBJECT/chassis0
189 SERVICE=$(mapper get-service $OBJECT)
190 INTERFACE=$STATE_INTERFACE.Chassis
191 PROPERTY=RequestedPowerTransition
192 VALUE=$INTERFACE.Transition.Off
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500193 G_REQUESTED_STATE=$INTERFACE.PowerState.Off
194 G_QUERY="chassisstate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500195 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
196 ;;
197 chassison)
198 OBJECT=$STATE_OBJECT/chassis0
199 SERVICE=$(mapper get-service $OBJECT)
200 INTERFACE=$STATE_INTERFACE.Chassis
201 PROPERTY=RequestedPowerTransition
202 VALUE=$INTERFACE.Transition.On
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500203 G_REQUESTED_STATE=$INTERFACE.PowerState.On
204 G_QUERY="chassisstate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500205 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
206 ;;
207 poweroff)
208 OBJECT=$STATE_OBJECT/host0
209 SERVICE=$(mapper get-service $OBJECT)
210 INTERFACE=$STATE_INTERFACE.Host
211 PROPERTY=RequestedHostTransition
212 VALUE=$INTERFACE.Transition.Off
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500213 G_REQUESTED_STATE=$INTERFACE.HostState.Off
214 G_QUERY="hoststate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500215 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
216 ;;
217 poweron)
218 OBJECT=$STATE_OBJECT/host0
219 SERVICE=$(mapper get-service $OBJECT)
220 INTERFACE=$STATE_INTERFACE.Host
221 PROPERTY=RequestedHostTransition
222 VALUE=$INTERFACE.Transition.On
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500223 G_REQUESTED_STATE=$INTERFACE.HostState.Running
224 G_QUERY="hoststate"
Anthony Wilson3ae0a352018-09-13 14:47:56 -0500225 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE
226 ;;
Anthony Wilson79f697e2018-09-13 13:48:52 -0500227 bmcstate)
228 OBJECT=$STATE_OBJECT/bmc0
229 SERVICE=$(mapper get-service $OBJECT)
230 INTERFACE=$STATE_INTERFACE.BMC
231 PROPERTY=CurrentBMCState
232 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
233 ;;
234 chassisstate)
235 OBJECT=$STATE_OBJECT/chassis0
236 SERVICE=$(mapper get-service $OBJECT)
237 INTERFACE=$STATE_INTERFACE.Chassis
238 PROPERTY=CurrentPowerState
239 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
240 ;;
241 hoststate)
242 OBJECT=$STATE_OBJECT/host0
243 SERVICE=$(mapper get-service $OBJECT)
244 INTERFACE=$STATE_INTERFACE.Host
245 PROPERTY=CurrentHostState
246 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
247 ;;
Alexander Filippov86cffd92019-04-03 16:29:57 +0300248 osstate)
249 OBJECT=$STATE_OBJECT/host0
250 SERVICE=$(mapper get-service $OBJECT)
251 INTERFACE=$STATE_INTERFACE.OperatingSystem.Status
252 PROPERTY=OperatingSystemState
253 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
254 ;;
Anthony Wilson79f697e2018-09-13 13:48:52 -0500255 state|status)
Alexander Filippov86cffd92019-04-03 16:29:57 +0300256 for query in bmcstate chassisstate hoststate bootprogress osstate
Anthony Wilson79f697e2018-09-13 13:48:52 -0500257 do
258 handle_cmd $query
259 done
260 ;;
Anthony Wilson50c5f882018-09-13 14:19:37 -0500261 bootprogress)
262 OBJECT=$STATE_OBJECT/host0
263 SERVICE=$(mapper get-service $OBJECT)
264 INTERFACE=$STATE_INTERFACE.Boot.Progress
265 PROPERTY=BootProgress
266 state_query $SERVICE $OBJECT $INTERFACE $PROPERTY
267 ;;
Anthony Wilson0f359832018-09-13 14:28:07 -0500268 power)
269 OBJECT=/org/openbmc/control/power0
270 SERVICE=$(mapper get-service $OBJECT)
271 INTERFACE=org.openbmc.control.Power
272 for property in pgood state pgood_timeout
273 do
274 # get_property can potentially return several
275 # different formats of values, so we do the parsing outside
276 # of get_property depending on the query. These queries
277 # return 'i VALUE' formatted strings.
278 STATE=$(get_property $SERVICE $OBJECT $INTERFACE $property \
279 | sed 's/i[ ^I]*//')
280 printf "%s = %s\n" $property $STATE
281 done
282 ;;
Anthony Wilson189cf242018-10-23 01:18:21 -0500283 chassiskill)
284 /usr/libexec/chassiskill
285 ;;
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600286 hostrebootoff)
Vishwanatha Subbanna6d3a2c52019-10-24 07:21:30 -0500287 OBJECT=$CONTROL_OBJECT/host0/auto_reboot
288 SERVICE=$(mapper get-service $OBJECT)
289 INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy
290 PROPERTY=AutoReboot
291 VALUE=false
292 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "b" $VALUE
293 ;;
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600294 hostrebooton)
Vishwanatha Subbanna6d3a2c52019-10-24 07:21:30 -0500295 OBJECT=$CONTROL_OBJECT/host0/auto_reboot
296 SERVICE=$(mapper get-service $OBJECT)
297 INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy
298 PROPERTY=AutoReboot
299 VALUE=true
300 set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "b" $VALUE
301 ;;
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600302 bmcrebootoff)
303 disable_bmc_reboot
304 ;;
305 bmcrebooton)
306 enable_bmc_reboot
307 ;;
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500308 recoveryoff)
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600309 handle_cmd hostrebootoff
310 handle_cmd bmcrebootoff
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500311 mask_systemd_target $HOST_TIMEOUT_TARGET
Vishwanatha Subbanna84b3b292019-11-04 05:43:19 -0600312 mask_systemd_target $HOST_CRASH_TARGET
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500313 ;;
314 recoveryon)
Vishwanatha Subbannaa65d30d2019-11-13 01:26:12 -0600315 handle_cmd hostrebooton
316 handle_cmd bmcrebooton
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500317 unmask_systemd_target $HOST_TIMEOUT_TARGET
Vishwanatha Subbanna84b3b292019-11-04 05:43:19 -0600318 unmask_systemd_target $HOST_CRASH_TARGET
Vishwanatha Subbanna7a787dd2019-10-31 06:02:31 -0500319 ;;
Anthony Wilson79f697e2018-09-13 13:48:52 -0500320 *)
Anthony Wilsonea87db42018-09-26 16:06:38 -0500321 print_usage_err "Invalid command '$1'"
Anthony Wilson79f697e2018-09-13 13:48:52 -0500322 ;;
323 esac
324}
325
Anthony Wilsonea87db42018-09-26 16:06:38 -0500326for arg in "$@"; do
327 case $arg in
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500328 -w|--wait)
329 G_WAIT=30
330 continue
331 ;;
Anthony Wilsonea87db42018-09-26 16:06:38 -0500332 -h|--help)
333 print_help
334 ;;
Andrew Jeffery60c3ac82019-10-02 09:29:29 +0930335 -v|--verbose)
336 G_VERBOSE=y
337 ;;
Anthony Wilsonea87db42018-09-26 16:06:38 -0500338 -*)
339 print_usage_err "Unknown option: $arg"
340 ;;
341 *)
Anthony Wilsonacf54d02018-09-20 15:19:28 -0500342 G_ORIG_CMD=$arg
Anthony Wilsonea87db42018-09-26 16:06:38 -0500343 handle_cmd $arg
344 break
345 ;;
346 esac
347done