diff --git a/snmp/zfs-linux b/snmp/zfs-linux old mode 100644 new mode 100755 index c5f3625..87677d0 --- a/snmp/zfs-linux +++ b/snmp/zfs-linux @@ -2,6 +2,13 @@ import json import subprocess +def proc_err(cmd, proc): + # output process error and first line of error code + return "{}{}".format( + subprocess.CalledProcessError(proc.returncode, cmd, proc.stderr), + " ({})".format(proc.stderr.splitlines()[0]) if proc.stderr.splitlines() else "" + ) + def main(args): res = {} @@ -95,9 +102,24 @@ def main(args): PREFETCH_METADATA_MISSES_PERCENT = DEMAND_METADATA_MISSES / ARC_MISSES * 100 # pools - proc = subprocess.run(['/sbin/zpool', 'list', '-pH'], stdout=subprocess.PIPE, universal_newlines=True) - if proc.returncode != 0: - return proc.returncode + exact_size = True + zpool_cmd = ['/sbin/zpool'] + zpool_cmd_list = zpool_cmd + ['list', '-p', '-H'] + std = {'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE, 'universal_newlines': True} + + ## account for variations between ZoL zfs versions + proc = subprocess.run(zpool_cmd_list, **std) + if (proc.returncode == 1) and (('root' in proc.stderr) or ('admin' in proc.stderr)): + zpool_cmd = ['sudo'] + zpool_cmd # elevate zpool with sudo + zpool_cmd_list = zpool_cmd + ['list', '-p', '-H'] + proc = subprocess.run(zpool_cmd_list, **std) + if (proc.returncode == 2): + # -p option is not present in older versions + del zpool_cmd_list[zpool_cmd_list.index('-p')] # try removing -p to fix the issue + proc = subprocess.run(zpool_cmd_list, **std) + exact_size = False + if (proc.returncode != 0): + return proc_err(zpool_cmd_list, proc) pools = [] FIELDS = ['name', 'size', 'alloc', 'free', 'expandsz', 'frag', 'cap', 'dedup'] @@ -110,6 +132,18 @@ def main(args): info['dedup'] = info['dedup'].rstrip('x') info['cap'] = info['cap'].rstrip('%') + # zfs-06.5.11 fix + if not exact_size: + zpool_cmd_get = zpool_cmd + ['get', '-pH', 'size,alloc,free', info['name']] + proc2 = subprocess.run(zpool_cmd_get, **std) + if (proc2.returncode != 0): + return proc_err(zpool_cmd_get, proc2) + + info2 = dict([tuple(s.split('\t')[1:3]) for s in proc2.stdout.splitlines()]) + info['size'] = info2['size'] + info['alloc'] = info2['allocated'] + info['free'] = info2['free'] + pools.append(info) res = {