FreeBSD: Update usage of py-sysctl

py-sysctl now includes the CTLTYPE_NODE type nodes in the list returned
by sysctl.filter() on FreeBSD head.  It also provides descriptions now.

Eliminate the subprocess call to get descriptions, and filter out the
nodes so we only deal with values.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Ryan Moeller <ryan@iXsystems.com>
Closes #11318
This commit is contained in:
Ryan Moeller 2020-12-08 17:02:16 +00:00 committed by Brian Behlendorf
parent e5f732edbb
commit 513c196200
3 changed files with 26 additions and 28 deletions

View File

@ -59,14 +59,20 @@ if sys.platform.startswith('freebsd'):
# Requires py27-sysctl on FreeBSD # Requires py27-sysctl on FreeBSD
import sysctl import sysctl
def is_value(ctl):
return ctl.type != sysctl.CTLTYPE_NODE
def load_kstats(namespace): def load_kstats(namespace):
"""Collect information on a specific subsystem of the ARC""" """Collect information on a specific subsystem of the ARC"""
base = 'kstat.zfs.misc.%s.' % namespace base = 'kstat.zfs.misc.%s.' % namespace
return [(kstat.name, D(kstat.value)) for kstat in sysctl.filter(base)] fmt = lambda kstat: (kstat.name, D(kstat.value))
kstats = sysctl.filter(base)
return [fmt(kstat) for kstat in kstats if is_value(kstat)]
def load_tunables(): def load_tunables():
return dict((ctl.name, ctl.value) for ctl in sysctl.filter('vfs.zfs')) ctls = sysctl.filter('vfs.zfs')
return dict((ctl.name, ctl.value) for ctl in ctls if is_value(ctl))
elif sys.platform.startswith('linux'): elif sys.platform.startswith('linux'):

View File

@ -85,16 +85,24 @@ if sys.platform.startswith('freebsd'):
VDEV_CACHE_SIZE = 'vdev.cache_size' VDEV_CACHE_SIZE = 'vdev.cache_size'
def is_value(ctl):
return ctl.type != sysctl.CTLTYPE_NODE
def namefmt(ctl, base='vfs.zfs.'):
# base is removed from the name
cut = len(base)
return ctl.name[cut:]
def load_kstats(section): def load_kstats(section):
base = 'kstat.zfs.misc.{section}.'.format(section=section) base = 'kstat.zfs.misc.{section}.'.format(section=section)
# base is removed from the name fmt = lambda kstat: '{name} : {value}'.format(name=namefmt(kstat, base),
fmt = lambda kstat: '{name} : {value}'.format(name=kstat.name[len(base):],
value=kstat.value) value=kstat.value)
return [fmt(kstat) for kstat in sysctl.filter(base)] kstats = sysctl.filter(base)
return [fmt(kstat) for kstat in kstats if is_value(kstat)]
def get_params(base): def get_params(base):
cut = 8 # = len('vfs.zfs.') ctls = sysctl.filter(base)
return {ctl.name[cut:]: str(ctl.value) for ctl in sysctl.filter(base)} return {namefmt(ctl): str(ctl.value) for ctl in ctls if is_value(ctl)}
def get_tunable_params(): def get_tunable_params():
return get_params('vfs.zfs') return get_params('vfs.zfs')
@ -111,25 +119,8 @@ if sys.platform.startswith('freebsd'):
return '{} version {}'.format(name, version) return '{} version {}'.format(name, version)
def get_descriptions(_request): def get_descriptions(_request):
# py-sysctl doesn't give descriptions, so we have to shell out. ctls = sysctl.filter('vfs.zfs')
command = ['sysctl', '-d', 'vfs.zfs'] return {namefmt(ctl): ctl.description for ctl in ctls if is_value(ctl)}
# The recommended way to do this is with subprocess.run(). However,
# some installed versions of Python are < 3.5, so we offer them
# the option of doing it the old way (for now)
if 'run' in dir(subprocess):
info = subprocess.run(command, stdout=subprocess.PIPE,
universal_newlines=True)
lines = info.stdout.split('\n')
else:
info = subprocess.check_output(command, universal_newlines=True)
lines = info.split('\n')
def fmt(line):
name, desc = line.split(':', 1)
return (name.strip(), desc.strip())
return dict([fmt(line) for line in lines if len(line) > 0])
elif sys.platform.startswith('linux'): elif sys.platform.startswith('linux'):

View File

@ -144,13 +144,14 @@ pretty_print = True
if sys.platform.startswith('freebsd'): if sys.platform.startswith('freebsd'):
# Requires py27-sysctl on FreeBSD # Requires py-sysctl on FreeBSD
import sysctl import sysctl
def kstat_update(): def kstat_update():
global kstat global kstat
k = sysctl.filter('kstat.zfs.misc.arcstats') k = [ctl for ctl in sysctl.filter('kstat.zfs.misc.arcstats')
if ctl.type != sysctl.CTLTYPE_NODE]
if not k: if not k:
sys.exit(1) sys.exit(1)