#!/usr/bin/python3 # dinfo # Gathers info about drive errors and power cycle counts, and finds the slots the drives should be in. # Copyright 2021, Mike McPhee # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version.############ import subprocess import re import sys class drive: device = None serial = None row = None slot = None sas3ircuRow = None sas3ircuSlot = None hours = None pwrcycl = None offline = None pending = None def __init__(self, device): self.device = device #grabbing serial serialLine = subprocess.check_output("smartctl -i /dev/"+device+" | grep -i 'serial number'", shell=True, encoding='utf-8').strip('\n') serial = serialLine.split() self.serial = serial[2] infolist = subprocess.check_output("smartctl -x /dev/"+device+" | grep -i 'power_on_hours\|power_cycle_count\|offline_uncorrectable\|current_pending_sector' | awk '{print $8}'", shell=True, encoding = 'utf-8').split('\n') del infolist[len(infolist)-1] if(len(infolist)==3): self.hours = infolist[0] self.pwrcycl = infolist[1] self.offline = infolist[2] self.pending = infolist[3] else: self.hours = infolist[0] self.pwrcycl = infolist[1] self.offline = "N/A" self.pending = "N/A" def findSlot(self): self.slot = subprocess.check_output("ls -l /dev/disk/by-vdev | grep -wi "+self.device+" | awk '{print $9}'", shell=True, encoding = 'utf-8').strip('\n') def print(self): print(f"\n*----------------------------------dinfo2---------------------------------------*\nDevice: {self.device} \nSlot: {self.slot}\nSerial Number: {self.serial}\nPowered-On Hours: {self.hours}\nPower Cycle Count: {self.pwrcycl}\nOffline Uncorrectable Sector Count: {self.offline}\nCurrent Pending Sector Count: {self.pending}\n\n") supportedBoards = ['X10DRL-I', 'X11SPL-F'] print("\n*----------------------------------dinfo2---------------------------------------*\nGathers info about drive errors and power cycle counts, along with the drive's device identifier and physical slot.\n"); #print(sys.argv[1]) boardtype = subprocess.check_output("ipmitool fru | grep -i 'board product' | awk '{print $4}'", shell=True, encoding = 'utf-8').strip('\n') boardtype = str(boardtype).strip(" ") byvdev = subprocess.check_output("find /dev/disk/by-vdev -empty", shell=True, encoding = 'utf-8').strip('\n') byvdev = str(byvdev).strip(" ") #print(f"\nbyvdev: "+byvdev+"---") if byvdev=="": #if supportedBoards.count(boardtype.upper())>0: print(f"Motherboard model number: {boardtype}") #devlist = subprocess.check_output("ls /dev | grep -i da | grep -v 'p[0-9]$' | grep -v ada", shell =True, encoding = 'utf-8').split('\n') devlist = subprocess.check_output("ls /dev | grep -i sd | grep -v '[0-9]$' | awk '{print $1}'", shell =True, encoding = 'utf-8').split('\n') del devlist[len(devlist)-1] if len(sys.argv)>2: if sys.argv[1]== "list" : if sys.argv[2] == "devices": print("\nDevices Found: ") for a in devlist: print(f"{a}") if sys.argv[2] == "all": # Looping through each device found in /dev for x in devlist: currentdrive = drive(x) #currentdrive.findSlotS3() #currentdrive.findSlotCC(boardtype) currentdrive.findSlot() currentdrive.print() elif devlist.count(sys.argv[2]): output = drive(sys.argv[2]) #output.findSlotS3() #output.findSlotCC(boardtype) output.findSlot() output.print() else: print("\nInvalid arguments used. Device does not exist.") else: print("\nInvalid arguments used. Must use 'list all' or 'list da#'." ) else: print("\nInvalid arguments used. dinfo accepts: \n\nlist devices --> lists devices found in /dev.\n\nlist all --> list info for all devices.\n\nlist *device id (da#)*: --> lists info for specific device.\n*------------------------------------------------------------------------------*\n") else: print("\nError. Device slots could not be determined. Run \"dmap\" first.")