Skip to content

Volume resize usage event may record incorrect size in cloud_usage #13555

Description

@Yuliia7-1

problem

When a volume is resized, CloudStack publishes a EVENT_VOLUME_RESIZE usage event that is later used for billing calculations and stored in cloud_usage. I'm using a volume with a Custom Disk Offering.

In VolumeApiServiceImpl.orchestrateResizeVolume(), the volume size is updated before the usage event is published:

if (currentSize == volume.getSize() && currentSize != newSize) {
    volume.setSize(newSize);
} else if (volume.getSize() != newSize) {
    newSize = volume.getSize();
}

_volsDao.update(volume.getId(), volume);

The usage event is then published using:

UsageEventUtils.publishUsageEvent(
    EventTypes.EVENT_VOLUME_RESIZE,
    volume.getAccountId(),
    volume.getDataCenterId(),
    volume.getId(),
    volume.getName(),
    volume.getDiskOfferingId(),
    volume.getTemplateId(),
    volume.getSize(),
    Volume.class.getName(),
    volume.getUuid()
);

Observed Behaviour

The resize event uses volume.getSize() instead of the final resize target value (newSize).

In environments where billing is calculated from cloud_usage, we have observed discrepancies between:
the current volume size reported by CloudStack APIs/UI, and the size stored in cloud_usage following resize operations.

As a result, billing records may not accurately reflect the expected volume size history after one or more resize operations.

The reproduction steps are as follows:

  1. Create or use an existing volume with an initial size of 120 GB.

  2. Resize the volume from 120 GB to 122 GB.
    A VOLUME.RESIZE entry is created in the usage_event table with a size of 120 GB.
    After the usage aggregation job runs, the corresponding records in the cloud_usage table are also generated with a size of 120 GB.

  3. Resize the volume from 122 GB to 124 GB.
    The usage_event entry records 122 GB instead of 124 GB.
    The aggregated cloud_usage records are generated using 122 GB.

  4. Resize the volume from 124 GB to 126 GB.
    The usage_event entry records 124 GB.
    The aggregated cloud_usage records are generated using 124 GB.

  5. Resize the volume from 126 GB to 130 GB.
    The usage_event entry records 126 GB.
    The aggregated cloud_usage records are generated using 126 GB.

  6. Resize the volume from 130 GB to 132 GB.
    The usage_event entry records 130 GB.
    The aggregated cloud_usage records are generated using 130 GB.

Observed behaviour:

The size stored in usage_event after a volume resize operation is the previous volume size rather than the new resized size. Since usage aggregation relies on the data recorded in usage_event, the generated records in cloud_usage also contain the previous volume size.

As a result, a volume resized from 120 GB to 122 GB continues to be billed as 120 GB, a volume resized from 122 GB to 124 GB continues to be billed as 122 GB, and so on. The discrepancy persists until another resize operation occurs.

For example, after the final resize operation, the volume size shown in CloudStack is 132 GB, while both usage_event and cloud_usage reflect 130 GB, resulting in under-reporting of storage usage for billing purposes.

versions

4.19.1

What to do about it?

The resize usage event should be published using the actual final resized value (newSize) that was determined during the resize workflow.

For example:

UsageEventUtils.publishUsageEvent(
    EventTypes.EVENT_VOLUME_RESIZE,
    volume.getAccountId(),
    volume.getDataCenterId(),
    volume.getId(),
    volume.getName(),
    volume.getDiskOfferingId(),
    volume.getTemplateId(),
    newSize,
    Volume.class.getName(),
    volume.getUuid()
);

This would ensure that usage records and billing calculations are based on the intended resize value.

Affected Code: server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java

Method: orchestrateResizeVolume(...)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions