All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

diskcheck 21 KB
Newer Older
Dan Reading's avatar
Dan Reading committed
1
#! /bin/bash
2
#
3
# Copyright (c) 2013-2017 University of Utah and the Flux Group.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
# 
# {{{EMULAB-LICENSE
# 
# This file is part of the Emulab network testbed software.
# 
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
# 
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
# License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this file.  If not, see <http://www.gnu.org/licenses/>.
# 
# }}}
#
Dan Reading's avatar
Dan Reading committed
24 25 26 27 28 29 30 31 32 33 34 35
echo -n ' Starting diskcheck..'

# find the number of disks
# find the size of each disk
# first arg is the log output file, if not set then /tmp/...

declare error=""
declare err=""

source checkutils.sh
source hbis.sh

36 37 38
x=$(caller)
[[ "${x/NULL}" = "$x" ]] && declare -ri diskcheck_standalone=0 || declare -ri diskcheck_standalone=1

Dan Reading's avatar
Dan Reading committed
39 40
## declare -p todo_exit

41 42 43
main_diskcheck() {
    initialize $@
    cp /dev/null $tmplog
Dan Reading's avatar
Dan Reading committed
44 45 46 47

    SMARTCTL=$(findSmartctl)
    drivenames=$(getdrivenames)

Dan Reading's avatar
Dan Reading committed
48 49 50 51 52 53 54 55 56
    # run through the drivelist filtering out non-local drives or other devices 
    for i in $drivenames ; do
        model=$(getmodel $i)
    	if [ "$model" == "iSCSIDisk" ] ; then
	    echo "Filter out $i because $model"
	    drivenames=${drivenames/${i}}
	fi
    done
    
Dan Reading's avatar
Dan Reading committed
57 58
    if [ -z "$drivenames" ] ; then
	echo "No drives found. exit"
59
	(( $diskcheck_standalone )) && exit 1 || return 1
Dan Reading's avatar
Dan Reading committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
    fi

    # array to put drive inventory
    unset -v driveinv ; declare -a driveinv=()
    # array of drives to hold each drive inventory
    unset -v drive ; declare -a drive=($drivenames)

    numberofdrives=${#drive[*]}

   # the index into dirveinv array
    # DISKUNIT SN=<serial> TYPE=<PATA|SATA|SCSI|RAID> SECSIZE=<#> SECTORS=<#> RSPE ED=<MBs> WSPEED=<MBs> 
    declare -i -r header=0
    declare -i -r header_val=1
    declare -i -r name=2
    declare -i -r name_val=3
    declare -i -r driver=4
    declare -i -r driver_val=5
    declare -i -r type=6
    declare -i -r type_val=7
    declare -i -r size=8
    declare -i -r size_val=9
    declare -i -r temp=10
    declare -i -r temp_val=11
    declare -i -r model=12
    declare -i -r model_val=13
    declare -i -r serial=14 
    declare -i -r serial_val=15
    declare -i -r bpers=16
    declare -i -r bpers_val=17
    declare -i -r sectors=18
    declare -i -r sectors_val=19
    declare -i -r wspeed=20    
    declare -i -r wspeed_val=21
    declare -i -r rspeed=22
    declare -i -r rspeed_val=23
95 96
    declare -i -r wcache=24
    declare -i -r wcache_val=25
97
    declare -i -r lastslot=25 # used for iteration thru values
Dan Reading's avatar
Dan Reading committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118

    # init a default string
    unset -v d; declare -a d=()
    for ((i=0;i<=$lastslot;i++)) ; do
	case $i in
	    $header ) d[$header]="DISKUNIT" ;;
	    $header_val ) d[$header_val]="$header_val" ;;
	    $name ) d[$name]="Device=" ;;
	    $name_val ) d[$name_val]="unset " ;;
	    $driver ) d[$driver]="Driver=" ;;
	    $driver_val ) d[$driver_val]="\"UNKNOWN\" " ;;
	    $type ) d[$type]="TYPE=" ;;
	    $type_val ) d[$type_val]="\"UNKNOWN\"" ;;
	    $size ) d[$size]="Size=" ;;
	    $size_val ) d[$size_val]="unk" ;;
	    $temp ) d[$temp]="Temp=" ;;
	    $temp_val ) d[$temp_val]="unk" ;;
	    $model ) d[$model]="Model=" ;;
	    $model_val ) d[$model_val]="unk" ;;
	    $serial  ) d[$serial]="SN=" ;;
	    $serial_val ) d[$serial_val]="\"UNKNOWN\"" ;;
119 120
	    $wcache  ) d[$wcache]="wcache=" ;;
	    $wcache_val ) d[$wcache_val]="\"UNKNOWN\"" ;;
Dan Reading's avatar
Dan Reading committed
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
	    $bpers ) d[$bpers]="SECSIZE=" ;;
	    $bpers_val ) d[$bpers_val]="unk" ;;
	    $sectors ) d[$sectors]="SECTORS=" ;;
	    $sectors_val ) d[$sectors_val]="\"UNKNOWN\"" ;;
	    $wspeed   ) d[$wspeed]="WSPEED=" ;;
	    $wspeed_val ) d[$wspeed_val]="\"UNKNOWN\"" ;;
	    $rspeed ) d[$rspeed]="RSPEED=" ;;
	    $rspeed_val ) d[$rspeed_val]="\"UNKNOWN\"" ;;
	esac
    done

    #default string
    driveinvinit="${d[@]}"

    # initalize the driveinv array
    for ((idx=0; idx<$numberofdrives; idx++)) ; do
	driveinv[$idx]="$driveinvinit" 
    done

    #now fill in the array values
    for ((idx=0; idx<$numberofdrives; idx++)) ; do
	unset -v d ; declare -a d=(${driveinv[$idx]})
	for ((i=0;i<=$lastslot;i++)) ; do
	    case $i in
		$header_val ) d[$header_val]="$idx" ;;
		$name_val ) d[$name_val]="${drive[$idx]}" ;;
		$sectors_val ) d[$sectors_val]=$(getsectors ${drive[$idx]}) ;;
		$bpers_val ) d[$bpers_val]=$(getbpers ${drive[$idx]}) ;;
		$driver_val ) d[$driver_val]=$(getdriver ${drive[$idx]}) ;;
		$type_val ) d[$type_val]=$(gettype ${drive[$idx]}) ;;
		$temp_val ) d[$temp_val]=$(gettemp ${drive[$idx]}) ;;
		$model_val ) d[$model_val]=$(getmodel ${drive[$idx]}) ;;
		$serial_val ) d[$serial_val]=$(getserial ${drive[$idx]}) ;;
	    esac
	done
156
	# Must have sectors_val an bpers_val before calculating size
Dan Reading's avatar
Dan Reading committed
157 158 159 160 161 162 163 164
	for ((i=0;i<=$lastslot;i++)) ; do
	    case $i in
		$size_val ) 
		x=$((${d[$sectors_val]}*${d[$bpers_val]}))
		d[$size_val]=$(($x / 1000000000))		
		;;
	    esac
	done
165 166 167 168 169 170
	# Must have size val before attempting disk speed tests
	if (( $mfsmode == 1 )) ; then
	    for ((i=0;i<=$lastslot;i++)) ; do
		case $i in
		    $rspeed_val ) 
		# check the size, if small then might be a USB drive
171
		    if [ ${d[$size_val]} -gt 8 ] ; then
172 173
			d[$rspeed_val]=$(getrspeed ${drive[$idx]})
		    else
174
			d[$type_val]="SMALL"
175 176 177
		    fi
		    ;;
		    $wspeed_val ) 
178
		    # check the WCE before the speed test
179
		    d[$wcache_val]=$(getwcache ${drive[$idx]})
180
		    if [ ${d[$size_val]} -gt 8 ] ; then
181 182
			d[$wspeed_val]=$(getwspeed ${drive[$idx]})
		    else
183
			d[$type_val]="SMALL"
184 185 186 187 188 189
		    fi
		    ;;
		esac
	    done
	fi
	
Dan Reading's avatar
Dan Reading committed
190 191 192
	# update driveinv with modified data
	driveinv[$idx]=${d[@]}
    done
Dan Reading's avatar
Dan Reading committed
193
    
194
    if (( $collect_flag )) ; then
195 196 197
	printf "%s%d\n"  "DISKINFO UNITS=" ${numberofdrives} >> ${logfile4tb}
	for (( idx=0; idx<$numberofdrives; idx++)) ; do
	    unset -v d ; declare -a d=(${driveinv[$idx]})
198
	    printf "%s %s\""%s\"" %s\""%s\"" %s%s %s%s %s%s %s%s %s%s" \
199 200
		${d[$header]} \
		${d[$serial]} ${d[$serial_val]} \
201
		${d[$wcache]} ${d[$wcache_val]} \
202 203 204 205 206 207 208 209 210 211 212 213 214
		${d[$type]} ${d[$type_val]} \
		${d[$bpers]} ${d[$bpers_val]} \
		${d[$sectors]} ${d[$sectors_val]} \
		${d[$wspeed]} ${d[$wspeed_val]} \
		${d[$rspeed]} ${d[$rspeed_val]} >> ${logfile4tb}
	    printf " %s%s %s%s %s%s %s%s %s%s\n" \
		${d[$name]} ${d[$name_val]} \
		${d[$size]} ${d[$size_val]} \
		${d[$temp]} ${d[$temp_val]} \
		${d[$model]} ${d[$model_val]} \
		${d[$driver]} ${d[$driver_val]} >> ${logfile4tb}
	done
    fi
Dan Reading's avatar
Dan Reading committed
215 216

# we are done if in MFS mode
217 218 219
if (( $mfsmode )) ; then
    (( $diskcheck_standalone )) && exit 0 || return 0
fi
220

Dan Reading's avatar
Dan Reading committed
221 222
#output to log file
{
223
echo "Diskcheck $(date): "
224
echo -e "name\t\tdriver\ttype\tsize\ttemp\tmodel\t\t\tserial\t\twcache"
Dan Reading's avatar
Dan Reading committed
225 226
for ((idx=0; idx<${numberofdrives}; idx++)) ; do
    unset -v d ; declare -a d=(${driveinv[$idx]})
227
    echo -e "${d[$name_val]}\t${d[$driver_val]}\t${d[$type_val]}\t${d[$size_val]}\t${d[$temp_val]}\t${d[$model_val]}\t\t${d[$serial_val]}\t${d[$wcache_val]}"
Dan Reading's avatar
Dan Reading committed
228 229 230 231 232 233 234 235
done
} > ${tmplog} 2>&1
cat ${tmplog} >> ${logfile} 

driveinfo=""
# echo name,size and serial to stdout, addr serialnumber
for ((idx=0; idx<${#driveinv[*]}; idx++)) ; do
    unset -v d ; declare -a d=(${driveinv[$idx]})
236
    echo -n "${d[$name_val]} ${d[$size_val]} ${d[$serial_val]} ${d[$wcache_val]}  "
237
    driveinfo+="${d[$serial_val]} "
Dan Reading's avatar
Dan Reading committed
238
done
239
echo ""
Dan Reading's avatar
Dan Reading committed
240 241 242

driveinfo=${driveinfo% } # get rid of trailing space

243
if (( $check_flag )) ; then
Dan Reading's avatar
Dan Reading committed
244
# Now check against the testbed DB
245 246 247 248 249 250
# readtmcinfo /proj/emulab-ops/nodecheck/pc507/pc507  tmccinfo
    tbinfo=$(getfromtb DISKUNIT)
    tbinfo=${tbinfo% }  # get rid of trailing space
    
# echo driveinfo:$driveinfo: tbinfo:$tbinfo: 
{
Dan Reading's avatar
Dan Reading committed
251
#save for both output to stdout and log file 
252 253 254 255 256 257 258 259
    if [ -z "$tbinfo" ] ; then
	failed="TBmiss no info"
	echo "TBmiss empty info returned. "
    fi
    
#upper case
    tbinfo=${tbinfo^^}
    driveinfo=${driveinfo^^}
260

Dan Reading's avatar
Dan Reading committed
261
# turn space seperated string into array
262 263
    unset -v tb; declare -a tb=(${tbinfo// / })
    unset -v have; declare -a have=(${driveinfo// / })
264 265

#   lines commented with #-# disable the checking of HD order
266 267 268
    
    havecnt=${#have[*]}
    tbcnt=${#tb[*]}
269 270 271
#-#     numserial=${tbcnt}
#-#     maxcnt=${tbcnt}
#-#     
272
    if [[ ${tbcnt} -ne ${havecnt} ]] ; then
273 274
	failed="TBmiss "
#-#     [[ ${tbcnt} -gt ${havecnt} ]] && maxcnt=${tbcnt} || maxcnt=${havecnt}
275
    fi
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
#-#     
#-#     for ((idx=0; idx<$maxcnt; idx++)) ; do
#-# 	for ((ifi=0; ifi<$havecnt; ifi++)) ; do
#-# 	    for ((tbi=0; tbi<$tbcnt; tbi++)) ; do
#-# 		if [ "${have[$ifi]}" = "${tb[$tbi]}" ] ; then
#-# 		    have[$ifi]=''
#-# 		    tb[$tbi]=''
#-# 	    fi
#-# 	    done
#-# 	done
#-#     done
#-# #turn array into string
     haveresult=${have[@]-""}
     tbresult=${tb[@]-""}
# comment out the next if statment and uncommet the #-# lines for drive
# ordering not to matter when comparing drives found with tbdb
Dan Reading's avatar
Dan Reading committed
292 293
     if [[ "$haveresult" != "$tbresult" ]] ; then
	 failed=" found $haveresult but tbdb says $tbresult "
294 295
     fi
#-#     
Dan Reading's avatar
Dan Reading committed
296
#-#     if [[ "$haveresult" != "$tbresult" ]] ; then
297 298 299 300 301 302 303
#-# 	if [[ $haveresult ]] ; then
#-# 	    failed="${failed}: NotIn TB $haveresult"
#-# 	fi
#-# 	if [[ $tbresult ]] ; then
#-# 	    failed="${failed}: TB Claims $tbresult"
#-# 	fi
#-#     fi
304 305 306 307
    
    echo -n "Have $havecnt drive"
    [[ ${havecnt} -gt 1 ]] && echo -n "s" 
    [[ -z ${failed} ]] && echo " OK" || echo " $failed" FAILED
Dan Reading's avatar
Dan Reading committed
308 309

} > ${tmplog} 2>&1
310 311
    cat ${tmplog} >> $logfile
    cat ${tmplog}
312
fi # matching endif of (( $check_flag ))
Dan Reading's avatar
Dan Reading committed
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
}

getdriveinfo () {
#need to make sure smartcrl is installed
{
#    echo -n "${FUNCNAME[0]}:${LINENO} " ; echo "args::$@::"
    declare buildscan=""
    logout="$1"
    tmpout="$2"

    if [ "${SMARTCTL}" != "$NOSM" ] ; then
	rtn=$($SMARTCTL --scan)
	# unrecongnized
	if [ -n "$(echo $rtn | grep 'UNRECOGNIZED OPTION')" ] ; then
	    error="(smartctl option '--scan' not supported. Attempt alternet method) "
	    err=scan
	elif [ -n "$(echo $rtn | grep -v 'device')" ] ; then
            # output in unexpected format - missing deliminator "device"
	    error="(smartctl option '--scan' strange ouput. Attempt alternet method) "
	    err=scan
	# empty
	elif [ -z "$rtn" ] ; then
	    dt=$(df / | grep /dev)
	    dt=${dt:5}
	    dt=${dt%% *}
	    error="(smartctl device_type '$dt' not supported"
	    err=device
	fi
	[[ $error ]] && echo "$error"
    else
	error="smartmontools missing."
	err="missing"
	echo "$error. FAIL "
    fi
} > ${logout} 2>&1

# put smartctl --scan into driveinv array
# a better control flow control could be used 

placeholder=" . . . . . device"
case $err in
    scan | missing | device )
	case $os in
	    Linux )
		list="a b c d e f g h i j k l m n o p"
		for i in $list
		do
		    if [ -b /dev/sd${i} ] ; then
			buildscan+="/dev/sd${i} $placeholder"
		    fi
		done
		;;
	    FreeBSD )
		list="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
		for i in $list
		do
		    [[ -b /dev/da${i} ]] && buildscan+="/dev/da${i} $placeholder " 
		    [[ -c /dev/ad${i} ]] && buildscan+="/dev/ad${i} $placeholder " 
		    [[ -c /dev/amrd${i} ]] && buildscan+="/dev/amrd${i} $placeholder " 
		done
		;;
	    * )
		echo "${FUNCNAME[0]}:${LINENO} Internal error"
376
		(( $diskcheck_standalone )) && exit 1 || return 1
Dan Reading's avatar
Dan Reading committed
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
		;;
	esac
	unset -v scan
	[[ $buildscan ]] && declare -a scan=($buildscan) || declare -a scan=("")
#	echo -n "${FUNCNAME[0]}:${LINENO} " ; echo "buildscan::${buildscan}::"
	;;
    root )
	echo -n "$error. FAIL " >> ${tmpout}
	echo "Last attempt return roots mount point" >> ${tmpout}
	x=$(df / | grep /dev)
	lastattempt="${x%% *} $placeholder "
	unset -v scan ; declare -a scan=($lastattempt)
	;;
    * )
        # get the output of --scan into array scan
	 unset -v scan ; declare -a scan=($rtn)
#	 echo -n "${FUNCNAME[0]}:${LINENO} " ; echo "rtn::${rtn}::"
	;;
esac

# the result
echo -n "${scan[@]}"

}

getdriver() { 
    # don't support this right now
#    smtcl=$(findSmartctl)
#    if [ "${smtcl/smartcl}" == "$smtcl" ] ; then
#	echo "UNKNOWN"
#	return 0
#    fi
409
    echo "NoInfo"
Dan Reading's avatar
Dan Reading committed
410 411 412 413 414
    return 0
}
gettype() { 
    smtcl=$(findSmartctl)
    if [ "${smtcl/smartctl}" == "$smtcl" ] ; then
415
	echo "NoInfo"
Dan Reading's avatar
Dan Reading committed
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
	return 0
    fi
    res=$($smtcl -i $1 | grep "ATA Version is")
    if [ -n "$res" ] ; then
	res=${res##*is: }
	res=${res// /} #get rid of spaces
	[[ $res > 6 ]] && res="SATA" || res="PATA"
	echo $res
	return 0
    fi
    res=$($smtcl -i $1 | grep "SAS")
    if [ -n "$res" ] ; then
	echo "SAS"
	return 0
    fi
    res=$($smtcl -i $1 | grep "SCSI")
    if [ -n "$res" ] ; then
	echo "SCSI"
	return 0
    fi
    echo "UNKNOWN"
    return 0
}
gettemp() { 
    smtcl=$(findSmartctl)
    if [ "${smtcl/smartctl}" == "$smtcl" ] ; then
442
	echo "NoInfo"
Dan Reading's avatar
Dan Reading committed
443 444 445 446 447 448 449 450 451 452 453 454
	return 0
    fi
    res="$($smtcl  -l scttempsts $1 | grep -i "Current Temperature:" | awk '{print $3}')"
    if [ -z $res ] ; then
        #type 2
	res="$($smtcl -a $1 | grep -i "Current Drive Temperature:" | awk '{print $4}')"
    fi
    [[ $res ]] && echo $res || echo "UNKNOWN"
    return 0
}
getmodel() { 
    smtcl=$(findSmartctl)
Dan Reading's avatar
Dan Reading committed
455

Dan Reading's avatar
Dan Reading committed
456 457 458 459 460 461 462 463 464 465 466 467
    if [ "${smtcl/smartctl}" == "$smtcl" ] ; then
	#don't have smartctl, maybe we can use hdparm
	hdp=$(which hdparm)
	if [ "${hdp/hdparm}" != "${hdp}" ] ; then
	    x=$(hdparm -I $1 | grep -i 'Model Number:')
	    x=${x/Model Number: }
	    res=${x/# */}
	    res=${res%# */}
	    # note: can get the model from '/proc/scsi/scsi'
	else
	    # XXX 	# note: 'camcontrol devlist'
	                # will give model on FreeBSD
468
	    echo "NoInfo"
Dan Reading's avatar
Dan Reading committed
469 470 471 472 473 474 475 476 477 478
	    return 0
	fi
    else
	res=$($smtcl -a $1 | grep 'Device Model:')
	res=${res/Device Model: }
	if [ -z "$res" ] ; then
	    res=$($smtcl -a $1 | grep 'Product:')
	    res=${res/Product: }
	fi
        # remove leading spaces
Dan Reading's avatar
Dan Reading committed
479
#	res=${res##* }
Dan Reading's avatar
Dan Reading committed
480 481 482 483
    fi
    # no internal spaces
    res=${res// /}
    res=${res// /-}
Dan Reading's avatar
Dan Reading committed
484 485


Dan Reading's avatar
Dan Reading committed
486 487 488 489 490 491 492 493 494 495 496
    [[ $res ]] && echo "$res" || echo "UNKNOWN"
    return 0
}
getserial() {
    res=""
    if [ "$os" == "Linux" ] ; then
	smtcl=$(findSmartctl)
	if [ "${smtcl/smartctl}" == "$smtcl" ] ; then
	#don't have smartctl, maybe we can use hdparm
	    hdp=$(which hdparm)
	    if [ "${hdp/hdparm}" != "${hdp}" ] ; then
497
		res=$(hdparm -I $1 2>/dev/null | grep -i 'Serial number:')
Dan Reading's avatar
Dan Reading committed
498 499 500 501 502 503 504 505 506 507 508 509
	    fi
	else
	    res=$($smtcl -a $1 | grep -i 'Serial number:')
	fi
	res=${res,,} # lower case
	res=${res/serial number: }
#	res=$(echo $res | tr 'a-z' 'A-Z') # upper case
	res=${res^^} # upper case
    fi
    if [ "$os" == "FreeBSD" ] ; then
	# note: if the device is mfi then 'mfiutil show drives' will list
	# serial numbers 
510 511 512 513 514 515 516
	smtcl=$(findSmartctl)
	if [ "${smtcl/smartctl}" == "$smtcl" ] ; then
	#don't have smartctl, maybe we can use camcontrol
	    cmc=$(which camcontrol)
	    if [ "${cmc/camcontrol}" != "${cmc}" ] ; then
		sd=$1
		sd=${sd#/dev/}
517
		res=$(camcontrol inquiry $sd -S 2>/dev/null)
518 519 520 521 522 523 524
	    fi
	else
	    res=$($smtcl -a $1 | grep -i 'Serial number:')
	    res=${res,,} # lower case
	    res=${res/serial number: }
#	    res=$(echo $res | tr 'a-z' 'A-Z') # upper case
	    res=${res^^} # upper case
Dan Reading's avatar
Dan Reading committed
525 526 527 528 529
	fi
    fi
    [[ $res ]] && echo "$res" || echo "UNKNOWN"
    return 0
}
530
getwcache() {
531
    res="NA"
532 533 534
    if [ "$os" == "Linux" ] ; then
	smtcl=$(findSmartctl_getopt)
	if [ "${smtcl/smartctl}" == "$smtcl" ] ; then
535
	    # don't have smartctl, maybe we can use hdparm
536 537 538
	    hdp=$(which hdparm)
	    if [ "${hdp/hdparm}" != "${hdp}" ] ; then
		x=$(hdparm -W $1 2>/dev/null | grep -i 'write-caching')
539
		if [ "${x/on}" != "$x" ] ; then
540
		    res="enabled"
541 542
		elif [ "${x/off}" != "$x" ] ; then
		    res="disabled"
543
		    hdparm -W1 $1  > /dev/null 2>&1
544 545 546
		fi
	    fi
	else
547 548
	    x=$($smtcl --get=wcache $1 | grep -i Write | grep -i cache)
	    if [ "${x/Enabled}" != "$x" ] ; then
549
		res="enabled"
550 551
	    elif [ "${x/Disabled}" != "$x" ] ; then
		res="disabled"
552
		$smtcl --set=wcache,on $1 > /dev/null 2>&1
553 554
	    else
		res="WCE_not_supported"
555 556
	    fi
	fi
557 558
    elif [ "$os" == "FreeBSD" ] ; then
	# try camcontrol first
559 560 561 562 563
	if [ "$osrel" == "10" ] ; then
	    cmc=$(which camcontrol10)
	else
	    cmc=$(which camcontrol)
	fi
564
#set -x
565 566
	if [ "${cmc/camcontrol}" != "${cmc}" ] ; then
	    sd=${1#/dev/}		
Mike Hibler's avatar
Mike Hibler committed
567
	    x=$(camcontrol modepage $sd -m8 2>/dev/null | grep WCE)
568 569 570 571
	    if [ "${x/1}" != "$x" ] ; then
		res="enabled"
	    elif [ "${x/0}" != "$x" ] ; then
		res="disabled"
Dan Reading's avatar
Dan Reading committed
572
#		printf " %s:%s\n"  "Setting WCE" "$sd" >> ${logfile4tb}
573 574
		/usr/local/etc/emulab/camwce -P on $sd  > /dev/null 2>&1
	    fi
575
	fi
576
#set +x
577 578
	# don't have don't have camcontrol or it did not work, try smartctl
	if [ "$res" == "NA" ] ; then
579 580 581 582
	    smtcl=$(findSmartctl_getopt)
	    if [ "${smtcl/smartctl}" != "$smtcl" ] ; then
		x=$($smtcl --get=wcache $1 | grep -i Write | grep -i cache)
		if [ "${x/Enabled}" != "$x" ] ; then
583
		    res="enabled"
584
		elif [ "${x/Disabled}" != "$x" ] ; then
585
		    res="disabled"
586
		    $smtcl --set=wcache,on $1 > /dev/null 2>&1
587 588 589
		fi
	    fi
	fi
590 591 592
    else
	echo "try to get WCE unknown OS $os"
	return 0
593 594 595 596
    fi
    [[ $res ]] && echo "$res" || echo "UNKNOWN"
    return 0
}
Dan Reading's avatar
Dan Reading committed
597 598 599 600 601 602 603
getbpers() { 
    hdname=$1
    case $os in
	Linux )
	    hdname=${hdname##*/}
	    res=$(dmesg | grep "logical blocks" | grep $hdname)
	    if [ -z "$res" ] ; then
604
		res=$(dmesg | grep "hardware sectors" | grep $hdname)
Dan Reading's avatar
Dan Reading committed
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
	    fi
	    res=${res%%-byte *}
	    res=${res##*] }
	    res=${res#* }
	    [[ $res ]] || res=512
	    ;;
	FreeBSD )
	    hdname=${hdname##*/}
	    res=$(grep sectors /var/run/dmesg.boot | grep $hdname)
	    if [ -z "$res" ] ; then
		hdnamex=${hdname/ad/ada}
		res=$(grep sectors /var/run/dmesg.boot | grep $hdnamex)
		if [ -z "$res" ] ; then
		    echo 512
		    return 0
		fi
	    fi
	    if [ "$res" == "${res/sectors)}" ] ; then
		# this format: "da0: 140014MB (286749480 512 byte sectors: 255H 63S/T 17849C)"
		res=${res%%byte sectors*}
		res=${res##*(}
		res=${res#* }
	    else
		# this format: "mfid0: 5869927MB (12021612416 sectors) RAID volume '' is optimal"
		# just assume 512
		res=512
	    fi
	    [[ $res ]] || res=512
	    ;;
	* ) echo "$FUNCNAME internal error"
635
	(( $diskcheck_standalone )) && exit 1 || return 1
Dan Reading's avatar
Dan Reading committed
636 637 638 639 640 641 642 643 644 645 646 647 648
	    ;;
    esac
    echo $res
    return 0
}

getsectors() { 
    hdname=$1
    case $os in
	Linux )
	    hdname=${hdname##*/}
	    res=$(dmesg | grep "logical blocks" | grep $hdname)
	    if [ -z "$res" ] ; then
649 650 651
		res=$(dmesg | grep "hardware sectors" | grep $hdname)
	    else
		res=${res%%-byte *}
Dan Reading's avatar
Dan Reading committed
652 653
	    fi
	    res=${res##*] }
654
            res=${res%% *}
Dan Reading's avatar
Dan Reading committed
655 656 657 658 659 660
	    [[ $res ]] || res=0
	    ;;
	FreeBSD )
	    hdname=${hdname##*/}
	    res=$(grep sectors /var/run/dmesg.boot | grep $hdname)
	    if [ -z "$res" ] ; then
Mike Hibler's avatar
Mike Hibler committed
661 662 663 664 665 666 667 668 669 670 671 672
		# XXX fixme right
		case $hdname in
		    ad4 ) hdnamex="ada0" ;;
		    ad6 ) hdnamex="ada1" ;;
		    ad8 ) hdnamex="ada2" ;;
		    ad10 ) hdnamex="ada3" ;;
		    ad12 ) hdnamex="ada4" ;;
		    ad14 ) hdnamex="ada5" ;;
		    ad16 ) hdnamex="ada6" ;;
		    ad18 ) hdnamex="ada7" ;;
		    * )   hdnamex=$hdname ;;
		esac
Dan Reading's avatar
Dan Reading committed
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700
		res=$(grep sectors /var/run/dmesg.boot | grep $hdnamex)
		if [ -z "$res" ] ; then
		    res=$(grep ${hdname} /var/run/dmesg.boot)
		    if [ -z "$res" ] ; then
			echo 0
			return 0
		    fi
		    # fake and go by the size 
		    res=${res%%MB*}
		    res=${res##* }
		    echo $(( $res * 2048 )) # assume 512 byte sectors
		    return 0
		fi
	    fi
	    if [ "$res" == "${res/sectors)}" ] ; then
	        # this format: "da0: 140014MB (286749480 512 byte sectors: 255H 63S/T 17849C)"
		res=${res%%byte sectors*} # truncate 'byte sectors' to end
		res=${res##*(} # chop off begining to sector number
		res=${res%% *} # get rid of everthing after the space
	    else
		# this format: "mfid0: 5869927MB (12021612416 sectors) RAID volume '' is optimal"
		res=${res%%sectors)*}
		res=${res##*(}
		res=${res%% *}
	    fi
	    [[ $res ]] || res=0
	    ;;
	* ) echo "$FUNCNAME internal error"
701
	(( $diskcheck_standalone )) && exit 1 || return 1
Dan Reading's avatar
Dan Reading committed
702 703 704 705 706 707
	    ;;
    esac
    echo $res
    return 0
}

708 709 710 711 712 713 714

getwspeed() {
    hdname=$1
    # disk is mounted somewhere then don't do the raw write speed
    canwe=$(df | grep $hdname)
    [[ $canwe ]] && { echo mounted; return 0; }

Dan Reading's avatar
Dan Reading committed
715
    dd=$USE_DD
716 717 718
    [[ -x $dd ]] || { echo "$dd"; return 0; }
    args=$(ddargs)

Dan Reading's avatar
Dan Reading committed
719
    add_on_exit 'rm -f /tmp/ddresultw'
Dan Reading's avatar
Dan Reading committed
720
    [[ -n "$TDD_DD" ]] && export TDD_DD
Mike Hibler's avatar
Mike Hibler committed
721
    $dd if=/dev/zero of=$hdname $args >/tmp/ddresultw 2>&1
Dan Reading's avatar
Dan Reading committed
722
    res=$(grep bytes /tmp/ddresultw)
723

Dan Reading's avatar
Dan Reading committed
724 725 726
    echo $(parsedd $res)
    return 0
}
727

Dan Reading's avatar
Dan Reading committed
728 729
getrspeed() { 
    hdname=$1
730

Dan Reading's avatar
Dan Reading committed
731
    # do we have a working dd
Dan Reading's avatar
Dan Reading committed
732
    dd=$USE_DD
733 734
    [[ -x $dd ]] || { echo "$dd"; return 0; }
    args=$(ddargs)
735

Dan Reading's avatar
Dan Reading committed
736
    add_on_exit 'rm -f /tmp/ddresultr'
Dan Reading's avatar
Dan Reading committed
737
    [[ -n "$TDD_DD" ]] && export TDD_DD
Mike Hibler's avatar
Mike Hibler committed
738
    $dd of=/dev/null if=$hdname $args >/tmp/ddresultr 2>&1
Dan Reading's avatar
Dan Reading committed
739
    res=$(grep bytes /tmp/ddresultr)
740

Dan Reading's avatar
Dan Reading committed
741 742 743 744 745 746 747 748
    echo $(parsedd $res)
    return 0
}

parsedd() {
    if [ "$os" == "Linux" ] ; then 
	# linux dd returns 9 positional elements
	if [ $# -lt 9 ] ; then
749
	    x="DDparseERR"
Dan Reading's avatar
Dan Reading committed
750 751 752 753 754
	else
	    y=$9
	    if [ $y != ${y/MB} ] ; then
		x=$8
	    else
755
		x="ParesddError"
Dan Reading's avatar
Dan Reading committed
756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774
	    fi
	fi
    elif [ "$os" == "FreeBSD" ] ; then 
	if [ $# -lt 8 ] ; then
	    x="DDtimeinERR"
	else
            x=$7
	    x=${x#(}
	    y=$8
	    # FreeBSD seems to return val in bytes/sec, check and convirt to Mb/sec
	    if [ "$y" == "bytes/sec)" ] ; then
		x=$(( $x / 1048576 ))
	    fi
	fi
    fi
    echo $x
    return 0
}

775
main_diskcheck $@
Dan Reading's avatar
Dan Reading committed
776

777
(( $diskcheck_standalone )) && exit 0 || return 0