summaryrefslogtreecommitdiff
path: root/meta-ibs
diff options
context:
space:
mode:
authorNikita Kosenkov <NKosenkov@IBS.RU>2022-06-22 18:19:58 +0300
committerNikita Kosenkov <NKosenkov@IBS.RU>2022-06-22 18:19:58 +0300
commitaaecac2908a0063cba8a3628cb089f7e0b9491bd (patch)
tree4009563db13741e9c9172eee2d175c63aa63f1af /meta-ibs
parente60eec485d293211c989bbb04c5040982a3b5452 (diff)
downloadopenbmc-aaecac2908a0063cba8a3628cb089f7e0b9491bd.tar.xz
ibmcutl: added analog obmcutil
Diffstat (limited to 'meta-ibs')
-rw-r--r--meta-ibs/meta-common/recipes-ibs/ibmcutil/ibmcutil.bb14
-rwxr-xr-xmeta-ibs/meta-common/recipes-ibs/ibmcutil/ibmcutil/ibmcutil507
-rw-r--r--meta-ibs/meta-common/recipes-ibs/images/obmc-phosphor-image.bbappend1
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 \
"