-
Notifications
You must be signed in to change notification settings - Fork 39
Description
Describe the Bug
Hi,
After upgrading ZFS to 2.3.2-2bpo12+2, the zpool provider’s get_pool_data implementation in puppetlabs-zfs_core no longer parses the zpool status output correctly. This breaks ZFS-related resources that rely on get_pool_data ( zpool disk list), while the same code works fine with ZFS 2.2.7-1~bpo12+1
I’ve implemented a small parsing change that works with both ZFS 2.2.7-1bpo12+1 and 2.3.2-2bpo12+2 and would be happy to open a PR if this approach looks acceptable.
Environment
- OS: Debian 12 (bookworm)
- Puppet: 7.x
- Module:
puppetlabs-zfs_core(version: 1.6.1) - ZFS:
- Working: 2.2.7-1~bpo12+1
- Broken: 2.3.2-2~bpo12+2
Problem description
With ZFS 2.3.2-2bpo12+2, the format of zpool status output changed slightly. The current get_pool_data implementation in the zpool provider assumes tab-indented lines and uses this logic:
out = execute("zpool status #{zpool_opts} #{@resource[:pool]}", failonfail: false, combine: false)
zpool_data = out.lines.select { |line| line.index("\t") == 0 }.map { |l| l.strip.split("\s")[0] }
zpool_data.shift
zpool_dataOn ZFS 2.3.2-2bpo12+2, the status table uses spaces and a NAME STATE READ WRITE CKSUM header.
On ZFS 2.2.7-1bpo12+1, the same code works correctly with the older zpool status formatting.
Analysis
The core issue is the parsing strategy inside get_pool_data:
It assumes that each row of interest starts with a tab and uses line.index("\t") == 0 to filter lines.
With ZFS 2.3.2-2bpo12+2, the output is still a table but the indentation and formatting changed enough that this condition no longer matches.
Proposed fix
I changed get_pool_data to:
Find the table header line matching NAME STATE READ WRITE CKSUM.
From there, collect only the indented lines (pool and device rows).
Take just the first column as the device/pool name.
def get_pool_data
# https://docs.oracle.com/cd/E19082-01/817-2271/gbcve/index.html
# we could also use zpool iostat -v mypool for a (little bit) cleaner output
zpool_opts = case Facter.value(:kernel)
# use full device names ("-P") on Linux/ZOL to prevent
# mismatches between creation and display paths:
when 'Linux'
'-P'
else
''
end
out = execute("zpool status #{zpool_opts} #{@resource[:pool]}", failonfail: false, combine: false)
lines = out.lines
# Skip until we reach the NAME/STATE/READ/WRITE/CKSUM header
lines = lines.drop_while { |l| !(l =~ /^\s*NAME\s+STATE\s+READ\s+WRITE\s+CKSUM/) }
# Now collect only the indented table rows (NAME, pool name, devices)
zpool_data = lines
.select { |l| l =~ /^\s+/ } # only indented lines
.map { |l| l.strip.split(/\s+/)[0] } # first column only
# First entry is "NAME", remove it so first element is the pool name
zpool_data.shift
zpool_data
end##Backwards compatibility
I’ve tested this against:
ZFS 2.2.7-1bpo12+1: returns the same device list as before (no change in behaviour).
ZFS 22.3.2-2bpo12+2: correctly returns the pool and device list where the previous code returned an empty/incorrect array.
The logic is based purely on the NAME STATE READ WRITE CKSUM header and indentation, which appears stable across both versions.