5cff136951
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>
351 lines
13 KiB
Bash
Executable File
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
|