Created
February 1, 2015 21:34
-
-
Save mcrosson/cac0bbb04d22f45a4c67 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python2 | |
# -*- coding: utf-8 -*- | |
from __future__ import print_function | |
import subprocess, pprint, json | |
from collections import defaultdict | |
btrfs_bin = '/sbin/btrfs' | |
filesystems = [] | |
label = None | |
uuid = None | |
devices = None | |
devid = None | |
path = None | |
filesystem = {} | |
cmd = subprocess.Popen([btrfs_bin, 'fi', 'show', '--all-devices'], stdout=subprocess.PIPE) | |
for line in cmd.stdout: | |
set_values = False | |
line = line.strip().split() | |
if len(line) < 1: | |
continue | |
if line[0].startswith('Label'): | |
label = line[1] | |
uuid = line[3] | |
elif line[0].startswith('Total'): | |
devices = line[2] | |
elif line[0].startswith('devid'): | |
devid = line[1] | |
path = line[7] | |
set_values = True | |
if set_values: | |
filesystem['uuid'] = uuid | |
filesystem['label'] = label | |
filesystem['devices'] = devices | |
filesystem['devid'] = devid | |
filesystem['path'] = path | |
filesystems.append(filesystem) | |
cmd = subprocess.Popen([btrfs_bin, 'fi', 'show', '--mounted'], stdout=subprocess.PIPE) | |
for line in cmd.stdout: | |
line = line.strip().split() | |
if len(line) < 1: | |
continue | |
if line[0].startswith('Label'): | |
for filesystem in filesystems: | |
if filesystem['uuid'] == line[3]: | |
filesystem['mounted'] = True | |
break | |
cmd = subprocess.Popen(['/bin/mount'], stdout=subprocess.PIPE) | |
cmd = subprocess.Popen(['/bin/grep', 'btrfs'], stdin=cmd.stdout, stdout=subprocess.PIPE) | |
for line in cmd.stdout: | |
mount_info = {} | |
line = line.strip().split() | |
mount_info['device'] = line[0] | |
mount_info['mountpoint'] = line[2] | |
opts = line[5].strip('(').strip(')').split(',') | |
for opt in opts: | |
if opt.startswith('subvol'): | |
mount_info['subvol'] = opt[7:] | |
opts.remove(opt) | |
mount_info['opts'] = opts | |
blk_uuid = None | |
cmd = subprocess.Popen(['/sbin/blkid', mount_info['device']], stdout=subprocess.PIPE) | |
for line in cmd.stdout: | |
line = line.strip() | |
if len(line) > 0: | |
line = line.split() | |
blk_uuid = line[1].strip('UUID=').strip('"') | |
filesystem = None | |
for fs in filesystems: | |
if fs['uuid'] == blk_uuid: | |
filesystem = fs | |
break | |
mounts = [] | |
if filesystem.has_key('mounts'): | |
mounts = filesystem['mounts'] | |
mounts.append(mount_info) | |
filesystem['mounts'] = mounts | |
for filesystem in filesystems: | |
subvols = {} | |
if filesystem.has_key('mounted') and filesystem['mounted'] is True: | |
cmd = subprocess.Popen([btrfs_bin, 'subvolume', 'list', fs['mounts'][0]['mountpoint']], stdout=subprocess.PIPE) | |
for line in cmd.stdout: | |
line = line.strip().split() | |
subvol = {} | |
subvol['id'] = line[1] | |
subvol['top_level'] = line[6] | |
subvol['path'] = line[-1] | |
subvols[subvol['id']] = subvol | |
mounts = fs['mounts'] | |
for mount in mounts: | |
sid = None | |
uuid = None | |
parent = None | |
parent_uuid = None | |
top_level = None | |
flags = None | |
cmd = subprocess.Popen([btrfs_bin, 'subvolume', 'show', mount['mountpoint']], stdout=subprocess.PIPE) | |
for line in cmd.stdout: | |
line = line.strip().split(':') | |
if len(line) < 2: | |
continue | |
if line[0].startswith('Object'): | |
sid = line[1].strip() | |
elif line[0].startswith('uuid'): | |
uuid = line[1].strip() | |
elif line[0].startswith('Parent'): | |
if 'uuid' in line[0]: | |
parent_uuid = line[1].strip() | |
else: | |
parent = line[1].strip() | |
elif line[0].startswith('Top Level'): | |
top_level = line[1].strip() | |
elif line[0].startswith('Flags'): | |
flags = line[1].strip() | |
subvol = subvols[sid] | |
subvol['uuid'] = uuid | |
subvol['parent'] = parent | |
subvol['parent_uuid'] = parent_uuid | |
subvol['top_level'] = top_level | |
subvol['flags'] = flags | |
fs['subvols'] = subvols | |
print(json.dumps(filesystems, indent=1)) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python2 | |
# -*- coding: utf-8 -*- | |
# {{ ansible_managed }} | |
from __future__ import print_function | |
import subprocess, re, pprint, json, glob | |
from collections import defaultdict | |
arrays = [] | |
for array in glob.glob('/dev/md?'): | |
device = array.strip() | |
name = array.split('/')[-1] | |
array = {} | |
array['dev_name'] = name | |
array['device'] = device | |
array['devices'] = {} | |
info = subprocess.Popen(['/sbin/mdadm', '-D', device], stdout=subprocess.PIPE) | |
for line in info.stdout: | |
line = line.strip() | |
if len(line) < 1: | |
continue | |
values = line.split(':') | |
key = values[0].strip() | |
if key.startswith('/dev/') or key.startswith('Creation') or key.startswith('Array Size') or key.startswith('Used Dev') or key.startswith('Persistence') or key.startswith('Update Time') or key.startswith('Number '): | |
continue | |
value = None | |
if len(values) < 2: | |
devices = array['devices'] | |
values = key.split() | |
device = values[-1] | |
devices[device] = {} | |
devices[device]['number'] = values[0] | |
devices[device]['major'] = values[1] | |
devices[device]['minor'] = values[2] | |
devices[device]['raid_device'] = values[3] | |
devices[device]['state'] = ','.join(values[4:-1]) | |
else: | |
value = ':'.join(values[1:]).strip() | |
array[key] = value | |
arrays.append(array) | |
print(json.dumps(arrays, indent=1)) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python2 | |
# -*- coding: utf-8 -*- | |
# {{ ansible_managed }} | |
from __future__ import print_function | |
import subprocess, re, pprint, json | |
from collections import defaultdict | |
def print_tab(): | |
print(' ', end='') | |
zpool_bin = '/sbin/zpool' | |
sudo_bin = '/usr/bin/sudo' | |
cut_bin = '/usr/bin/cut' | |
pools = [] | |
cmd = subprocess.Popen([zpool_bin, 'list', '-H'], stdout=subprocess.PIPE) | |
cmd = subprocess.Popen([cut_bin, '-f1'], stdin=cmd.stdout, stdout=subprocess.PIPE) | |
for line in cmd.stdout: | |
pool = {} | |
pool['name'] = line.strip() | |
pools.append(pool) | |
for pool in pools: | |
zpool_cmd_list = [sudo_bin, zpool_bin, 'status', pool['name']] | |
zpool_status = subprocess.Popen(zpool_cmd_list, stdout=subprocess.PIPE) | |
status = defaultdict(lambda: defaultdict(str)) | |
disks = [] | |
critical_errors = [] | |
total_errors = 0 | |
error_flag = False | |
has_text = re.compile('\D+') # any non digit | |
for line in zpool_status.stdout: | |
line = line.strip() | |
if line.startswith('scsi') or line.startswith('ad') or line.startswith('da') or line.startswith('sd') or 'luks' in line or 'zfs' in line or 'crypt' in line: | |
values = line.split() | |
disk = values[0] | |
read_err = values[2] | |
disks.append(disk) | |
if 'UNAVAIL' in line: | |
critical_errors.append(disk) | |
continue | |
# Do some string checks in case number of errors climbs to high (e.g. 2.15k) | |
if re.search(has_text, read_err) is not None or int(read_err) > 0: | |
error_flag = True | |
total_errors += int(read_err) | |
write_err = values[3] | |
if re.search(has_text, write_err) is not None or int(write_err) > 0: | |
error_flag = True | |
total_errors += int(write_err) | |
chksum_err = values[4] | |
if re.search(has_text, chksum_err) is not None or int(chksum_err) > 0: | |
error_flag = True | |
total_errors += int(chksum_err) | |
status[disk]['read'] = read_err | |
status[disk]['write'] = write_err | |
status[disk]['chksum'] = chksum_err | |
pool['disks'] = disks | |
pool['status'] = status | |
pool['critical_errors'] = critical_errors | |
pool['total_errors'] = total_errors | |
pool['error_flag'] = error_flag | |
print(json.dumps(pools, indent=1)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment