diff options
author | Nikita Kosenkov <NKosenkov@IBS.RU> | 2022-06-22 18:19:58 +0300 |
---|---|---|
committer | Nikita Kosenkov <NKosenkov@IBS.RU> | 2022-06-22 18:19:58 +0300 |
commit | aaecac2908a0063cba8a3628cb089f7e0b9491bd (patch) | |
tree | 4009563db13741e9c9172eee2d175c63aa63f1af /meta-ibs | |
parent | e60eec485d293211c989bbb04c5040982a3b5452 (diff) | |
download | openbmc-aaecac2908a0063cba8a3628cb089f7e0b9491bd.tar.xz |
ibmcutl: added analog obmcutil
Diffstat (limited to 'meta-ibs')
3 files changed, 522 insertions, 0 deletions
diff --git a/meta-ibs/meta-common/recipes-ibs/ibmcutil/ibmcutil.bb b/meta-ibs/meta-common/recipes-ibs/ibmcutil/ibmcutil.bb new file mode 100644 index 0000000000..893d007928 --- /dev/null +++ b/meta-ibs/meta-common/recipes-ibs/ibmcutil/ibmcutil.bb @@ -0,0 +1,14 @@ +SUMMARY = "ibmcutil" +DESCRIPTION = "Provides a CLI for host and chassis power management" + +SRC_URI = "file://ibmcutil;subdir=${BP}" + +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${IBSBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658" + +RDEPENDS:${PN} = "bash" + +do_install:append() { + install -d ${D}${bindir} + install -m 0755 ${S}/ibmcutil ${D}${bindir}/ibmcutil +} diff --git a/meta-ibs/meta-common/recipes-ibs/ibmcutil/ibmcutil/ibmcutil b/meta-ibs/meta-common/recipes-ibs/ibmcutil/ibmcutil/ibmcutil new file mode 100755 index 0000000000..be4da15e5b --- /dev/null +++ b/meta-ibs/meta-common/recipes-ibs/ibmcutil/ibmcutil/ibmcutil @@ -0,0 +1,507 @@ +#!/bin/bash -e + +set -euo pipefail + +OPTS="bmcstate,bootprogress,chassiskill,chassisoff,chassison,chassisstate,hoststate,\ +osstate,power,poweroff,poweron,state,status,hostrebootoff,hostrebooton,recoveryoff,recoveryon,\ +bmcrebootoff, bmcrebooton, listbootblock listlogs showlog deletelogs, stopofftargets" + +USAGE="Usage: ibmcutil [-h] [--wait] [--verbose] [--id=<INSTANCE_ID>] + {$OPTS}" + +INTERFACE_ROOT=xyz.openbmc_project +STATE_INTERFACE=$INTERFACE_ROOT.State +CONTROL_INTERFACE=$INTERFACE_ROOT.Control + +OBJECT_ROOT=/xyz/openbmc_project +STATE_OBJECT=$OBJECT_ROOT/state +CONTROL_OBJECT=$OBJECT_ROOT/control + +HOST_TIMEOUT_TARGET=obmc-host-timeout@0.target +HOST_CRASH_TARGET=obmc-host-crash@0.target + +## NOTE: The following global variables are used only in the run_timeout cmd. +## By declaring these globally instead of passing them through the +## intermediary functions, which may not be "best practice", the readability +## and cleanliness of the code should at least be increased. + +# The command passed in to be executed (e.g. poweron/off, status, etc.) +# This will be be used in some instances of error reporting +G_ORIG_CMD= +# The state an interface should be in after executing the requested command. +G_REQUESTED_STATE= +# The query to run during a poweron/off or chassison/off to check that +# the requested state (G_REQUESTED_STATE) of the interface has been reached. +G_QUERY= +# Wait the set period of time for state transitions to be successful before +# continuing on with the program or reporting an error if timeout reached. +G_WAIT= +# Print the journal to the console +G_VERBOSE= +# Instance id, default 0 +G_INSTANCE_ID="0" + +print_help () +{ + echo "$USAGE" + echo "" + echo "positional arguments:" + echo " {$OPTS}" + echo "" + echo "Examples:" + echo "" + echo "ibmcutil hostrebootoff Disable auto reboot of Host from Quiesce state" + echo "ibmcutil hostrebootoffonetime Disable auto reboot of Host from" + echo " Quiesce state for a single boot" + echo "ibmcutil hostrebooton Enable auto reboot of Host from Quiesce state" + echo "" + echo "ibmcutil bmcrebootoff Disable reboot of BMC" + echo "ibmcutil bmcrebooton Enable reboot of BMC" + echo "" + echo "ibmcutil recoveryoff Disable handling boot watchdog timeout and host crash" + echo " Also, disable BMC and Host auto reboots" + echo "" + echo "ibmcutil recoveryon Enable handling boot watchdog timeout and host crash" + echo " Also, enable BMC and Host auto reboots" + echo "" + echo "ibmcutil listbootblock Check for and list any errors blocking the boot" + echo " of the system" + echo "" + echo "ibmcutil listlogs List all phosphor-logging entries on the" + echo " system" + echo "" + echo "ibmcutil showlog <log> Display details of input log. Format of <log>" + echo " should match listlogs output" + echo "" + echo "ibmcutil deletelogs Delete all phosphor-logging entries from" + echo " system" + echo "ibmcutil stopofftargets Manually stop all obmc targets in power off" + echo " path" + echo "" + echo "optional arguments (must precede the positional options above):" + echo " -h, --help show this help message and exit" + echo " -w, --wait block until state transition succeeds or fails" + echo " -v, --verbose print the journal to stdout if --wait is supplied" + echo " -i, -id instance id, default 0" + exit 0 +} + +run_timeout () +{ + local timeout="$1"; shift + local cmd="$*" + local verbose_child= + + if [ -n "$G_VERBOSE" ]; then + journalctl -f & + verbose_child=$! + fi + + $cmd + + # Run a background query for the transition to the expected state + # This will be killed if the transition doesn't succeed within + # a timeout period. + ( + while ! grep -q "$G_REQUESTED_STATE" <<< "$(handle_cmd "$G_QUERY")" ; do + sleep 1 + done + ) & + wait_child=$! + + # Could be bad if process is killed before 'timeout' occurs if + # transition doesn't succeed. + trap -- "" SIGTERM + + # Workaround for lack of 'timeout' command. + ( + sleep "$timeout" + kill $wait_child + ) > /dev/null 2>&1 & + + if ! wait $wait_child; then + echo "Unable to confirm '$G_ORIG_CMD' success" \ + "within timeout period (${timeout}s)" + fi + + if [ -n "$verbose_child" ]; then + kill $verbose_child + fi +} + +run_cmd () +{ + local cmd="$*"; + + if [ -n "$G_WAIT" ]; then + run_timeout "$G_WAIT" "$cmd" + else + $cmd + fi +} + +set_property () +{ + run_cmd busctl set-property "$@" +} + +get_property () +{ + G_WAIT="" + run_cmd busctl get-property "$@" +} + +state_query () +{ + local state + state=$(get_property "$@" | cut -d '"' -f2) + printf "%-20s: %s\n" "$4" "$state" +} + +print_usage_err () +{ + echo "ERROR: $1" >&2 + echo "$USAGE" + exit 1 +} + +mask_systemd_target () +{ + target="$*" + systemctl mask "$target" +} + +unmask_systemd_target () +{ + target="$*" + systemctl unmask "$target" +} + +disable_bmc_reboot () +{ + dir="/run/systemd/system/" + file="reboot-guard.conf" + units=("reboot" "poweroff" "halt") + + for unit in "${units[@]}"; do + mkdir -p "${dir}${unit}.target.d" + echo -e "[Unit]\nRefuseManualStart=yes" >> "${dir}${unit}.target.d/${file}" + done +} + +enable_bmc_reboot () +{ + dir="/run/systemd/system/" + file="reboot-guard.conf" + units=("reboot" "poweroff" "halt") + + for unit in "${units[@]}"; do + rm -rf "${dir}${unit}.target.d/${file}" + rm -rf "${dir}${unit}.target.d" + done +} + +# will write blocking errors to stdout +check_boot_block_errors () +{ + # array of boot block objects + blockArray=() + + # Look for any objects under logging that implement the + # xyz.openbmc_project.Logging.ErrorBlocksTransition + subtree="$(busctl call xyz.openbmc_project.ObjectMapper \ + /xyz/openbmc_project/object_mapper \ + xyz.openbmc_project.ObjectMapper \ + GetSubTree sias "/xyz/openbmc_project/logging/" 0 1 \ + xyz.openbmc_project.Logging.ErrorBlocksTransition)" + + # remove quotation marks + # shellcheck disable=SC2001 + subtree="$(echo "$subtree" | sed 's/\"//g')" + + for entry in $subtree; do + if [[ ${entry} =~ "xyz/openbmc_project/logging/block"* ]]; then + blockArray+=( "$entry" ) + fi + done + + # now find associated error log for each boot block error + for berror in "${blockArray[@]}"; do + assocs="$(busctl call xyz.openbmc_project.Logging "$berror" \ + org.freedesktop.DBus.Properties Get \ + ss xyz.openbmc_project.Association.Definitions Associations)" + + # remove quotation marks + # shellcheck disable=SC2001 + assocs="$(echo "$assocs" | sed 's/\"//g')" + + for entry in $assocs; do + if [[ ${entry} =~ "xyz/openbmc_project/logging/entry"* ]]; then + echo "Blocking Error: $entry" + fi + done + done +} + +# helper function to check for boot block errors and notify user +check_and_warn_boot_block() +{ + blockingErrors=$(check_boot_block_errors) + if [ -n "$blockingErrors" ]; then + echo !!!!!!!!!! + echo "WARNING! System has blocking errors that will prevent boot" + echo "$blockingErrors" + echo !!!!!!!!!! + fi +} + +# list all phosphor-logging entries +list_logs() +{ + # Look for any objects under logging that implement the + # xyz.openbmc_project.Logging.Entry + busctl -j call xyz.openbmc_project.ObjectMapper \ + /xyz/openbmc_project/object_mapper \ + xyz.openbmc_project.ObjectMapper \ + GetSubTreePaths sias "/xyz/openbmc_project/logging/" 0 1 \ + xyz.openbmc_project.Logging.Entry +} + +# display input log details +show_log() +{ + busctl -j call xyz.openbmc_project.Logging \ + "$1" \ + org.freedesktop.DBus.Properties \ + GetAll s xyz.openbmc_project.Logging.Entry +} + +# delete all phosphor-logging entries +delete_logs() +{ + busctl call xyz.openbmc_project.Logging \ + /xyz/openbmc_project/logging \ + xyz.openbmc_project.Collection.DeleteAll DeleteAll +} + +# stop all targets associated with powering off a system +stop_off_targets() +{ + systemctl stop \ + obmc-chassis-powered-off@0.target \ + obmc-host-stop-pre@0.target \ + obmc-host-stopped@0.target \ + obmc-host-stopping@0.target \ + obmc-power-off@0.target \ + obmc-power-stop-pre@0.target \ + obmc-power-stop@0.target +} + + + +handle_cmd () +{ + case "$1" in + chassisoff) + OBJECT=$STATE_OBJECT/chassis$G_INSTANCE_ID + SERVICE=$(mapper get-service $OBJECT) + INTERFACE=$STATE_INTERFACE.Chassis + PROPERTY=RequestedPowerTransition + VALUE=$INTERFACE.Transition.Off + G_REQUESTED_STATE=$INTERFACE.PowerState.Off + G_QUERY="chassisstate" + set_property "$SERVICE" $OBJECT $INTERFACE $PROPERTY "s" $VALUE + ;; + chassison) + check_and_warn_boot_block + OBJECT=$STATE_OBJECT/chassis$G_INSTANCE_ID + SERVICE=$(mapper get-service $OBJECT) + INTERFACE=$STATE_INTERFACE.Chassis + PROPERTY=RequestedPowerTransition + VALUE=$INTERFACE.Transition.On + G_REQUESTED_STATE=$INTERFACE.PowerState.On + G_QUERY="chassisstate" + set_property "$SERVICE" $OBJECT $INTERFACE $PROPERTY "s" $VALUE + ;; + poweroff) + OBJECT=$STATE_OBJECT/host$G_INSTANCE_ID + SERVICE=$(mapper get-service $OBJECT) + INTERFACE=$STATE_INTERFACE.Host + PROPERTY=RequestedHostTransition + VALUE=$INTERFACE.Transition.Off + G_REQUESTED_STATE=$INTERFACE.HostState.Off + G_QUERY="hoststate" + set_property "$SERVICE" $OBJECT $INTERFACE $PROPERTY "s" $VALUE + ;; + poweron) + check_and_warn_boot_block + OBJECT=$STATE_OBJECT/host$G_INSTANCE_ID + SERVICE=$(mapper get-service $OBJECT) + INTERFACE=$STATE_INTERFACE.Host + PROPERTY=RequestedHostTransition + VALUE=$INTERFACE.Transition.On + G_REQUESTED_STATE=$INTERFACE.HostState.Running + G_QUERY="hoststate" + set_property "$SERVICE" $OBJECT $INTERFACE $PROPERTY "s" $VALUE + ;; + bmcstate) + OBJECT=$STATE_OBJECT/bmc0 + SERVICE=$(mapper get-service $OBJECT) + INTERFACE=$STATE_INTERFACE.BMC + PROPERTY=CurrentBMCState + state_query "$SERVICE" $OBJECT $INTERFACE $PROPERTY + ;; + chassisstate) + OBJECT=$STATE_OBJECT/chassis$G_INSTANCE_ID + SERVICE=$(mapper get-service $OBJECT) + INTERFACE=$STATE_INTERFACE.Chassis + PROPERTY=CurrentPowerState + state_query "$SERVICE" $OBJECT $INTERFACE $PROPERTY + ;; + hoststate) + OBJECT=$STATE_OBJECT/host$G_INSTANCE_ID + SERVICE=$(mapper get-service $OBJECT) + INTERFACE=$STATE_INTERFACE.Host + PROPERTY=CurrentHostState + state_query "$SERVICE" $OBJECT $INTERFACE $PROPERTY + ;; + osstate) + OBJECT=$STATE_OBJECT/host$G_INSTANCE_ID + SERVICE=$(mapper get-service $OBJECT) + INTERFACE=$STATE_INTERFACE.OperatingSystem.Status + PROPERTY=OperatingSystemState + state_query "$SERVICE" $OBJECT $INTERFACE $PROPERTY + ;; + state|status) + for query in bmcstate chassisstate hoststate bootprogress osstate + do + handle_cmd $query + done + check_and_warn_boot_block + ;; + bootprogress) + OBJECT=$STATE_OBJECT/host$G_INSTANCE_ID + SERVICE=$(mapper get-service $OBJECT) + INTERFACE=$STATE_INTERFACE.Boot.Progress + PROPERTY=BootProgress + state_query "$SERVICE" $OBJECT $INTERFACE $PROPERTY + ;; + power) + OBJECT=/org/openbmc/control/power0 + SERVICE=$(mapper get-service $OBJECT) + INTERFACE=org.openbmc.control.Power + for property in pgood state pgood_timeout + do + # get_property can potentially return several + # different formats of values, so we do the parsing outside + # of get_property depending on the query. These queries + # return 'i VALUE' formatted strings. + STATE=$(get_property "$SERVICE" $OBJECT $INTERFACE $property \ + | sed 's/i[ ^I]*//') + printf "%s = %s\n" $property "$STATE" + done + ;; + chassiskill) + handle_cmd chassisoff + ;; + hostrebootoff) + OBJECT=$CONTROL_OBJECT/host$G_INSTANCE_ID/auto_reboot + SERVICE=$(mapper get-service $OBJECT) + INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy + PROPERTY=AutoReboot + VALUE=false + set_property "$SERVICE" $OBJECT $INTERFACE $PROPERTY "b" $VALUE + ;; + hostrebootoffonetime) + OBJECT=$CONTROL_OBJECT/host$G_INSTANCE_ID/auto_reboot/one_time + SERVICE=$(mapper get-service $OBJECT) + INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy + PROPERTY=AutoReboot + VALUE=false + set_property "$SERVICE" $OBJECT $INTERFACE $PROPERTY "b" $VALUE + ;; + hostrebooton) + OBJECT=$CONTROL_OBJECT/host$G_INSTANCE_ID/auto_reboot + SERVICE=$(mapper get-service $OBJECT) + INTERFACE=$CONTROL_INTERFACE.Boot.RebootPolicy + PROPERTY=AutoReboot + VALUE=true + set_property "$SERVICE" $OBJECT $INTERFACE $PROPERTY "b" $VALUE + ;; + bmcrebootoff) + disable_bmc_reboot + ;; + bmcrebooton) + enable_bmc_reboot + ;; + recoveryoff) + handle_cmd hostrebootoff + handle_cmd bmcrebootoff + mask_systemd_target $HOST_TIMEOUT_TARGET + mask_systemd_target $HOST_CRASH_TARGET + ;; + recoveryon) + handle_cmd hostrebooton + handle_cmd bmcrebooton + unmask_systemd_target $HOST_TIMEOUT_TARGET + unmask_systemd_target $HOST_CRASH_TARGET + ;; + listbootblock) + blockingErrors=$(check_boot_block_errors) + if [ -z "$blockingErrors" ]; then + echo "No blocking errors present" + else + echo "$blockingErrors" + fi + ;; + listlogs) + list_logs + ;; + showlog) + show_log "$2" + ;; + deletelogs) + delete_logs + ;; + stopofftargets) + stop_off_targets + ;; + *) + print_usage_err "Invalid command '$1'" + ;; + esac +} + +shiftcnt=0 +for arg in "$@"; do + case $arg in + -w|--wait) + G_WAIT=30 + shiftcnt=$((shiftcnt+1)) + continue + ;; + -h|--help) + print_help + ;; + -v|--verbose) + G_VERBOSE=y + shiftcnt=$((shiftcnt+1)) + ;; + -i=*|--id=*) + G_INSTANCE_ID="${arg#*=}" + shiftcnt=$((shiftcnt+1)) + ;; + -*) + print_usage_err "Unknown option: $arg" + ;; + *) + G_ORIG_CMD=$arg + # shift out the optional parameters + shift $shiftcnt + # pass all arguments to handle_cmd in case command takes additional + # parameters + handle_cmd "$@" + break + ;; + esac +done diff --git a/meta-ibs/meta-common/recipes-ibs/images/obmc-phosphor-image.bbappend b/meta-ibs/meta-common/recipes-ibs/images/obmc-phosphor-image.bbappend index f8f80c9389..bf8f1b8b33 100644 --- a/meta-ibs/meta-common/recipes-ibs/images/obmc-phosphor-image.bbappend +++ b/meta-ibs/meta-common/recipes-ibs/images/obmc-phosphor-image.bbappend @@ -9,6 +9,7 @@ IMAGE_INSTALL += " openssl-bin \ biosconfig-manager \ bmcweb-init-certs \ firmware-watchdog \ + ibmcutil \ smbios-mdrv2 \ psu-manager \ " |