e8418fd2da
Why I did it Requirements from Microsoft for fwutil update all state that all firmwares which support this upgrade flow must support upgrade within a single boot cycle. This conflicted with a number of Mellanox upgrade flows which have been revised to safely meet this requirement. How I did it Added --no-power-cycle flags to SSD and ONIE firmware scripts Modified Platform API to call firmware upgrade flows with this new flag during fwutil update all Added a script to our reboot plugin to handle installing firmwares in the correct order with prior to reboot How to verify it Populate platform_components.json with firmware for CPLD / BIOS / ONIE / SSD Execute fwutil update all fw --boot cold CPLD will burn / ONIE and BIOS images will stage / SSD will schedule for reboot Reboot the switch SSD will install / CPLD will refresh / switch will power cycle into ONIE ONIE installer will upgrade ONIE and BIOS / switch will reboot back into SONiC In SONiC run fwutil show status to check that all firmware upgrades were successful
223 lines
5.2 KiB
Bash
Executable File
223 lines
5.2 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Copyright (c) 2020-2021 NVIDIA CORPORATION & AFFILIATES.
|
|
# Apache-2.0
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
#
|
|
|
|
|
|
this_script="$(basename $(realpath ${0}))"
|
|
lock_file="/var/run/${this_script%.*}.lock"
|
|
|
|
onie_mount=/mnt/onie-boot
|
|
onie_lib=/lib/onie
|
|
os_boot=/host
|
|
|
|
print_help() {
|
|
cat <<EOF
|
|
update
|
|
The 'update' command will reboot system to ONIE update mode
|
|
and ONIE will perform automatically update of previously
|
|
added (i.e. pending) FW (ONIE itself, BIOS or CPLD) image.
|
|
|
|
EOF
|
|
}
|
|
|
|
enable_onie_access() {
|
|
if [[ ! -d "${onie_mount}" ]]; then
|
|
mkdir ${onie_mount}
|
|
fi
|
|
|
|
if ! mountpoint -q "${onie_mount}"; then
|
|
mount LABEL="ONIE-BOOT" ${onie_mount}
|
|
fi
|
|
|
|
if [[ ! -e "${onie_lib}" ]]; then
|
|
ln -s ${onie_mount}/onie/tools/lib/onie ${onie_lib}
|
|
fi
|
|
}
|
|
|
|
disable_onie_access() {
|
|
if [[ -e "${onie_lib}" ]]; then
|
|
unlink ${onie_lib}
|
|
fi
|
|
|
|
if mountpoint -q "${onie_mount}"; then
|
|
umount -rf ${onie_mount}
|
|
fi
|
|
|
|
if [[ -d "${onie_mount}" ]]; then
|
|
rmdir ${onie_mount}
|
|
fi
|
|
}
|
|
|
|
enable_onie_fw_update_mode() {
|
|
if [[ ! -f ${os_boot}/grub/grubenv || ! -f ${onie_mount}/grub/grubenv ]]; then
|
|
return 1
|
|
fi
|
|
|
|
register_terminate_handler
|
|
|
|
grub-editenv ${os_boot}/grub/grubenv set onie_entry="ONIE" || return $?
|
|
grub-editenv ${onie_mount}/grub/grubenv set onie_mode="update" || return $?
|
|
|
|
return 0
|
|
}
|
|
|
|
disable_onie_fw_update_mode() {
|
|
if [[ ! -f ${os_boot}/grub/grubenv || ! -f ${onie_mount}/grub/grubenv ]]; then
|
|
return 1
|
|
fi
|
|
|
|
grub-editenv ${os_boot}/grub/grubenv unset onie_entry || return $?
|
|
grub-editenv ${onie_mount}/grub/grubenv set onie_mode="install" || return $?
|
|
|
|
return 0
|
|
}
|
|
|
|
show_pending() {
|
|
if [[ ! -d ${onie_mount}/onie/update/pending ]]; then
|
|
return 0
|
|
fi
|
|
|
|
num=$(find ${onie_mount}/onie/update/pending -type f | wc -l)
|
|
if [[ ${num} -ge 1 ]]; then
|
|
${onie_mount}/onie/tools/bin/onie-fwpkg show-pending
|
|
fi
|
|
|
|
return ${num}
|
|
}
|
|
|
|
system_reboot() {
|
|
echo "INFO: Rebooting in 5 sec..."
|
|
|
|
# Give user some time to cancel the update
|
|
sleep 5s
|
|
|
|
# Use SONiC reboot scenario
|
|
/usr/local/bin/reboot
|
|
}
|
|
|
|
terminate_handler() {
|
|
local -r _rc="$?"
|
|
local -r _sig="${1}"
|
|
|
|
echo
|
|
echo "WARNING: Interrupted by ${_sig}: disable ONIE firmware update mode"
|
|
echo
|
|
|
|
enable_onie_access
|
|
disable_onie_fw_update_mode
|
|
rc=$?
|
|
disable_onie_access
|
|
|
|
if [[ ${rc} -ne 0 ]]; then
|
|
echo "ERROR: failed to disable ONIE firmware update mode"
|
|
exit ${rc}
|
|
fi
|
|
|
|
exit ${_rc}
|
|
}
|
|
|
|
register_terminate_handler() {
|
|
trap "terminate_handler SIGHUP" SIGHUP
|
|
trap "terminate_handler SIGINT" SIGINT
|
|
trap "terminate_handler SIGQUIT" SIGQUIT
|
|
trap "terminate_handler SIGTERM" SIGTERM
|
|
}
|
|
|
|
unlock_handler() {
|
|
/usr/bin/flock -u ${1}
|
|
}
|
|
|
|
register_unlock_handler() {
|
|
trap "unlock_handler ${1}" EXIT
|
|
}
|
|
|
|
unlock_script_state_change() {
|
|
/usr/bin/flock -u ${lock_fd}
|
|
}
|
|
|
|
lock_script_state_change(){
|
|
exec {lock_fd}>${lock_file}
|
|
/usr/bin/flock -x ${lock_fd}
|
|
register_unlock_handler ${lock_fd}
|
|
}
|
|
|
|
# Multiprocessing synchronization
|
|
lock_script_state_change
|
|
|
|
# Process command arguments
|
|
cmd="${1}"
|
|
|
|
# Optional argument
|
|
arg="${2}"
|
|
|
|
if [[ -z "${cmd}" ]]; then
|
|
# Default to 'show' if no command is specified.
|
|
cmd="show"
|
|
fi
|
|
|
|
case "${cmd}" in
|
|
add|remove)
|
|
if [[ -z "${arg}" ]]; then
|
|
echo "ERROR: This command requires a firmware update file name"
|
|
echo "Run: '${this_script} help' for complete details"
|
|
exit 1
|
|
fi
|
|
;;
|
|
update)
|
|
enable_onie_access
|
|
show_pending
|
|
rc=$?
|
|
if [[ ${rc} -ne 0 ]]; then
|
|
enable_onie_fw_update_mode
|
|
rc=$?
|
|
disable_onie_access
|
|
if [[ ${rc} -eq 0 ]]; then
|
|
if [[ "${arg}" == "--no-reboot" ]]; then
|
|
echo "INFO: ONIE firmware update successfully STAGED for install at NEXT reboot. Please reboot manually to complete installation."
|
|
exit 0
|
|
else
|
|
system_reboot
|
|
fi
|
|
else
|
|
echo "ERROR: failed to enable ONIE firmware update mode"
|
|
exit ${rc}
|
|
fi
|
|
else
|
|
echo "ERROR: No firmware images for update"
|
|
echo "Run: '${this_script} add <image>' before update"
|
|
disable_onie_access
|
|
exit 1
|
|
fi
|
|
;;
|
|
purge|show-pending|show-results|show|show-log|help)
|
|
;;
|
|
*)
|
|
echo "ERROR: Unknown command: ${cmd}"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
enable_onie_access
|
|
${onie_mount}/onie/tools/bin/onie-fwpkg "$@"
|
|
rc=$?
|
|
if [[ "${cmd}" = "help" ]]; then
|
|
print_help
|
|
fi
|
|
disable_onie_access
|
|
|
|
exit ${rc}
|