Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support OS9 -> SONiC fast-reboot migration #1414

Merged
merged 4 commits into from
Mar 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion build_debian.sh
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ sudo cp files/initramfs-tools/union-mount $FILESYSTEM_ROOT/etc/initramfs-tools/s
sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/union-mount
sudo cp files/initramfs-tools/varlog $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/varlog
sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/varlog
# Management interface (eth0) dhcp can be optionally turned off (during a migration from another NOS to SONiC)
sudo cp files/initramfs-tools/mgmt-intf-dhcp $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/mgmt-intf-dhcp
sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-bottom/mgmt-intf-dhcp
sudo cp files/initramfs-tools/union-fsck $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/union-fsck
sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/union-fsck
sudo chroot $FILESYSTEM_ROOT update-initramfs -u
Expand Down Expand Up @@ -221,7 +224,8 @@ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y in
unzip \
gdisk \
sysfsutils \
grub2-common
grub2-common \
ethtool

sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y download \
grub-pc-bin
Expand Down
134 changes: 126 additions & 8 deletions files/image_config/platform/rc.local
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,92 @@
#
# By default this script does nothing.

# 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

form -> from

# 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
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for sonic, we are using the same mac for management interface and vlan interface. are you using the same mac for you management interface and vlan interface? The goal here is to make sure your vlan interface has the same mac as our vlan interface.


# 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
echo "$onie_grub_cfg not found" >> /etc/migration.log
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
Expand All @@ -29,6 +105,44 @@ if [ ! -e /host/machine.conf ]; then
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
mkdir -p /mnt/nos_migration
mount $nos_dev /mnt/nos_migration
mkdir -p /host/fast-reboot

# Copy relevant files
nos_migration_import /mnt/nos_migration/mgmt_interface.cfg /host/migration
nos_migration_import /mnt/nos_migration/minigraph.xml /host/migration
nos_migration_import /mnt/nos_migration/arp.json /host/fast-reboot
nos_migration_import /mnt/nos_migration/fdb.json /host/fast-reboot
nos_migration_import /mnt/nos_migration/default_routes.json /host/fast-reboot

umount /mnt/nos_migration
rmdir /mnt/nos_migration
fi

update_mgmt_interface_macaddr /host/migration/mgmt_interface.cfg
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure this will work for any platform?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an assumption that the platform supports ethtool to modify the eth (GbE in S6100/Z9100) case using igb. If the platform does not support ethtool to change the EEPROM, the alternative (workaround) is to note that the unit has migrated and apply the previous NOS' mac to eth0 (using ip link set) everytime the unit reboots...


migration="TRUE"
umount /mnt/onie-boot
fi
Expand Down Expand Up @@ -96,6 +210,10 @@ if [ -f /host/image-$sonic_version/platform/firsttime ]; then
# Combine information in minigraph and init_cfg.json to form initiate config DB dump file.
# TODO: After moving all information from minigraph to DB, sample config DB dump should be provide
sonic-cfggen -H -m -j /etc/sonic/init_cfg.json --print-data > /etc/sonic/config_db.json
elif [ -n "$migration" ] && [ -f /host/migration/minigraph.xml ]; then
# Use the minigraph that was imported from the NOS
mv /host/migration/minigraph.xml /etc/sonic/
sonic-cfggen -m -j /etc/sonic/init_cfg.json --print-data > /etc/sonic/config_db.json
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-H -m -j

else
# Use default minigraph.xml
cp /usr/share/sonic/device/$platform/minigraph.xml /etc/sonic/
Expand Down Expand Up @@ -127,26 +245,26 @@ if [ -f /host/image-$sonic_version/platform/firsttime ]; then

grub_bin=$(ls /host/image-$sonic_version/platform/x86_64-grub/grub-pc-bin*.deb 2> /dev/null)
if [ -z "$grub_bin" ]; then
echo "Unable to locate grub package !" >> /etc/migration.log
log_migration "Unable to locate grub package !"
firsttime_exit
fi

dpkg -i $grub_bin > /dev/null 2>&1
if [ $? != 0 ]; then
echo "Unable to install grub package !" >> /etc/migration.log
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
echo "Unable to determine sonic partition !" >> /etc/migration.log
log_migration "Unable to determine sonic partition !"
firsttime_exit
fi

grub-install --boot-directory=/host --recheck $sonic_dev 2>/dev/null
if [ $? != 0 ]; then
echo "grub install failed !" >> /etc/migration.log
log_migration "grub install failed !"
firsttime_exit
fi

Expand All @@ -163,7 +281,7 @@ if [ -f /host/image-$sonic_version/platform/firsttime ]; then
if [ ! -z "$console_port" ] && [ "$console_port" != "$CONSOLE_PORT" ]; then
sed -i -e "s/\-\-port=$console_port/\-\-port=$CONSOLE_PORT/g" /host/grub.cfg
fi
echo "grub.cfg console port=$console_port & installer.conf CONSOLE_PORT=$CONSOLE_PORT" >> /etc/migration.log
log_migration "grub.cfg console port=$console_port & installer.conf CONSOLE_PORT=$CONSOLE_PORT"
fi

if [ ! -z "$CONSOLE_DEV" ]; then
Expand All @@ -175,7 +293,7 @@ if [ -f /host/image-$sonic_version/platform/firsttime ]; then
if [ "$console_dev" != "$CONSOLE_DEV" ]; then
sed -i -e "s/console=ttyS$console_dev/console=ttyS$CONSOLE_DEV/g" /host/grub.cfg
fi
echo "grub.cfg console dev=$console_dev & installer.conf CONSOLE_DEV=$CONSOLE_DEV" >> /etc/migration.log
log_migration "grub.cfg console dev=$console_dev & installer.conf CONSOLE_DEV=$CONSOLE_DEV"
fi

if [ ! -z "$VAR_LOG_SIZE" ]; then
Expand All @@ -186,7 +304,7 @@ if [ -f /host/image-$sonic_version/platform/firsttime ]; then
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
echo "grub.cfg var_log_size=$var_log_size & installer.conf VAR_LOG_SIZE=$VAR_LOG_SIZE" >> /etc/migration.log
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
Expand Down
36 changes: 36 additions & 0 deletions files/initramfs-tools/mgmt-intf-dhcp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/sh
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to use /bin/bash here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the shellcheck! I want to use sh as is the convention with other initramfs scripts..


PREREQS="union-mount"

prereqs() { echo "$PREREQS"; }

case $1 in
prereqs)
prereqs
exit 0
;;
esac

# Extract kernel parameters
set -- $(cat /proc/cmdline)
for x in "$@"; do
case "$x" in
mgmt-intf-dhcp=*)
val="${x#mgmt-intf-dhcp=}"

if [ -z "$val" ]; then
echo "ERROR: mgmt-intf-dhcp value (on/off) not specified !"
exit 0
fi

if [ -e "${rootmnt}/etc/network/interfaces" ]; then
if [ "$val" = "off" ]; then
sed -i 's/iface eth0 inet dhcp/iface eth0 inet static/g' ${rootmnt}/etc/network/interfaces
elif [ "$val" = "on" ]; then
sed -i 's/iface eth0 inet static/iface eth0 inet dhcp/g' ${rootmnt}/etc/network/interfaces
fi
fi

;;
esac
done