Open plimptm opened 3 days ago
I've noticed an inconsistency in how blivet reports the size of the underlying pv.
The blivet vg size property appears to reach straight back to read the size of the underlying block device read_current_size and subtracts only the volume group metadata, completely ignoring the pv metadata (and any unusable blocks)
If I subtract a total of 8 MiB (4 MiB for pv metadata + 4 MiB for vg metadata) from 10 GiB, the math adds up:
>>> pv.size - vg.lvm_metadata_space*2
Size (9.9921875 GiB)
>>> pv.size - vg.lvm_metadata_space*2 == lv.size
True
I would expect pvs to be handled by blivet with similar properties to other lvm objects, with an accounting for metadata, but it appears they are handled as DiskDevice type objects.
>>> vg.lvm_metadata_space
Size (4 MiB)
>>> pv.lvm_metadata_space
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'DiskDevice' object has no attribute 'lvm_metadata_space'
Hi, thank you for the report. First of all I am not saying there is no bug the code or that our calculation of metadata sizes in LVM is perfect. I know it's not and we had more than a few issues with it in the past.
There is one problem with your example -- you are not supposed to call the resize
function directly, but either use the Blivet.resize_device
helper function or register the ActionResizeDevice
action directly (unfortunately our API is not very user friendly and our documentation is not the best in the world). Using the actions might prevent some of the problems you see (there are some additional fail safe mechanisms in the actions that sometimes fix/hide problems from the lower layer).
Expected behaviors:
* calling the `resize` method with unallocated PEs in the parent volume group will expand the logical volume to fill those unallocated PEs * calling the `resize` method with no unallocated PEs in the parent volume group will see that the logical volume and volume groups sizes already match and return something indicating there are no available extents
That's not how the resize
function works. resize
will simply try to resize the device to its target_size
. Which for existing devices is just their size.
The reason for this is that resize
is a generic function that works the same for all devices -- so resize for partition and LV is the same function that (in general) is called when processing the ActionResizeDevice
action.
The question is why resize
actually tried to resize the LV, it shouldn't do that by itself, I suspect the reason is some rounding and alignment for PE size we do and that we actually rounded the size up somewhere resulting in trying to resize the LV.
The blivet vg size property appears to reach straight back to read the size of the underlying block device read_current_size and subtracts only the volume group metadata, completely ignoring the pv metadata (and any unusable blocks)
In our code there is a difference between size and free space. For VG the size is the sum of the PV sizes minus the PV metadata calculated in lvm_metadata_space
. The VG metadata (including things like pmspare) and other unusable space is accounted for in free_space
(for us VG metadata is still part of VG so part of its size) so free_space
should be used when resizing (or to be more precise LV max_size
should be used when checking if the LV can be resized).
I would expect pvs to be handled by blivet with similar properties to other lvm objects, with an accounting for metadata, but it appears they are handled as DiskDevice type objects.
Because the device itself is disk, the format is LVM PV so for LVM PV specific values you need to look at pv.format
.
The low level API in blivet (especially for LVM) is horribly complicated. The upper level API (helper functions in the Blivet
object) hide most of these things and I definitely do not recommend using the low level API to anyone.
But all the complicated explanations above aside -- we definitely do have a bug somewhere, because we think there is one free extent in your VG (free space = 4 MiB free extents = 1
) when there isn't one (Free PE / Size 0 / 0
). So that's definitely not right.
Can you please share the entire blivet log from your system? If you run the code below it will save the log to /tmp/blivet.log
:
from blivet import util
util.set_up_logging()
import blivet; b=blivet.Blivet(); b.reset()
if you don't want to share the entire log publicly you can send it to me to vtrefny AT redhat.com
, thank you.
I have been troubleshooting the use of this library in the ansible linux-system-roles collection and have traced an issue with the resizing capabilities to what I believe to be a size calculation bug in blivet. I searched the issues and didn't see anything related, so I'm opening this here.
Note: I first encountered this bug while trying to use blivet to resize a logical volume (after resizing the underlying disk) but have been able to reproduce the issue by simply calling the
LVMLogicalVolumeDevice.resize()
method even when there is no extra space available.Expected behaviors:
resize
method with unallocated PEs in the parent volume group will expand the logical volume to fill those unallocated PEsresize
method with no unallocated PEs in the parent volume group will see that the logical volume and volume groups sizes already match and return something indicating there are no available extentsActual behavior:
LVM specs:
Server OS: RHEL 9.2