sonic-buildimage/files/image_config/platform/rc.local
Ying Xie 5cff136951 [console speed] lock console speed to start up speed (#1734)
Auto negotiating console speed could cause sonic to lock on a wrong
speed under rare conditions. The only way to come out of the wrong
speed is to issue line break or restart console service with forced
speed, or reboot sonic.

Lock down the console speed to avoid these situations.

Signed-off-by: Ying Xie <ying.xie@microsoft.com>
2018-11-01 15:12:22 -07:00

351 lines
13 KiB
Bash
Executable File

#!/bin/sh -x
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
SONIC_VERSION=$(sonic-cfggen -y /etc/sonic/sonic_version.yml -v build_version)
FIRST_BOOT_FILE="/host/image-${SONIC_VERSION}/platform/firsttime"
# In case the unit is migrating from another NOS, save the logs
log_migration() {
echo $1 >> /host/migration/migration.log
}
# Import files from another NOS's partition onto SONiC
nos_migration_import() {
[ -f $1 ] && cp $1 $2 || log_migration "ERROR: $1 not found!"
}
# While migrating form another NOS, we need to preserve the MAC addresses
# of eth0 (and eventually switchports).
# Update the eth0 mac and also the EEPROM using ethtool so that subsequent
# reboots use the NOS's mac.
# Input : mgmt_interface.cfg file imported from the previous NOS.
update_mgmt_interface_macaddr() {
mgmt_config=$1
if [ ! -f "$mgmt_config" ]; then
log_migration "ERROR : unable update eth0 MAC : $mgmt_config not found!"
return
fi
# Save the previous NOS's mac
old_mac=`ip link show eth0 | grep ether | awk '{print $2}'`
[ -z "$old_mac" ] && log_migration "Unable to retrieve old mac address !" && return
# Extract, validate and set the eth0's mac address for the current session
new_mac=$(grep "macaddr" $mgmt_config | awk -F'=' '{print $2}')
log_migration "Setting eth0 mac as $new_mac."
if [ `echo $new_mac | egrep "^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$"` ]; then
ip link set eth0 down
ip link set eth0 address $new_mac
ip link set eth0 up
else
log_migration "ERROR: mac imported from NOS is invalid : $new_mac !"
return
fi
# Get the ethtool magic and offset for changing the mac address in the EEPROM
ethtool_magic=$(grep "ethtool_magic" $mgmt_config | awk -F'=' '{print $2}')
ethtool_offset=$(grep "ethtool_offset" $mgmt_config | awk -F'=' '{print $2}')
if [ -z "$ethtool_magic" ] || [ -z "$ethtool_offset" ]; then
log_migration "Unable to retrieve ethtool params ($ethtool_magic,$ethtool_offset)"
return
fi
log_migration "eth0 mac in EEPROM before update:"
ethtool -e eth0 offset $ethtool_offset length 6 >> /host/migration/migration.log
# Update the mac address in the EEPROM for subsequent reboots
# Write only changed octets
for i in 1 2 3 4 5 6; do
offset=$(($ethtool_offset+$i-1))
old_mac_octet="$(echo $old_mac | cut -d":" -f$i)"
new_mac_octet="$(echo $new_mac | cut -d":" -f$i)"
if [ "$old_mac_octet" != "$new_mac_octet" ]; then
ethtool -E eth0 magic $ethtool_magic offset $offset value 0x$new_mac_octet
if [ $? != 0 ]; then
log_migration "ERROR: unable to update eth0 EEPROM!"
log_migration "index $i, magic $ethtool_magic offset $offset, value $new_mac_octet"
return
fi
fi
done
log_migration "eth0 mac in EEPROM after update:"
ethtool -e eth0 offset $ethtool_offset length 6 >> /host/migration/migration.log
# Update the 70-persistent-net.rules with the new mac for eth0
log_migration "/etc/udev/rules.d/70-persistent-net.rules : replacing $old_mac with $new_mac for eth0"
sed -i "/eth0/ s/ATTR{address}==\"$old_mac\"/ATTR{address}==\"$new_mac\"/g" /etc/udev/rules.d/70-persistent-net.rules
}
firsttime_exit() {
rm -rf $FIRST_BOOT_FILE
exit 0
}
# Given a string of tuples of the form field=value, extract the value for a field
# In : $string, $field
# Out: $value
value_extract() {
set -- $string
for x in "$@"; do
case "$x" in
$field=*)
value="${x#$field=}"
esac
done
}
# Set up previous and next reboot cause files
process_reboot_cause() {
REBOOT_CAUSE_FILE="/var/cache/sonic/reboot-cause.txt"
PREVIOUS_REBOOT_CAUSE_FILE="/var/cache/sonic/previous-reboot-cause.txt"
# Set the previous reboot cause accordingly
# If this is the first boot after an image install, state that as the
# cause. Otherwise, move REBOOT_CAUSE_FILE to PREVIOUS_REBOOT_CAUSE_FILE.
# REBOOT_CAUSE_FILE should always exist, but we add the else case
# to ensure we always generate PREVIOUS_REBOOT_CAUSE_FILE here
if [ -f $FIRST_BOOT_FILE ]; then
echo "SONiC image installation" > $PREVIOUS_REBOOT_CAUSE_FILE
elif [ -f $REBOOT_CAUSE_FILE ]; then
mv -f $REBOOT_CAUSE_FILE $PREVIOUS_REBOOT_CAUSE_FILE
else
echo "Unknown reboot cause" > $PREVIOUS_REBOOT_CAUSE_FILE
fi
# Set the default cause for the next reboot
echo "Unexpected reboot" > $REBOOT_CAUSE_FILE
}
program_console_speed()
{
speed=$(cat /proc/cmdline | grep -Eo 'console=ttyS[0-9]+,[0-9]+' | cut -d "," -f2)
if [ -z "$speed" ]; then
CONSOLE_SPEED=9600
else
CONSOLE_SPEED=$speed
fi
sed -i "s|\-\-keep\-baud .* %I| $CONSOLE_SPEED %I|g" /lib/systemd/system/serial-getty@.service
systemctl daemon-reload
}
#### Begin Main Body ####
# Set up previous and next reboot cause files
process_reboot_cause
# If the machine.conf is absent, it indicates that the unit booted
# into SONiC from another NOS. Extract the machine.conf from ONIE.
if [ ! -e /host/machine.conf ]; then
mkdir -p /host/migration
onie_dev=$(blkid | grep ONIE-BOOT | head -n 1 | awk '{print $1}' | sed -e 's/:.*$//')
mkdir -p /mnt/onie-boot
mount $onie_dev /mnt/onie-boot
onie_grub_cfg=/mnt/onie-boot/onie/grub/grub-machine.cfg
if [ ! -e $onie_grub_cfg ]; then
log_migration "$onie_grub_cfg not found"
else
. ./$onie_grub_cfg
grep = $onie_grub_cfg | sed -e 's/onie_//' -e 's/=.*$//' | while read var ; do
eval val='$'onie_$var
echo "onie_${var}=${val}" >> /host/machine.conf
done
fi
# Extract the previous NOS's partition that contains the migration artifacts
set -- $(cat /proc/cmdline)
for x in "$@"; do
case "$x" in
nos-config-part=*)
nos_val="${x#nos-config-part=}"
;;
esac
done
if [ -n "$nos_val" ]; then
nos_dev=$(findfs $nos_val)
if [ $? != 0 ]; then
log_migration "ERROR: nos_dev not found. Check grub parameters"
fi
else
log_migration "ERROR: nos_val not found. Check grub parameters"
fi
if [ -n "$nos_dev" ]; then
# Mount the previous NOS's partition
NOS_DIR=/mnt/nos_migration
MG_GZFILE=$NOS_DIR/minigraph.xml.gz.base64.txt
MG_FILE=$NOS_DIR/minigraph.xml
ACL_GZFILE=$NOS_DIR/acl.json.gz.base64.txt
ACL_FILE=$NOS_DIR/acl.json
SNMP_FILE=$NOS_DIR/snmp.yml
mkdir -p $NOS_DIR
mount $nos_dev $NOS_DIR
mkdir -p /host/fast-reboot
# decode & unzip minigraph.xml.gz.base64.txt
[ -f $MG_GZFILE ] && /usr/bin/base64 -d $MG_GZFILE | /bin/gunzip > $MG_FILE
[ -f $ACL_GZFILE ] && /usr/bin/base64 -d $ACL_GZFILE | /bin/gunzip > $ACL_FILE
# Copy relevant files
nos_migration_import $NOS_DIR/mgmt_interface.cfg /host/migration
nos_migration_import $MG_FILE /host/migration
nos_migration_import $ACL_FILE /host/migration
nos_migration_import $SNMP_FILE /host/migration
nos_migration_import $NOS_DIR/arp.json /host/fast-reboot
nos_migration_import $NOS_DIR/fdb.json /host/fast-reboot
nos_migration_import $NOS_DIR/default_routes.json /host/fast-reboot
umount $NOS_DIR
rmdir $NOS_DIR
fi
update_mgmt_interface_macaddr /host/migration/mgmt_interface.cfg
migration="TRUE"
umount /mnt/onie-boot
fi
. /host/machine.conf
program_console_speed
if [ -f $FIRST_BOOT_FILE ]; then
echo "First boot detected. Performing first boot tasks..."
if [ -n "$aboot_platform" ]; then
platform=$aboot_platform
elif [ -n "$onie_platform" ]; then
platform=$onie_platform
else
echo "Unknown SONiC platform"
firsttime_exit
fi
# Try to take old configuration saved during installation
# and create a flag in /tmp/ to let updategraph service know
if [ -d /host/old_config ]; then
mv -f /host/old_config /etc/sonic/
rm -rf /etc/sonic/old_config/old_config
touch /tmp/pending_config_migration
elif [ -f /host/minigraph.xml ]; then
mkdir -p /etc/sonic/old_config
mv /host/minigraph.xml /etc/sonic/old_config/
touch /tmp/pending_config_migration
elif [ -n "$migration" ] && [ -f /host/migration/minigraph.xml ]; then
mkdir -p /etc/sonic/old_config
mv /host/migration/minigraph.xml /etc/sonic/old_config/
[ -f /host/migration/acl.json ] && mv /host/migration/acl.json /etc/sonic/old_config/
[ -f /host/migration/snmp.yml ] && mv /host/migration/snmp.yml /etc/sonic/old_config/
touch /tmp/pending_config_migration
[ -f /etc/sonic/updategraph.conf ] && sed -i -e "s/enabled=false/enabled=true/g" /etc/sonic/updategraph.conf
else
touch /tmp/pending_config_initialization
fi
if [ -d /host/image-$SONIC_VERSION/platform/$platform ]; then
dpkg -i /host/image-$SONIC_VERSION/platform/$platform/*.deb
fi
# If the unit booted into SONiC from another NOS's grub,
# we now install a grub for SONiC.
if [ -n "$onie_platform" ] && [ -n "$migration" ]; then
grub_bin=$(ls /host/image-$SONIC_VERSION/platform/x86_64-grub/grub-pc-bin*.deb 2> /dev/null)
if [ -z "$grub_bin" ]; then
log_migration "Unable to locate grub package !"
firsttime_exit
fi
dpkg -i $grub_bin > /dev/null 2>&1
if [ $? != 0 ]; then
log_migration "Unable to install grub package !"
firsttime_exit
fi
# Determine the block device to install grub
sonic_dev=$(blkid | grep SONiC-OS | head -n 1 | awk '{print $1}' | sed -e 's/[0-9]:.*$//')
if [ -z "$sonic_dev" ]; then
log_migration "Unable to determine sonic partition !"
firsttime_exit
fi
grub-install --boot-directory=/host --recheck $sonic_dev 2>/dev/null
if [ $? != 0 ]; then
log_migration "grub install failed !"
firsttime_exit
fi
# The SONiC "raw" build mode has already generated a proto grub.cfg
# as part of the migration. Platform specific constants need to be
# retrieved from installer.conf (if present) and assigned.
. /usr/share/sonic/device/$platform/installer.conf
if [ ! -z "$CONSOLE_PORT" ]; then
field="\-\-port"
string=$(grep $field /host/grub.cfg)
value_extract $string $field
console_port=$value
if [ ! -z "$console_port" ] && [ "$console_port" != "$CONSOLE_PORT" ]; then
sed -i -e "s/\-\-port=$console_port/\-\-port=$CONSOLE_PORT/g" /host/grub.cfg
fi
log_migration "grub.cfg console port=$console_port & installer.conf CONSOLE_PORT=$CONSOLE_PORT"
fi
if [ ! -z "$CONSOLE_DEV" ]; then
field="console"
string=$(grep $field /host/grub.cfg)
value_extract $string $field
console_dev_name=$(echo $value | sed -e "s/^.*=//" -e "s/,.*//")
console_dev="${console_dev_name#ttyS}"
if [ "$console_dev" != "$CONSOLE_DEV" ]; then
sed -i -e "s/console=ttyS$console_dev/console=ttyS$CONSOLE_DEV/g" /host/grub.cfg
fi
log_migration "grub.cfg console dev=$console_dev & installer.conf CONSOLE_DEV=$CONSOLE_DEV"
fi
if [ ! -z "$VAR_LOG_SIZE" ]; then
field="var_log_size"
string=$(grep $field /host/grub.cfg)
value_extract $string $field
var_log_size=$value
if [ ! -z "$var_log_size" ] && [ "$var_log_size" != "$VAR_LOG_SIZE" ]; then
sed -i -e "s/var_log_size=$var_log_size/var_log_size=$VAR_LOG_SIZE/g" /host/grub.cfg
fi
log_migration "grub.cfg var_log_size=$var_log_size & installer.conf VAR_LOG_SIZE=$VAR_LOG_SIZE"
fi
# Set the root based on the label
sonic_root=$(blkid | grep SONiC-OS | head -n 1 | awk '{print $1}' | sed -e 's/:.*$//')
sonic_root=$(echo "$sonic_root" | sed 's/\//\\\//g')
sed -i -e "s/%%SONIC_ROOT%%/$sonic_root/g" /host/grub.cfg
# Add the Diag and ONIE entries
mount $onie_dev /mnt/onie-boot
. /mnt/onie-boot/onie/grub.d/50_onie_grub >> /host/grub.cfg
umount /mnt/onie-boot
# Initialize the SONiC's grub config
mv /host/grub.cfg /host/grub/grub.cfg
fi
firsttime_exit
fi
exit 0