# -*-Shell-script-*-
# 
# disk-functions: This file contains functions used xrnginstall  
#                 and panini/spirit to configure and access
#                 the 2nd pci block device/partition on a VM
#
# Update : 10/24/2018
#                   This script is extended to have regular disk functions
#                   that are used in pxe_install.sh and other bake scripts.               
#
# Copyright (c) 2014-2019 by Cisco Systems, Inc.
# All rights reserved.
#

/usr/bin/logger -p 0 -t udev  "(source: calvados/hostos_pkg/boot/scripts/Disk-functions) "

#Source function library
. /etc/init.d/spirit-functions

if [ -f /etc/init.d/spirit_pd.sh -a "$spirit_pd_sourced" != "true" ]; then
   . /etc/init.d/spirit_pd.sh
   spirit_pd_sourced=true
fi

readonly fs_sb_output=/tmp/fs_sb_output
readonly EXT2_FS_MAGIC_NUMBER=0xEF53

cmdline=$(cat /proc/cmdline)

PLATFORM=`echo $cmdline | sed 's/^.*platform=//' | cut -d" " -f1`
PLATFORM=$(override_platform_type ${PLATFORM}  $SIMULATION)
if [ "$PLATFORM" == "scapa" ]; then
    readonly DISK1_PV=ecu_disk1
else
    readonly DISK1_PV=pci_disk1
fi
readonly DISK1_LV=ssd_disk1_
readonly DISK1_LABEL=DISK_ONE

# Default size set for debug partition, 10M
readonly DEBUG_PART_SIZE_DEFAULT=10

# 5 sub-partitions: 1 for hostOS, 2 for Calvados VMs, 2 for XR VMs
# Note: The maximum length of a mkfs.ext4 volume label is 16 bytes.
#       When used (e.g., asr9k) Ensure "D1_XXXX_LV[X]_DISK1_LABEL" < 16
readonly D1_HOST_LV=hostos

D1_CVDS_LABEL_LV1=cd_1
D1_CVDS_LV1=calvados_1

D1_CVDS_LABEL_LV2=cd_2
D1_CVDS_LV2=calvados_2

readonly D1_XR_LV1=xr_1
readonly D1_XR_LV2=xr_2

declare -F pd_create_dummy_volumes >& /dev/null
  if [ $? -eq 0 ]; then
     readonly D1_NUM_LV=5
  else
     readonly D1_NUM_LV=3
  fi

function DFLOG {
    local msg=$1
    echo "$(date -R): $msg" >> /var/log/disk-functions.log
}
readonly -f DFLOG

#get_disk_by_ata_port returns sd[a|b] for the given ata port.
function get_disk_by_ata_port {
   local -a ata_path=($(find /sys/devices -name ata5))
   for i in ${ata_path[@]}; do
       local block=`find $i -name block`
       if [ -n "$block" ]; then
          local device=`ls $block`
          echo "${device}"
          return
       fi
   done
}

#get_disk_model returns device model code for given disk ($1)
function get_disk_model {
    local model=`smartctl -i /dev/$1 | grep "Device Model:" |sed -e 's/Device Model://' -e 's/^[ |\t]*//'`
    echo "${model}"
}

#Get the attribute id for attribute SSD Life Left for the given ssd model.
function get_ssd_life_left_id 
{
    local model="${1}"
    local id
    case "${model}" in
    "Micron P400m-MTFDDAK200MAN"|"Micron_M550_MTFDDAT256MAY")
       id=202
       ;; 
    "SMART SATA SHSLM32G3BCCTHD22"|"SMART iSATA SHSLM32GEBCITHD02")
       id=231
       ;;
    "KINGSTON SKC380S3120G")
       id=231
       ;;
    "UGBA1TPH32H0S2-PNN-CTF")
       id=231
       ;;
    *)
    #The following SSDs used in xr platforms does not support SSD Life Left:
    #ST96023AS(Seagate),STM00017A892(STEC)
       id=""
       ;;
    esac
    echo "${id}"
}

#First honor smartctl -H check result. If passed, further apply specific
#checks. List of such specific checks being conducted:
# - SSD Life Left 
#   If attribute SSD Life Left is supported, ensure its reading stands 
#   1% above vendor suggested threshold.
function check_disk_health
{
    local disk=/dev/$1
    local model="${2}"

    #smartctl return code with bit 3(1<<3), bit 2(1<<2) and bit1(1<<1)
    #corresponding to internal FAILSTATUS, FAILSMART and FAILDEV defs.
    #smartctl -H check fail in ata/scsi-smart aspects sets FAILSTATUS,
    #FAILSMART or FAILDEV respectively. For use case of smartctl -H in
    #our scripts check those three bits are good enough.
    local FAILURE_DEF=14

    smartctl -H ${disk} >/dev/null 2>&1
    rc=$?
    if (($rc & $FAILURE_DEF)); then         
       #Health check failed
       return 1
    else
       #Further check attribute SSD Life Left, if supported, to ensure
       #its reading stands 1% above the vendor suggested threshold. If
       #SSD Life Left by name exists in the attrbute list of smartctl,
       #take it. Otherwise, get it by its attr id per vendor's def.
       
       local attr
       attr=`smartctl -A ${disk} | grep  ".*SSD_Life_Left.*Pre-fail"`
       if [ -z "${attr}" ]; then
          local attr_id=$(get_ssd_life_left_id "${model}")
          if [ -n "$attr_id" ]; then
             attr=`smartctl -A ${disk} | grep  "${attr_id}.*Pre-fail"`
          fi
       fi
       if [ -n "${attr}" ]; then
          local result=`echo "${attr}" |awk '{print $4}'`
          local thresh=`echo "${attr}" |awk '{print $6}'`
          thresh=$(($thresh + 1))
          if [ -n "${result}" -a "${thresh}" -a $result -le $thresh ]; then
             return 1
          fi
       fi
       #If needed, apply other specific checks here
    fi
    return 0
}

#Check disks and call PD functions to report failures.
#Failures are classified as follows:
#Primary disk:
#   - Missing: fatal event
#   - Health check failure: h/w error event
#   - ATA failed: fatal event
#Other disks:
#   - All failures: h/w error event
#
#A disk which did not pass health check may still fully functional at 
#that moment but it can fail soon. No guarantee how long it can last. 
#Because of that, a health check failure will be reported as h/w err
#event, too.
#
#Upon reciving of a fatal event, PD usually does a reload to the card
#while an error event does not reload the card,thus keeping it in the 
#failed state for diagnosis.
function check_disks
{
    local disk_faiulre_reported

    # Make primary disk still available
    if [ ! -b /dev/$disk ]; then
        step_log_console "Primary disk /dev/$disk is missing."
        echo "$(date):Primary disk /dev/$disk is missing\n" >&107
        disk_faiulre_reported=true
        declare -F pd_notify_hw_fatal_event >/dev/null 2>&107 && \
                pd_notify_hw_fatal_event "Primary disk is missing."
    else
        # Further check its health
        check_disk_health $disk "$disk_model"
        if [ $? -ne 0 ]; then
            step_log_console "Primary disk /dev/$disk health check failed"
            echo "$(date):Primary disk /dev/$disk health check failed.\n" >&107
            disk_faiulre_reported=true
            smartctl -a /dev/$disk >&107 2>&1
            declare -F pd_notify_hw_error_event >/dev/null 2>&107 && \
                pd_notify_hw_error_event "Primary disk health check failed, impending drive failure expected. SAVE ALL DATA."
        fi
    fi
    # Make sure secondary disk exists if it is supposed to be
    if [ ! -b /dev/$second_disk ]; then
        declare -F pd_platform_has_second_disk >/dev/null 2>&107 && \
                pd_platform_has_second_disk
        if [ $? -eq 0 ]; then
            step_log_console "Secondary disk /dev/$second_disk is missing."
            echo "$(date):Secondary disk /dev/$second_disk is missing.\n" >&107
            disk_faiulre_reported=true
            declare -F pd_notify_hw_error_event >/dev/null 2>&107 && \
                    pd_notify_hw_error_event "Secondary disk is missing."
        fi
    else
        # Further check its health
        check_disk_health $second_disk "$second_disk_model"
        if [ $? -ne 0 ]; then
            step_log_console "Secondary disk /dev/$seond_disk health check failed"
            echo "$(date):Secondary disk /dev/$second_disk health check failed.\n" >&107
            disk_faiulre_reported=true
            smartctl -a /dev/$second_disk >&107 2>&1
            declare -F pd_notify_hw_error_event >/dev/null 2>&107 && \
                pd_notify_hw_error_event "Secondary disk health check failed, impending drive failure expected. SAVE ALL DATA."
        fi
    fi

    #Report and log ata errors if observed. Considering same messages can
    #be repeatedly observed in dmesg buffer, log them only ONCE and limit
    #report to 3 times.
    local error=$(dmesg | grep ".* ata.*reset failed, giving up")
    if [ -n "${error}" ]; then
       if [ $ata_error_report_count -lt 3 -a "$disk_failure_reported" != "true" ]; then
          local ata_port=`echo "${error}"|sed -e "s/^.*\(ata[0-9]*\).*$/\1/"`
          local ata_disk=$(get_disk_by_ata_port "${ata_port}")
          if [ "$ata_disk" == "$disk" ]; then
               ata_disk="Primary"
          elif [ "${ata_disk}" == "${second_disk}" ]; then
               ata_disk="Secondary"
          else 
               #if not sda/sdb
               ata_disk="Tertiary"
          fi
          step_log_console "${ata_disk} disk ATA failed"
          echo "$(date):${ata_disk} disk ATA failed." >&107
          if [ "${ata_disk}" == "Primary" ]; then
             declare -F pd_notify_hw_fatal_event >/dev/null 2>&107 && \
                pd_notify_hw_fatal_event "${ata_disk} disk failed."
          else
             declare -F pd_notify_hw_error_event >/dev/null 2>&107 && \
                pd_notify_hw_error_event "${ata_disk} disk failed."
          fi
          ata_error_report_count=$(($ata_error_report_count + 1))
       fi
 
       if [ "$ata_error_logged" != "true" ]; then
          echo "$(date):logging ata messages:" >&107
          dmesg|grep " ata" >&107
          ata_error_logged=true
       fi
    fi

    sync
}

# Check/repair filesystem.
# Args: $1-storage device name, $2-mount point
# Return: (error code returned by fsck)
function check_repair_fs {
    local dev=$1
    local mnt=$2
    local status=0

    echo "$FUNCNAME $dev $mnt called at $(date)" >&107

    DFLOG "Checking filesystem in $dev $mnt ..."
    #abort check if partition is already mounted
    local mount=`mount | grep "$dev"`
    if [ ! -z "$mount" ]; then
        DFLOG "Aborting fs check. Device $dev is mounted."
        # equivalent to fsck error code (8) for operational error
        return 8
    fi

    fsck -fy $dev >&107 2>&1
    status=$?
    if [ $status -eq 0 ]; then
        DFLOG "No errors found"
    fi
    if [ $status -eq 1 ]; then
        DFLOG "Errors were found and corrected"
    fi
    if [ $status -gt 1 ]; then
        DFLOG "Error encountered"
    fi
    /sbin/tune2fs -c 0 -i 0 $dev >&107 2>&1
    return $status
}
readonly -f check_repair_fs

function check_fs_sb {
    local return_code=0
    local fs_mn=0
    local part=${1}

    dumpe2fs -h ${part}  > $fs_sb_output 2>&1
    if (( $? != 0 )); then
        # This can happen when baking for the first time
        echo "check_fs_sb: dumpe2fs for ${part} returned with error"  >&107 2>&1
        cat $fs_sb_output >&107 2>&1
        return_code=1
    else
        fs_mn=$(grep "magic number" $fs_sb_output | awk '{print $4}')
        if (( $fs_mn != $EXT2_FS_MAGIC_NUMBER )); then
            echo "check_fs_sb: magic number for ${part} not found" >&107 2>&1
            cat $fs_sb_output >&107 2>&1
            return_code=2
        fi
    fi

    return $return_code
}
readonly -f check_fs_sb

function format_partition {
    local dev_name=${1} label=${2}
    local caller="$(ps -o comm= $PPID)"

    DFLOG "$FUNCNAME:format partition dev [$dev_name] label [$label] requested by $caller"
    DFLOG "$FUNCNAME:$(file $dev_name)"

    # Reformat partition with an ext4 file system
    if [ "$PLATFORM" == "ncs1001" ]; then
        /sbin/mkfs.ext4 -L ${label} -b 4096 -O ^huge_file -vv ${dev_name} >&107 2>&1
        ret=$?
        if [ $ret -eq 0 ]; then
            /sbin/tune2fs -c 0 -i 0 ${dev_name}  >&107 2>&1
        fi
    else
        /sbin/mkfs.ext4 -L ${label} -b 4096 -O ^huge_file -vv ${dev_name} >&107 2>&1
        ret=$?
        if [ $ret -eq 0 ]; then
            /sbin/tune2fs -c 0 -i 0 ${dev_name} >&107 2>&1
        fi
    fi
    sync
}
readonly -f format_partition

function format_partition_ext2 {
    local dev_name=${1} label=${2}
    local caller="$(ps -o comm= $PPID)"

    DFLOG "$FUNCNAME:format partition dev [$dev_name] label [$label] requested by $caller"
    DFLOG "$FUNCNAME:$(file $dev_name)"

    /sbin/mkfs.ext2 -L ${label} -b 4096 -O ^huge_file -vv ${dev_name} >&107 2>&1
    ret=$?
    if [ $ret -eq 0 ]; then
        /sbin/tune2fs -c 0 -i 0 ${dev_name} >&107 2>&1
    fi
    sync
}
readonly -f format_partition_ext2
# Format disk1 of calvados
function format_calvados_partition {
    local dev_name=/dev/mapper/${DISK1_PV}-${DISK1_LV}${D1_CVDS_LV1}
    local label=${DISK1_LABEL}

    # PI team to review and enable
    # if [[ $VIRT_METHOD == "lxc" ]]; then
    #    label = "${D1_CVDS_LABEL_LV1}_${DISK1_LABEL}"
    # fi
    # Reformat partition with an ext4 file system
    /sbin/mkfs.ext4 -L ${label} -b 4096 -O ^huge_file -vv ${dev_name} >&107 2>&1
    ret=$?
    if [ $ret -eq 0 ]; then
        /sbin/tune2fs -c 0 -i 0 ${dev_name} >&107 2>&1
    fi
    sync
}
readonly -f format_calvados_partition

function check_fs_partition {
    local dev_name=${1} label=${2}

    check_fs_sb ${dev_name}
    # Even though super block is EXT4, redo mkfs.
    # The Partition label may have changed

    format_partition ${dev_name} ${label}
}

function check_fs_partition_ext2 {
    local dev_name=${1} label=${2}

    check_fs_sb ${dev_name}
    # Even though super block is EXT4, redo mkfs.
    # The Partition label may have changed
    format_partition_ext2 ${dev_name} ${label}
}
readonly -f check_fs_partition_ext2
# Get size of the disk, in MB
# Parameter: disk (ex: /dev/sda)
# Return: $DISK_SIZE
function get_disk_size {
    local dev=${1}

    #
    # Handle optional disks
    #
    if [ ! -b $dev ]
    then
        let "DISK_SIZE=0"
        return
    fi

    max=$(fdisk -l ${dev} 2>&107 | grep "Disk ${dev}:"  | cut -d ',' -f2)
    max=${max%bytes}
    let "DISK_SIZE=$max/1000000"
}

function provision_disk_one {
  local args=$1
  local logvol_size
  local total_disk_size
  declare -a pdisks=($@)
  static_part=${STATIC_SEC_DISK_PARTITION[@]}
  # check for multiple disks
  local gotone

  for i in "${pdisks[@]}"
  do
      gotone=1

      secondary_disks="${secondary_disks} /dev/$i"
      dev=/dev/$i

      if [ ! -b "${dev}" ]; then
        return
      fi
      step_log_console "Partitioning PCI block device $dev"

      # Check if it is a PCI device
      local pci_disk_check=$(udevadm info -q path -n ${dev} 2>&107 \
                             | grep pci | grep -v usb)

      if [ -z "$pci_disk_check" ]; then
         echo "Not a pci/usb block device ${dev}"
         return
      fi

      #Is volume group name same as desired
      OLD_DISK1_PV=$(pvdisplay ${dev} 2>&107 | grep "VG Name" | awk '{print $3}')
      if [[ "${OLD_DISK1_PV}" == "${DISK1_PV}" ]]; then
          # If volume group name is as expected, check the number of 
          # LVs in this VG. And check if the name of the calvados
          # volume matches the expected name (calvados_1). 

          cnt=$(lvscan 2>&107 | grep -c ${DISK1_PV}\/${DISK1_LV})
          if [[ ${cnt} == ${D1_NUM_LV} ]]; then
               #Volume count matches remove any stale xr_data_lv in pci_disk
               lvremove -f /dev/pci_disk1/xr_data_lv* >> /tmp/log 2>&1 
              # Volume count matches, check if the volume name matches 
              cnt=$(lvscan 2>&107 | grep ${D1_CVDS_LV1} | wc -l)
              if [[ ${cnt} == 1 ]]; then
                check_fs_secondary_vols "${DISK1_PV}" "${dev}"
                ret=$?

                if [ "${ret}" == 0 ]; then
                    step_log_console "Retaining Volume Group ${DISK1_PV}"
                    return
                else
                    step_log_console "Removing Volume Group ${DISK1_PV}"
                fi
              fi
          fi
          declare -F pd_remove_tpa_volume >& /dev/null
          if [ $? -eq 0 ]; then
            # PD remove app hosting lv
            pd_remove_tpa_volume ${DISK1_PV}
          fi
          LOG_PV1=$(pvdisplay ${dev} 2>&107 )
          step_log_console "PV display : ${LOG_PV1}"
          LOG_LV1=$(lvscan 2>&107 )
          step_log_console "LV scan : ${LOG_LV1}"
          step_log_console "Removing Volume Group ${DISK1_PV}"
          vgremove -f ${DISK1_PV}  >&107 2>&1
          pvremove -ff -y ${dev} >&107 2>&1
      else
          if [ "$PLATFORM" == "scapa" -a \
                "${OLD_DISK1_PV}" == "pci_disk1" ]; then
              #Do we have same number of logical volumes
              cnt=$(lvscan 2>&107 | grep ${DISK1_LV} | wc -l)
              if [[ ${cnt} == ${D1_NUM_LV} ]]; then
                  #Rename the volumes group name ! need active here ?
                  vgrename -v /dev/pci_disk1 /dev/ecu_disk1
                  return
              fi
	      /usr/bin/logger -p 0 -t udev "ecu : mismatch in number of logical volumes: ${cnt} to ${D1_NUM_LV}"
          fi
          LOG_PV1=$(pvdisplay ${dev} 2>&107 )
          step_log_console "PV display: ${LOG_PV1}"
          LOG_LV1=$(lvscan 2>&107 )
          step_log_console "LV scan: ${LOG_LV1}"

          #Remove the physical volume on the device
          step_log_console "Removing Volume Group ${DISK1_PV} due to mis-match"
          vgremove -f ${OLD_DISK1_PV} >&107 2>&1
          pvremove -ff -y ${dev} >&107 2>&1
      fi
      get_disk_size ${dev}
      let total_disk_size=$total_disk_size+DISK_SIZE
  done

  if [ "$gotone" = "" ]
  then
    return
  fi

  # Remove any stale disk one volume groups on devices
  # other than secondary disk for Compute cards on NCS6k
  declare -F pd_remove_stale_disk_one_vg >/dev/null 2>&1
  if [ $? -eq 0 ]; then
     pd_remove_stale_disk_one_vg ${BOARDTYPE} ${DISK1_PV} ${secondary_disks} 
  fi

  #Remove recovery related leftover volumes
  declare -F pd_remove_recovery_disk_loop_volumes >/dev/null 2>&1
  if [ $? -eq 0 ]; then
     step_log_console "Removing recovery disk loop volumes"
     pd_remove_recovery_disk_loop_volumes "/dev/${SECONDARY_DISK}" 
  fi

  if [[ "$PLATFORM" == "asr9k" ]]; then
  /bin/dd if=/dev/zero of=${dev} bs=1024 count=10000 >&107 2>&1
  else
  secondary_disks=$(echo "${secondary_disks}" | sed -e 's/^[ \t]*//')
  /bin/dd if=/dev/zero of=${secondary_disks[0]} bs=1024 count=10000 >&107 2>&1
  fi
  pvcreate -ff -y ${secondary_disks} >&107 2>&1
  vgcreate -f -y ${DISK1_PV} ${secondary_disks} >&107 2>&1

  #Logical volume for Host
  let logvol_size=$total_disk_size*${DISK_SSD_HOST_SIZE}/100
  lvcreate -L ${logvol_size} -n ${DISK1_LV}${D1_HOST_LV} ${DISK1_PV} >&107 2>&1
  check_fs_partition "/dev/mapper/${DISK1_PV}-${DISK1_LV}${D1_HOST_LV}" \
                     "${D1_HOST_LV}_${DISK1_LABEL}"

  let cal_logvol_size=$total_disk_size*${DISK_SSD_CALVADOS_SIZE}/100
  let xr_logvol_size=$total_disk_size*${DISK_SSD_XR_SIZE}/100

  if [[ $VIRT_METHOD == "lxc" ]] || [[ $PLATFORM == "asr9k" ]]; then
    #Logical volume for Calvados VM1/2
    lvcreate -L ${cal_logvol_size} -n ${DISK1_LV}${D1_CVDS_LV1} ${DISK1_PV} >&107 2>&1 
    check_fs_partition "/dev/mapper/${DISK1_PV}-${DISK1_LV}${D1_CVDS_LV1}" \
                       "${D1_CVDS_LABEL_LV1}_${DISK1_LABEL}"
  
  
   # lvcreate -L ${cal_logvol_size} -n ${DISK1_LV}${D1_CVDS_LV2} ${DISK1_PV} >&107 2>&1
    #check_fs_partition "/dev/mapper/${DISK1_PV}-${DISK1_LV}${D1_CVDS_LV2}" \
     #                  "${D1_CVDS_LABEL_LV2}_${DISK1_LABEL}"

    #Logical volume for XR VM1/2
    if [ ! -z "$static_part" ]; then
    lvcreate -L ${xr_logvol_size} -n ${DISK1_LV}${D1_XR_LV1} ${DISK1_PV} >&107 2>&1
    check_fs_partition "/dev/mapper/${DISK1_PV}-${DISK1_LV}${D1_XR_LV1}" \
                       "${D1_XR_LV1}_${DISK1_LABEL}"

    #lvcreate -L ${xr_logvol_size} -n ${DISK1_LV}${D1_XR_LV2} ${DISK1_PV} >&107 2>&1
    #check_fs_partition "/dev/mapper/${DISK1_PV}-${DISK1_LV}${D1_XR_LV2}" \
     #                  "${D1_XR_LV2}_${DISK1_LABEL}"
    fi
    declare -F pd_create_tpa_volume >& /dev/null
    if [ $? -eq 0 ]; then
        # asr9k creates app hosting lv
        pd_create_tpa_volume ${DISK1_PV}
    fi
  else
    #Logical volume for Calvados VM1/2
    lvcreate -L ${cal_logvol_size} -n ${DISK1_LV}${D1_CVDS_LV1} ${DISK1_PV} >&107 2>&1

    check_fs_partition "/dev/mapper/${DISK1_PV}-${DISK1_LV}${D1_CVDS_LV1}" \
                       "${DISK1_LABEL}"

  declare -F pd_create_dummy_volumes >& /dev/null
  if [ $? -eq 0 ]; then
    #creating two dummy volumes for ncs6k and ncs4k to make vol count to 5 to support 61x to 524 downgrade 
    pd_create_dummy_volumes ${DISK1_PV}
  fi
    
    #lvcreate -L ${cal_logvol_size} -n ${DISK1_LV}${D1_CVDS_LV2} ${DISK1_PV} >&107 2>&1
    #check_fs_partition "/dev/mapper/${DISK1_PV}-${DISK1_LV}${D1_CVDS_LV2}" \
     #                  "${DISK1_LABEL}"

    #Logical volume for XR VM1/2
    if [ ! -z "$static_part" ]; then
    lvcreate -L ${xr_logvol_size} -n ${DISK1_LV}${D1_XR_LV1} ${DISK1_PV} >&107 2>&1

    check_fs_partition "/dev/mapper/${DISK1_PV}-${DISK1_LV}${D1_XR_LV1}" \
                       "${DISK1_LABEL}"

   # lvcreate -L ${xr_logvol_size} -n ${DISK1_LV}${D1_XR_LV2} ${DISK1_PV} >&107 2>&1
   # check_fs_partition "/dev/mapper/${DISK1_PV}-${DISK1_LV}${D1_XR_LV2}" \
    #                   "${DISK1_LABEL}"
    fi

    # Create 18+ GB Install repository in disk1 as LV for panini platform
    if [ "$BOARDTYPE" == "RP" -o "$BOARDTYPE" == "CC" ] && [[ "$SIMULATION" == 0 ]]; then
        declare -F pd_create_install_repo_in_disk >&107 2>&1
        if [ $? -eq 0 ]
        then
            pd_create_install_repo_in_disk
        fi
    fi

  fi
}

# Run a soft filesystem check on each of the secondary disk volumes to check for
# filesystem corruption through bad sectors, superblocks etc.
# Failing this check, these volumes will need to be re-partitioned and re-formatted.
function check_fs_secondary_vols {
    local disk1_pv=${1}
    local dev=${2}
    local retval=0
    local is_ssd_local=0

    declare -F pd_check_fs_secondary_vols >&107 2>&1
    if [ $? -eq 0 ]; then
        # filesystem check DISK1_LV LVs
        pd_check_fs_secondary_vols ${1} ${DISK1_LV}
        return $?
    fi

    declare -F pd_check_for_secondary_vols_resize >&107 2>&1
    if [ $? -eq 0 ]; then
        # Check for DISK1_LV change in sizes
        pd_check_for_secondary_vols_resize ${dev}
        if [ $? -ne 0 ]; then
            step_log_console "Secondary volumes need to be resized"
            return 1
        fi
    fi

    # Currently this check is in place only for platforms that have their main disk
    # hosting secondary disk volumes since recovering such a partition on a live
    # system is non-trivial.
    for _pv in `pvdisplay | awk '/PV Name.*dev.sda/{print $3}'`; do
        # If there is an existing PV on disk(sda) hosting secondary disk volumes,
        local vg_name=`pvdisplay $_pv | awk '/VG Name/{print $3}' | grep $disk1_pv`
        if [ -n "${vg_name}" ]; then
           is_ssd_local=1 
           break
        fi
    done

    if [ "${is_ssd_local}" == 0 ]; then
        step_log_file "Secondary disk fs check is only for platforms that host secondary disk volumes on the main disk"
        return $retval
    fi
    
    lvchange -a y /dev/${disk1_pv} >&107 2>&1
    ssd_lvnames=`lvdisplay ${disk1_pv} | grep "LV Path" | awk '{print $3}'`
    for lv in ${ssd_lvnames[@]}; do
        check_fs_sb $lv
        retval=$?
        if [ "${retval}" != 0 ]; then
            step_log_console "Filesystem for $lv is corrupt!!"
            step_log_console "Need to re-format ${DISK1_PV} volumes"
            break
        fi
    done
    lvchange -a n /dev/${disk1_pv} >&107 2>&1 
    step_log_console "Final return val $retval  ...."
    return $retval
}

function activate_disk_one_vg {
    modprobe dm-mod
    disk1_pv=($(pvscan | grep ${DISK1_PV} | awk '{print $4}'))
    if [ "${disk1_pv}" == "${DISK1_PV}" ]; then
        lvchange -a y /dev/${DISK1_PV} >&107 2>&1
    fi
}

# Mount a filesystem by label. Before its mounting, run fsck to fix corrutpion
# if found.
function mount_fs_label {
    local label=${1}
    local dir=${2}
    local journalled=${3}
    local dev="$(blkid -L $label)"
    local caller="$(ps -o comm= $PPID)"

    DFLOG "mounting fs label $label on $dir requested by $caller"
    if [ -b "$dev" ]; then
       DFLOG "$(blkid $dev)"
    else
       DFLOG "No filesystem labeled $label is present"
    fi
    echo "$(date) mount ${label} ${dir}" >&107 2>&1
    check_repair_fs ${dev} ${dir}
    if [ ! -d ${dir} ]; then
       mkdir -p ${dir}
    fi
    if [ "${journalled}" = "true" ]; then
        mount -o discard,noatime,data=journal -L ${label} ${dir} >&107 2>&1
    else
        mount -o discard,noatime -L ${label} ${dir} >&107 2>&1
    fi
    if [ $? -ne 0 ]; then
        DFLOG "Mounting failed"
    fi
}                                    

function mount_disk_one {
    local mount_dir=${1}
    local label=${DISK1_LABEL}
    local install=$(cat /proc/cmdline | grep install=)
   
    if [ -n "${install}" ]; then
        return
    fi

    # Activate volume group on disk1
    activate_disk_one_vg >&107 2>&1 

    local vm_type=`cat /proc/cmdline | grep vmtype=`
    if [ -z "${vm_type}" ] || [[ "${vm_type}" =~ "hostos" ]]; then
        label=${D1_HOST_LV}_${DISK1_LABEL}
    fi
    if [[ $VIRT_METHOD == "lxc" ]] || [[ $PLATFORM == "asr9k" ]]; then
        if [ -z "${vm_type}" ] || [[ "${vm_type}" =~ "sysadmin-vm" ]]; then
            label=${D1_CVDS_LABEL_LV1}_${DISK1_LABEL}
        fi
        if [ -z "${vm_type}" ] || [[ "${vm_type}" =~ "xr-vm" ]]; then
            label=${D1_XR_LV1}_${DISK1_LABEL}
        fi
        # TBD: When are V2 labels to be used?
    fi

    # Loop through each of the block-device and mount the filesystem
    # that was labeled "DISK_ONE" during install.

    for device in `find /dev/ -xdev -type b`; do
        out=$(dumpe2fs -h ${device} 2>&107 | grep "Filesystem volume name:" | \
              awk '{print $4}')
        if [ "${out}" == "${label}" ]; then
            mkdir -p ${mount_dir} >&107 2>&1
            fsck -fy ${device} >&107 2>&1
            /sbin/tune2fs -c 0 -i 0 ${device} >&107 2>&1
            mount -o discard,noatime ${device} ${mount_dir} >&107 2>&1
            # somewhere may have mounted the device to RDONLY 
            # mount the device to RDONLY, then remount path to RW
            if [ $? -ne 0 ]; then
                mount -o ro,discard ${device} ${mount_dir} >&107 2>&1
                if [ $? -ne 0 ]; then
                    echo "Mount ${device} at ${mount_dir} as RDONLY failed"
                    return
                fi
                mount -o remount,rw,discard,noatime ${mount_dir} >&107 2>&1
                if [ $? -ne 0 ]; then
                    echo "Re-mount ${mount_dir} as Read/Write failed"
                    return
                fi
            fi
            echo "Mount ${device} at ${mount_dir}"
            if  [[ $PLATFORM == "panini" ]] && [[ "${vm_type}" =~ "hostos" ]]; then
                 mkdir ${mount_dir}/dumper
            fi 
            return
        fi
    done
}


function remove_old_volumes {

  # function copied from http://grox.net/sysadm/unix/nuke.lvm
  # adapted for spirit
  # Remove volumes on /dev/sda and /dev/sdb with the name panini*
  # of pci*

  declare -F pd_remove_old_volumes >&107 2>&1
  if [ $? -eq 0 ]; then
    # Remove non-DISK1_LV LVs
    pd_remove_old_volumes ${DISK1_LV} ${DISK1_PV}
    return
  fi

  step_log_console "Inside Volume-Cleaning Function"
  /usr/bin/logger -p 0 -t udev "ecu : Inside Volume-Cleaning Function"
  # remove existings lvm configs for for panini_vol_grp
  for _vol in `lvdisplay | awk '/LV Path/{print $3}' | awk '/panini_vol_grp/{print $1}'`; do
    umount -f $_vol >> /tmp/log 2>&1
    lvchange -an $_vol >&107 2>&1
    yes | lvremove -f $_vol >&107 2>&1
    step_log_console "Removed LVM ${_vol} for Panini"
  done

 # remove existings lvm configs for for app_vol_grp
  for _vol in `lvdisplay | awk '/LV Path/{print $3}' | awk '/app_vol_grp/{print $1}'`; do
    umount -f $_vol >> /tmp/log 2>&1
    lvchange -an $_vol >&107 2>&1
    yes | lvremove -f $_vol >&107 2>&1
    step_log_console "Removed LVM ${_vol} for App-Host"
  done

 # removing app-vol-groups
  for _vol in `vgdisplay | awk '/VG Name/{print $3}' | awk '/app_vol_grp/{print $1}'`; do
    vgchange -an $_vol >&107 2>&1
    yes | vgremove -f $_vol >&107 2>&1
    step_log_console "Removed App-Vol Grp ${_vol}"
  done

  for _vol in `vgdisplay | awk '/VG Name/{print $3}' | awk '/panini_vol_grp/{print $1}'`; do
    vgchange -an $_vol >&107 2>&1
    yes | vgremove -f $_vol >&107 2>&1
    step_log_console "Removed Panini Vol-Grp ${_vol}"
  done

  # last step didn't get 'em all...
  for _vol in /dev/mapper/panini*; do
    if [ -b "$_vol" ]; then
      dd if=/dev/zero of=$_vol bs=512 count=12 >&107 2>&1
      step_log_console "Formatted Panini volume ${_vol}"
    fi
  done


  # Formatting App-Volume Groups
  # last step didn't get 'em all...
  for _vol in /dev/mapper/app* ; do
    if [ -b "$_vol" ]; then
        dd if=/dev/zero of=$_vol bs=512 count=12 >&107 2>&1
        step_log_console "Formatted App-Volume ${_vol}"
    fi
  done

  for _pv in `pvdisplay | awk '/PV Name.*dev.sda/{print $3}'`; do
    # If there is an existing PV on disk(sda) hosting secondary disk volumes,
    # delete ONLY non disk1 volumes under it.
    local vg_name=`pvdisplay $_pv | awk '/VG Name/{print $3}' | grep $DISK1_PV`
    if [ -z $vg_name ] || [ "${BOARDTYPE}" != "RP" -a "${BOARDTYPE}" != "CC" ]; then
        yes | pvremove -ff -y $_pv >&107 2>&1
    else
        for _vol in `lvdisplay ${vg_name} | awk '/LV Path/{print $3}' | grep -v ${DISK1_LV}`; do
            umount -f $_vol >> /tmp/log 2>&1
            lvchange -an $_vol >&107 2>&1
            yes | lvremove -f $_vol >&107 2>&1
        done
    fi
  done

  # just in case some were missed... (some always are)
  for _pv in $disks; do
    yes | pvremove -ff -y $_pv >&107 2>&1
    dd if=/dev/zero of=$_pv bs=512 count=255 >&107 2>&1
  done

  step_log_console "Removed PV"

  # see what else the system still knows about
  # and get rid of them, too.
  # note that we ignore 'sd*' partitions and that this
  # assumes that we don't need dm-? for the system
  # that we're running on. i know, big assumption.
  #
  for _part in `awk '/dm-/{print $4}' /proc/partitions`; do
    yes | pvremove -ff -y $_part >&107 2>&1
    dd if=/dev/zero of=$_part bs=512 count=255 >&107 2>&1
  done
  step_log_console "Exiting from the Volume Cleaning Section"

}

function check_disk_one_space {
  local dev=/dev/${1}
  local dsize=0

  if [ ! -b "${dev}" ]; then
    return 0
  fi
  echo "Checking PCI block device $dev disk space"

  # Check if it is a PCI device
  local pci_disk_check=$(udevadm info -q path -n ${dev} 2>&107 \
                         | grep pci | grep -v usb)

  if [ ! -z "${pci_disk_check}" ]; then
    # find disk one volume group name
    DISK1PV=$(pvdisplay ${dev} 2>&107 | grep "VG Name" | awk '{print $3}')

    if [[ "${DISK1PV}"="ecu_disk1" || "${DISK1PV}"="pci_disk1" ]]; then
      local label=${DISK1PV}-${DISK1_LV}${D1_CVDS_LV1}
      local device=/dev/mapper/$label

      #Do we have same number of logical volumes
      cnt=$(lvscan 2>&107 | grep ${DISK1_LV} | wc -l)
      if [[ ${cnt} == "${D1_NUM_LV}" ]]; then
        # Activate volume group on disk1
        activate_disk_one_vg

        # mount calvados-1 partition to check disk space
        DISK1MNT=$(mktemp -d /tmp/disk1dev.XXXXXX)
        mount -o ro,noload ${device} ${DISK1MNT} 2>&107 || return 1

        dsize=$(df -Pk ${DISK1MNT} | tail -1 | awk {'print $4'})
        echo "PCI block device ${dev} free space: ${dsize}K"

        # unmount ISO, we no longer need it
        [ -d "${DISK1MNT}" ] && umount ${DISK1MNT} && rmdir ${DISK1MNT}
        if [ "${dsize}" -gt 2000000 ]; then
          return 0
        else
          return 1
        fi
      fi
    fi
  fi
  /usr/bin/logger -p 0 -t udev "ecu : disk-functions : check_disk_one_space - this disk need partition properly, continue install"
  # this disk need partition properly, continue install.
  return 0
}

function pxe_install_second_disk_pre_check {
    # check disk space, need at least 2G disk space for install image for pxe boot
    if [ ! -z ${SIMULATION} ]; then
      check_disk_one_space "${second_disk}${1}"
      if [ $? -eq 1 ]; then
        pxeflag=1
	/usr/bin/logger -p 0 -t udev "ecu : disk-functions : pxe_install_second_disk_pre_check - There is not enough disk space in /misc/disk1 to copy internal PXE boot image"
        echo "There is not enough disk space in /misc/disk1 to copy internal PXE boot image."
      fi

      while [ -n "${pxeflag}" ]; do
        echo "Choose an option :"
        echo "1). Format /misc/disk1, and continue install"
        echo "2). Abort install"
        printf "option [1/2]? "
        read answers123

        if [ "${answers123}" = "1" -o "${answers123}" = "2" ]; then
          if [ "${answers123}" = "1" ]; then
            printf "Option 1 is selected. Existing files on /misc/disk1 will be lost.  Continue? [y/n] "
          elif [ "${answers123}" = "2" ]; then
            printf "Option 2 is selected. Installation will be terminated.  Confirm? [y/n] "
          fi

          read answers

          if [ "${answers}" = "y" ]; then
            if [ "${answers123}" -eq 1 ]; then
              format_calvados_partition
              echo "format disk1 passed to sysadmin VM"
            /usr/bin/logger -p 0 -t udev "ecu : disk-functions : pxe_install_second_disk_pre_check - format disk1 passed to sysadmin VM"  
	    break
            elif [ "${answers123}" -eq 2 ]; then
              echo "Installation terminated.  Please clean up /misc/disk1 and rerun install."
	      /usr/bin/logger -p 0 -t udev "ecu : disk-functions : pxe_install_second_disk_pre_check - Installation terminated.  Please clean up /misc/disk1 and rerun install."
              call_reboot
              exit
            fi
          fi
        fi
      done
    fi
}


function reformat_partition {
    local dev_name=${1}

    # Reformat partition with an ext4 file system
    if [ "$PLATFORM" == "ncs1001" ]; then
        /sbin/mkfs.ext4 -b 4096 -O ^huge_file -vv ${dev_name}
        /sbin/tune2fs -c 0 -i 0 ${dev_name}
    else
        /sbin/mkfs.ext4 -b 4096 -O ^huge_file -vv ${dev_name} >&107 2>&1
        /sbin/tune2fs -c 0 -i 0 ${dev_name} >&107 2>&1
    fi
    sync
}
readonly -f reformat_partition

# Get debug partition (dp) offset and size
function get_dp_offset {
    local dev=${1}
    max=$(fdisk -l ${dev} 2>/dev/null | grep "Disk /dev"  | cut -d ',' -f2)
    max=${max%bytes}
    max=$(($max / 1000000))
    startm=$(($max - 10))
    startb=$(($startm * 1000000))
    dpstarts=$(($startb / 512))
    endb=$(($max * 1000000))
    dpends=$(($endb / 512))
    if [ $(($startm % 512)) -ne 0 ]; then
       dpstarts=$(($dpstarts + 1))
    fi
    dpdiffs=$(($dpends - $dpstarts + 1))
    dpoffset=$(($dpstarts * 512))
    dpsizeb=$(($dpdiffs * 512))
}
# Mount dp to /tmp/bakelog. If dp does not exist, create dp.
function prepare_dploop {
    local dev=${1}
    local src=${2}
    mkdir -p ${LOGFLOWDIR}.sav
    rm -rf ${LOGFLOWDIR}.sav/*
    cp -rf ${LOGFLOWDIR}/* ${LOGFLOWDIR}.sav/ >&107 2>&1
    cp -f ${LOGDIR}/${LOGFILE0} ${LOGFLOWDIR}.sav/ >&107 2>&1
    cp -f ${LOGDIR2}/${LOGFILE} ${LOGFLOWDIR}.sav/ >&107 2>&1
    rm -rf ${LOGFLOWDIR}/*
    dploop=$(losetup --find)
    losetup --offset $dpoffset --sizelimit $dpsizeb ${dploop} ${dev}
    local label=`blkid ${dploop} | grep "debug" | grep "ext4"`
    if [ -z "$label" ]; then
       if [ -z "$src" ]; then
          check_fs_partition ${dploop} "debug"
       else
          losetup -d ${dploop} >&107 2>&1
          return 1 
       fi
    fi
    mount -o discard,noatime ${dploop} ${LOGFLOWDIR} >&107 2>&1
    if [ $? -eq 0 -a -z "$src" ]; then
       avail=$(df -k | grep ${dploop} |awk '{print $4}')
       if [ "$avail" -lt 1536 ]; then
          umount ${LOGFLOWDIR} >/dev/null 2>&1
          check_fs_partition ${dploop} "debug"
          mount -o discard,noatime  ${dploop} ${LOGFLOWDIR} >&107 2>&1
       fi
    fi
    if [ $? -ne 0 ]; then
       umount ${LOGFLOWDIR} >/dev/null 2>&1
       losetup -d ${dploop} >&107 2>&1
       cp -rf ${LOGFLOWDIR}.sav/* ${LOGFLOWDIR}/ >&107 2>&1 
       rm -rf ${LOGFLOWDIR}.sav 
       return 1
    fi
    if [ -z "$src" ]; then
       avail=$(df -k | grep ${dploop} |awk '{print $4}')
       if [ "$avail" -lt 1536 ]; then
          umount ${LOGFLOWDIR} >/dev/null 2>&1
          losetup -d ${dploop} >&107 2>&1
          cp -rf ${LOGFLOWDIR}.sav/* ${LOGFLOWDIR}/ >&107 2>&1
          rm -rf ${LOGFLOWDIR}.sav
          return 1
       fi
    fi

    cp -rf ${LOGFLOWDIR}.sav/* ${LOGFLOWDIR}/ >&107 2>&1 
    rm -rf ${LOGFLOWDIR}.sav 
    sync
    return 0
}

# Fix ported from CSCvi96682
function mount_install_repo {
    local label=$1
    local dir=$2

    local dev=$(blkid -L $label)

    # Check if journaling is present. if not, create it
    tune2fs -l ${dev} | grep -q "has_journal"
    if [ $? -ne 0 ]; then
        tune2fs -j ${dev}
    fi

    # Mount the repo
    mount_fs_label ${label} ${dir}

    # Clean un-mount to finalize the FS
    umount ${dir}

    # Disable journaling to delete Journal entries
    tune2fs -O ^has_journal ${dev}

    check_repair_fs ${dev} ${dir}

    # Enable journaling
    tune2fs -j ${dev}

    # Mount the repo
    mount_fs_label ${label} ${dir}
}
# This function gets the real device name(s) from the given symlink(s)
# example: /dev/xrmdisk-->sda input:xrmdisk output:sda
function get_disk_devices
{
   local -a sym_devices=("$@")
   local devices=""
   local disk=""
   for disk in ${sym_devices[@]}; do
      devices="${devices} $(basename $(readlink -f /dev/${disk}))"
   done
   echo ${devices}
}
readonly -f get_disk_devices

function create_sub_part_file_disk_boot {
echo "

n
p
1


w" > /tmp/fdisk_repo.input
echo "

n
p
1


w" > /tmp/fdisk_boot.input
}
readonly -f create_sub_part_file_disk_boot


# Layout of the calvados data partition:
#   Sub-partition 1     /var/log
#   Sub-partition 2     /misc/config
#   Sub-partition 3     /misc/scratch
function create_sub_part_file_disk_data {
echo "

n
p
1

+${DISK_CALVADOS_LOG_SIZE}M
n
p
2

+${DISK_CALVADOS_CONFIG_SIZE}M
n
p
3


w" > /tmp/fdisk_data.input
}
readonly -f create_sub_part_file_disk_data

# Get size of the disk, in MB
# First parameter is the disk (ex: /dev/sda)
# Returns answer in $DISK_SIZE
function get_disk_size {
    local dev=${1}
    max=$(fdisk -l ${dev} 2>&107 | grep "Disk /dev"  | cut -d ',' -f2)
    max=${max%bytes}
    let "DISK_SIZE=$max / 1000000"
    step_log_console "${dev} disk size is ${DISK_SIZE}MB"
}

function create_fdisk_partition {
    local dev_name=${1}
    local dev=/dev/${dev_name}
    step_log_file "Create fdisk partition ${dev}"
    # zero the first 10000 1024 blocks
    /bin/dd if=/dev/zero of=${dev} bs=1024 count=10000 >&107 2>&1

    /sbin/fdisk -S 62 ${dev} < ${2} >&107 2>&1
}


function find_parted_total_partition {
    local dev_name=${1}
    local dev=/dev/${dev_name}
    local tpart=$(parted $dev print | grep "partition" | wc -l) >&107 2>&1
    echo "${tpart}"
}
readonly -f find_parted_total_partition

function find_fdisk_total_partition {
    local dev_name=${1}
    local dev=/dev/${dev_name}
    local tpart=$(fdisk -u -l $dev | grep "^${dev}" | wc -l) >&107 2>&1
    echo "${tpart}"
}
readonly -f find_fdisk_total_partition

function mark_part_bootable {
    local dev_name=${1}
    local dev=/dev/${dev_name}
    local i;

    step_log_file "Mark part bootable ${dev}"
    if [ "$(/sbin/fdisk -l ${dev} 2>&107 | \
                grep ${2} |awk {'print $2;'})" != "*" ]; then
      for (( i=1 ; $i <= 5 ; i++ )) ; do
        # Toggle first parition as bootable
        if [ "$(/sbin/fdisk -l ${dev} 2>&107 | \
                  grep ${2} |awk {'print $2;'})" != "*" ]; then
          /sbin/fdisk ${dev} << EOF >&107 2>&1
a
1
w
EOF
        fi
        if [ "$(/sbin/fdisk -l ${dev} 2>&107 | \
                  grep ${2} |awk {'print $2;'})" == "*" ]; then
            break
        fi
      done
    fi
}
readonly -f mark_part_bootable

function find_fs_offset {
    local start=$(fdisk -u -l ${1} | grep "${1}${2}" | awk '{print $2}')
    if [ "${start}" == "*" ]; then
        start=$(fdisk -u -l ${1} | grep "${1}${2}" | awk '{print $3}')
    fi
    local offset=$(expr ${start} \* 512)
    echo ${offset}
}
readonly -f find_fs_offset

function find_fs_sizelimit {
    local result
    local sizelimit
    local start=$(fdisk -u -l ${1} | grep "${1}${2}" | awk '{print $2}')
    local endlimit=$(fdisk -u -l ${1} | grep "${1}${2}" | awk '{print $3}')

    if [ "${start}" == "*" ]; then
        start=$(fdisk -u -l ${1} | grep "${1}${2}" | awk '{print $3}')
        endlimit=$(fdisk -u -l ${1} | grep "${1}${2}" | awk '{print $4}')
    fi
    result=$((${endlimit} - ${start}))
    expr ${result} \* 512
}
readonly -f find_fs_sizelimit

function setup_loop_offset {
    local offset=$(find_fs_offset ${1} ${2})
    local sizelimit=$(find_fs_sizelimit ${1} ${2})
    loop=$(losetup --find)
    if (( $? != 0 )); then
        return 1 
    fi
    losetup ${loop} ${1} -o ${offset} --sizelimit ${sizelimit}
    if (( $? != 0 )); then
        losetup -d ${loop}
        echo ""
    fi
    echo "${loop}"
}
readonly -f setup_loop_offset

function clean_partition {
    local dev=${1}

    temp_dir=$(mktemp -d) >&107 2>&1
    mount ${dev} ${temp_dir}  >&107 2>&1
    rm -rf ${temp_dir}/  >&107 2>&1
    umount ${temp_dir}   >&107 2>&1
    rm -rf ${temp_dir}   >&107 2>&1
}

function check_for_disk_errors {
    disk_name=$1
    second_disk_name=$2   
    step_log_console "Checking disks: $disk_name $second_disk_name"
    smartctl -a /dev/$disk_name >&107 2>&1
    if [ -n "{$second_disk_name}" ]; then
       smartctl -a /dev/$second_disk_name >&107 2>&1
    fi
    ata_error_report_count=0
    disk_model=$(get_disk_model $disk_name)
    second_disk_model=$(get_disk_model $second_disk_name)
    check_disks     
}

function create_and_prep_repository {
    local disk_name=$1
    local part_num=$2
    step_log_console "---Starting to prepare repository---"
    step_log_file "Create sub partition on /dev/${disk_name}${part_num}"

    check_fix_disk_part "${disk_name}${part_num}" "1" "/tmp/fdisk_repo.input"

    loop_dev=$(setup_loop_offset "/dev/${disk_name}${part_num}" "p1")
    if [ -z "${loop_dev}" ]; then
      step_log_console "Cannot setup loop device for ${disk}${PART_NUM_REP}"
    fi
    START=$(date +%s)
    check_fs_partition "${loop_dev}" "Repository"
    clean_partition ${loop_dev}
    END=$(date +%s)
    DIFF=$(( $END - $START ))
    step_log_console "File system creation on /dev/${disk_name}${part_num} took ${DIFF} seconds"
    sleep 2
    losetup -d ${loop_dev}
}

function check_fix_disk_part {

    local dev_name=${1}
    local dev=/dev/${dev_name}
    local expected_part=${2}

    # Always wape off old partition
    #total_part=$(find_parted_total_partition ${dev_name})
    total_part=0

    if [[ "${total_part}" != "${expected_part}" ]]; then
        create_fdisk_partition ${dev_name} ${3}
        total_part=$(find_fdisk_total_partition ${dev_name})
        if [[ "${total_part}" != "${expected_part}" ]]; then        
            step_log_console $"Problem with partition creating. Keep going"
            declare -F pd_notify_error_event  &>/dev/null && \
                pd_notify_error_event "Problem found with partition creation: total partitions = ${total_part}, expected partitions = ${expected_part}"
#          exit
        fi
    fi
}
readonly -f check_fix_disk_part

function create_fdisk_input () {
echo "

n
p
1


w" > /tmp/fdisk_rootfs.input
}

function create_mkfs_host_boot_lv () {
    host_boot_sz=$1
    host_lvname=$2
    host_label=$3
    exec 107>&1

    vol_grp="panini_vol_grp"
    host_lvname_full="/dev/panini_vol_grp/${host_lvname}"
    
    echo $'---Starting to create host logical volume---'
    echo $"lvcreate -L ${host_boot_sz}M -n ${host_lvname} panini_vol_grp"
    lvcreate -L ${host_boot_sz}M -n ${host_lvname} ${vol_grp}
    
    check_fs_partition "${host_lvname_full}" "${host_label}"
    clean_partition "${host_lvname_full}"
    return 0
}

function create_mkfs_calvados_boot_lv () {
    cal_boot_sz=$1
    cal_lvname=$2
    cal_label=$3
    exec 107>&1

    vol_grp="panini_vol_grp"
    cal_lvname_full="/dev/${vol_grp}/${cal_lvname}"
    
    create_fdisk_input
    echo $'---Starting to create Calvados logical volume---'
    echo $"lvcreate -L ${cal_boot_sz}M -n ${cal_lvname} ${vol_grp}"
    lvcreate -L ${cal_boot_sz}M -n ${cal_lvname} ${vol_grp}

    check_fix_disk_part "${vol_grp}/${cal_lvname}" "1" "/tmp/fdisk_rootfs.input"
    mark_part_bootable "${vol_grp}/${cal_lvname}" "${vol_grp}/${cal_lvname}p1"
    
    for subprt in p1 ; do
        loop_dev=$(setup_loop_offset "${cal_lvname_full}" "${subprt}")
        if [ -z "${loop_dev}" ]; then
            echo "Cannot setup loop device for ${cal_lvname}"
            return 1
        fi
        check_fs_partition "${loop_dev}" "${cal_label}"
        set +e
        losetup -d ${loop_dev}
        set -e
    done
    return 0
}

function create_mkfs_xr_boot_lv () {
    xr_boot_sz=$1
    xr_lvname=$2
    xr_label=$3
    exec 107>&1

    vol_grp="panini_vol_grp"
    xr_lvname_full="/dev/${vol_grp}/${xr_lvname}"
    
    create_fdisk_input
    echo $'---Starting to create XR logical volume---'
    echo $"lvcreate -L ${xr_boot_sz}M -n ${xr_lvname} ${vol_grp}"
    lvcreate -L ${xr_boot_sz}M -n ${xr_lvname} ${vol_grp}

    check_fix_disk_part "${vol_grp}/${xr_lvname}" "1" "/tmp/fdisk_rootfs.input"
    
    for subprt in p1 ; do
        loop_dev=$(setup_loop_offset "${xr_lvname_full}" "${subprt}")
        if [ -z "${loop_dev}" ]; then
            echo "Cannot setup loop device for ${xr_lvname}"
            return 1
        fi
        check_fs_partition "${loop_dev}" "${xr_label}"
        set +e
        losetup -d ${loop_dev}
        set -e
    done
    return 0
}
