fix: return (size, format, used, parent) from volume_size_info in list context (#294)

PVE's content API (and the bpg/proxmox Terraform provider through it)
calls volume_size_info in list context and dies "no format" when the
second value is missing, so every disk on a truenas storage failed to
refresh. Mirrors ZFSPoolPlugin: used comes from usedbydataset, and a
missing zvol now dies instead of reporting a size of 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adams
2026-10-12 16:14:42 -04:00
co-authored by Claude Opus 5.5
parent c45c3b0abf
commit 664dfe6a3e
2 changed files with 67 additions and 2 deletions
+12 -2
View File
@@ -985,10 +985,20 @@ sub volume_size_info {
my ($class, $scfg, $storeid, $volname, $timeout) = @_;
_resolve_token($storeid, $scfg);
my (undef, undef, undef, $parent, undef, undef, $format) = $class->parse_volname($volname);
my $zvol = _zvol_prefix($scfg) . "/$volname";
my $enc = uri_escape($zvol, "^A-Za-z0-9\\-_.~");
my $ds = _api($scfg, 'GET', "/pool/dataset/id/$enc") // {};
return $ds->{volsize}{parsed} // 0;
my $ds = _api($scfg, 'GET', "/pool/dataset/id/$enc");
die "volume_size_info: zvol '$zvol' not found on $scfg->{truenas_host}\n"
unless ref $ds eq 'HASH' && defined $ds->{volsize}{parsed};
my $size = int($ds->{volsize}{parsed});
my $used = int($ds->{usedbydataset}{parsed} // $ds->{used}{parsed} // 0);
# List context is (size, format, used, parent), as in ZFSPoolPlugin. A bare
# scalar here made the content API die with "no format" (#294).
return wantarray ? ($size, $format, $used, $parent) : $size;
}
sub path {
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/perl
# volume_size_info contract: scalar context → size; list context →
# (size, format, used, parent). PVE's content API dies "no format" otherwise.
use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/lib", "$FindBin::Bin/../perl5";
use Test::More;
use MockTrueNAS;
use PVE::Storage::Custom::TrueNAS;
my $TN = 'PVE::Storage::Custom::TrueNAS';
MockTrueNAS->install(datasets => {
'tank/vm/vm-100-disk-0' => {
volsize => { parsed => 34359738368 },
usedbydataset => { parsed => 1073741824 },
used => { parsed => 2147483648 },
},
'tank/vm/vm-100-cloudinit' => {
volsize => { parsed => 4194304 },
used => { parsed => 65536 },
},
});
subtest 'scalar context returns size' => sub {
my $size = $TN->volume_size_info(MockTrueNAS::scfg(), 'store', 'vm-100-disk-0');
is($size, 34359738368, 'size');
};
subtest 'list context returns (size, format, used, parent) (#294)' => sub {
my @r = $TN->volume_size_info(MockTrueNAS::scfg(), 'store', 'vm-100-disk-0');
is(scalar @r, 4, 'four values');
is($r[0], 34359738368, 'size');
is($r[1], 'raw', 'format');
is($r[2], 1073741824, 'used prefers usedbydataset');
ok(!defined $r[3], 'no parent');
};
subtest 'used falls back to used when usedbydataset is absent' => sub {
my (undef, $fmt, $used) = $TN->volume_size_info(MockTrueNAS::scfg(), 'store', 'vm-100-cloudinit');
is($fmt, 'raw', 'cloud-init drive has a format');
is($used, 65536, 'used');
};
subtest 'missing zvol dies instead of reporting size 0' => sub {
eval { $TN->volume_size_info(MockTrueNAS::scfg(), 'store', 'vm-100-disk-9') };
like($@, qr/not found/, 'dies');
};
done_testing();