Skip to content

Conversation

@arddennis
Copy link

SUMMARY

When volume already exists we need to be able to resize it. To preserve idempotency existing volume capacity is compared with the definde one. If size differs executes resize on the volume. We do not check if allocated size is smaller than configured size, but libirt will throw an error when resize to a lower volume will be attempted.

Calculation of the size from xml moved to a separate function to reduce complexity of the create class method.
Volume resize moved to a more global place where it is attempted/tested all the time.

ISSUE TYPE
  • Feature Pull Request
COMPONENT NAME

community.libvirt.virt_volume

ADDITIONAL INFORMATION

A play like this:

---
- name: Test libvirt volume creation
  hosts: mylibvirthost
  become: true
  tasks:
    - name: Create empty volume
      community.libvirt.virt_volume:
        state: present
        name: testing_volume-boot
        pool: int_ceph
        xml: |
          <volume>
            <name>testing_volume-boot</name>
            <capacity unit='G'>10</capacity>
            <target>
              <format type='raw'/>
            </target>
          </volume>

    - name: Update existing volume
      community.libvirt.virt_volume:
        state: present
        name: testing_volume-boot
        pool: int_ceph
        xml: |
          <volume>
            <name>testing_volume-boot</name>
            <capacity unit='G'>20</capacity>
            <target>
              <format type='raw'/>
            </target>
          </volume>

Should result in 20G volume and not keep it 10G. There is also no command option to resize the volume, so logically we need to implement a way to resize the volume if defined size is different.

Before:

TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
ok: [mylibvirthost]

TASK [Create empty volume] ****************************************************************************************************************************************************************************************
[WARNING]: The 'name' parameter is ignored; the volume name is taken from the XML definition ('testing_volume-boot').
changed: [mylibvirthost]

TASK [Update existing volume] *************************************************************************************************************************************************************************************
ok: [mylibvirthost]

PLAY RECAP ********************************************************************************************************************************************************************************************************
mylibvirthost : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

After:

TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
ok: [mylibvirthost]

TASK [Create empty volume] ****************************************************************************************************************************************************************************************
[WARNING]: The 'name' parameter is ignored; the volume name is taken from the XML definition ('testing_volume-boot').
changed: [mylibvirthost]

TASK [Update existing volume] *************************************************************************************************************************************************************************************
changed: [mylibvirthost]

PLAY RECAP ********************************************************************************************************************************************************************************************************
mylibvirthost : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

When volume already exists we need to be able to resize it. To preserve
idempotency existing volume capacity is compared with the definde one.
If size differs executes resize on the volume. We do not check if
allocated size is smaller than configured size, but libirt will throw an
error when resize to a lower volume will be attempted.

Calculation of the size from xml moved to a separate function to reduce
complexity of the create class method.
Volume resize moved to a more global place where it is attempted/tested
all the time.
Copy link
Contributor

@Andersson007 Andersson007 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arddennis hello, thanks for the PR
Could you please add a changelog fragment?

@Andersson007
Copy link
Contributor

@csmart @thinkdoggie what do you think about the change?

# https://libvirt.org/html/libvirt-libvirt-storage.html#virStorageVolInfo
created_volume_size_bytes = createdStorageVolPtr.info()[1]
if created_volume_size_bytes != size_bytes:
createdStorageVolPtr.resize(size_bytes)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually change the size of the underlying disks, whether raw or qcow2? Or just the definition within the VM?

Once a drive changes size, the user still needs to adjust any filesystem or partitions, it might be good to include that in the docs?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change the capacity on the volume using libvirt pool. And yes, this does not touch the filesystem on the volume.

Usually an image has a resize scrip (growroot for example) to cover this. And once the server(vm) is rebooted fs is grown as well.

I can extend doc string for the module on state.present option And add something like:
On existing volumes if size in xml differs module attempts to resize capacity of the volume.

There is more can be done or mentioned. For example, info method returns 3 values: type, capacity, allocation. So if allocation is bigger than a new size an exception will be raised. Should this be in the docs as well? Should I add an exception handling and add failed to the module results?

Copy link
Collaborator

@csmart csmart Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think any docs that will help the user to make good use of the feature are worthwhile 👍

If shrinking is not supported, we should call that out, perhaps in an example in the docs.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added minimal description to a state option that it can also be used to resize existing volumes if new capacity is bigger than current capacity. To be able to resize, it might be needed to introduce a new option allow_shrink and (potentially) resize command (if both ways is supported). Can you elaborate about example? I am a bit afraid to add extra and non directly relevant information to a module description.

Copy link
Collaborator

@csmart csmart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to add a test to resize a defined volume, then check the size, or such?

Extended state description with the statement that it can be used to
resize existing volumes if new capacity is bigger than current.

Added "Tests for volume resize" to verify resize behaviour. It creates
volume of defined size, then check idempotency and finally attempts to
resize the volume. Assert checks resulting size of the volume.
@arddennis
Copy link
Author

Is it possible to add a test to resize a defined volume, then check the size, or such?

Added test to resize volume. the module currently can only grow volumes as for the shrink operation we'll need to add allow_shrink option. So test cover only resize to bigger volume.

@thinkdoggie
Copy link
Contributor

thinkdoggie commented Nov 12, 2025

Hi @arddennis Thank you for this excellent PR!

I have a suggestion to improve the user experience: currently, when a user attempts to shrink a volume (new capacity < current capacity), the operation fails with a libvirt error message. While this correctly prevents data loss, it would be better to add an explicit check in the module code before calling resize() to provide a more graceful, Ansible-friendly error message. The check would:

  • Provide a clear error message at the Ansible level instead of bubbling up a libvirt exception
  • Fail fast before making the libvirt API call
  • Be consistent with the documentation which already mentions "bigger capacity"
  • Show both current and requested sizes to help users understand the issue

Additionally, it would be helpful to add a test case that verifies shrink operations are properly rejected.

@thinkdoggie
Copy link
Contributor

Another suggestion regarding documentation: it would be helpful to document that the resize functionality has varying support across different storage backend types.

Based on libvirt's implementation, not all storage pool types support volume resize operations. This would help users understand potential limitations before attempting resize operations.

@arddennis
Copy link
Author

Another suggestion regarding documentation: it would be helpful to document that the resize functionality has varying support across different storage backend types.

Based on libvirt's implementation, not all storage pool types support volume resize operations. This would help users understand potential limitations before attempting resize operations.

I have plans to purpose additional things like diff and check support for the modules, introduce proper module errors instead of python exceptions, but I feel that the changes should be as small as possible. Or its review and accept process will be unlimited.

Would be good to get a feedback if this is need/wanted and I can add it here or as a separate change after this merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants