[Arista]: Add support to convert vfat file system to ext4 (#201)
This commit will convert the existing file system of flash drive on Arista switches from VFAT to EXT4 in the booting of SONiC. It will take the whole flash and therefore remove the recovery partition. There is a check in the script making sure that the conversion operation will not happen on a non-Arista switch or if the existing file system is not VFAT.
This commit is contained in:
parent
7bd90505a1
commit
6d8f57631b
@ -113,6 +113,13 @@ sudo dpkg --root=$FILESYSTEM_ROOT -i target/debs/linux-image-3.16.0-4-amd64_*.de
|
|||||||
## Update initramfs for booting with squashfs+aufs
|
## Update initramfs for booting with squashfs+aufs
|
||||||
cat files/initramfs-tools/modules | sudo tee -a $FILESYSTEM_ROOT/etc/initramfs-tools/modules > /dev/null
|
cat files/initramfs-tools/modules | sudo tee -a $FILESYSTEM_ROOT/etc/initramfs-tools/modules > /dev/null
|
||||||
|
|
||||||
|
## Hook into initramfs: change fs type from vfat to ext4 on arista switches
|
||||||
|
sudo mkdir -p $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/
|
||||||
|
sudo cp files/initramfs-tools/arista-convertfs $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-convertfs
|
||||||
|
sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/scripts/init-premount/arista-convertfs
|
||||||
|
sudo cp files/initramfs-tools/mke2fs $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/mke2fs
|
||||||
|
sudo chmod +x $FILESYSTEM_ROOT/etc/initramfs-tools/hooks/mke2fs
|
||||||
|
|
||||||
## Hook into initramfs: after partition mount and loop file mount
|
## Hook into initramfs: after partition mount and loop file mount
|
||||||
## 1. Prepare layered file system
|
## 1. Prepare layered file system
|
||||||
## 2. Bind-mount docker working directory (docker aufs cannot work over aufs rootfs)
|
## 2. Bind-mount docker working directory (docker aufs cannot work over aufs rootfs)
|
||||||
|
170
files/initramfs-tools/arista-convertfs
Normal file
170
files/initramfs-tools/arista-convertfs
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
prereqs)
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
set -e
|
||||||
|
# set -x
|
||||||
|
total_mem=$(free | awk '/^Mem:/{print $2}')
|
||||||
|
tmpfs_size=$(( $total_mem / 20 * 17 ))
|
||||||
|
free_mem_thres=$(( $total_mem / 20 * 18 ))
|
||||||
|
tmp_mnt='/mnt/ramdisk-convfs'
|
||||||
|
root_mnt='/mnt/root-convfs'
|
||||||
|
root_dev=''
|
||||||
|
flash_dev=''
|
||||||
|
block_flash=''
|
||||||
|
aboot_flag=''
|
||||||
|
backup_file=''
|
||||||
|
|
||||||
|
# Get the fullpath of flash device, e.g., /dev/sda
|
||||||
|
get_flash_dev() {
|
||||||
|
for dev in $(ls /sys/block); do
|
||||||
|
local is_mmc=$(echo "$dev" | grep 'mmcblk.*boot.*' | cat)
|
||||||
|
if [ -n "$is_mmc" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
local devid=$(realpath "/sys/block/$dev/device")
|
||||||
|
local is_device=$(echo "$devid" | grep '^/sys/devices/' | cat)
|
||||||
|
local is_flash=$(echo "$devid" | grep "$block_flash" | cat)
|
||||||
|
if [ -n "$is_device" -a -n "$is_flash" ]; then
|
||||||
|
flash_dev="/dev/$dev"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Wait for root_dev to be ready
|
||||||
|
wait_for_root_dev() {
|
||||||
|
local try_rounds=30
|
||||||
|
while [ $try_rounds -gt 0 ]; do
|
||||||
|
if [ -e "$root_dev" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
try_rounds=$(( $try_rounds - 1 ))
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Alway run cleanup before exit
|
||||||
|
cleanup() {
|
||||||
|
if grep -q "$root_mnt" /proc/mounts; then
|
||||||
|
umount "$root_mnt"
|
||||||
|
fi
|
||||||
|
if grep -q "$tmp_mnt" /proc/mounts; then
|
||||||
|
umount "$tmp_mnt"
|
||||||
|
fi
|
||||||
|
[ -e "$root_mnt" ] && rmdir "$root_mnt"
|
||||||
|
[ -e "$tmp_mnt" ] && rmdir "$tmp_mnt"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
notification() {
|
||||||
|
cat << EOF
|
||||||
|
A failure happend in modifying the root file system which stopped the upgrade. Manual interventions are needed to fix the issue. Note that:
|
||||||
|
1) files in the old root file system may have been lost and the old partition table may have been corrupted;
|
||||||
|
2) The files in the old root file system were copied to $tmp_mnt;
|
||||||
|
3) The old partition table was dumped to the file $tmp_mnt/$backup_file by sfdisk;
|
||||||
|
4) Quitting the current shell will lose all files mentioned above permanently.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
run_cmd() {
|
||||||
|
if ! eval "$1"; then
|
||||||
|
echo "$2"
|
||||||
|
notification
|
||||||
|
sh
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Extract kernel parameters
|
||||||
|
set -- $(cat /proc/cmdline)
|
||||||
|
for x in "$@"; do
|
||||||
|
case "$x" in
|
||||||
|
block_flash=*)
|
||||||
|
block_flash="${x#block_flash=}"
|
||||||
|
;;
|
||||||
|
Aboot=*)
|
||||||
|
aboot_flag="${x#Aboot=}"
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
root_dev="$ROOT"
|
||||||
|
|
||||||
|
#Check aboot and root_dev is vfat
|
||||||
|
[ -z "$aboot_flag" ] && exit 0
|
||||||
|
if [ -z "$root_dev" ]; then
|
||||||
|
echo "Error: root device name is not provided"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! wait_for_root_dev; then
|
||||||
|
echo "Error: timeout in waiting for $root_dev"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
blkid | grep "$root_dev.*vfat" -q || exit 0
|
||||||
|
|
||||||
|
|
||||||
|
# Get flash dev name
|
||||||
|
if [ -z "$block_flash" ]; then
|
||||||
|
echo "Error: flash device info is not provided"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! get_flash_dev; then
|
||||||
|
echo "Error: flash device is not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check memory size for tmpfs
|
||||||
|
free_mem=$(free | awk '/^Mem:/{print $4}')
|
||||||
|
if [ "$free_mem" -lt "$free_mem_thres" ]; then
|
||||||
|
echo "Error: memory is not enough"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Backup partition table
|
||||||
|
mkdir -p "$root_mnt"
|
||||||
|
mount "$root_dev" "$root_mnt"
|
||||||
|
backup_file=backup.$(date +%Y-%m-%d.%H-%M-%S)
|
||||||
|
sfdisk -d "$flash_dev" > "$root_mnt/$backup_file"
|
||||||
|
|
||||||
|
# Check total size of files in root
|
||||||
|
total_file_size=$(du -s "$root_mnt" | awk '{print $1}')
|
||||||
|
if [ "$total_file_size" -gt "$tmpfs_size" ]; then
|
||||||
|
echo "Error: total file size is too large"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create tmpfs, and copy files to tmpfs
|
||||||
|
mkdir -p "$tmp_mnt"
|
||||||
|
mount -t tmpfs -o size="${tmpfs_size}k" tmpfs "$tmp_mnt"
|
||||||
|
cp -a "$root_mnt/." "$tmp_mnt/"
|
||||||
|
umount "$root_mnt"
|
||||||
|
|
||||||
|
#### Lines below will modify the root file system, so any failure will be trapped to shell for manual interventions.
|
||||||
|
|
||||||
|
# Create a new partition table (content in flash_dev will be deleted)
|
||||||
|
err_msg="Error: repartitioning $flash_dev failed"
|
||||||
|
cmd="echo ';' | sfdisk $flash_dev"
|
||||||
|
run_cmd "$cmd" "$err_msg"
|
||||||
|
|
||||||
|
sleep 5
|
||||||
|
err_msg="Error: timeout in waiting for $root_dev after repartition"
|
||||||
|
cmd="wait_for_root_dev"
|
||||||
|
run_cmd "$cmd" "$err_msg"
|
||||||
|
|
||||||
|
err_msg="Error: formatting to ext4 failed"
|
||||||
|
cmd="mke2fs -t ext4 -m2 -F -O '^huge_file' $root_dev"
|
||||||
|
run_cmd "$cmd" "$err_msg"
|
||||||
|
|
||||||
|
err_msg="Error: mounting $root_dev to $root_mnt failed"
|
||||||
|
cmd="mount -t ext4 $root_dev $root_mnt"
|
||||||
|
run_cmd "$cmd" "$err_msg"
|
||||||
|
|
||||||
|
err_msg="Error: copying files form $tmp_mnt to $root_mnt failed"
|
||||||
|
cmd="cp -a $tmp_mnt/. $root_mnt/"
|
||||||
|
run_cmd "$cmd" "$err_msg"
|
||||||
|
|
50
files/initramfs-tools/mke2fs
Normal file
50
files/initramfs-tools/mke2fs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#Part of the code is revised based on initramfs-tools/hooks/fsck and initramfs-tool is under GPL v2.
|
||||||
|
|
||||||
|
PREREQ=""
|
||||||
|
|
||||||
|
prereqs()
|
||||||
|
{
|
||||||
|
echo "$PREREQ"
|
||||||
|
}
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
prereqs)
|
||||||
|
prereqs
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
. /usr/share/initramfs-tools/hook-functions
|
||||||
|
|
||||||
|
copy_exec /sbin/mke2fs
|
||||||
|
copy_exec /sbin/sfdisk
|
||||||
|
copy_exec /sbin/fdisk
|
||||||
|
|
||||||
|
fstypes="ext4"
|
||||||
|
|
||||||
|
for type in $fstypes; do
|
||||||
|
prog="/sbin/mkfs.${type}"
|
||||||
|
if [ -h "$prog" ]; then
|
||||||
|
link=$(readlink -f "$prog")
|
||||||
|
copy_exec "$link"
|
||||||
|
ln -s "$link" "${DESTDIR}/$prog"
|
||||||
|
elif [ -x "$prog" ] ; then
|
||||||
|
copy_exec "$prog"
|
||||||
|
else
|
||||||
|
echo "Warning: /sbin/mkfs.${type} doesn't exist, can't install to initramfs, ignoring."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for type in $fstypes; do
|
||||||
|
prog="/sbin/fsck.${type}"
|
||||||
|
if [ -h "$prog" ]; then
|
||||||
|
link=$(readlink -f "$prog")
|
||||||
|
copy_exec "$link"
|
||||||
|
ln -s "$link" "${DESTDIR}/$prog"
|
||||||
|
elif [ -x "$prog" ] ; then
|
||||||
|
copy_exec "$prog"
|
||||||
|
else
|
||||||
|
echo "Warning: /sbin/fsck.${type} doesn't exist, can't install to initramfs, ignoring."
|
||||||
|
fi
|
||||||
|
done
|
Loading…
Reference in New Issue
Block a user