diff --git a/build_debian.sh b/build_debian.sh index 033ac6ff270f..bc04a71800ce 100755 --- a/build_debian.sh +++ b/build_debian.sh @@ -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 @@ -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 diff --git a/files/image_config/platform/rc.local b/files/image_config/platform/rc.local index aa44cadf52bc..c5bfae19f9b8 100755 --- a/files/image_config/platform/rc.local +++ b/files/image_config/platform/rc.local @@ -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 +} + # 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 + 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 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 diff --git a/files/initramfs-tools/mgmt-intf-dhcp b/files/initramfs-tools/mgmt-intf-dhcp new file mode 100644 index 000000000000..52f7ff5f495c --- /dev/null +++ b/files/initramfs-tools/mgmt-intf-dhcp @@ -0,0 +1,36 @@ +#!/bin/sh + +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 diff --git a/platform/broadcom/sonic-platform-modules-dell b/platform/broadcom/sonic-platform-modules-dell index d2f58195831e..fac81d02276d 160000 --- a/platform/broadcom/sonic-platform-modules-dell +++ b/platform/broadcom/sonic-platform-modules-dell @@ -1 +1 @@ -Subproject commit d2f58195831e6e7016992ef449778f3474e60e95 +Subproject commit fac81d02276d7245233c0401ac699029b0b41cdd