Page 2 of 2 FirstFirst 12
Results 11 to 11 of 11

Thread: Adding space to file system (LVM)

  1. #11
    Join Date
    Sep 2011
    Beans
    469

    Re: Adding space to file system (LVM)

    I have finished the storage check script and ended up using a single script instead of two.

    The bulk of the script is error checking and avoiding problems...although I am sure it will not catch 100% of all potential problems but it "should" be sufficient.

    I will share the code here but BE WARNED, this script will resize your File System under certain circumstances. Even though it should be safe, you need to make sure you designed your LVM for such a script and you have the correct references for any potential file systems as noted near line 152 that is commented "Check validity of File System names." I chose to use the LV names to keep it short but you can set it to whatever you like. I did it this way to avoid operator typos that run it manually or set it up wrong in the crontab. All the important stuff is pre-defined inside the script.

    Here is how my system is designed:

    Volume Group = LVG (Size=342 GB, 0 free)

    Logical Volumes in LVG:
    root (Size=8GB)
    opt (Size=75GB)
    bak (Size=125GB)
    temp (Size=125GB)

    File Systems:
    /dev/mapper/LVG-root (Size=8GB), Mounted on /
    /dev/mapper/LVG-opt (Size=50GB), Mounted on /opt
    /dev/mapper/LVG-bak (Size=100GB), Mounted on /var/backup
    /dev/mapper/LVG-temp (Size=100GB), Mounted on /var/temp

    Here is a sample crontab file for checking 3 file systems that I expect will grow over time. Note that I am not including the root partition since I do not expect it to be growing over time...however, I do have Nagios monitoring it so I will get notified but by a different method. This process is meant to check AND grow the FS as needed. When they get within 5 GB of being full, it will try to increment the file system by 1 GB. Click on this link to read about my thoughts on how to maintain a crontab schedule.

    Code:
    ########################################
    # Name: Crontab Schedule for root user
    # Author: LHammonds
    ############# Update Log ###############
    # 2012-05-01 - LTH - Created schedule
    ########################################
    
    SHELL=/bin/sh
    PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
    
    # m h dom mon dow command
    
    #
    # Get date/time from network time server every hour
    #
    0 * * * * /etc/network/if-up.d/ntpdate
    #
    # Daily check for available space on /opt
    #
    0 1 * * * /var/scripts/prod/check-storage.sh opt 5 1 > /dev/null 2>&1
    #
    # Daily check for available space on /var/backup
    #
    0 2 * * * /var/scripts/prod/check-storage.sh bak 5 1 > /dev/null 2>&1
    #
    # Daily check for available space on /var/temp
    #
    0 3 * * * /var/scripts/prod/check-storage.sh temp 5 1 > /dev/null 2>&1
    Here is the script. Notice that the resize2fs command is currently commented out on line 64. That means this script will operate in a mode that will not affect the system as it is now. You uncomment the command by removing the pound characters from the beginning to make it actually perform a resize. Feel free to try it out on the commandline by issuing various threshold values which are below the current available space and above to see how it works without fear of it doing anything to your system.

    /var/scripts/prod/check-storage.sh
    Code:
    #!/bin/bash
    #############################################
    ## Name          : check-storage.sh
    ## Version       : 1.2
    ## Date          : 2012-05-01
    ## Author        : LHammonds
    ## Purpose       : Check available space for a file system and expand if necessary.
    ## Compatibility : Verified on Ubuntu Server 10.04.4 LTS
    ## Requirements  : None
    ## Run Frequency : Recommend once per day for each FS to monitor.
    ## Parameters    :
    ##    1 = (Required) File System name (e.g. opt)
    ##    2 = (Required) File System Threshold (e.g. 2G)
    ##    3 = (Required) Amount to increase File System (e.g. 1G)
    ## Exit Codes    :
    ##    0 = Success (either nothing was done or FS expanded without error)
    ##    1 = ERROR: Missing or incorrect parameter(s)
    ##    2 = ERROR: Invalid parameter value(s)
    ##    4 = ERROR: Lock file detected
    ##    8 = ERROR: Resize2fs error
    ##   16 = SEVERE: No room to expand
    ##   32 = ERROR: Script not run by root user
    ################ CHANGE LOG #################
    ## DATE       WHO WHAT WAS CHANGED
    ## ---------- --- ----------------------------
    ## 2012-05-01 LTH Created script.
    ## 2012-05-02 LTH Improved log messages.
    ## 2012-05-02 LTH Improved email messages.
    #############################################
    
    ## Import standard variables and functions. ##
    source /var/scripts/common/standard.conf
    
    ## Define local variables.
    LOGFILE="${TEMPDIR}/check-storage.log"
    LOCKFILE="${TEMPDIR}/check-storage.lock"
    ErrorFlag=0
    ReturnCode=0
    
    #######################################
    ##            FUNCTIONS              ##
    #######################################
    
    function f_cleanup()
    {
      if [ -f ${LOCKFILE} ];then
        ## Remove lock file so other check space jobs can run.
        rm ${LOCKFILE} 1>/dev/null 2>&1
      fi
      exit ${ErrorFlag}
    }
    
    function f_showhelp()
    {
      echo -e "\nUsage : ${SCRIPTNAME} FileSystemName ThresholdSizeInGB AmountToIncreaseByInGB\n"
      echo -e "\nExample: ${SCRIPTNAME} opt 2 1\n"
    }
    
    function f_auto-increment()
    {
      let RoomInLV=${LVSize}-${FSSize}
      if [[ ${RoomInLV} -gt ${FSIncreaseBy} ]]; then
        ## There is room in the LV to increase space to the FS.
        #resize2fs ${FSVol} ${NewFSSize}G
        ReturnCode=$?
        echo "`date +%Y-%m-%d_%H:%M:%S` --- resize2fs ${FSVol} ${NewFSSize}G, ReturnCode=${ReturnCode}" | tee -a ${LOGFILE}
        if [[ ${ReturnCode} -ne 0 ]]; then
          ## There was an error in resize2fs.
          return ${ReturnCode}
        fi
      else
        ## There is not enough room in the LV to increase space in the FS.
        return 50
      fi
      return 0
    }
    
    #######################################
    ##           MAIN PROGRAM            ##
    #######################################
    
    if [ -f ${LOCKFILE} ]; then
      # Lock file detected.  Abort script.
      echo "Check space script aborted"
      echo "This script tried to run but detected the lock file: ${LOCKFILE}"
      echo "Please check to make sure the file does not remain when check space is not actually running."
      f_sendmail "ERROR: check storage script aborted" "This script tried to run but detected the lock file: ${LOCKFILE}\n\nPlease check to make sure the file does not remain when check space is not actually running.\n\nIf you find that the script is not running/hung, you can remove it by typing 'rm ${LOCKFILE}'"
      ErrorFlag=4
      f_cleanup
    else
      echo "`date +%Y-%m-%d_%H:%M:%S` ${SCRIPTNAME}" > ${LOCKFILE}
    fi
    
    ## Requirement Check: Script must run as root user.
    if [ "$(id -u)" != "0" ]; then
      ## FATAL ERROR DETECTED: Document problem and terminate script.
      echo "ERROR: Root user required to run this script."
      echo ""
      ErrorFlag=32
      f_cleanup
    fi
    
    ## Check existance of required command-line parameters.
    case "$1" in
      "")
        f_showhelp
        ErrorFlag=1
        f_cleanup
        ;;
      --help|-h|-?)
        f_showhelp
        ErrorFlag=1
        f_cleanup
        ;;
      *)
        FSName=$1
        ;;
    esac
    case "$2" in
      "")
        f_showhelp
        ErrorFlag=1
        f_cleanup
        ;;
      --help|-h|-?)
        f_showhelp
        ErrorFlag=1
        f_cleanup
        ;;
      *)
        FSThreshold=$2
        ;;
    esac
    case "$3" in
      "")
        f_showhelp
        ErrorFlag=1
        f_cleanup
        ;;
      --help|-h|-?)
        f_showhelp
        ErrorFlag=1
        f_cleanup
        ;;
      *)
        FSIncreaseBy=$3
        ;;
    esac
    
    ## Check validity of File System name.
    case "${FSName}" in
      "opt")
        FSVol="/dev/LVG/opt"
        FSMap="/dev/mapper/LVG-opt"
        ;;
      "bak")
        FSVol="/dev/LVG/bak"
        FSMap="/dev/mapper/LVG-bak"
        ;;
      "temp")
        FSVol="/dev/LVG/temp"
        FSMap="/dev/mapper/LVG-temp"
        ;;
      *)
        echo "ERROR: ${FSName} does not match a known file system defined in this script."
        f_showhelp
        ErrorFlag=2
        f_cleanup
        ;;
    esac
    
    ## Check validity of threshold value.
    test ${FSThreshold} -eq 0 1>/dev/null 2>&1
    if [[ $? -eq 2 ]]; then
      ## Threshold parameter is not an integer.
      echo "ERROR: ${FSThreshold} is not an integer."
      f_showhelp
      ErrorFlag=2
      f_cleanup
    fi
    
    ## Check validity of increment value.
    test ${FSIncreaseBy} -eq 0 1>/dev/null 2>&1
    if [[ $? -eq 2 ]]; then
      ## FSIncreaseBy parameter is not an integer.
      echo "ERROR: ${FSIncreaseBy} is not an integer."
      f_showhelp
      ErrorFlag=2
      f_cleanup
    fi
    
    ## Get available space for the file system.
    FSAvailable="`df --block-size=g ${FSMap} | awk '{ print $4 }' | tail -n 1 | sed 's/G//'`"
    
    ## Get the current size of the File System.
    FSSize="`df --block-size=g ${FSMap} | awk '{ print $2 }' | tail -n 1 | sed 's/G//'`"
    
    ## Get the current size of the Logical Volume for the File System
    LVSize="`lvs --noheadings --nosuffix --units=g ${FSMap} | awk '{ print $4}' | sed 's/[.].*//'`"
    
    ## Calculate the new size of the FS in case we need it.
    let NewFSSize=${FSSize}+${FSIncreaseBy}
    
    if [[ ${FSAvailable} -lt ${FSThreshold} ]]; then
      echo "`date +%Y-%m-%d_%H:%M:%S` - Starting expansion of ${FSVol}" | tee -a ${LOGFILE}
      echo "`date +%Y-%m-%d_%H:%M:%S` --- LVSize=${LVSize}GB, FSSize=${FSSize}GB, FSAvail=${FSAvailable}GB, FSThreshold=${FSThreshold}GB, FSIncreaseBy=${FSIncreaseBy}GB" | tee -a ${LOGFILE}
      ## Run the auto-expansion function.
      f_auto-increment
      ReturnCode=$?
      case ${ReturnCode} in
      0)
        f_sendmail "NOTICE: File System Expanded" "${FSVol} was expanded because it was nearing max capacity.  Please review disk space usage and plan appropriately. LVSize=${LVSize}GB, FSSize=${FSSize}GB, FSAvailable=${FSAvailable}GB, FSThreshold=${FSThreshold}GB, FSIncreaseBy=${FSIncreaseBy}GB"
        ;;
      50)
        echo "`date +%Y-%m-%d_%H:%M:%S` - SEVERE: No room to expand ${FSVol}" | tee -a ${LOGFILE}
        ErrorFlag=16
        f_sendmail "SEVERE: No room to expand ${FSVol}" "There is not enough room in the Logical Volume to expand the ${FSVol} File System.  Immediate action is required.  Make sure there is free space in the Volume Group 'LVG' and then expand the Logical Volume...then expand the File System.\n\nLVSize=${LVSize}GB, FSSize=${FSSize}GB, FSAvailable=${FSAvailable}GB, FSThreshold=${FSThreshold}GB, FSIncreaseBy=${FSIncreaseBy}GB.\n\nType 'vgs' to see if there is any free space in the Volume Group which can be given to the Logical Volume.\n\nType 'lvs' to see the current sizes of the LVs.\n\nType 'lvdisplay' to see a list of Logical Volumes so you can get the LV Name which is used in the lvextend and resize2fs commands.\n\nType 'lvextend -L+1G /dev/LVG/opt' if you want to extend the opt Logical Volume by 1 gigabyte (assuming there is 1GB available in the Volume Group).\n\nType 'df --block-size=g' to see a list of file systems and their associated size and available space.\n\nType 'resize2fs /dev/LVG/opt ${NewFSSize}G' to set the size of opt to ${NewFSSize} gigabytes. Make sure you set the size to the desired end-result which should be LARGER than the current FS size so you do not lose data."
        ;;
      *)
        echo "`date +%Y-%m-%d_%H:%M:%S` - ERROR: Expansion failure for ${FSVol}" | tee -a ${LOGFILE}
        ErrorFlag=8
        f_sendmail "ERROR: File System Expansion Failed" "${FSVol} Expansion failed with return code of ${ReturnCode}.  LVSize=${LVSize}GB, FSSize=${FSSize}GB, FSAvailable=${FSAvailable}GB, FSThreshold=${FSThreshold}GB, FSIncreaseBy=${FSIncreaseBy}GB"
        ;;
      esac
      echo "`date +%Y-%m-%d_%H:%M:%S` - Finished expansion of ${FSVol}" | tee -a ${LOGFILE}
    else
      echo "`date +%Y-%m-%d_%H:%M:%S` - ${FSVol} ${FSAvailable}G>${FSThreshold}G No action required." | tee -a ${LOGFILE}
    fi
    
    ## Perform cleanup routine.
    f_cleanup
    Oh, one last thing...my code uses functions and variable I have pulled out into a common-use file which are specific to my environment (you need to change to suit your environment). Here are the pertinent bits:

    /var/scripts/common/standard.conf
    Code:
    ## Global Variables ##
    TEMPDIR="/var/temp"
    MYDOMAIN="example.com"
    ADMINEMAIL="admin@${MYDOMAIN}"
    REPORTEMAIL="lhammonds@${MYDOMAIN}"
    HOSTNAME=$(hostname -s)
    SCRIPTNAME=$0
    MAILFILE="${TEMPDIR}/mailfile.$$"
    
    ## Global Functions ##
    
    function f_sendmail()
    {
      ## Purpose: Send email message.
      ## Parameter #1 = Subject
      ## Parameter #2 = Body
      echo "From: ${ADMINEMAIL}" > ${MAILFILE}
      echo "To: ${REPORTEMAIL}" >> ${MAILFILE}
      echo "Subject: ${1}" >> ${MAILFILE}
      echo "" >> ${MAILFILE}
      echo -e ${2} >> ${MAILFILE}
      echo "" >> ${MAILFILE}
      echo -e "\n\nServer: ${HOSTNAME}\nProgram: ${SCRIPTNAME}\nLog: ${LOGFILE}" >> ${MAILFILE}
      sendmail -t < ${MAILFILE}
      rm ${MAILFILE}
    }
    Here is the typical output when it does not have to increase the FS:

    /var/temp/check-storage.log
    Code:
    2012-05-01_01:00:00 - /dev/LVG/opt 44G>2G No action required.
    2012-05-01_02:00:00 - /dev/LVG/bak 91G>2G No action required.
    2012-05-01_03:00:00 - /dev/LVG/temp 93G>2G No action required.
    2012-05-02_01:00:00 - /dev/LVG/opt 44G>2G No action required.
    2012-05-02_02:00:00 - /dev/LVG/bak 91G>2G No action required.
    2012-05-02_03:00:00 - /dev/LVG/temp 93G>2G No action required.
    2012-05-03_01:00:00 - /dev/LVG/opt 44G>2G No action required.
    2012-05-03_02:00:00 - /dev/LVG/bak 91G>2G No action required.
    2012-05-03_03:00:00 - /dev/LVG/temp 93G>2G No action required.
    Here is a sample of what the log will look like when it perform increases...notice how I had to increase the threshold in order for it to fire off the increase (but it still just issued a single gigabyte increase):

    /var/temp/check-storage.log
    Code:
    2012-05-02_01:00:00 - Starting expansion of /dev/LVG/opt
    2012-05-02_01:00:00 --- LVSize=75GB, FSSize=50GB, FSAvail=44GB, FSThreshold=50GB, IncreaseBy=1GB
    2012-05-02_01:00:00 --- resize2fs /dev/LVG/opt 51, ReturnCode=0
    2012-05-02_01:00:00 - Finished expansion of /dev/LVG/opt
    2012-05-02_02:00:00 - Starting expansion of /dev/LVG/bak
    2012-05-02_02:00:00 --- LVSize=125GB, FSSize=99GB, FSAvail=91GB, FSThreshold=100GB, IncreaseBy=1GB
    2012-05-02_02:00:00 --- resize2fs /dev/LVG/bak 100, ReturnCode=0
    2012-05-02_02:00:00 - Finished expansion of /dev/LVG/bak
    2012-05-02_03:00:00 - Starting expansion of /dev/LVG/temp
    2012-05-02_03:00:00 --- LVSize=125GB, FSSize=99GB, FSAvail=93GB, FSThreshold=100GB, IncreaseBy=1GB
    2012-05-02_03:00:00 --- resize2fs /dev/LVG/temp 100, ReturnCode=0
    2012-05-02_03:00:00 - Finished expansion of /dev/LVG/temp
    EDIT #1: The log file output is not all that great in 1.0. I spruced it up with more info in version 1.1. Have fun!

    EDIT #2: Updated to version 1.2, improved email notifications and other minor changes.

    Here is a sample email for the situation where there is not enough room available in the LV to extend the FS:
    Code:
    From: admin@example.com
    To: dirkdiggler@example.com
    Sent: Wednesday, May 2, 2012 2:47:17 PM
    Subject: SEVERE: No room to expand /dev/LVG/opt
    
    There is not enough room in the Logical Volume to expand the /dev/LVG/opt File System. Immediate action is required. Make sure there is free space in the Volume Group 'LVG' and then expand the Logical Volume...then expand the File System.
    
    LVSize=75GB, FSSize=50GB, FSAvailable=44GB, FSThreshold=55GB, FSIncreaseBy=55GB.
    
    Type 'vgs' to see if there is any free space in the Volume Group which can be given to the Logical Volume.
    
    Type 'lvs' to see the current sizes of the LVs.
    
    Type 'lvdisplay' to see a list of Logical Volumes so you can get the LV Name which is used in the lvextend and resize2fs commands.
    
    Type 'lvextend -L+1G /dev/LVG/opt' if you want to extend the opt Logical Volume by 1 gigabyte (assuming there is 1GB available in the Volume Group).
    
    Type 'df --block-size=g' to see a list of file systems and their associated size and available space.
    
    Type 'resize2fs /dev/LVG/opt 105G' to set the size of opt to 105 gigabytes. Make sure you set the size to the desired end-result which should be LARGER than the current FS size so you do not lose data.
    
    Server: mail
    Program: ./check-storage.sh
    Log: /var/temp/check-storage.log
    Last edited by LHammonds; May 3rd, 2012 at 02:55 PM. Reason: Updated script to version 1.2

Page 2 of 2 FirstFirst 12

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •