If you provide space for customer's data you probably get request from management to provide info about usable and allocated disk/storage space.
Usable is what you provide to customer (if you have two mirrored 300G disks, you provide 300G or something less, since some space goes for metadata).
Allocated is what is used at the moment and this is actually what you charge (billable storage).
Since I had variety of configurations and storages, like internal disks, DAS (directly attached storage), and SAN (storage area network), it was convenient for me to write script that easily generates storage report.
I had UFS/ZFS file systems. The UFS was on the top of SVM (Solaris Volume Manager).
I also had different file systems within one device, so script has to sum them and report one disk size as total for that system.
The idea was to have a configuration file with HOSTNAME:METADEVICE_OR_ZFS:DESC:UFS/ZFS and to have script that reads configuration file and generate the report.
# HOSTNAME:METADEVICE_OR_ZFS:DESC:UFS/ZFS #------------------------------------- # --------- sds1 StorEdge 6120 kingkong:t1_sds1-s0:sds1:zfs # --------- sds2 StorEdge 6120 trex:fc.san.hrc.r10.sds2-s1:sds2:zfs # --------- sds3 StorEdge 6120 trex:fc.san.hrc.r10.sds3-s0:sds3:zfs # --------- sds4 StorEdge 6120 kingkong:sds4-s1:sds4:zfs # --------- sds5 StorEdge 6120 kingkong:sds5-s0:sds5:zfs snake:sds5-1:sds5:zfs # --------- sds6 StorEdge 6120 trex:sds6-s2:sds6:zfs # --------- sds7 StorEdge 6120 kingkong:sds7-s0:sds7:zfs # --------- sds8 StorEdge 6120 kingkong:space:sds8:zfs # ---------- tip-0 StorEdge 3510 gorilla:d100:tip-0:ufs # ---------- tip-1 StorEdge 3510 gorilla:d200:tip-1:ufs # --------- gorilla-internal SunFire X4200 gorilla:ora01:gorilla-internal:zfs # ---------- winston StorEdge 6130 unicorn:d100:winston:ufs # ---------- lucky StorEdge 6130 unicorn:d200:lucky:ufs # --------- unicorn-internal SunFire X4200 unicorn:ora01:unicorn-internal:zfs # --------- monkey SunFire X4500 monkey:pool.0:monkey:zfs monkey:pool.1:monkey:zfs monkey:pool.2:monkey:zfs |
The script is
# cat reportstorage.sh #!/bin/sh #set -x # ----------------------------------------------- # Gets storage report for manager's name # ----------------------------------------------- # configuration file global_infile=storage.conf # prepare input file, ignore comments and blank lines, uniq (maybe duplicated entries), sort cat ${global_infile} | sed -e '/^#/d' -e '/^$/d' | sort | uniq > ${global_infile}.$$ # separate input temporary file for ufs/zfs ufs_infile=ufs_infile.$$ zfs_infile=zfs_infile.$$ cat ${global_infile}.$$ | awk -F: '$4=="ufs"' > ${ufs_infile} cat ${global_infile}.$$ | awk -F: '$4=="zfs"' > ${zfs_infile} # --------------------------------- # functions # ------------------------------- # --- FUNCTION: process hosts with ufs/metadevices process_ufs() { # get list of hosts that has metadevices ufs_hostlist=`cat ${ufs_infile} | awk -F: '{print $1}' | sort | uniq` # process host for ufs_host in ${ufs_hostlist} do fping -q ${ufs_host} #-q=quite if [ $? -eq 0 ] then # for system in the loop, get mount point of metadevice, from ${ufs_infile} metadevice=`cat ${ufs_infile} | awk -F: '$1=="'${ufs_host}'" {print $2}'` # process all metadevices in a system for md in ${metadevice} do # find mount point of metadevice mount=`ssh ${ufs_host} mount | gegrep -w "/dev/md/dsk/${md}" | awk '{print $1}'` # find total size of md usable=`ssh ${ufs_host} df -k ${mount} | gegrep -v "^Filesystem" | awk '{print $2}'` # total # find used size of md alocated=`ssh ${ufs_host} df -k ${mount} | gegrep -v "^Filesystem" | awk '{print $3}'` #used # from ${ufs_infile} get description of metadevice ufs_desc=`cat ${ufs_infile} | awk -F: '$1=="'${ufs_host}'" && $2=="'${md}'" {print $3}'` # screen output FYI printf "%-20s %-20s %-20s %-20s %-20s \n" \ "Host:${ufs_host}" "Mount:${mount}" " Desc:${ufs_desc}" \ "Total[KB]=${usable}" "Used[KB]=${alocated}" # feed tmp file for further processing echo ${ufs_desc} >> ufs_desc.$$ echo "${ufs_desc} ${usable} ${alocated}" >> ufs_of.$$ done else echo "Host ${ufs_host} is not reachable." fi done } # --- FUNCTION: process hosts with zfs process_zfs() { # get list of hosts that has zfs zfs_hostlist=`cat ${zfs_infile} | awk -F: '{print $1}' | sort | uniq` # process host for zfs_host in ${zfs_hostlist} do fping -q ${zfs_host} #-q=quite if [ $? -eq 0 ] then # for system in the loop, get zfs, from ${zfs_infile} zetafs=`cat ${zfs_infile} | awk -F: '$1=="'${zfs_host}'" {print $2}'` # process all zfs in a system for zfs in ${zetafs} do # find used, avail, total size of zfs used=`ssh ${zfs_host} zfs get -H -p used ${zfs} | awk '{print $3}'` # allocated in bytes avail=`ssh ${zfs_host} zfs get -H -p avail ${zfs} | awk '{print $3}'` # free in bytes total=`(echo "${used}+${avail}" | bc -l)` # total in bytes # from ${zfs_infile} get description of zfs zfs_desc=`cat ${zfs_infile} | awk -F: '$1=="'${zfs_host}'" && $2=="'${zfs}'" {print $3}'` # screen output FYI printf "%-20s %-20s %-20s %-20s %-20s \n" \ "Host:${zfs_host}" "ZFS:${zfs}" " Desc:${zfs_desc}" "Total[B]:${total}" "Used[B]:${used}" # feed tmp file for further processing echo ${zfs_desc} >> zfs_desc.$$ echo "${zfs_desc} ${total} ${used}" >> zfs_of.$$ done else echo "Host ${zfs_host} is not reachable." fi done } # --- FUNCTION: clean temp files tmp_file_cleaning() { [ -f ${global_infile}.$$ ] && rm ${global_infile}.$$ [ -f ${ufs_infile} ] && rm ${ufs_infile} [ -f ufs_desc.$$ ] && rm ufs_desc.$$ [ -f ufs_of.$$ ] && rm ufs_of.$$ [ -f ${zfs_infile} ] && rm ${zfs_infile} [ -f zfs_desc.$$ ] && rm zfs_desc.$$ [ -f zfs_of.$$ ] && rm zfs_of.$$ } # --- cleaning in case of script termination and regular exit trap tmp_file_cleaning HUP INT QUIT ABRT EXIT # Process UFS and ZFS process_ufs ; process_zfs # ----- LOOK FOR SAME DESCRIPTION AND SUM THEIR VALUES # remove duplicated description from tmp file cat ufs_desc.$$ | sort| uniq > ufs_desc.$$.tmp ; mv ufs_desc.$$.tmp ufs_desc.$$ cat zfs_desc.$$ | sort| uniq > zfs_desc.$$.tmp ; mv zfs_desc.$$.tmp zfs_desc.$$ # print title on screen FYI printf "------------------------------------------------------------------------- \n" printf "%-15s %15s %15s \n" "Description" "Usable/Total[GB]" "Allocated/Used[GB]" printf "------------------------------------------------------------------------- \n" # for each description, calculate sum values, print on screen # UFS - received in KB for description in `cat ufs_desc.$$` do cat ufs_of.$$ | \ awk '$1=="'${description}'" {sumusable+=$2; sumalocated+=$3} \ END {printf "%-15s %11.0f %15.0f \n", "'${description}'", sumusable/1024/1024, sumalocated/1024/1024, "\n" }' done # ZFS - received in B for description in `cat zfs_desc.$$` do cat zfs_of.$$ | \ awk '$1=="'${description}'" {sumusable+=$2; sumalocated+=$3} \ END {printf "%-15s %11.0f %15.0f \n", "'${description}'", sumusable/1024/1024/1024, sumalocated/1024/1024/1024, "\n" }' done exit 0 |
Output during processing is like:
# sh reportstorage.sh Host:gorilla Mount:/ora02 Desc:tip-0 Total[KB]=351683990 Used[KB]=51386171 Host:gorilla Mount:/ora03 Desc:tip-1 Total[KB]=351683990 Used[KB]=104905219 Host:tiger Mount:/.0 Desc:tiger-internal Total[KB]=10326524 Used[KB]=1580099 Host:tiger Mount:/shipping Desc:tiger-internal Total[KB]=10326524 Used[KB]=10307 Host:tiger Mount:/viewstore Desc:tiger-internal Total[KB]=103269854 Used[KB]=66251208 Host:tiger Mount:/buildstore Desc:tiger-internal Total[KB]=103269854 Used[KB]=14611264 Host:tiger Mount:/ccase_rls Desc:tiger-internal Total[KB]=20653809 Used[KB]=13518282 Host:tiger Mount:/vobstore Desc:tiger-internal Total[KB]=359090412 Used[KB]=263585448 Host:unicorn Mount:/.100 Desc:winston Total[KB]=207028354 Used[KB]=139473176 Host:unicorn Mount:/.200 Desc:lucky Total[KB]=207028354 Used[KB]=59108156 Host:trex ZFS:fc.san.hrc.r10.sds2-s1 Desc:sds2 Total[B]:930128855040 Used[B]:745045099008 Host:trex ZFS:fc.san.hrc.r10.sds3-s0 Desc:sds3 Total[B]:930128855040 Used[B]:871588045824 Host:trex ZFS:scsi.das.zfs.r60.d1-12 Desc:trex-das Total[B]:2342762053632 Used[B]:1355473254762 Host:trex ZFS:scsi.int.zpool.r1.d2d3 Desc:trex-internal Total[B]:71873593344 Used[B]:599597056 Host:trex ZFS:sds6-s2 Desc:sds6 Total[B]:1910992011264 Used[B]:1310114274816 Host:pigeon ZFS:pool.0 Desc:pigeon Total[B]:14571842568192 Used[B]:6553773370872 Host:borax ZFS:bob.0 Desc:bob0-4.div.w.5 Total[B]:1175344644096 Used[B]:722208151552 Host:borax ZFS:space.1 Desc:borax-das-1 Total[B]:1752909742080 Used[B]:1562364591690 Host:borax ZFS:space.2 Desc:borax-das-2 Total[B]:1752909742080 Used[B]:1286738422500 Host:clearvoice ZFS:space0 Desc:clearvoice-internal Total[B]:293836161024 Used[B]:270715788800 |
The result on the screen is like:
---------------------------------------------------- Description Usable/Total[GB] Allocated/Used[GB] ---------------------------------------------------- tiger-internal 579 343 lucky 197 56 tip-0 335 49 tip-1 335 100 winston 197 133 trex-das 2182 1262 trex-internal 67 1 pigeon 13571 6104 |