-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Changes from all commits
2a577b8
5a806b8
71572c5
68efae0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
# 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 | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we sure this will work for any platform? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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/ | ||
|
@@ -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 | ||
|
||
|
@@ -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 | ||
|
@@ -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 | ||
|
@@ -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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#!/bin/sh | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better to use /bin/bash here There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
form -> from