├── .gitignore ├── README.md ├── adaptec-raid.png ├── adaptec-raid.ps1 ├── adaptec-raid.sh ├── userparameter_adaptec_raid_linux.conf ├── userparameter_adaptec_raid_win.conf └── zbx_adaptec_raid.xml /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | zbx-adaptec-raid.zip 3 | *.zip 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zbx-adaptec-raid 2 | Zabbix Template and PowerShell\BASH script with Low Level Discovery (LLD) for Adaptec RAID Controllers. 3 | For Windows and Linux. 4 | 5 | ![alt_text](https://github.com/GOID1989/zbx-adaptec-raid/blob/master/adaptec-raid.png) 6 | 7 | ## Prerequisites: 8 | - Adaptec Storage Manager CLI Tools (Windows and Linux) 9 | - Add UserParameter to zabbix-agent config 10 | - Smartmon tool on linux if you wish to monitor the smart values of the drives 11 | 12 | **ToDO:** 13 | - [X] Temperature monitoring 14 | - [X] Battery status check 15 | 16 | **Tested on:** 17 | - Adaptec 6805 18 | - Adaptec 6405 19 | - Adaptec 2405 20 | - Adaptec 5405 21 | - Adaptec 8885q 22 | - AAR-2820SA 23 | - Windows 2008r2 24 | - Windows 2012r2 25 | - Windows 2016 26 | - Debian 6 27 | 28 | ## Notice 29 | - Script written with LLD-support for Multi-controller env - ~~BUT not tested!~~ (tested) Please notify me if check this in those conf. 30 | - On Linux machine Battery LLD not tested 31 | - Trigger value for Temperature got from [Official Post](http://ask.microsemi.com/app/answers/detail/a_id/15345/~/temperature-requirement-for-series-2%2C-5%2C-6%2C-7%2C-and-8-adaptec-raid-controllers) 32 | -------------------------------------------------------------------------------- /adaptec-raid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GOID1989/zbx-adaptec-raid/32437964272f01aed6a1911a221bcbe1ecb36540/adaptec-raid.png -------------------------------------------------------------------------------- /adaptec-raid.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .VERSION 3 | 0.2 4 | 5 | .SYNOPSIS 6 | Script with LLD support for getting data from Adaptec RAID Controller to Zabbix monitoring system. 7 | 8 | .DESCRIPTION 9 | The script may generate LLD data for Adaptec RAID Controllers, Logical Drives, Physical Drives. 10 | 11 | .NOTES 12 | Author: GOID1989 13 | Github: https://github.com/GOID1989/zbx-adaptec-raid 14 | #> 15 | 16 | Param ( 17 | [switch]$version = $false, 18 | [ValidateSet("lld","health")][Parameter(Position=0, Mandatory=$True)][string]$action, 19 | [ValidateSet("ad","ld","pd","bt")][Parameter(Position=1, Mandatory=$True)][string]$part, 20 | [string][Parameter(Position=2)]$ctrlid, 21 | [string][Parameter(Position=3)]$partid 22 | ) 23 | 24 | $cli = "C:\Program Files\Adaptec\Adaptec Storage Manager\arcconf.exe" 25 | 26 | function LLDControllers() 27 | { 28 | $response = & $cli "GETVERSION".Split() | Where-Object {$_ -match "^Controllers found"} 29 | $ctrl_count = ($response -replace 'Controllers found: ','').Trim() 30 | 31 | for($i = 1; $i -le $ctrl_count; $i++ ){ 32 | [array]$response = & $cli "GETCONFIG $i AD".Split() 33 | 34 | $ctrl_model = (($response[6] -split ':')[1]).Trim() 35 | $ctrl_sn = (($response[7] -split ':')[1]).Trim() 36 | 37 | $ctrl_info = [string]::Format('{{"{{#CTRL.ID}}":"{0}","{{#CTRL.MODEL}}":"{1}","{{#CTRL.SN}}":"{2}"}},',$i,$ctrl_model, $ctrl_sn) 38 | $ctrl_json += $ctrl_info 39 | } 40 | 41 | $lld_data = '{"data":[' + $($ctrl_json -replace ',$') + ']}' 42 | return $lld_data 43 | } 44 | 45 | function LLDBattery() 46 | { 47 | $response = & $cli "GETVERSION".Split() | Where-Object {$_ -match "^Controllers found"} 48 | $ctrl_count = ($response -replace 'Controllers found: ','').Trim() 49 | 50 | for($i = 1; $i -le $ctrl_count; $i++ ){ 51 | $response = & $cli "GETCONFIG $i ad".Split() | Where-Object {$_ -match "Controller Battery Information"} 52 | if($response.Length -ne 0){ 53 | $response = & $cli "GETCONFIG $i ad".Split() | Where-Object {$_ -match "^\s+Status\s+[:]"} 54 | if($response.Length -gt 0) { 55 | $ctrl_info = [string]::Format('{{"{{#CTRL.ID}}":"{0}","{{#CTRL.BATTERY}}":"{1}"}},',$i,$i) 56 | $ctrl_json += $ctrl_info 57 | } 58 | } 59 | } 60 | 61 | $lld_data = '{"data":[' + $($ctrl_json -replace ',$') + ']}' 62 | return $lld_data 63 | } 64 | 65 | function LLDLogicalDrives() 66 | { 67 | $response = & $cli "GETVERSION".Split() | Where-Object {$_ -match "^Controllers found"} 68 | $ctrl_count = ($response -replace 'Controllers found: ','').Trim() 69 | 70 | for($i = 1; $i -le $ctrl_count; $i++ ){ 71 | $response = & $cli "GETCONFIG $i ad".Split() | Where-Object {$_ -match "Logical devices/Failed/Degraded"} 72 | $res = $response -match '[:\s](\d+)' 73 | $ld_count = $Matches[1] 74 | 75 | #Get IDs of logical devices 76 | [array]$response = & $cli "GETCONFIG $i ld".Split() | Where-Object {$_ -match "Logical device number"} 77 | 78 | foreach($logical_dev in $response){ 79 | $res = ($logical_dev -match '\d+$') 80 | $ld_id = $Matches[0] 81 | 82 | [array]$response = & $cli "GETCONFIG $i ld $ld_id".Split() | Where-Object {$_ -match "Logical device name|RAID level"} 83 | 84 | $ld_name = ($response[0] -split ':')[1].Trim() 85 | $ld_raid = ($response[1] -split ':')[1].Trim() 86 | 87 | # If name of LD not set 88 | if($ld_name -eq "") { $ld_name = $ld_id } 89 | 90 | $ld_info = [string]::Format('{{"{{#CTRL.ID}}":"{0}","{{#LD.ID}}":"{1}","{{#LD.NAME}}":"{2}","{{#LD.RAID}}":"{3}"}},',$i,$ld_id, $ld_name,$ld_raid) 91 | $ld_json += $ld_info 92 | } 93 | } 94 | 95 | $lld_data = '{"data":[' + $($ld_json -replace ',$') + ']}' 96 | return $lld_data 97 | } 98 | 99 | function LLDPhysicalDrives() 100 | { 101 | $response = & $cli "GETVERSION".Split() | Where-Object {$_ -match "^Controllers found"} 102 | $ctrl_count = ($response -replace 'Controllers found: ','').Trim() 103 | 104 | for($i = 1; $i -le $ctrl_count; $i++ ){ 105 | [array]$response = & $cli "GETCONFIG $i pd".Split() | Where-Object {$_ -match "Device\s[#]\d+|Device is "} 106 | 107 | for($j = 0; $j -lt $response.Length;){ 108 | if($response[$j+1] -match "Hard drive"){ 109 | $pd_id = ($response[$j] -replace "Device #").Trim() 110 | 111 | $pd_info = [string]::Format('{{"{{#CTRL.ID}}":"{0}","{{#PD.ID}}":"{1}"}},',$i,$pd_id) 112 | $pd_json += $pd_info 113 | } 114 | $j = $j + 2 115 | } 116 | } 117 | $lld_data = '{"data":[' + $($pd_json -replace ',$') + ']}' 118 | return $lld_data 119 | } 120 | 121 | function GetControllerStatus() 122 | { 123 | Param ( 124 | # Controller component 125 | [ValidateSet("main","battery","temperature")][string]$ctrl_part 126 | ) 127 | 128 | switch($ctrl_part){ 129 | "main" { 130 | $response = & $cli "GETCONFIG $ctrlid ad".Split() | Where-Object {$_ -match "Controller Status"} 131 | $ctrl_status = ($response -split ':')[1].Trim() 132 | } 133 | "battery" { 134 | $response = & $cli "GETCONFIG $ctrlid ad".Split() | Where-Object {$_ -match "^\s+Status\s+[:]"} 135 | if($response.Length -ne 0) { 136 | $ctrl_status = ($response -split ':')[1].Trim() 137 | } else { 138 | $ctrl_status = "No battery module" 139 | } 140 | } 141 | "temperature" { 142 | $response = & $cli "GETCONFIG $ctrlid ad".Split() | Where-Object {$_ -match "^\s+Temperature\s+[:]"} 143 | # Exctract Celsius value 144 | $res = $response -match '(\d+).*[C]' 145 | $ctrl_status = $Matches[1] 146 | } 147 | } 148 | 149 | return $ctrl_status 150 | } 151 | 152 | function GetLogicalDriveStatus() 153 | { 154 | $response = & $cli "GETCONFIG $ctrlid ld $partid".Split() | Where-Object {$_ -match "Status of logical device"} 155 | $ld_status = ($response -split ':')[1].Trim() 156 | return $ld_status 157 | } 158 | 159 | function GetPhysicalDriveStatus() 160 | { 161 | [array]$response = & $cli "GETCONFIG $ctrlid pd".Split() | Where-Object {$_ -match "^\s+State\s+[:] "} 162 | 163 | $pd_status = ($response[$partid] -split ':')[1].Trim() 164 | return $pd_status 165 | } 166 | 167 | switch($action){ 168 | "lld" { 169 | switch($part){ 170 | "ad" { write-host $(LLDControllers) } 171 | "ld" { write-host $(LLDLogicalDrives)} 172 | "pd" { write-host $(LLDPhysicalDrives)} 173 | "bt" { write-host $(LLDBattery)} 174 | } 175 | } 176 | "health" { 177 | switch($part) { 178 | "ad" { write-host $(GetControllerStatus -ctrl_part $partid) } 179 | "ld" { write-host $(GetLogicalDriveStatus)} 180 | "pd" { write-host $(GetPhysicalDriveStatus) } 181 | } 182 | } 183 | default {Write-Host "ERROR: Wrong argument: use 'lld' or 'health'"} 184 | } 185 | -------------------------------------------------------------------------------- /adaptec-raid.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # .VERSION 3 | # 0.2 4 | # 5 | # .SYNOPSIS 6 | # Script with LLD support for getting data from Adaptec RAID Controller to Zabbix monitoring system. 7 | # 8 | # .DESCRIPTION 9 | # The script may generate LLD data for Adaptec RAID Controllers, Logical Drives, Physical Drives. 10 | # 11 | # .NOTES 12 | # Author: GOID1989 13 | # Github: https://github.com/GOID1989/zbx-adaptec-raid 14 | # 15 | 16 | cli='/usr/local/sbin/arcconf' 17 | cli_sg='/usr/bin/sg_scan' 18 | cli_smart='/usr/sbin/smartctl' 19 | 20 | action=$1 21 | part=$2 22 | 23 | LLDControllers() { 24 | ctrl_count=$($cli GETCONFIG 1 AL | grep "Controllers found:" | cut -f2 -d":" | sed -e 's/^ //' ) 25 | 26 | i=1 27 | ctrl_json="" 28 | while [ $i -le $ctrl_count ] 29 | do 30 | ctrl_model=$($cli GETCONFIG $i AD | grep "Controller Model" | cut -f2 -d":" | sed -e 's/^ //' ) 31 | ctrl_sn=$($cli GETCONFIG $i AD | grep "Controller Serial Number" | cut -f2 -d":" | sed -e 's/^ //' ) 32 | 33 | ctrl_info="{\"{#CTRL.ID}\":\"$i\",\"{#CTRL.MODEL}\":\"$ctrl_model\",\"{#CTRL.SN}\":\"$ctrl_sn\"}," 34 | ctrl_json=$ctrl_json$ctrl_info 35 | 36 | i=$((i+1)) 37 | done 38 | 39 | ctrl_json=$(echo $ctrl_json | sed -e 's/,$//') 40 | lld_data="{\"data\":[$ctrl_json]}" 41 | 42 | echo $lld_data 43 | } 44 | 45 | LLDBattery() { 46 | # No controllers with battery on Linux machine 47 | # NEED SIMULATE 48 | ctrl_count=$($cli GETCONFIG 1 AL | grep "Controllers found:" | cut -f2 -d":" | sed -e 's/^ //' ) 49 | 50 | i=1 51 | bt_json="" 52 | while [ $i -le $ctrl_count ] 53 | do 54 | #ctrl_bt=$($cli GETCONFIG $i AD | grep "Controller Battery Information" ) 55 | len=${#ctrl_bt} 56 | if [ $len -ne 0 ] 57 | then 58 | bt_status=$($cli GETCONFIG $ctrl_id AD | grep -E "^\s+Status\s+[:]" | cut -f2 -d":" | sed -e 's/^ //' ) 59 | len=${#bt_status} 60 | if [ $len -ne 0 ] 61 | then 62 | bt_info="{\"{#CTRL.ID}\":\"$i\",\"{#CTRL.BATTERY}\":\"$i\"}," 63 | bt_json=$bt_json$bt_info 64 | fi 65 | fi 66 | i=$((i+1)) 67 | done 68 | 69 | bt_json=$(echo $bt_json | sed -e 's/,$//') 70 | lld_data="{\"data\":[$bt_json]}" 71 | 72 | echo $lld_data 73 | 74 | #echo "{\"data\":[]}" 75 | } 76 | 77 | LLDLogicalDrives() { 78 | ctrl_count=$($cli GETCONFIG 1 AL | grep "Controllers found:" | cut -f2 -d":" | sed -e 's/^ //' ) 79 | 80 | i=1 81 | ld_json="" 82 | while [ $i -le $ctrl_count ] 83 | do 84 | ld_count=$($cli GETCONFIG $i AD | grep "Logical devices/Failed/Degraded" | cut -f2 -d":" | cut -f1 -d"/" | sed -e 's/^ //' ) 85 | 86 | ld_ids=$($cli GETCONFIG $i LD | grep "Logical device number " | cut -f4 -d" " | sed -e 's/^ //' ) 87 | 88 | for ld_id in $ld_ids; do 89 | ld_name=$($cli GETCONFIG $i LD $ld_id | grep "Logical device name" | cut -f2 -d":" | sed -e 's/^ //' ) 90 | ld_raid=$($cli GETCONFIG $i LD $ld_id | grep "RAID level" | cut -f2 -d":" | sed -e 's/^ //' ) 91 | 92 | if [ "$ld_name" = "" ] 93 | then 94 | ld_name=$ld_id 95 | fi 96 | 97 | ld_info="{\"{#CTRL.ID}\":\"$i\",\"{#LD.ID}\":\"$ld_id\",\"{#LD.NAME}\":\"$ld_name\",\"{#LD.RAID}\":\"$ld_raid\"}," 98 | ld_json=$ld_json$ld_info 99 | done 100 | 101 | i=$((i+1)) 102 | done 103 | 104 | ld_json=$(echo $ld_json | sed -e 's/,$//') 105 | lld_data="{\"data\":[$ld_json]}" 106 | 107 | echo $lld_data 108 | } 109 | 110 | LLDPhysicalDrives() { 111 | ctrl_count=$($cli GETCONFIG 1 AL | grep "Controllers found:" | cut -f2 -d":" | sed -e 's/^ //' ) 112 | 113 | i=1 114 | pd_json="" 115 | while [ $i -le $ctrl_count ] 116 | do 117 | pd_list=($($cli GETCONFIG $i PD | grep "Device #" | cut -f2 -d"#" )) 118 | pd_list_type=($($cli GETCONFIG 1 PD | grep 'Device is a' | sed -e 's/ /_/g')) 119 | 120 | # ToDo: NEEED CHECK IS A HARD DRIVE OR SOMETHING ELSE 121 | for pd_id in "${pd_list[@]}"; do 122 | type=${pd_list_type[$pd_id]} 123 | case "$type" in 124 | "_________Device_is_a_Hard_drive") 125 | pd_info="{\"{#CTRL.ID}\":\"$i\",\"{#PD.ID}\":\"$pd_id\"}," 126 | pd_json=$pd_json$pd_info 127 | ;; 128 | esac 129 | done 130 | 131 | i=$((i+1)) 132 | done 133 | 134 | pd_json=$(echo $pd_json | sed -e 's/,$//') 135 | lld_data="{\"data\":[$pd_json]}" 136 | 137 | echo $lld_data 138 | } 139 | 140 | LLDSmart() { 141 | need_write="0" 142 | echo "{" 143 | echo "\"data\":[" 144 | $cli_sg | cut -f1 -d ":" | while read smart_dev 145 | do 146 | if [ $need_write = "1" ] 147 | then 148 | echo "," 149 | fi 150 | echo "{\"{#ADAPTEC_DISK}\":\"$smart_dev\"}" 151 | need_write="1" 152 | done 153 | echo "]" 154 | echo "}" 155 | } 156 | 157 | GetControllerStatus() { 158 | ctrl_id=$1 159 | ctrl_part=$2 160 | 161 | ctrl_status="" 162 | case "$ctrl_part" in 163 | "main") 164 | ctrl_status=$($cli GETCONFIG $ctrl_id AD | grep "Controller Status" | cut -f2 -d":" | sed -e 's/^ //' ) 165 | ;; 166 | "battery") 167 | ctrl_status=$($cli GETCONFIG $ctrl_id AD | grep -E "^\s+Status\s+[:]" | cut -f2 -d":" | sed -e 's/^ //' ) 168 | ;; 169 | "temperature") 170 | ctrl_status=$($cli GETCONFIG $ctrl_id AD | grep -E "^\s+Temperature\s+[:]" | cut -f2 -d":" | awk '{print $1}' ) 171 | ;; 172 | esac 173 | 174 | echo $ctrl_status 175 | } 176 | 177 | GetLogicalDriveStatus() { 178 | ctrl_id=$1 179 | ld_id=$2 180 | 181 | ld_status=$($cli GETCONFIG $ctrl_id LD $ld_id | grep "Status of logical device" | cut -f2 -d":" | sed -e 's/^ //' ) 182 | 183 | echo $ld_status 184 | } 185 | 186 | GetPhysicalDriveStatus() { 187 | ctrl_id=$1 188 | pd_id=$2 189 | pd_status=($($cli GETCONFIG $ctrl_id PD | grep -oP '^\s+State.*$' | cut -f2 -d":" )) 190 | 191 | echo ${pd_status[$pd_id]} 192 | } 193 | 194 | 195 | GetSmartHealth() { 196 | disk_dev=$1 197 | 198 | disk_health=$($cli_smart -H $disk_dev | grep "SMART Health Status" | cut -f2 -d":" | sed -e 's/^ //' ) 199 | echo $disk_health 200 | } 201 | 202 | GetSmartTemp() { 203 | disk_dev=$1 204 | 205 | disk_temp=$($cli_smart -A $disk_dev | grep "Current Drive Temperature" | cut -f2 -d":" | cut -f1 -d"C" | sed -e 's/^ //' ) 206 | echo $disk_temp 207 | } 208 | 209 | GetSmartTripTemp() { 210 | disk_dev=$1 211 | 212 | disk_temp=$($cli_smart -A $disk_dev | grep "Drive Trip Temperature" | cut -f2 -d":" | cut -f1 -d"C" | sed -e 's/^ //' ) 213 | echo $disk_temp 214 | } 215 | 216 | GetSmartDefects() { 217 | disk_dev=$1 218 | 219 | disk_defects=$($cli_smart -A $disk_dev | grep "Elements in grown defect list" | cut -f2 -d":" | sed -e 's/^ //' ) 220 | echo $disk_defects 221 | } 222 | 223 | case "$action" in 224 | "lld") 225 | case "$part" in 226 | "ad") 227 | LLDControllers 228 | ;; 229 | "ld") 230 | LLDLogicalDrives 231 | ;; 232 | "pd") 233 | LLDPhysicalDrives 234 | ;; 235 | "bt") 236 | LLDBattery 237 | ;; 238 | "smart") 239 | LLDSmart 240 | ;; 241 | esac 242 | ;; 243 | "health") 244 | case "$part" in 245 | "ad") 246 | GetControllerStatus "$3" "$4" 247 | ;; 248 | "ld") 249 | GetLogicalDriveStatus "$3" "$4" 250 | ;; 251 | "pd") 252 | GetPhysicalDriveStatus "$3" "$4" 253 | ;; 254 | esac 255 | ;; 256 | "smart") 257 | case "$part" in 258 | "health") 259 | GetSmartHealth "$3" 260 | ;; 261 | "temp") 262 | GetSmartTemp "$3" 263 | ;; 264 | "triptemp") 265 | GetSmartTripTemp "$3" 266 | ;; 267 | "defects") 268 | GetSmartDefects "$3" 269 | ;; 270 | esac 271 | ;; 272 | *) 273 | echo "Invalid usage of script" 274 | ;; 275 | esac -------------------------------------------------------------------------------- /userparameter_adaptec_raid_linux.conf: -------------------------------------------------------------------------------- 1 | UserParameter=adaptec.raid[*],/etc/zabbix/scripts/adaptec-raid.sh $1 $2 $3 $4 2 | -------------------------------------------------------------------------------- /userparameter_adaptec_raid_win.conf: -------------------------------------------------------------------------------- 1 | UserParameter=adaptec.raid[*],powershell -NoProfile -NoLogo -ExecutionPolicy Bypass -File "C:\Program Files (x86)\Zabbix Agent\Scripts\adaptec-raid.ps1" $1 $2 $3 $4 2 | -------------------------------------------------------------------------------- /zbx_adaptec_raid.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0 4 | 2019-02-05T07:49:00Z 5 | 6 | 7 | Templates 8 | 9 | 10 | 11 | 1009 | 1010 | 1011 | --------------------------------------------------------------------------------