179f697e0SAnthony Wilson#!/bin/sh -e 279f697e0SAnthony Wilson 379f697e0SAnthony Wilsonset -euo pipefail 479f697e0SAnthony Wilson 53ae0a354SAnthony WilsonOPTS="bmcstate,bootprogress,chassisoff,chassison,chassisstate,hoststate,\ 63ae0a354SAnthony Wilsonpower,poweroff,poweron,state,status" 70f35983dSAnthony Wilson 8*acf54d08SAnthony WilsonUSAGE="Usage: obmcutil [-h] [--wait] 90f35983dSAnthony Wilson {$OPTS}" 1079f697e0SAnthony Wilson 1179f697e0SAnthony WilsonINTERFACE_ROOT=xyz.openbmc_project 1279f697e0SAnthony WilsonSTATE_INTERFACE=$INTERFACE_ROOT.State 1379f697e0SAnthony Wilson 1479f697e0SAnthony WilsonOBJECT_ROOT=/xyz/openbmc_project 1579f697e0SAnthony WilsonSTATE_OBJECT=$OBJECT_ROOT/state 1679f697e0SAnthony Wilson 17*acf54d08SAnthony Wilson## NOTE: The following global variables are used only in the run_timeout cmd. 18*acf54d08SAnthony Wilson## By declaring these globally instead of passing them through the 19*acf54d08SAnthony Wilson## intermediary functions, which may not be "best practice", the readability 20*acf54d08SAnthony Wilson## and cleanliness of the code should at least be increased. 21*acf54d08SAnthony Wilson 22*acf54d08SAnthony Wilson# The command passed in to be executed (e.g. poweron/off, status, etc.) 23*acf54d08SAnthony Wilson# This will be be used in some instances of error reporting 24*acf54d08SAnthony WilsonG_ORIG_CMD= 25*acf54d08SAnthony Wilson# The state an interface should be in after executing the requested command. 26*acf54d08SAnthony WilsonG_REQUESTED_STATE= 27*acf54d08SAnthony Wilson# The query to run during a poweron/off or chassison/off to check that 28*acf54d08SAnthony Wilson# the requested state (G_REQUESTED_STATE) of the interface has been reached. 29*acf54d08SAnthony WilsonG_QUERY= 30*acf54d08SAnthony Wilson# Wait the set period of time for state transitions to be successful before 31*acf54d08SAnthony Wilson# continuing on with the program or reporting an error if timeout reached. 32*acf54d08SAnthony WilsonG_WAIT= 33*acf54d08SAnthony Wilson 34f3f16fa9SAnthony Wilsonprint_help () 35f3f16fa9SAnthony Wilson{ 36f3f16fa9SAnthony Wilson echo "$USAGE" 37f3f16fa9SAnthony Wilson echo "" 38f3f16fa9SAnthony Wilson echo "positional arguments:" 390f35983dSAnthony Wilson echo " {$OPTS}" 40f3f16fa9SAnthony Wilson echo "" 41f3f16fa9SAnthony Wilson echo "optional arguments:" 42f3f16fa9SAnthony Wilson echo " -h, --help show this help message and exit" 43*acf54d08SAnthony Wilson echo " -w, --wait block until state transition succeeds or fails" 44f3f16fa9SAnthony Wilson exit 0 45f3f16fa9SAnthony Wilson} 46f3f16fa9SAnthony Wilson 47*acf54d08SAnthony Wilsonrun_timeout () 48*acf54d08SAnthony Wilson{ 49*acf54d08SAnthony Wilson local timeout="$1"; shift 50*acf54d08SAnthony Wilson local cmd="$@" 51*acf54d08SAnthony Wilson 52*acf54d08SAnthony Wilson $cmd 53*acf54d08SAnthony Wilson 54*acf54d08SAnthony Wilson # Run a background query for the transition to the expected state 55*acf54d08SAnthony Wilson # This will be killed if the transition doesn't succeed within 56*acf54d08SAnthony Wilson # a timeout period. 57*acf54d08SAnthony Wilson ( 58*acf54d08SAnthony Wilson while ! grep -q $G_REQUESTED_STATE <<< $(handle_cmd $G_QUERY) ; do 59*acf54d08SAnthony Wilson sleep 1 60*acf54d08SAnthony Wilson done 61*acf54d08SAnthony Wilson ) & 62*acf54d08SAnthony Wilson child=$! 63*acf54d08SAnthony Wilson 64*acf54d08SAnthony Wilson # Could be bad if process is killed before 'timeout' occurs if 65*acf54d08SAnthony Wilson # transition doesn't succeed. 66*acf54d08SAnthony Wilson trap -- "" SIGTERM 67*acf54d08SAnthony Wilson 68*acf54d08SAnthony Wilson # Workaround for lack of 'timeout' command. 69*acf54d08SAnthony Wilson ( 70*acf54d08SAnthony Wilson sleep $timeout 71*acf54d08SAnthony Wilson kill $child 72*acf54d08SAnthony Wilson ) > /dev/null 2>&1 & 73*acf54d08SAnthony Wilson 74*acf54d08SAnthony Wilson if ! wait $child; then 75*acf54d08SAnthony Wilson echo "Unable to confirm '$G_ORIG_CMD' success" \ 76*acf54d08SAnthony Wilson "within timeout period (${timeout}s)" 77*acf54d08SAnthony Wilson fi 78*acf54d08SAnthony Wilson} 79*acf54d08SAnthony Wilson 80*acf54d08SAnthony Wilsonrun_cmd () 81*acf54d08SAnthony Wilson{ 82*acf54d08SAnthony Wilson local cmd="$@"; 83*acf54d08SAnthony Wilson 84*acf54d08SAnthony Wilson if [ -n "$G_WAIT" ]; then 85*acf54d08SAnthony Wilson run_timeout $G_WAIT "$cmd" 86*acf54d08SAnthony Wilson else 87*acf54d08SAnthony Wilson $cmd 88*acf54d08SAnthony Wilson fi 89*acf54d08SAnthony Wilson} 90*acf54d08SAnthony Wilson 913ae0a354SAnthony Wilsonset_property () 923ae0a354SAnthony Wilson{ 93*acf54d08SAnthony Wilson run_cmd busctl set-property "$@" 943ae0a354SAnthony Wilson} 953ae0a354SAnthony Wilson 9679f697e0SAnthony Wilsonget_property () 9779f697e0SAnthony Wilson{ 98*acf54d08SAnthony Wilson G_WAIT="" 99*acf54d08SAnthony Wilson run_cmd busctl get-property "$@" 10079f697e0SAnthony Wilson} 10179f697e0SAnthony Wilson 10279f697e0SAnthony Wilsonstate_query () 10379f697e0SAnthony Wilson{ 10479f697e0SAnthony Wilson local state=$(get_property "$@" | cut -d '"' -f2) 10579f697e0SAnthony Wilson printf "%-20s: %s\n" $4 $state 10679f697e0SAnthony Wilson} 10779f697e0SAnthony Wilson 108ea87db40SAnthony Wilsonprint_usage_err () 109ea87db40SAnthony Wilson{ 110ea87db40SAnthony Wilson echo "ERROR: $1" >&2 111ea87db40SAnthony Wilson echo "$USAGE" 112ea87db40SAnthony Wilson exit 1 113ea87db40SAnthony Wilson} 114ea87db40SAnthony Wilson 11579f697e0SAnthony Wilsonhandle_cmd () 11679f697e0SAnthony Wilson{ 11779f697e0SAnthony Wilson case "$1" in 1183ae0a354SAnthony Wilson chassisoff) 1193ae0a354SAnthony Wilson OBJECT=$STATE_OBJECT/chassis0 1203ae0a354SAnthony Wilson SERVICE=$(mapper get-service $OBJECT) 1213ae0a354SAnthony Wilson INTERFACE=$STATE_INTERFACE.Chassis 1223ae0a354SAnthony Wilson PROPERTY=RequestedPowerTransition 1233ae0a354SAnthony Wilson VALUE=$INTERFACE.Transition.Off 124*acf54d08SAnthony Wilson G_REQUESTED_STATE=$INTERFACE.PowerState.Off 125*acf54d08SAnthony Wilson G_QUERY="chassisstate" 1263ae0a354SAnthony Wilson set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE 1273ae0a354SAnthony Wilson ;; 1283ae0a354SAnthony Wilson chassison) 1293ae0a354SAnthony Wilson OBJECT=$STATE_OBJECT/chassis0 1303ae0a354SAnthony Wilson SERVICE=$(mapper get-service $OBJECT) 1313ae0a354SAnthony Wilson INTERFACE=$STATE_INTERFACE.Chassis 1323ae0a354SAnthony Wilson PROPERTY=RequestedPowerTransition 1333ae0a354SAnthony Wilson VALUE=$INTERFACE.Transition.On 134*acf54d08SAnthony Wilson G_REQUESTED_STATE=$INTERFACE.PowerState.On 135*acf54d08SAnthony Wilson G_QUERY="chassisstate" 1363ae0a354SAnthony Wilson set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE 1373ae0a354SAnthony Wilson ;; 1383ae0a354SAnthony Wilson poweroff) 1393ae0a354SAnthony Wilson OBJECT=$STATE_OBJECT/host0 1403ae0a354SAnthony Wilson SERVICE=$(mapper get-service $OBJECT) 1413ae0a354SAnthony Wilson INTERFACE=$STATE_INTERFACE.Host 1423ae0a354SAnthony Wilson PROPERTY=RequestedHostTransition 1433ae0a354SAnthony Wilson VALUE=$INTERFACE.Transition.Off 144*acf54d08SAnthony Wilson G_REQUESTED_STATE=$INTERFACE.HostState.Off 145*acf54d08SAnthony Wilson G_QUERY="hoststate" 1463ae0a354SAnthony Wilson set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE 1473ae0a354SAnthony Wilson ;; 1483ae0a354SAnthony Wilson poweron) 1493ae0a354SAnthony Wilson OBJECT=$STATE_OBJECT/host0 1503ae0a354SAnthony Wilson SERVICE=$(mapper get-service $OBJECT) 1513ae0a354SAnthony Wilson INTERFACE=$STATE_INTERFACE.Host 1523ae0a354SAnthony Wilson PROPERTY=RequestedHostTransition 1533ae0a354SAnthony Wilson VALUE=$INTERFACE.Transition.On 154*acf54d08SAnthony Wilson G_REQUESTED_STATE=$INTERFACE.HostState.Running 155*acf54d08SAnthony Wilson G_QUERY="hoststate" 1563ae0a354SAnthony Wilson set_property $SERVICE $OBJECT $INTERFACE $PROPERTY "s" $VALUE 1573ae0a354SAnthony Wilson ;; 15879f697e0SAnthony Wilson bmcstate) 15979f697e0SAnthony Wilson OBJECT=$STATE_OBJECT/bmc0 16079f697e0SAnthony Wilson SERVICE=$(mapper get-service $OBJECT) 16179f697e0SAnthony Wilson INTERFACE=$STATE_INTERFACE.BMC 16279f697e0SAnthony Wilson PROPERTY=CurrentBMCState 16379f697e0SAnthony Wilson state_query $SERVICE $OBJECT $INTERFACE $PROPERTY 16479f697e0SAnthony Wilson ;; 16579f697e0SAnthony Wilson chassisstate) 16679f697e0SAnthony Wilson OBJECT=$STATE_OBJECT/chassis0 16779f697e0SAnthony Wilson SERVICE=$(mapper get-service $OBJECT) 16879f697e0SAnthony Wilson INTERFACE=$STATE_INTERFACE.Chassis 16979f697e0SAnthony Wilson PROPERTY=CurrentPowerState 17079f697e0SAnthony Wilson state_query $SERVICE $OBJECT $INTERFACE $PROPERTY 17179f697e0SAnthony Wilson ;; 17279f697e0SAnthony Wilson hoststate) 17379f697e0SAnthony Wilson OBJECT=$STATE_OBJECT/host0 17479f697e0SAnthony Wilson SERVICE=$(mapper get-service $OBJECT) 17579f697e0SAnthony Wilson INTERFACE=$STATE_INTERFACE.Host 17679f697e0SAnthony Wilson PROPERTY=CurrentHostState 17779f697e0SAnthony Wilson state_query $SERVICE $OBJECT $INTERFACE $PROPERTY 17879f697e0SAnthony Wilson ;; 17979f697e0SAnthony Wilson state|status) 18079f697e0SAnthony Wilson for query in bmcstate chassisstate hoststate 18179f697e0SAnthony Wilson do 18279f697e0SAnthony Wilson handle_cmd $query 18379f697e0SAnthony Wilson done 18479f697e0SAnthony Wilson ;; 18550c5f88dSAnthony Wilson bootprogress) 18650c5f88dSAnthony Wilson OBJECT=$STATE_OBJECT/host0 18750c5f88dSAnthony Wilson SERVICE=$(mapper get-service $OBJECT) 18850c5f88dSAnthony Wilson INTERFACE=$STATE_INTERFACE.Boot.Progress 18950c5f88dSAnthony Wilson PROPERTY=BootProgress 19050c5f88dSAnthony Wilson state_query $SERVICE $OBJECT $INTERFACE $PROPERTY 19150c5f88dSAnthony Wilson ;; 1920f35983dSAnthony Wilson power) 1930f35983dSAnthony Wilson OBJECT=/org/openbmc/control/power0 1940f35983dSAnthony Wilson SERVICE=$(mapper get-service $OBJECT) 1950f35983dSAnthony Wilson INTERFACE=org.openbmc.control.Power 1960f35983dSAnthony Wilson for property in pgood state pgood_timeout 1970f35983dSAnthony Wilson do 1980f35983dSAnthony Wilson # get_property can potentially return several 1990f35983dSAnthony Wilson # different formats of values, so we do the parsing outside 2000f35983dSAnthony Wilson # of get_property depending on the query. These queries 2010f35983dSAnthony Wilson # return 'i VALUE' formatted strings. 2020f35983dSAnthony Wilson STATE=$(get_property $SERVICE $OBJECT $INTERFACE $property \ 2030f35983dSAnthony Wilson | sed 's/i[ ^I]*//') 2040f35983dSAnthony Wilson printf "%s = %s\n" $property $STATE 2050f35983dSAnthony Wilson done 2060f35983dSAnthony Wilson ;; 20779f697e0SAnthony Wilson *) 208ea87db40SAnthony Wilson print_usage_err "Invalid command '$1'" 20979f697e0SAnthony Wilson ;; 21079f697e0SAnthony Wilson esac 21179f697e0SAnthony Wilson} 21279f697e0SAnthony Wilson 213ea87db40SAnthony Wilsonfor arg in "$@"; do 214ea87db40SAnthony Wilson case $arg in 215*acf54d08SAnthony Wilson -w|--wait) 216*acf54d08SAnthony Wilson G_WAIT=30 217*acf54d08SAnthony Wilson continue 218*acf54d08SAnthony Wilson ;; 219ea87db40SAnthony Wilson -h|--help) 220ea87db40SAnthony Wilson print_help 221ea87db40SAnthony Wilson ;; 222ea87db40SAnthony Wilson -*) 223ea87db40SAnthony Wilson print_usage_err "Unknown option: $arg" 224ea87db40SAnthony Wilson ;; 225ea87db40SAnthony Wilson *) 226*acf54d08SAnthony Wilson G_ORIG_CMD=$arg 227ea87db40SAnthony Wilson handle_cmd $arg 228ea87db40SAnthony Wilson break 229ea87db40SAnthony Wilson ;; 230ea87db40SAnthony Wilson esac 231ea87db40SAnthony Wilsondone 232