#!/bin/bash
####################################################################
#
#      File: S26check-flash.sup2
#      Name: Anupam Bhandari
#
#       Description:
#       fsck script before mounting for Sup2
#	Actual location on disk: /etc/rc.d/rcS.d/S26check-flash
#
#
# Copyright (c) 1985-2004, 2015 by cisco Systems, Inc.
# All rights reserved.
#
#
# $Id: $
# ---------------------------------------------------------------
#####################################################################

. /etc/init.d/mod_ins/module-load-functions
. /etc/init.d/sup.include


boot_debug "`date`::check-flash Start"
CKSUM=/isanboot/sbin/psscksum
CKDIRS="ascii bin boot debug linux"
OPTIONAL_CKDIRS="licenses no-erase"
MIRROR=/isanboot/bin/startup_cfg_mirror
DESTROY="/isanboot/bin/startup_cfg_tool destroy"
LABELFILE=cfglabel.sysmgr
    
# Say yes to all corrections.
FSCK_OPTS=-y

CFG0_FSCK_FAIL=0
CFG1_FSCK_FAIL=0

STATUS_OK=0
STATUS_BAD=1
STATUS_NOCFG=2
     
CFG0_STATUS=$STATUS_OK
CFG1_STATUS=$STATUS_OK
CFG_STATUS=$STATUS_OK

# -f takes 25 sec boot time. Is -f needed or we were just being 
# paranoid. INSIEME_TODO:
FORCE_CHECK=

if [ -n "$MAX_ALLOWED_VDCS" ]; then
boot_debug "Number of vdcs supported = $MAX_ALLOWED_VDCS"
else
MAX_ALLOWED_VDCS=1;
boot_debug "Number of vdcs supported = $MAX_ALLOWED_VDCS"
fi

function config_ok {

    if [ -f $1/$LABELFILE ]; then

        CFG_STATUS=$STATUS_OK
    
        for dir in $CKDIRS
        do
            action $CKSUM -c $1/$dir
            if [ $? -ne 0 ]; then
                CFG_STATUS=$STATUS_BAD
                break
            fi
        done

        if [ $CFG_STATUS -eq $STATUS_OK ]; then
            for dir in $OPTIONAL_CKDIRS
            do
                if [ -f $1/$dir ]; then
                    action $CKSUM -c $1/$dir
                    if [ $? -ne 0 ]; then
                        CFG_STATUS=$STATUS_BAD
                        break
                    fi
                fi
            done
        fi

    else

        CFG_STATUS=$STATUS_NOCFG
    fi
}

function print_big_warning {
    boot_debug "startup-config had fatal error and was reinitialized!"
}

function print_no_cfg_warning {
    boot_debug "Warning: switch is starting up with default configuration"
}


    
#####################################################
#         FSCK    
#####################################################    

echo
echo -n "Checking all filesystems."

#CSCth76245 Disable CTRL+C before doing filesystem operation.
trap '' 2

# CHECK THE NUMBER OF PARTITIONS
# On a good system,
# total paritions including the parent is 8.
#Linux(debug)# cat /proc/partitions |grep sda
#   8        0   62522712 sda
#   8        1     524288 sda1
#   8        2    2479281 sda2
#   8        3    4958563 sda3
#   8        4   21693714 sda4
#   8        5    4958563 sda5
#   8        6    4958563 sda6
#   8        7   21693714 sda7
#Linux(debug)# cat /proc/partitions |grep sda| wc -l
#8

if [ -n "$IS_N3K" ]; then
    total_exp_partitions=7
else
    total_exp_partitions=8
fi
total_partitions=$(cat /proc/partitions |grep ${FLASH_DEV} | wc -l)
if [ $total_partitions -lt $total_exp_partitions ]; then
    boot_debug "Disk is not partitioned properly.."
    boot_debug ">>> Disk will be re-initialized. <<<"
    touch $FORMAT_FLASH_FILE
    exit
fi

#
# CHECK FOR BOOTLOADER
#
echo "Checking bootloader - `date`" >> /tmp/boot_uptime.log
boot_debug "Checking bootloader"
action "" e2fsck $FSCK_OPTS $DEV_BOOTLOADER_FILE
retval=$?
if [ $retval -eq 4 ]; then
    boot_debug "ERROR: Internal disk has unrecoverable error (1); please do \"init system\""
elif [ $retval -eq 1 ]; then
    echo -n "r"
fi
echo -n "."

#
# CHECK FOR CFG0
#
echo "Checking cfg0 - `date`" >> /tmp/boot_uptime.log
boot_debug "Checking cfg0"
action "" e2fsck $FSCK_OPTS $FORCE_CHECK $DEV_CFG0_FILE
retval=$?
if [ $retval -eq 4 -o "$reformat_cfg0" = "yes" ]; then
    echo -n "R"
    
    action "" echo "CFG0 has fatal error ($retval), reinitialized"
    action "" mke2fs -j $DEV_CFG0_FILE

    CFG0_FSCK_FAIL=1
        
elif [ $retval -eq 1 ]; then
    echo -n "r"
fi
echo -n "."

#
# CHECK FOR CFG1
#
echo "Checking cfg1 - `date`" >> /tmp/boot_uptime.log
boot_debug "Checking cfg1"
action "" e2fsck $FSCK_OPTS $FORCE_CHECK $DEV_CFG1_FILE
retval=$?
if [ $retval -eq 4 -o "$reformat_cfg1" = "yes" ]; then
    echo -n "R"
        
    action "" echo "CFG1 has fatal error ($retval), reinitialized"
    action "" mke2fs -j $DEV_CFG1_FILE

    CFG1_FSCK_FAIL=1
        
elif [ $retval -eq 1 ]; then
    echo -n "r"
fi
echo -n "."
    

#
# CHECK FOR LOGFLASH
#
# TODO - N3K_BRINGUP
if [ -n "$IS_N3K" ]; then
    echo "Skipping LOGFLASH check for N3k..."
else
echo "Checking logflash - `date`" >> /tmp/boot_uptime.log
# Temporary hack.
if [ ! -d /sys/block/sda/sda7 ]; then
    echo "Logflash partition not found..."
    /isanboot/sbin/init-system --logflash-only
fi
boot_debug "Checking logflash"
action "" e2fsck $FSCK_OPTS $FORCE_CHECK $DEV_LOGFLASH_FILE

retval=$?
if [ $retval -eq 4 -o $retval -eq 8 -o "$reformat_logflash" = "yes" ]; then
    
    echo -n "R"
    action "" echo "Logflash filesystem has fatal error ($retval), reinitialized"
    action "" mke2fs -j $DEV_LOGFLASH_FILE

elif [ $retval -eq 1 ]; then
    echo -n "r"    
fi
echo -n "."
fi

#
# CHECK FOR PSS
#
echo "Checking pss - `date`" >> /tmp/boot_uptime.log
boot_debug "Checking pss"
action "" e2fsck $FSCK_OPTS $FORCE_CHECK $DEV_PSS_FILE
retval=$?
# INSIEME: If the partition goes bad that e2fsck
# cannot even recognize the filesystem, it returns 8.
# Lets handle exit code 8 also.
if [ $retval -eq 4 -o $retval -eq 8 -o "$reformat_pss" = "yes" ]; then
    
    echo -n "R"

    action "" echo "PSS filesystem has fatal error ($retval), reinitialized"
    action "" mke2fs -j $DEV_PSS_FILE
    retval=$?
    if [ $retval -ne 0 ]; then
        boot_debug "pss is not paritioned properly."
        boot_debug ">>> Disk will be re-initialized. <<<"
        touch $FORMAT_FLASH_FILE
    fi

elif [ $retval -eq 1 ]; then
    echo -n "r"    
fi

echo -n "."

#
# CHECK FOR PLOG
#
## TODO - N3K_BRINGUP
if [ -n "$IS_N3K" ]; then
    echo "Skipping plog check for N3k..."
else
echo "Checking plog - `date`" >> /tmp/boot_uptime.log
boot_debug "Checking plog"
action "" e2fsck $FSCK_OPTS $FORCE_CHECK $DEV_PLOG_FILE
retval=$?
# INSIEME: If the partition goes bad that e2fsck
# cannot even recognize the filesystem, it returns 8.
# Lets handle exit code 8 also.
if [ $retval -eq 4 -o $retval -eq 8 -o "$reformat_plog" = "yes" ]; then
    
    echo -n "R"

    action "" echo "Plog filesystem has fatal error ($retval), reinitialized"
    action "" mke2fs -j $DEV_PLOG_FILE
    retval=$?
    if [ $retval -ne 0 ]; then
        boot_debug "plog is not paritioned properly."
        boot_debug ">>> Disk will be re-initialized. <<<"
        touch $FORMAT_FLASH_FILE
    fi

elif [ $retval -eq 1 ]; then
    echo -n "r"    
fi

echo -n "."
fi


# INSIEME_TODO: OBFL currently not ready.
#echo "Checking obfl - `date`" >> /tmp/boot_uptime.log
#boot_debug "Checking obfl"
#action "" e2fsck -p -f $DEV_OBFL_FILE

#retval=$?
    
#if [ $retval -eq 4 -o $retval -eq 8  -o "$reformat_obfl" = "yes" ]; then
#    
#    echo -n "R"
#
#    action "" echo "OBFL filesystem has fatal error ($retval), reinitialized"
#    action "" mke2fs -j -c $DEV_OBFL_FILE
#
#elif [ $retval -eq 1 ]; then
#    echo -n "r"    
#fi

#echo -n "."


#
# CHECK FOR BOOTFLASH
#
echo "Checking bootflash - `date`" >> /tmp/boot_uptime.log
boot_debug "Checking bootflash:"

if [ "$forcecheck" = "yes" ]; then  
    action "" e2fsck $FORCE_CHECK $FSCK_OPTS $DEV_BOOTFLASH_FILE
else
    action "" e2fsck $FSCK_OPTS $DEV_BOOTFLASH_FILE
fi
retval=$?
if [ $retval -eq 4 ]; then
    boot_debug "Error: bootflash: has unrecoverable error."
    boot_debug "Formatting bootflash:"
    action "" mke2fs -j $DEV_BOOTFLASH_FILE
    retval=$?
    if [ $retval -ne 0 ]; then
        boot_debug "bootflash is not paritioned properly."
        boot_debug ">>> Disk will be re-initialized. <<<"
        touch $FORMAT_FLASH_FILE
    fi

elif [ $retval -eq 1 ]; then
    echo -n "r"
fi



#####################################################
#      Check startup-config
#####################################################    
    
boot_debug "Mounting $MNT_CFG0_DIR"
action "mounting cfg0" mount $MNT_CFG0_DIR
result=$?
if [ $result -ne 0 ]; then
   echo -e "/mnt/cfg/0 dir return $result \n"
fi

if [ $result -eq 0 ]; then    
    boot_debug "Mounting $MNT_CFG1_DIR"
    action "mounting cfg1" mount $MNT_CFG1_DIR
    result=$?
    if [ $result -ne 0 ]; then
       echo -e "/mnt/cfg/1 dir return $result \n"
    fi
fi    

# assume user interruptions is not an error, to prevent
# init-system on ^C
if [ $result -eq 8 ]; then
    result=0
fi

# Note that we check the file-system but if it is bad we do not
# do init-system here. init-system requires klm_nvram etc
# needs to be loaded and done later.
# so we save the result in a file and once all drivers are 
# loaded we check the 'result' of this operation.
# if there was a failure, only then we do init system

if [ $result -ne 0 ] ; then
    # we will check if we have to do init-system in S26 script
    action "" echo mount returns error code: $result
    boot_debug "Config partitions are not paritioned properly.\nDisk will be re-initialized.";
    touch $FORMAT_FLASH_FILE
else
    
    # if both disks are bad, print warning
    if [ $CFG0_FSCK_FAIL -eq 1 -a $CFG1_FSCK_FAIL -eq 1 ]; then
        print_big_warning
    else

        config_ok $MNT_CFG0_DIR
        CFG0_STATUS=$CFG_STATUS
        boot_debug "CFG0 status: $CFG0_STATUS"
            
        config_ok $MNT_CFG1_DIR
        CFG1_STATUS=$CFG_STATUS
        boot_debug "CFG1 status: $CFG1_STATUS"
            
        if [ $CFG0_STATUS -ne $STATUS_OK -o $CFG1_STATUS -ne $STATUS_OK ]; then
	    # try to do mirroring from "good" to "bad"
    
    	    if [ $CFG0_STATUS -eq $STATUS_OK ]; then
                boot_debug "Mirroring startup-config from cfg0 to cfg1"
                $MIRROR 0
	        elif [ $CFG1_STATUS -eq $STATUS_OK ]; then
                boot_debug "Mirroring startup-config from cfg1 to cfg0"
                $MIRROR 1
            else
                # No startup-config due to error

                action "" echo "Reinitializing startup-config 0"
                action "" $DESTROY 0 0

		        action "" echo "Reinitializing startup-config 1"
                action "" $DESTROY 1 0

                if [ $CFG0_STATUS -eq $STATUS_BAD -o $CFG1_STATUS -eq $STATUS_BAD ]; then
                    print_big_warning
                fi
                    
                # no config available
                print_no_cfg_warning
            fi
	fi
        #check for vdc directories. If they do not exist initialise them here
        if [ $MAX_ALLOWED_VDCS -gt 1 ]; then
            vdc_idx=2
            while [ $vdc_idx -le $MAX_ALLOWED_VDCS ]
            do
                boot_debug "Looking for vdc directory $MNT_CFG0_DIR/$VDC_PREFIX$vdc_idx"
                boot_debug "VDC_PREFIX = $VDC_PREFIX"
                if [ ! -d $MNT_CFG0_DIR/$VDC_PREFIX$vdc_idx ]; then
                    action "" echo "Reinitializing startup-config 0 for vdc $vdc_idx"
                    action "" $DESTROY 0 $vdc_idx
                    action "" echo "Reinitializing startup-config 1 for vdc $vdc_idx"
                    action "" $DESTROY 1 $vdc_idx
                fi
            vdc_idx=`expr $vdc_idx + 1`   #increment vdc_idx
            done
        fi
    
    fi

    sync
    sync
fi
#CSCth76245 Enable CTRL+C after doing filesystem operation.
trap 2
echo "check flash End - `date`" >> /tmp/boot_uptime.log
boot_debug "`date`::check-flash End"
echo ""
