From 513c1962003b4cb76d49054c6542b12b7ec0ebe0 Mon Sep 17 00:00:00 2001 From: Ryan Moeller Date: Tue, 8 Dec 2020 17:02:16 +0000 Subject: [PATCH] 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 Signed-off-by: Ryan Moeller Closes #11318 --- cmd/arc_summary/arc_summary2 | 10 +++++++-- cmd/arc_summary/arc_summary3 | 39 ++++++++++++++---------------------- cmd/arcstat/arcstat.in | 5 +++-- 3 files changed, 26 insertions(+), 28 deletions(-) diff --git a/cmd/arc_summary/arc_summary2 b/cmd/arc_summary/arc_summary2 index 636f7b46d9..75b5697526 100755 --- a/cmd/arc_summary/arc_summary2 +++ b/cmd/arc_summary/arc_summary2 @@ -59,14 +59,20 @@ if sys.platform.startswith('freebsd'): # Requires py27-sysctl on FreeBSD import sysctl + def is_value(ctl): + return ctl.type != sysctl.CTLTYPE_NODE + def load_kstats(namespace): """Collect information on a specific subsystem of the ARC""" 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(): - 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'): diff --git a/cmd/arc_summary/arc_summary3 b/cmd/arc_summary/arc_summary3 index bd49e1b537..61a8e3b3ee 100755 --- a/cmd/arc_summary/arc_summary3 +++ b/cmd/arc_summary/arc_summary3 @@ -85,16 +85,24 @@ if sys.platform.startswith('freebsd'): 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): base = 'kstat.zfs.misc.{section}.'.format(section=section) - # base is removed from the name - fmt = lambda kstat: '{name} : {value}'.format(name=kstat.name[len(base):], + fmt = lambda kstat: '{name} : {value}'.format(name=namefmt(kstat, base), 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): - cut = 8 # = len('vfs.zfs.') - return {ctl.name[cut:]: str(ctl.value) for ctl in sysctl.filter(base)} + ctls = sysctl.filter(base) + return {namefmt(ctl): str(ctl.value) for ctl in ctls if is_value(ctl)} def get_tunable_params(): return get_params('vfs.zfs') @@ -111,25 +119,8 @@ if sys.platform.startswith('freebsd'): return '{} version {}'.format(name, version) def get_descriptions(_request): - # py-sysctl doesn't give descriptions, so we have to shell out. - command = ['sysctl', '-d', 'vfs.zfs'] - - # 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]) + ctls = sysctl.filter('vfs.zfs') + return {namefmt(ctl): ctl.description for ctl in ctls if is_value(ctl)} elif sys.platform.startswith('linux'): diff --git a/cmd/arcstat/arcstat.in b/cmd/arcstat/arcstat.in index 40ab975c6a..9e7c52a6c7 100755 --- a/cmd/arcstat/arcstat.in +++ b/cmd/arcstat/arcstat.in @@ -144,13 +144,14 @@ pretty_print = True if sys.platform.startswith('freebsd'): - # Requires py27-sysctl on FreeBSD + # Requires py-sysctl on FreeBSD import sysctl def kstat_update(): 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: sys.exit(1)