Skip to content

[UI BUG] Resource limits for type 15 (ObjectStorage) and 16 (GPU) do not sync/display correctly in Web UI #13944

Description

@ms30063600

problem

Hi,

I found that more resource limits are shown in the application then is actually mentioned in https://cloudstack.apache.org/api/apidocs-4.22/apis/updateResourceLimit.html. So I asked my AI assistent. He/she came up with additional resource type ids 12, 13, 14, 15 and 16. This seemed to work fine, except that it does not work for resource type id 15 and 16, based on that my newly imposed limits were not shown in the application. But then I tried the listResourceLimit api endpoint, and the values for both resource types (15, 16) were shown correctly. So this is about the presentation of this data in the UI.
The following problem description is created by the AI assistent. But I hope the picture is clear already.

Kind regards, Maurice.

There is a synchronization and presentation discrepancy between the CloudStack backend API and the Vue.js Web UI regarding resource limits for newer resource types (specifically resourcetype 15 for ObjectStorage and 16 for GPU).
While the backend correctly processes these values via updateResourceLimit and returns them accurately via listResourceLimits, the Web UI limits configuration panel fails to parse, map, or visually reflect these values accurately.
Steps to Reproduce

  1. Update the GPU resource limit for a domain/account via the API using: updateResourceLimit resourcetype=16 max=2 ...
  2. Verify the backend successfully registered the limit by calling the listResourceLimits API endpoint (the value shows up correctly).
  3. Log into the CloudStack Web UI as a Root Admin and navigate to the limits configuration for that same domain/account.
  4. Observe that the values for "Max. Object Storage (GiB)" and/or "Max. GPUs" do not reflect the values set via the API, or fail to display the updated state.
    Expected Behavior
    The Web UI's frontend mapping array should dynamically parse or correctly hardcode mappings for sequential backend resource IDs beyond 11 (including 12 through 16) so that administrative changes made via the API align 1:1 with the graphical dashboard views.
    Actual Behavior
    The backend successfully enforces and reports the limits via API, but the Web UI component fails to map the frontend input fields to resourcetype 15 and 16 data payloads.

versions

The versions of ACS, hypervisors, storage, network etc..

The steps to reproduce the bug

...

What to do about it?

No response

Activity

boring-cyborg commented on Aug 21, 2026

@boring-cyborg

Thanks for opening your first issue here! Be sure to follow the issue template!

DaanHoogland commented on Aug 21, 2026

@DaanHoogland
Contributor

@ms30063600 / Maurice, the UI is behind the API in principle. Some people feel you should implement immediately in the UI what you implement in the API. I could agree less. Or actually couldn’t oppose more. The API is prone to PoC and shouldn’t be sold as clickable bait in my not so humble opinion. However, and more specific to you example, feel free to implement UI changes that reflect the current state of this particular API if you feel you need it. Object Storage and GPU are latecomers though not entirely new any more.

@abh1sar @vishesh92 , maybe you guys have more inviting ideas on this?

added this to the unplanned milestone on Aug 21, 2026
modified the milestones: unplanned, 24.0.0 on Aug 26, 2026

stag7824 commented on Sep 14, 2026

@stag7824

I had a look at this. I could not reproduce it for resource types 15 and 16 specifically, and I think the diagnosis in the report is off — though there is a real gap next door.

ResourceLimitTab.vue builds the limits panel entirely from what listResourceLimits returns; there is no hardcoded list of types to filter against. Each label is looked up as:

$t('label.max' + item.resourcetypename.replace('_', ''))

For 15 and 16 that resolves to label.maxobjectstorage and label.maxgpu, and both are present in en.json ("Max. Object Storage (GiB)" and "Max. GPUs"). Resolving all 17 Resource.ResourceType values through that expression against the real locale file, the only one that misses is type 12, backup → label.maxbackup, which exists in no locale. That row renders the raw key. I've opened #14163 for it.

Two things that may actually be behind what you saw, @ms30063600 — both worth checking against your setup:

  1. Storage types are converted to GiB on the way out. ApiResponseHelper.createResourceLimitResponse divides by bytesToGiB and rounds up for every type where ResourceType.isStorageType is true, which includes object_storage (15). So a limit set in bytes via updateResourceLimit comes back in GiB in listResourceLimits, and the UI shows the GiB figure. Values under 1 GiB round up to 1. GPU (16) is not a storage type and is not converted. If the number you set and the number displayed differ by a factor of ~2^30, that's this.

  2. A limit of 0 displays as Unlimited. In fetchData, tagged limits are read as subItem.max || -1, so a stored 0 becomes -1. Untagged limits get corrected a few lines later by form[item.resourcetype] = item.max == null ? -1 : item.max, but tagged ones do not, and origValues is only recorded for the untagged entry — so a tagged limit of 0 both displays as Unlimited and is written back as -1 on the next save. That one looks like a genuine bug to me, separate from the label. Happy to raise it separately if it isn't already known.

Could you say which values you set for 15 and 16, and whether the rows were tagged? That would tell us which of these you hit.

ms30063600 commented on Sep 16, 2026

@ms30063600
Author

Hi @stag7824
I read your reaction last night. Let me perform a re-test, see below.
For this test I use the https://qa.cloudstack.cloud environment.
My test domain is "Domain2" with id="daaee52a-cb7a-4206-a862-6219e7341426". As far as I know the resource limits are reset daily.
Step 1: Show current resource limit values: see attached file result_demo_listResourceLimits_20260916-071214-172493.json.
Step 2: Update each resource limit for this domain (17 requests). The value that I set is: resourceid * 10 + 7. Done.
Step 3: Show current resource limit values run after step 2: see attached file result_demo_listResourceLimits_20260916-074146-360675.json.
This shows that the resource limits have the following values (excerpt taken from the json result file).
"resourcetype": "0",
"max": 7
"resourcetype": "1",
"max": 17
"resourcetype": "2",
"max": 27
"resourcetype": "3",
"max": 37
"resourcetype": "4",
"max": 47
"resourcetype": "5",
"max": 57
"resourcetype": "6",
"max": 67
"resourcetype": "7",
"max": 77
"resourcetype": "8",
"max": 87
"resourcetype": "9",
"max": 97
"resourcetype": "10",
"max": 107
"resourcetype": "11",
"max": 117
"resourcetype": "12",
"max": 127
"resourcetype": "13",
"max": 137
"resourcetype": "14",
"max": 147
"resourcetype": "15",
"max": 157
"resourcetype": "16",
"max": 167

Final step: compare with gui. To this end I supply two screenshots (note "Secondary storage limit" is in both, so you can see that I did not miss a single resource).
Please check that the various values are indeed in the screenshot. Also it appears here that the resource limits are shown in a different order than by increasing resourceid. Please check that the last two lines of the second screenshot that the limit is still "Unlimited". I expected to see there 157 and 167.

Kind regards,
Mau

Image Image

result_demo_listResourceLimits_20260916-071214-172493.json

result_demo_listResourceLimits_20260916-074146-360675.json

stag7824 commented on Oct 2, 2026

@stag7824

Thank you for the careful re-test, @ms30063600 — you were right and I was looking in the wrong place. My earlier note was about the Resource Limits edit tab; your screenshots are the usage view, which reads its values from listDomains rather than listResourceLimits, and that is where the bug is.

DomainJoinDaoImpl resolved the bucket and object storage limits through the account helper, ApiDBUtils.findCorrectResourceLimit, passing it the domain's id. That looks the id up in the account table, finds the root admin or nothing, and answers unlimited either way — so the configured value was never used. Every other resource type there already used the domain helper. One small correction to the report: in your screenshot the unlimited rows are Bucket (14) and Object Storage (15); GPU (16) shows 167 correctly.

There were also copy-paste mistakes in the backup rows (the backup limit was hidden whenever snapshots were unlimited, and backup storage whenever backups were). Your test didn't hit those because every limit was set, but they would show up on a domain with some limits left unlimited.

All three are fixed in #14293, with tests.

I still can't explain the VPC row in your first screenshot ("77 Available" but "0 / 67") — both numbers come from the same variable in this code, so it isn't from here. If you can reproduce it, the raw listDomains response for that domain would show whether vpclimit really comes back as 67.

ms30063600 commented on Oct 7, 2026

@ms30063600
Author

Hi @stag7824,
I could not respond earlier.
Thanks for the fix. Thanks for pointing out the flaw in my report. I agree that the VPC row is indeed odd. Do you still observe this after your fix?
Kind regards, Mau.

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions