Browse Source

changes for baba 6.2.0

tags/6.2.0
Lukas 11 months ago
parent
commit
449bf0f835
5 changed files with 422 additions and 337 deletions
  1. +4
    -0
      .gitignore
  2. +169
    -133
      baba.py
  3. +248
    -0
      devices.py
  4. +0
    -203
      smartvalues.py
  5. +1
    -1
      update.sh

+ 4
- 0
.gitignore View File

@@ -0,0 +1,4 @@
*~
__pycache__
build
.idea

+ 169
- 133
baba.py View File

@@ -1,34 +1,32 @@
#!/usr/bin/python3
from argparse import ArgumentParser
from os import listdir, getuid
from re import search
from shutil import copyfile, move
from subprocess import TimeoutExpired, Popen, PIPE, STDOUT
from sys import argv
from subprocess import TimeoutExpired, Popen
from urllib.request import urlretrieve
from smartvalues import Device
from devices import Device


__version__ = '6.1.3'
__versionDate__ = '2018-06-14'
__version__ = '6.2.0'
__versionDate__ = '2019-08-12'

supported = ('sd', 'mmcblk', 'sr', 'vd', 'nvme')

cols = [ ('Vendor / Model', 26), #25
('Serial', 21), #16
('Firmware', 10), #7
('Size', 9), #7
('Runtime', 12), #PoH 6
('Written', 10),
('Rpm', 6), # 5
('Life', 6), # 5
('S.M.A.R.T.', 10)]
paths = { 'model': ['/sys/block/{}/device/model', '/sys/block/{}/device/name'],
'serial': ['/sys/block/{}/device/serial'],
'firmware': ['/sys/block/{}/device/rev', '/sys/block/{}/device/fwrev'],
'size': ['/sys/block/{}/size'],
'vendor': ['/sys/block/{}/device/vendor']}
cols = [('Vendor / Model', 26), #25
('Serial', 21), #16
('Firmware', 10), #7
('Size', 9), #7
('Runtime', 12), #PoH 6
('Written', 10),
('Rpm', 6), # 5
('Life', 6), # 5
('S.M.A.R.T.', 10)]
alternatives = { 'model': ['/sys/block/{}/device/model', '/sys/block/{}/device/name'],
'serial': ['/sys/block/{}/device/serial'],
'firmware': ['/sys/block/{}/device/rev', '/sys/block/{}/device/fwrev'],
'size': ['/sys/block/{}/size'],
'vendor': ['/sys/block/{}/device/vendor']}

hdparmRex = { 'model': b'\sModel=([\w\s\-]*)[\,\n]',
'firmware': b'\s*FwRev=([\w\s\-\.]*)[\,\n]',
@@ -43,10 +41,30 @@ parser.add_argument('-u', '--update-drivedb', help='updating drivedb.h to increa
parser.add_argument('-s', '--self-update', help='installs the newest version of baba', action='store_true')
parser.add_argument('-t', '--timeout', help='the time to wait for a timeout in seconds (default 4)', nargs='?', default=4)
parser.add_argument('-v', '--verbose', help='increase output verbosity', action='store_true')
parser.add_argument('-w', '--written', help='use 32 KB LBAs instead of the default 512 Bytes to calculate the "written" value', action='store_true')
parser.add_argument('-w', '--written', help='use 32 KB LBAs instead of the default 512 Bytes to calculate the "written" value (only for non-nvme devices)', action='store_true')

args = parser.parse_args()


def from_file(devname, keys):
rv = ''
if type(keys) is str:
keys = [keys]

for key in keys:
for filename in alternatives[key]:
try:
with open(filename.format(devname)) as f:
if rv:
rv += ' '
rv += f.read().rstrip()
except FileNotFoundError:
pass
if rv:
return rv
return '-'


def update_drivedb():
"""Downloading and update the drivedb.h"""
print('Downloading new drivedb...', flush=True, end='')
@@ -61,128 +79,138 @@ def update_drivedb():
print('OK\nFinish!')


def calc_size(bytes, unit):
def calc_size(bytes, factor=1000, precision=0):
units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
template = '{:.?f} {}'.replace('?', str(precision))

if unit == 1024:
if factor == 1024:
units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB']
if bytes is 0:
rv = '-'

elif bytes < unit:
elif bytes < factor:
rv = '{} {}'.format(bytes, units[0])

elif bytes < unit**2:
rv = '{:.0f} {}'.format(bytes/unit, units[1])
elif bytes < factor**2:
rv = template.format(bytes/factor, units[1])

elif bytes < unit**3:
rv = '{:.0f} {}'.format(bytes/unit**2, units[2])
elif bytes < factor**3:
rv = template.format(bytes/factor**2, units[2])

elif bytes < unit**4:
rv = '{:.0f} {}'.format(bytes/unit**3, units[3])
elif bytes < factor**4:
rv = template.format(bytes/factor**3, units[3])

elif bytes < unit**5:
rv = '{:.0f} {}'.format(bytes/unit**4, units[4])
elif bytes < factor**5:
rv = template.format(bytes/factor**4, units[4])

elif bytes < unit**6:
rv = '{:.0f} {}'.format(bytes/unit**5, units[5])
elif bytes < factor**6:
rv = template.format(bytes/factor**5, units[5])

return rv

def valuechecker(dev):
devname = dev.split('/')[-1]

def grabber(d, attributes):
rv = ''
for attr in attributes:
if attr in d:
if rv:
rv += ' '
rv += d[attr]
if rv:
return rv
return '-'


def valuechecker(dev, factor):
rv = {'vendor': '-',
'model': '-',
'serial': '-',
'firmware': '-',
'size': '-',
'runtime': '-',
'written': '-',
'rotation': '-',
'lifetime': '-',
'smart': '-'}

device = Device(dev, args.timeout)

try:
device = Device(dev, args.timeout)
smart_info = device.smart_result()
device.fetch_smart()
except TimeoutExpired:
smart_info = {'vendor': '-',
'model': '-',
'serial': '-',
'firmware': '-',
'size': '-',
'runtime': '?',
'written': '?',
'rotation': '?',
'lifetime': '?',
'smart': 'TIMEOUT'}
rv['smart'] = 'TIMEOUT'
rv['lifetime'] = '?'
rv['rotation'] = '?'
rv['runtime'] = '?'
rv['written'] = '?'

for key in smart_info:
if smart_info[key] is '-' and key in paths:

for path in paths[key]:
try:
data = open(path.format(devname), 'r').read().rstrip()
if key == 'size':
if devname.startswith('sr'):
data = '-'
else:
data = str(int(data)*512)

if data.rstrip():
smart_info[key] = data

except FileNotFoundError:
pass
hdparm_result = b''
for key in smart_info:
if smart_info[key] is '-' and key in hdparmRex:
if device.name.startswith(('nvme', 'sd', 'sr', 'vd')) and rv['smart'] != 'TIMEOUT':

if hdparm_result not in [b'', b'TIMEOUT']:
try:
proc = Popen(['hdparm', '-i', device.dev_path], stdout=PIPE, stderr=STDOUT)
proc.wait(2)
hdparm_result = proc.stdout.read()
if device.name.startswith('nvme'):
rv['model'] = grabber(device.smart_info, ['Model Number', 'Device Model'])

except TimeoutExpired:
hdparm_result = 'TIMEOUT'
elif device.name.startswith(('sd', 'vd')):
rv['model'] = grabber(device.smart_info, ['Model Family', 'Vendor', 'Device Model', 'Product'])

try:
smart_info[key] = search(hdparmRex[key], hdparm_result).group(1).rstrip().decode()
except (AttributeError, IndexError):
pass
unit = 1000
elif device.name.startswith('sr'):
rv['model'] = grabber(device.smart_info, ['Vendor', 'Product'])

if args.mib:
unit = 1024
rv['firmware'] = grabber(device.smart_info, ['Firmware Version', 'Revision'])
rv['serial'] = grabber(device.smart_info, ['Serial Number', 'Serial number'])

if smart_info['size'] != '-':
smart_info['size'] = calc_size(int(smart_info['size']), unit)
if smart_info['written'] not in ['-', '?']:
multiplicator = 512
if args.written:
multiplicator = 32*1000*1000 # 32 MB
smart_info['written'] = calc_size(int(smart_info['written']) * multiplicator, unit)
if device.name.startswith('sr') is False:
rv['smart'] = device.analyse('health')

if smart_info['vendor'] != '-':
vendor_model = '{} {}'.format(smart_info['vendor'], smart_info['model'])
else:
vendor_model = smart_info['model']
return [vendor_model,
smart_info['serial'],
smart_info['firmware'],
smart_info['size'],
smart_info['runtime'],
smart_info['written'],
smart_info['rotation'],
smart_info['lifetime'],
smart_info['smart']]
size = device.analyse('size')
if size:
rv['size'] = calc_size(int(size), factor)

runtime = device.analyse('runtime')
if runtime:
rv['runtime'] = runtime

rotation = device.analyse('rotation')
if rotation:
rv['rotation'] = rotation

lifetime = device.analyse('lifetime')
if lifetime:
rv['lifetime'] = lifetime

written = device.analyse('written')
if written:
written = int(written.split(' [')[0].replace('.', ''))
if device.name.startswith('nvme'):
rv['written'] = calc_size(written*512*1000, factor, precision=1)
else:
if args.written:
rv['written'] = calc_size(written*32000, factor, precision=1)
else:
rv['written'] = calc_size(written*512, factor, precision=1)

if rv['model'] == '-':
rv['model'] = from_file(device.name, ['vendor', 'model'])

if rv['serial'] == '-':
rv['serial'] = from_file(device.name, 'serial')

if rv['firmware'] == '-':
rv['firmware'] = from_file(device.name, 'firmware')

if rv['size'] == '-' and device.name.startswith('sr') is False:
size = int(from_file(device.name, 'size'))*512
rv['size'] = calc_size(size, factor=factor)

return [rv['model'],
rv['serial'],
rv['firmware'],
rv['size'],
rv['runtime'],
rv['written'],
rv['rotation'],
rv['lifetime'],
rv['smart']]


def short(s, max_len):
@@ -221,7 +249,6 @@ def colored(color, s):
return '\x1b[0m\x1b[1m\x1b[43m\x1b[30m{}\x1b[0m'.format(s)



if getuid() != 0:
exit('Please run as root!')

@@ -242,12 +269,16 @@ elif args.device:
devices = [args.device]
else:
devices = [f for f in sorted(listdir('/sys/block/')) if f.startswith(supported)]

factor = 1000
if args.mib:
factor = 1024


print('\x1b[1m{}'.format('Device'.ljust(8)), end='', flush=False)

for c in cols:
print(c[0].ljust(c[1]), end='',flush=False)
print(c[0].ljust(c[1]), end='', flush=False)
print('\x1b[0m')


@@ -262,25 +293,30 @@ for lno, filename in enumerate(devices):
print(filename.ljust(8), flush=True, end='')

#: get and print the other values
for i, value in enumerate(valuechecker('/dev/{}'.format(filename))):
if i is 8: # smart
if value is 'OK':
for i, value in enumerate(valuechecker('/dev/{}'.format(filename), factor=factor)):
if value is None:
value = '-'

if i is 8: # smart
if value in ('PASSED', 'OK'):
value = colored('green', ' OK ')
elif value is 'DSBLD':
elif value == 'DSBLD':
value = colored('red', ' DISABLED ')

elif value is 'UDMA':
elif value == 'UDMA':
value = colored('red', ' UltraDMA')
elif value is 'TIMEOUT':
elif value == 'TIMEOUT':
value = colored('purple', ' TIME-OUT ')
elif value is 'USBB':

elif value == 'UNKNOWN':
value = colored('blue', ' UNKNOWN ')

elif value == 'USBB':
value = colored('blue', 'USB-BRIDGE')
elif value is '-':
elif value == '-':
value = colored('dark', ' NO SMART ')
elif value != '-':
@@ -288,7 +324,7 @@ for lno, filename in enumerate(devices):
print(value, end='')

elif i is 7 and value not in ['-', '?']: # life
elif i is 7 and value not in ['-', '?']: # lifetime
value_str = str(value)
just = cols[i][1] - len(value_str) - 1


+ 248
- 0
devices.py View File

@@ -0,0 +1,248 @@
#!/usr/bin/env python3
from re import findall, M, search
from subprocess import Popen, PIPE, STDOUT
from sys import argv
from pprint import pprint


class Device(object):
def __init__(self, path, timeout=3):
self.path = path
self.name = path.split('/')[-1]
self.info = {}
self.timeout = float(timeout)

self.smart_data = {}
self.smart_info = {}
self.smart_health = 'UNKNOWN'
self.smart_support = 'UNKNOWN'
self.vendor_model = ''

def fetch_smart(self):
self.smart_data = {}
self.smart_info = {}
self.smart_health = 'UNKNOWN'
self.smart_support = 'UNKNOWN'
self.vendor_model = ''

process = Popen(['smartctl', '-a', self.path], stdout=PIPE, stderr=STDOUT)
returncode = process.wait(self.timeout)
output = process.stdout.read().decode()

# if returncode != 0: # TODO: IMPROVE ERROR HANDLING!
# raise FileNotFoundError(self.path)
try:
rex_support = search('SMART support is:\s*(Enabled|Disabled)', output)
if rex_support:
self.smart_support = rex_support.group(1)

if 'Unknown USB bridge' in output:
self.smart_health = 'USBB'

if self.name.startswith('nvme'):
info_data, smart_data = output.split('=== START OF SMART DATA SECTION ===')
elif self.name.startswith('sr') or self.smart_support == 'Disabled':
info_data = output.split('=== START OF INFORMATION SECTION ===')[1]
smart_data = None
else:
info_data, smart_data = output.split('=== START OF READ SMART DATA SECTION ===')

rex_health = search('(SMART overall-health self-assessment test result:|SMART Health Status:)\s*([\w\s\-!]+)\n', output)

if rex_health:
self.smart_health = rex_health.group(2).strip()


for m in findall('^(.+):\s+(.*)', info_data, flags=M):
self.smart_info[m[0]] = m[1]

if self.name.startswith('sd') and self.smart_support == 'Enabled':
for m in findall('^\s*(\d+)\s*([\w-]+)\s+(\w*)\s*(\w*)\s*(\w*)\s*([\w-]+)\s*([\w-]*)\s*(\w*)\s*([\w\-!]*)\s*(\d+)', smart_data, flags=M):
self.smart_data[m[0]] = {
'attribute_name': m[1],
'flag': m[2],
'value': m[3],
'worst': m[4],
'thresh': m[5],
'type': m[6],
'updated': m[7],
'when_failed': m[8],
'raw_value': m[9]
}

elif self.name.startswith('nvme'):
for m in findall('^(.+):\s+(.*)', smart_data, flags=M):
self.smart_data[m[0]] = m[1]

if 'Vendor' in self.smart_info:
self.vendor_model += self.smart_info['Vendor'].lower()
if 'Model Family' in self.smart_info:
self.vendor_model += self.smart_info['Model Family'].lower()
if 'Product' in self.smart_info:
self.vendor_model += self.smart_info['Product'].lower()

except ValueError:
pass

def analyse(self, mode):
if mode == 'lifetime':
return self._lifetime()
elif mode == 'runtime':
return self._runtime()
elif mode == 'rotation':
return self._rotation()
elif mode == 'size':
return self._size()
elif mode == 'health':
return self._health()
elif mode == 'written':
return self._written()
else:
raise AttributeError('Unknown mode: {}'.format(mode))

def _lifetime(self):
if self.smart_data is {} or self.smart_info is {}:
raise Exception('Please fetch smart data first')

lifetime = None

if self.name.startswith('nvme'):
if 'Percentage Used' in self.smart_data:
used = int(self.smart_data['Percentage Used'].split('%')[0])
lifetime = 100 - used

elif self.name.startswith('sd'):
if 'samsung' in self.vendor_model:
if '177' in self.smart_data: # Wear_Leveling_Count
lifetime = int(self.smart_data['177']['raw_value'])

if '179' in self.smart_data: # Used_Reserve_Block_Count
smart_179 = int(self.smart_data['179']['raw_value'])

if lifetime:
if lifetime > smart_179:
lifetime = smart_179
else:
lifetime = smart_179

elif 'crucial' in self.vendor_model:
if '202' in self.smart_data: # Remaining_lifetime_Perc or Percent_Lifetime_Used
lifetime = int(self.smart_data['202']['raw_value'])

elif 'ocz' in self.vendor_model:
if '209' in self.smart_data: # Remaining_Lifetime_Perc
lifetime = int(self.smart_data['209']['raw_value'])

return lifetime

def _health(self):
health = self.smart_health
sector_sum = 0

if self.smart_support == 'Disabled':
health = 'DSBLD'

elif self.name.startswith('sda'):
if 'SMART support is' in self.smart_info and self.smart_info['SMART support is'] == 'Disabled':
health = 'DSBLD'

if health == 'PASSED':
if '199' in self.smart_info: # UDMA_CRC_Error_Count
if int(self.smart_data['199']['raw_value']) >= 500:
health = 'UDMA'

if '5' in self.smart_info: # Reallocated_Sector_Ct
sector_sum += int(self.smart_data['5']['raw_value'])

if '197' in self.smart_info: # Current_Pending_Sector
sector_sum += int(self.smart_data['197']['raw_value'])

#: TODO -> INCORRECT!
if 'crucial' in self.vendor_model and '172' in self.smart_data: # Erase_Fail_Count
sector_sum += int(self.smart_data['172']['raw_value'])

elif self.name.startswith('nvme'):
if 'Critical Warning' in self.smart_data and self.smart_data['Critical Warning'] != '0x00':
health = 'WARN'
elif 'Warning Comp. Temperature Time' in self.smart_data and self.smart_data['Warning Comp. Temperature Time'] != '0':
health = 'TEMP E'
elif 'Warning Comp. Temperature Time' in self.smart_data and self.smart_data['Warning Comp. Temperature Time'] != '0':
health = 'TEMP W'
elif 'Media and Data Integrity Errors' in self.smart_data:
sector_sum += int(self.smart_data['Media and Data Integrity Errors'])

if sector_sum > 0:
health = str(sector_sum)

return health

def _size(self):
size = None
raw_size = None

if 'Total NVM Capacity' in self.smart_info:
raw_size = self.smart_info['Total NVM Capacity']

elif 'User Capacity' in self.smart_info:
raw_size = self.smart_info['User Capacity']

if raw_size:
rex = search('\s*([\d\.]*)', raw_size.replace('.', '').replace(',', ''))
if rex:
size = rex.group(1)
return size

def _rotation(self):
if self.name.startswith('nvme'):
return 'NVME'
elif 'Rotation Rate' in self.smart_info:
if self.smart_info['Rotation Rate'] == 'Solid State Device':
return 'SSD'
elif ' rpm' in self.smart_info['Rotation Rate']:
return self.smart_info['Rotation Rate'].split(' rpm', 1)[0]
return False

def _runtime(self):
hours = False

if self.name.startswith('sd') and '9' in self.smart_data:
hours = int(self.smart_data['9']['raw_value'])

elif self.name.startswith('nvme') and 'Power On Hours' in self.smart_data:
hours = int(self.smart_data['Power On Hours'])

if hours:
if hours < 24:
if hours == 1:
hours = '{} hour'.format(hours)
else:
hours = '{} hours'.format(hours)
elif hours < 365 * 24:
hours = '{:.1f} days'.format(hours / 24)
else:
hours = '{:.1f} years'.format(hours / 24 / 365)

return hours

def _written(self):
raw_written = None
if self.name.startswith('sd'):
if '241' in self.smart_data:
return self.smart_data['241']['raw_value'] # Total_LBAs_Written
elif self.name.startswith('nvme'):
if 'Data Units Written' in self.smart_data:
raw_written = self.smart_data['Data Units Written']
rex = search('\s*([\d\.]*)', raw_written)
if rex:
return rex.group(1)



if __name__ == '__main__':
dev = Device(argv[1])
dev.fetch_smart()
pprint(dev.smart_info)
#print(dev.analyse('lifetime'))
pprint(dev.smart_data)
#print(dev.health.encode())
#print(dev.support.encode())

+ 0
- 203
smartvalues.py View File

@@ -1,203 +0,0 @@
#!/usr/bin/env python3
from re import search
from subprocess import Popen, PIPE, STDOUT
from sys import argv


class Device(object):
def __init__(self, dev_path, timeout):
self.dev_path = dev_path
self.info = {}
self.timeout = float(timeout)
def _smart_analyse(self):
rex_db = { 'family' : b'Model Family:\s*([\w\s-]*)\n',
'model' : b'Device Model:\s*([\w\s-]*)\n',
'product' : b'Product:\s*([\w\s-]*)\n',
'vendor' : b'Vendor:\s*([\w\s-]*)\n',
'serial' : b'Serial Number:\s*([\w\s-]*)\n',
'revision': b'Revision:\s*([\w\s-]*)\n',
'firmware': b'Firmware Version:\s*([\w\s\.\-]*)\n',
'size' : b'User Capacity:\s*([\d\.]*) bytes',
'rotation': b'Rotation Rate:\s*([\w\s-]*)\n',
'support' : b'SMART support is:\s*(Enabled|Disabled)',
'health' : b'SMART overall-health self-assessment test result:\s*([\w\s\-\!]*)\n',
'usbbridge': b'\s+?Unknown USB bridge\s+?\[(.*)\]',
#'Raw_Read_Error_Rate' : b'Raw_Read_Error_Rate\s+\w*\s*\w*\s*\w*\s*\w*\s*[\w-]*\s*\w*\s*[\w-]*\s*(\d*)',
'Reallocated_Sector_Ct' : b'Reallocated_Sector_Ct\s+\w*\s*\w*\s*\w*\s*[\w\-]*\s*[\w-]*\s*\w*\s*[\w\-\!]*\s*(\d*)',
'Power_On_Hours' : b'Power_On_Hours\s+\w*\s*\w*\s*\w*\s*[\w\-]*\s*[\w-]*\s*\w*\s*[\w\-\!]*\s*(\d*)',
'Reallocated_Event_Count' : b'Reallocated_Event_Count\s+\w*\s*\w*\s*\w*\s*[\w\-]*\s*[\w-]*\s*\w*\s*[\w\-\!]*\s*(\d*)',
'Current_Pending_Sector' : b'Current_Pending_Sector\s+\w*\s*\w*\s*\w*\s*[\w\-]*\s*[\w-]*\s*\w*\s*[\w\-\!]*\s*(\d*)',
#'Offline_Uncorrectable' : b'Offline_Uncorrectable\s+\w*\s*\w*\s*\w*\s*\w*\s*[\w-]*\s*\w*\s*[\w\-\!]*\s*(\d*)',
'UDMA_CRC_Error_Count' : b'UDMA_CRC_Error_Count\s+\w*\s*\w*\s*\w*\s*[\w\-]*\s*[\w-]*\s*\w*\s*[\w\-\!]*\s*(\d*)',
'Total_LBAs_Written' : b'Total_LBAs_Written\s+\w*\s*\w*\s*\w*\s*[\w\-]*\s*[\w-]*\s*\w*\s*[\w\-\!]*\s*(\d*)',

'Wear_Leveling_Count' : b'Wear_Leveling_Count\s+\w*\s*(\d*)\s*\w*\s*[\w\-]*\s*[\w-]*\s*\w*\s*[\w\-\!]*\s*\d*',
'Remaining_lifetime_Perc' : b'Remaining_lifetime_Perc\s+\w*\s*(\d*)\s*\w*\s*[\w\-]*\s*[\w-]*\s*\w*\s*[\w\-\!]*\s*\d*',
'Percent_Lifetime_Used' : b'Percent_Lifetime_Used\s+\w*\s*(\d*)\s*\w*\s*[\w\-]*\s*[\w-]*\s*\w*\s*[\w\-\!]*\s*\d*',
'Total_Bad_Block_Count' : b'Total_Bad_Block_Count\s+\w*\s*\d*\s*\w*\s*[\w\-]*\s*[\w-]*\s*\w*\s*[\w\-\!]*\s*(\d*)',
'Erase_Fail_Count' : b'Erase_Fail_Count\s+\w*\s*\d*\s*\w*\s*[\w\-]*\s*[\w-]*\s*\w*\s*[\w\-\!]*\s*(\d*)',
'Used_Reserve_Block_Count': b'Used_Reserve_Block_Count\s+\w*\s*(\d*)\s*\w*\s*[\w\-]*\s*[\w-]*\s*\w*\s*[\w\-\!]*\s*\d*'
}
proc = Popen(['smartctl', '-a', self.dev_path], stdout=PIPE, stderr=STDOUT)
if self.timeout:
proc.wait(self.timeout)
else:
proc.wait()
data = proc.stdout.read()
for rex in rex_db:
try:
self.info[rex] = search(rex_db[rex], data).group(1).rstrip().decode()
except (AttributeError, IndexError):
pass
def smart_values(self):
if self.info == {}:
self._smart_analyse()
return self.info
def smart_result(self):
if self.info == {}:
self._smart_analyse()

vendor = '-' # ok
model = '-' # ok
serial = '-' # ok, hdparm better
firmware = '-' # ok
size = '-' # ok
runtime = '-' # S(tunden), T(age) J(ahre)
smart = 'OK'
rotation = '-' # ok
written = '-'
lifetime = '-'
if 'family' in self.info:
vendor = self.info['family']
elif 'vendor' in self.info:
vendor = self.info['vendor']
if 'model' in self.info:
model = self.info['model']
elif 'product' in self.info:
model = self.info['product']

if 'serial' in self.info:
serial = self.info['serial']
if 'firmware' in self.info:
firmware = self.info['firmware']

elif 'revision' in self.info:
firmware = self.info['revision']
if 'size' in self.info:
bytes = self.info['size']
size = ''.join(bytes.split('.'))
if 'Power_On_Hours' in self.info:
runtime = int(self.info['Power_On_Hours'])
if runtime < 24:
runtime = '{} hours'.format(runtime)
elif runtime < 365*24:
runtime = '{:.1f} days'.format(runtime/24)
else:
runtime = '{:.1f} years'.format(runtime/24/365)
if 'rotation' in self.info:
rotation = self.info['rotation']
if rotation == 'Solid State Device':
rotation = 'SSD'
elif ' rpm' in rotation:
rotation = rotation.split(' rpm',1)[0]
if 'support' in self.info:
support = self.info['support']
if support == 'Disabled':
smart = 'DSBLD'

elif 'health' in self.info:
health = self.info['health']
sector_sum = 0
if 'UDMA_CRC_Error_Count' in self.info:
error_count = int(self.info['UDMA_CRC_Error_Count'])
if error_count > 2000:
smart = 'UDMA'

if 'Reallocated_Sector_Ct' in self.info:
sector_count = self.info['Reallocated_Sector_Ct']
if sector_count != '0':
sector_sum += int(sector_count)
if 'Current_Pending_Sector' in self.info:
sector_count = self.info['Current_Pending_Sector']
if sector_count != '0':
sector_sum += int(sector_count)

if 'crucial' in ' '.join((vendor.lower(), model.lower())) and 'Erase_Fail_Count' in self.info:
error_count = self.info['Erase_Fail_Count']
if error_count != '0':
sector_sum += int(error_count)
if sector_sum > 0:
smart = str(sector_sum)
if health != 'PASSED':
smart = health

elif 'usbbridge' in self.info:
smart = 'USBB'
else:
smart = '-'
vendor_model = ' '.join((vendor, model)).lower()
if 'Total_LBAs_Written' in self.info:
written = self.info['Total_LBAs_Written']
if 'samsung' in vendor_model:
if 'Wear_Leveling_Count' in self.info:
lifetime = int(self.info['Wear_Leveling_Count'])

if 'Used_Reserve_Block_Count' in self.info:
if type(lifetime) is int:
if lifetime > int(self.info['Used_Reserve_Block_Count']):
lifetime = int(self.info['Used_Reserve_Block_Count'])
else:
lifetime = int(self.info['Used_Reserve_Block_Count'])

elif 'crucial' in vendor_model:
if 'Remaining_lifetime_Perc' in self.info:
lifetime = int(self.info['Remaining_lifetime_Perc'])
if 'Percent_Lifetime_Used' in self.info:
if type(lifetime) is int:
if lifetime > int(self.info['Percent_Lifetime_Used']):
lifetime = int(self.info['Percent_Lifetime_Used'])
else:
lifetime = int(self.info['Percent_Lifetime_Used'])
elif 'ocz' in vendor_model and 'Total_Bad_Block_Count' in self.info:
lifetime = int(self.info['Total_Bad_Block_Count'])
return {'vendor': vendor,
'model': model,
'serial': serial,
'firmware': firmware,
'size': size,
'runtime': runtime,
'written': written,
'rotation': rotation,
'lifetime': lifetime,
'smart': smart}


+ 1
- 1
update.sh View File

@@ -1,4 +1,4 @@
#!/bin/bash
wget http://baba.das-it-gesicht.de/ -O /tmp/baba.deb
wget https://baba.das-it-gesicht.de/ -O /tmp/baba.deb
dpkg -i /tmp/baba.deb
apt-get install -f

Loading…
Cancel
Save