├── README.md └── megaclisas-status /README.md: -------------------------------------------------------------------------------- 1 | megaclisas-status 2 | ================= 3 | 4 | http://hwraid.le-vert.net/wiki/DebianPackages -------------------------------------------------------------------------------- /megaclisas-status: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os 4 | import re 5 | import sys 6 | 7 | binarypath = "/usr/bin/megacli" 8 | 9 | # Adding a quick check to see if we're root, because on most cards I've tried this on 10 | # We need root access to query 11 | if __name__ == '__main__': 12 | if os.getenv('USER') != 'root': 13 | print 'You can only run this script as root or with sudo, sucks I know. Blame the RAID card' 14 | sys.exit(5) 15 | 16 | if len(sys.argv) > 2: 17 | print 'Usage: megaclisas-status [--nagios]' 18 | sys.exit(1) 19 | 20 | nagiosmode = False 21 | nagiosoutput = '' 22 | nagiosgoodarray = 0 23 | nagiosbadarray = 0 24 | nagiosgooddisk = 0 25 | nagiosbaddisk = 0 26 | 27 | # Check command line arguments to enable nagios or not 28 | if len(sys.argv) > 1: 29 | if sys.argv[1] == '--nagios': 30 | nagiosmode = True 31 | else: 32 | print 'Usage: megaclisas-status [--nagios]' 33 | sys.exit(1) 34 | 35 | # Check binary exists (and +x), if not print an error message 36 | # or return UNKNOWN nagios error code 37 | if os.path.exists(binarypath) and os.access(binarypath, os.X_OK): 38 | pass 39 | else: 40 | if nagiosmode: 41 | print 'UNKNOWN - Cannot find ' + binarypath 42 | else: 43 | print 'Cannot find ' + binarypath + '. Please install it.' 44 | sys.exit(3) 45 | 46 | 47 | # Get command output 48 | def getOutput(cmd): 49 | output = os.popen(cmd) 50 | lines = [] 51 | for line in output: 52 | line = line.strip() 53 | if not re.match(r'^$', line): 54 | lines.append(line) 55 | return lines 56 | 57 | 58 | def returnControllerNumber(output): 59 | for line in output: 60 | line = line.strip() 61 | if re.match(r'^Controller Count.*$', line): 62 | return int(line.split(':')[1].strip().strip('.')) 63 | 64 | 65 | def returnControllerModel(output): 66 | for line in output: 67 | if re.match(r'^Product Name.*$', line.strip()): 68 | return line.split(':')[1].strip() 69 | 70 | def returnControllerFirmware(output): 71 | for line in output: 72 | if re.match(r'^FW Package Build.*$', line.strip()): 73 | return line.split(':')[1].strip() 74 | 75 | 76 | def returnArrayNumber(output): 77 | i = 0 78 | for line in output: 79 | if re.match(r'^Number of Virtual (Disk|Drive).*$', line.strip()): 80 | i = line.split(':')[1].strip() 81 | return i 82 | 83 | def returnNextArrayNumber(output,curNumber): 84 | #Virtual Drive: 2 (Target Id: 2) 85 | for line in output: 86 | vdisk = re.match(r'^Virtual Drive: \d+ \(Target Id: (\d+)\)$', line.strip()) 87 | if vdisk and int(vdisk.group(1)) > curNumber: 88 | return int(vdisk.group(1)) 89 | return -1 90 | 91 | def returnArrayInfo(output, controllerid, arrayid): 92 | _id = 'c%du%d' % (controllerid, arrayid) 93 | operationlinennumber = False 94 | linenumber = 0 95 | ldpdcount = 0 96 | spandepth = 0 97 | 98 | for line in output: 99 | line = line.strip() 100 | if re.match(r'Number Of Drives\s*((per span))?:.*[0-9]+$', line): 101 | ldpdcount = line.split(':')[1].strip() 102 | if re.match(r'Span Depth *:.*[0-9]+$', line): 103 | spandepth = line.split(':')[1].strip() 104 | if re.match(r'^RAID Level\s*:.*$', line): 105 | raidlevel = line.split(':')[1].split(',')[0].split('-')[1].strip() 106 | raid_type = 'RAID' + raidlevel 107 | if re.match(r'^Size\s*:.*$', line): 108 | # Size reported in MB 109 | if re.match(r'^.*MB$', line.split(':')[1]): 110 | size = line.split(':')[1].strip('MB').strip() 111 | size = str(int(round((float(size) / 1000)))) + 'G' 112 | # Size reported in TB 113 | elif re.match(r'^.*TB$', line.split(':')[1]): 114 | size = line.split(':')[1].strip('TB').strip() 115 | size = str(int(round((float(size) * 1000)))) + 'G' 116 | # Size reported in GB (default) 117 | else: 118 | size = line.split(':')[1].strip('GB').strip() 119 | size = str(int(round((float(size))))) + 'G' 120 | if re.match(r'^State\s*:.*$', line): 121 | state = line.split(':')[1].strip() 122 | if re.match(r'^Ongoing Progresses\s*:.*$', line): 123 | operationlinennumber = linenumber 124 | linenumber += 1 125 | if operationlinennumber: 126 | inprogress = output[operationlinennumber + 1] 127 | else: 128 | inprogress = 'None' 129 | 130 | if ldpdcount and (int(spandepth) > 1): 131 | ldpdcount = int(ldpdcount) * int(spandepth) 132 | if int(raidlevel) < 10: 133 | raid_type = raid_type + "0" 134 | 135 | return [_id, raid_type, size, state, inprogress] 136 | 137 | 138 | def returnDiskInfo(output, controllerid): 139 | arrayid = False 140 | diskid = False 141 | table = [] 142 | state = 'undef' 143 | model = 'undef' 144 | for line in output: 145 | line = line.strip() 146 | if re.match(r'^Virtual (Disk|Drive): [0-9]+.*$', line): 147 | arrayid = line.split('(')[0].split(':')[1].strip() 148 | if re.match(r'Firmware state: .*$', line): 149 | state = line.split(':')[1].strip() 150 | if re.match(r'Inquiry Data: .*$', line): 151 | model = line.split(':')[1].strip() 152 | model = re.sub(' +', ' ', model) 153 | if re.match(r'PD: [0-9]+ Information.*$', line): 154 | diskid = line.split()[1].strip() 155 | 156 | if arrayid and state != 'undef' and model != 'undef' and diskid: 157 | table.append([str(arrayid), str(diskid), state, model]) 158 | state = 'undef' 159 | model = 'undef' 160 | 161 | return table 162 | 163 | cmd = binarypath + ' -adpCount -NoLog' 164 | output = getOutput(cmd) 165 | controllernumber = returnControllerNumber(output) 166 | 167 | bad = False 168 | 169 | # List available controller 170 | if not nagiosmode: 171 | print '-- Controller informations --' 172 | print '-- ID | Model | Firmware' 173 | controllerid = 0 174 | while controllerid < controllernumber: 175 | cmd = '%s -AdpAllInfo -a%d -NoLog' % (binarypath, controllerid) 176 | output = getOutput(cmd) 177 | controllermodel = returnControllerModel(output) 178 | firmwareversion = returnControllerFirmware(output) 179 | print 'c%d | %s | %s' % (controllerid, controllermodel, firmwareversion) 180 | controllerid += 1 181 | print '' 182 | 183 | controllerid = 0 184 | if not nagiosmode: 185 | print '-- Arrays informations --' 186 | print '-- ID | Type | Size | Status | InProgress' 187 | 188 | while controllerid < controllernumber: 189 | cmd = '%s -LdInfo -Lall -a%d -NoLog' % (binarypath, controllerid) 190 | arrayoutput = getOutput(cmd) 191 | arrayid = returnNextArrayNumber(arrayoutput,-1) 192 | cmd = '%s -LdGetNum -a%d -NoLog' % (binarypath, controllerid) 193 | output = getOutput(cmd) 194 | arraynumber = int(returnArrayNumber(output)) 195 | while arraynumber > 0: 196 | cmd = '%s -LDInfo -l%d -a%d -NoLog' % (binarypath, 197 | arrayid, controllerid) 198 | output = getOutput(cmd) 199 | arrayinfo = returnArrayInfo(output, controllerid, arrayid) 200 | if not nagiosmode: 201 | print ' | '.join(arrayinfo) 202 | if not arrayinfo[3] == 'Optimal': 203 | bad = True 204 | nagiosbadarray += 1 205 | else: 206 | nagiosgoodarray += 1 207 | #arrayid += 1 208 | arrayid = returnNextArrayNumber(arrayoutput,arrayid) 209 | arraynumber -= 1 210 | controllerid += 1 211 | if not nagiosmode: 212 | print '' 213 | 214 | if not nagiosmode: 215 | print '-- Disks informations' 216 | print '-- ID | Model | Status' 217 | 218 | controllerid = 0 219 | while controllerid < controllernumber: 220 | arrayid = 0 221 | cmd = '%s -LDInfo -lall -a%d -NoLog' % (binarypath, controllerid) 222 | output = getOutput(cmd) 223 | cmd = '%s -LdPdInfo -a%d -NoLog' % (binarypath, controllerid) 224 | output = getOutput(cmd) 225 | arraydisk = returnDiskInfo(output, controllerid) 226 | for array in arraydisk: 227 | if not array[2] == 'Online' and not array[2] == 'Online, Spun Up': 228 | bad = True 229 | nagiosbaddisk += 1 230 | else: 231 | nagiosgooddisk += 1 232 | if not nagiosmode: 233 | print 'c%du%sp%s | %s | %s' % (controllerid, array[0], 234 | array[1], array[3], array[2]) 235 | controllerid += 1 236 | 237 | if nagiosmode: 238 | status_line = 'Arrays: OK:%d Bad:%d - Disks: OK:%d Bad:%d' % \ 239 | (nagiosgoodarray, nagiosbadarray, nagiosgooddisk, nagiosbaddisk) 240 | if bad: 241 | print 'RAID ERROR - ' + status_line 242 | sys.exit(2) 243 | else: 244 | print 'RAID OK - ' + status_line 245 | else: 246 | if bad: 247 | print '\nThere is at least one disk/array in a NOT OPTIMAL state.' 248 | sys.exit(1) 249 | --------------------------------------------------------------------------------