''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' NAME:		check_nt_megaraid.vbs
' VERSION:	0.2
' AUTHOR:	alexander.rudolf@saxsys.de
'
' Requires: megacli for windows
' Arch:     x86, AMD64
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Option explicit
Dim strMegacliBin,strMegacliBinAMD64
Dim strProgramFiles,strProgramFilesAMD64
Dim strMegacliOpts
Dim strMegacliCmdln
Dim strAdapter
Dim strNextLine
Dim strLogicalDriveStatus
Dim strLgOK, strLgNotOK
Dim strPdOK, strPdNotOK
Dim strNagiosText
Dim numPdEnclosure, numPdSlot, numPdMediaErrorCount, numPdOtherErrorCount, numPdPredFailureCount, numPdFwState
Dim strPdAttribute, strPdValue
Dim MegacliResult
Dim numLogicalDriveCount, numLogicalDrive
Dim numPhysicalDriveCount, numPhysicalDrive
Dim numLineLength, numPosColonSign
Dim numNagiosResult
Dim objArgs
Dim objFSO
Dim objWScriptShell

' Command line arguments

Set objArgs = WScript.Arguments

If objArgs.Count = 0 Then
	Wscript.echo "Invalid number of arguments: Missing adapter number."
	Wscript.quit(2)
End if

If objArgs.Count > 1 Then
	Wscript.echo "Invalid number of arguments: Only one adapter number is supported."
	Wscript.quit(2)
End if

If objArgs.Item(0) = "--help" then
	Wscript.echo "Usage: check_nt_megaraid.vbs [option]"
	Wscript.echo "[option] can be one of the following:"
	Wscript.echo "   adapter number - i.e. 0 [0-9 supported]"
	Wscript.echo "   --help      - shows this help"
	Wscript.quit(2)
End If

' Sanity check for given adapter number

strAdapter = WScript.Arguments.Item(0)

If Left(strAdapter,1) < "0" or Left(strAdapter,1) > "9" Then
	Wscript.echo "Invalid adapter number: " & strAdapter
	Wscript.quit(2)
End If

' Creating needed objects

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objWScriptShell = WScript.CreateObject("WScript.Shell")

' Compiling local path to megacli.exe

strProgramFiles = objWScriptShell.ExpandEnvironmentStrings("%PROGRAMFILES%")
strProgramFilesAMD64 = objWScriptShell.ExpandEnvironmentStrings("%PROGRAMFILES(x86)%")
strMegacliBin = strProgramFiles & "\Intel\Megaraid\megacli.exe"
strMegacliBinAMD64 = strProgramFilesAMD64 & "\Intel\Megaraid\megacli.exe"

If NOT objFSO.fileExists(strMegacliBin) Then
	If objFSO.fileExists(strMegacliBinAMD64) Then
		strMegacliBin = strMegacliBinAMD64
	Else
		Wscript.echo "File not found: " & strMegacliBin
		If NOT strProgramFilesAMD64 = "%PROGRAMFILES(x86)%" Then
			Wscript.echo "                (" & strMegacliBinAMD64 & ")"
		End If
		Wscript.quit(2)
	End If
End if

' Command line for megacli.exe

strMegacliOpts = " -NoLog"

' Get number of virtual drives at this adapter

strMegacliCmdln = CHR(34) & strMegacliBin & CHR(34) & " -LdGetNum -a" & strAdapter & strMegacliOpts

Set MegacliResult = objWScriptShell.Exec(strMegacliCmdln)

Do while MegacliResult.StdOut.AtEndOfStream = false
	strNextLine = trim(MegacliResult.StdOut.Readline)
	numPosColonSign = instr(strNextLine,":")
	numLineLength = len(strNextLine)
	If not numLineLength = 0 Then
		If not numPosColonSign = 0 Then
			If Ucase(Trim(Left(strNextLine,(numPosColonSign - 1)))) = ("NUMBER OF VIRTUAL DRIVES CONFIGURED ON ADAPTER " & strAdapter ) Then
				numLogicalDriveCount = cInt(Trim(Right(strNextLine,(numLineLength - numPosColonSign))))
			End if
		End if
	End if
Loop

' for debugging
' Wscript.echo "numLogicalDriveCount = " & numLogicalDriveCount

' Get status of logical drives

numLogicalDrive = 0
strLgOK = ""

Do until numLogicalDrive > (numLogicalDriveCount -1)
	strMegacliCmdln = CHR(34) & strMegacliBin & CHR(34) & " -LdInfo -L" & numLogicalDrive & " -a" & strAdapter & strMegacliOpts
	Set MegacliResult = objWScriptShell.Exec(strMegacliCmdln)
	Do while MegacliResult.StdOut.AtEndOfStream = false
		strNextLine = trim(MegacliResult.StdOut.Readline)
		numPosColonSign = instr(strNextLine,":")
		numLineLength = len(strNextLine)
		If not numLineLength = 0 Then
			If not numPosColonSign = 0 Then
				If Ucase(Trim(Left(strNextLine,(numPosColonSign - 1)))) = "STATE" Then
					strLogicalDriveStatus = Trim(Right(strNextLine,(numLineLength - numPosColonSign)))
				End if
			End if
		End if
	Loop
	If ucase(strLogicalDriveStatus) = "OPTIMAL" Then
		strLgOK = strLgOK & numLogicalDrive & ","
	Else
		strLgNotOK = strLgNotOK & numLogicalDrive & "[" & strLogicalDriveStatus & "],"
	End If
	numLogicalDrive = numLogicalDrive + 1
Loop

If NOT strLgOK = "" Then
	strLgOK = Left(strLgOK,(Len(strLgOK) - 1))
End If

If NOT strLgNotOK = "" Then
	strLgNotOK = Left(strLgNotOK,(Len(strLgNotOK) - 1))
End If

' Wscript.echo "strLgOK = " & strLgOK
' Wscript.echo "strLgNotOK = " & strLgNotOK

' Get status of physical drives at this adapter

strMegacliCmdln = CHR(34) & strMegacliBin & CHR(34) & " -PdList -a" & strAdapter & strMegacliOpts

Set MegacliResult = objWScriptShell.Exec(strMegacliCmdln)

numPdEnclosure = -1
numPdSlot = -1
numPdMediaErrorCount = -1
numPdOtherErrorCount = -1
numPdPredFailureCount = -1
numPdFwState = -1

Do while MegacliResult.StdOut.AtEndOfStream = false
	strNextLine = trim(MegacliResult.StdOut.Readline)
	numPosColonSign = instr(strNextLine,":")
	numLineLength = len(strNextLine)
'	If not numLineLength = 0 Then
		If not numPosColonSign = 0 Then
			strPdAttribute = Ucase(Trim(Left(strNextLine,(numPosColonSign - 1))))
			strPdValue = Trim(Right(strNextLine,(numLineLength - numPosColonSign)))

			' Wscript.echo "strPdAttribute " & strPdAttribute
			' Wscript.echo "strPdValue " & strPdValue

			If strPdAttribute = "ENCLOSURE POSITION" Then
				numPdEnclosure = cInt(strPdValue)
			End if
			
			Select Case strPdAttribute
				Case "ENCLOSURE POSITION"
					numPdEnclosure = cInt(strPdValue)
				Case "SLOT NUMBER"
					numPdSlot = cInt(strPdValue)
				Case "MEDIA ERROR COUNT"
					numPdMediaErrorCount = cInt(strPdValue)
				Case "OTHER ERROR COUNT"
					numPdOtherErrorCount = cInt(strPdValue)
				Case "PREDICTIVE FAILURE COUNT"
					numPdPredFailureCount = cInt(strPdValue)
				Case "FIRMWARE STATE"
					If ucase(strPdValue) = "ONLINE, SPUN UP" Then
						numPdFwState = 0
					Else
						numPdFwState = 1
					End if				
			End Select
		Else
			If (numPdEnclosure + numPdSlot + numPdMediaErrorCount + numPdOtherErrorCount + numPdPredFailureCount + numPdFwState) > -6 Then
' for debugging
'				Wscript.echo "************************************************************"
'				Wscript.echo "* numPdEnclosure = " & numPdEnclosure
'				Wscript.echo "* numPdSlot = " & numPdSlot
'				Wscript.echo "* numPdMediaErrorCount = " & numPdMediaErrorCount
'				Wscript.echo "* numPdOtherErrorCount = " & numPdOtherErrorCount
'				Wscript.echo "* numPdPredFailureCount = " & numPdPredFailureCount
'				Wscript.echo "* numPdFwState = " & numPdFwState
				If (numPdMediaErrorCount + numPdOtherErrorCount + numPdPredFailureCount + numPdFwState) = 0 Then
					strPdOK = strPdOK & numPdEnclosure & ":" & numPdSlot & "," 
				Else
					strPdNotOK = strPdNotOK & numPdEnclosure & ":" & numPdSlot & ","
				End if
			End If
			numPdEnclosure = -1
			numPdSlot = -1
			numPdMediaErrorCount = -1
			numPdOtherErrorCount = -1
			numPdPredFailureCount = -1
			numPdFwState = -1
		End if
'	End if
Loop

If NOT strPdOK = "" Then
	strPdOK = Left(strPdOK,(Len(strPdOK) - 1))
End If

If NOT strPdNotOK = "" Then
	strPdNotOK = Left(strPdNotOK,(Len(strPdNotOK) - 1))
End If

' for debugging
' Wscript.echo "strPdOK = " & strPdOK
' Wscript.echo "strPdNotOK = " & strPdNotOK


' Compute overall check result

If (strLgNotOK & strPdNotOK) = "" Then
	strNagiosText = "OK - Logical drives: " & strLgOK & " Phyical drives: " & strPdOK
	numNagiosResult = 0
Else
	strNagiosText = "ERROR - "
		If strLgNotOK > "" Then
			strNagiosText = strNagiosText & "Failing logical drives: " & strLgNotOK & " "
		End if
		If strPdNotOK > "" Then
			strNagiosText = strNagiosText & "Failing physical drives: " & strPdNotOK & " "
		End if
	numNagiosResult = 2
End if	
	
' Handover results

Wscript.echo strNagiosText
Wscript.quit(numNagiosResult)
