winterhazel opened a new pull request, #13236:
URL: https://github.com/apache/cloudstack/pull/13236
### Description
This PR introduces the `quotaResourceStatement` API to the Quota plugin.
This API allows viewing the Quota consumption associated with a specific
resource. It will be used by the Quota UI rework in a separate PR.
In addition, some adjustments were made in the `quotaStatement` API in order
to allow including the consumption of subdomains in the resulting statement.
### Types of changes
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [X] New feature (non-breaking change which adds functionality)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [X] Enhancement (improves an existing feature and functionality)
- [ ] Cleanup (Code refactoring and cleanup, that may add test cases)
- [ ] Build/CI
- [X] Test (unit or integration test code)
### Feature/Enhancement Scale or Bug Severity
#### Feature/Enhancement Scale
- [ ] Major
- [X] Minor
### How Has This Been Tested?
I tested the API by fuzzing its parameters for root admin, domain admin, and
user accounts. In the tests, I validated that the API returned the expected
response while performing correct permission checking.
---
### Environment configuration
My environment had two domains: `ROOT` and `d1`.
```sql
MariaDB [cloud]> select uuid,name,path,parent from domain;
+--------------------------------------+------+------+--------+
| uuid | name | path | parent |
+--------------------------------------+------+------+--------+
| de3f3dfb-f84b-11f0-8ace-32e0826870ba | ROOT | / | NULL |
| dc5064ad-d4a8-4bb3-ae18-a52e4810ac3d | d1 | /d1/ | 1 |
+--------------------------------------+------+------+--------+
```
Each domain had a domain admin (`dr` for `ROOT` and `d1` for `d1`) and a
user account (`ur` for `ROOT` and `u1` for `d1`). `ROOT` also had a project and
the root admin.
```sql
MariaDB [cloud]> select uuid,account_name,domain_id,role_id from account;
+--------------------------------------+--------------------------+-----------+---------+
| uuid | account_name |
domain_id | role_id |
+--------------------------------------+--------------------------+-----------+---------+
| f684aae8-f84b-11f0-8ace-32e0826870ba | system |
1 | 1 |
| f684da1a-f84b-11f0-8ace-32e0826870ba | admin |
1 | 1 |
| 17dfdcce-fd02-46d0-85ae-7de91fda634c | baremetal-system-account |
1 | 4 |
| aaba75a0-a575-41be-80e1-dbea14c10e51 | dr |
1 | 3 |
| feaffae2-7ba4-45dc-b46f-20ae86192685 | d1 |
2 | 3 |
| 2f49212d-d6d5-437b-800d-a7bb4a8def4b | u1 |
2 | 4 |
| b029e8b8-e539-4d1a-906d-3d4f2fb36b82 | ur |
1 | 4 |
| b14100c6-d9f6-450e-87a2-0833bb45e5f8 | PrjAcct-aa-1 |
1 | NULL |
+--------------------------------------+--------------------------+-----------+---------+
```
---
### Test 1 (user accounts)
- `id`: returns the statement scoped to the owning account when the caller
has access to it, and an error when it does not.
```sh
(u1) 🐱 > quota resourcestatement
id=53c791d2-ac8f-4acb-9246-3a2b9eb354ea startdate=2026-01-01 enddate=2027-01-01
usagetype=1
{
"quotaresourcestatement": {
"items": [
{
"accountid": "2f49212d-d6d5-437b-800d-a7bb4a8def4b",
"enddate": "2026-05-24T20:59:59-0300",
"quotaconsumed": 2.46531524,
"startdate": "2026-05-23T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 5.69112164,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(u1) 🐱 > quota resourcestatement
id=e4e91818-cbb5-401a-bb42-35d976ea4e01 startdate=2026-01-01 enddate=2027-01-01
usagetype=1
🙈 Error: (HTTP 531, error code 4365) Caller does not have permission to
operate with provided resource.
```
- `accountid`: returns the statement scoped to the provided account if
accessible, or an empty list otherwise.
```sh
(u1) 🐱 > quota resourcestatement
id=53c791d2-ac8f-4acb-9246-3a2b9eb354ea startdate=2026-01-01 enddate=2027-01-01
usagetype=1 accountid=2f49212d-d6d5-437b-800d-a7bb4a8def4b (u1)
{
"quotaresourcestatement": {
"items": [
{
"accountid": "2f49212d-d6d5-437b-800d-a7bb4a8def4b",
"enddate": "2026-05-24T20:59:59-0300",
"quotaconsumed": 2.46531524,
"startdate": "2026-05-23T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 5.69112164,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(u1) 🐱 > quota resourcestatement
id=e4e91818-cbb5-401a-bb42-35d976ea4e01 startdate=2026-01-01 enddate=2027-01-01
usagetype=1 accountid=2f49212d-d6d5-437b-800d-a7bb4a8def4b (u1)
{
"quotaresourcestatement": {
"items": [],
"totalquota": 0,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
```
- `projectid`: returns the statement scoped to the provided project if
accessible, or an exception otherwise.
```sh
(u1) 🐱 > quota resourcestatement
id=6d7b3c73-7f06-4f23-9210-3af5889790d1 startdate=2026-01-01 enddate=2027-01-01
usagetype=1 projectid=c1ce41c4-7b01-4386-8264-479db5ace0bc
🙈 Error: (HTTP 432, error code 9999) The API [quotaResourceStatement]
does not exist or is not available for this account/user in project
[c1ce41c4-7b01-4386-8264-479db5ace0bc].
(ur) 🐱 > quota resourcestatement
id=6d7b3c73-7f06-4f23-9210-3af5889790d1 startdate=2026-01-01 enddate=2027-01-01
usagetype=1 projectid=c1ce41c4-7b01-4386-8264-479db5ace0bc
{
"quotaresourcestatement": {
"items": [
{
"accountid": "b14100c6-d9f6-450e-87a2-0833bb45e5f8",
"enddate": "2026-05-21T20:59:59-0300",
"quotaconsumed": 1.42573923,
"startdate": "2026-05-20T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 22.20631686,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
```
- `isrecursive`: ignored for user accounts.
```sh
(ur) 🐱 > quota resourcestatement
id=db0db635-df4d-42bb-9aca-19cc3d986ca0 startdate=2026-01-01 enddate=2027-01-01
usagetype=1 isrecursive=true
{
"quotaresourcestatement": {
"items": [
{
"accountid": "b029e8b8-e539-4d1a-906d-3d4f2fb36b82",
"enddate": "2026-05-24T20:59:59-0300",
"quotaconsumed": 2.46247754,
"startdate": "2026-05-23T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 18.9019186,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(ur) 🐱 > quota resourcestatement
id=db0db635-df4d-42bb-9aca-19cc3d986ca0 startdate=2026-01-01 enddate=2027-01-01
usagetype=1 isrecursive=false
{
"quotaresourcestatement": {
"items": [
{
"accountid": "b029e8b8-e539-4d1a-906d-3d4f2fb36b82",
"enddate": "2026-05-24T20:59:59-0300",
"quotaconsumed": 2.46247754,
"startdate": "2026-05-23T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 18.9019186,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
```
---
### Test 2 (domain admins)
- `id`: returns the statement scoped to the caller's domain.
```sh
(d1) 🐱 > quota resourcestatement
id=53c791d2-ac8f-4acb-9246-3a2b9eb354ea startdate=2026-01-01 enddate=2027-01-01
usagetype=1
{
"quotaresourcestatement": {
"items": [
{
"accountid": "2f49212d-d6d5-437b-800d-a7bb4a8def4b",
"enddate": "2026-05-24T20:59:59-0300",
"quotaconsumed": 2.46531524,
"startdate": "2026-05-23T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 14.60737768,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(d1) 🐱 > quota resourcestatement
id=db0db635-df4d-42bb-9aca-19cc3d986ca0 startdate=2026-01-01 enddate=2027-01-01
usagetype=1
{
"quotaresourcestatement": {
"items": [
{
"accountid": "2f49212d-d6d5-437b-800d-a7bb4a8def4b",
"enddate": "2026-05-21T20:59:59-0300",
"quotaconsumed": 1.42775528,
"startdate": "2026-05-20T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 25.15400928,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(d1) 🐱 > quota resourcestatement
id=6d7b3c73-7f06-4f23-9210-3af5889790d1 startdate=2026-01-01 enddate=2027-01-01
usagetype=1
{
"quotaresourcestatement": {
"items": [],
"totalquota": 0,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
```
- `accountid`: returns the statement scoped to the provided account if
accessible, or an exception otherwise.
```sh
(d1) 🐱 > quota resourcestatement
id=53c791d2-ac8f-4acb-9246-3a2b9eb354ea startdate=2026-01-01 enddate=2027-01-01
usagetype=1 accountid=2f49212d-d6d5-437b-800d-a7bb4a8def4b
{
"quotaresourcestatement": {
"items": [
{
"accountid": "2f49212d-d6d5-437b-800d-a7bb4a8def4b",
"enddate": "2026-05-24T20:59:59-0300",
"quotaconsumed": 2.46531524,
"startdate": "2026-05-23T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 11.44631141,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(d1) 🐱 > quota resourcestatement
id=53c791d2-ac8f-4acb-9246-3a2b9eb354ea startdate=2026-01-01 enddate=2027-01-01
usagetype=1 accountid=feaffae2-7ba4-45dc-b46f-20ae86192685
{
"quotaresourcestatement": {
"items": [
{
"accountid": "feaffae2-7ba4-45dc-b46f-20ae86192685",
"enddate": "2026-05-26T20:59:59-0300",
"quotaconsumed": 3.16106627,
"startdate": "2026-05-25T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
}
],
"totalquota": 3.16106627,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(d1) 🐱 > quota resourcestatement
id=53c791d2-ac8f-4acb-9246-3a2b9eb354ea startdate=2026-01-01 enddate=2027-01-01
usagetype=1 accountid=f684da1a-f84b-11f0-8ace-32e0826870ba
🙈 Error: (HTTP 531, error code 4365) Caller does not have permission to
operate with provided resource.
```
- `projectid`: returns the statement scoped to the provided project if
accessible, or an exception otherwise.
```sh
(d1) 🐱 > quota resourcestatement
id=6d7b3c73-7f06-4f23-9210-3af5889790d1 startdate=2026-01-01 enddate=2027-01-01
usagetype=1 projectid=c1ce41c4-7b01-4386-8264-479db5ace0bc
🙈 Error: (HTTP 531, error code 4365) Account Account
[{"accountName":"d1","id":5,"uuid":"feaffae2-7ba4-45dc-b46f-20ae86192685"}]
does not have permission to operate within domain
id=de3f3dfb-f84b-11f0-8ace-32e0826870ba
(dr) 🐱 > quota resourcestatement
id=6d7b3c73-7f06-4f23-9210-3af5889790d1 startdate=2026-01-01 enddate=2027-01-01
usagetype=1 projectid=c1ce41c4-7b01-4386-8264-479db5ace0bc
{
"quotaresourcestatement": {
"items": [
{
"accountid": "b14100c6-d9f6-450e-87a2-0833bb45e5f8",
"enddate": "2026-05-21T20:59:59-0300",
"quotaconsumed": 1.42573923,
"startdate": "2026-05-20T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 39.76108809,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
```
- `isrecursive`: allows domain admins to generate the statement including
usage records of subdomains.
```sh
(dr) 🐱 > quota resourcestatement
id=e4e91818-cbb5-401a-bb42-35d976ea4e01 startdate=2026-01-01 enddate=2027-01-01
usagetype=1 isrecursive=true
{
"quotaresourcestatement": {
"items": [
{
"accountid": "f684da1a-f84b-11f0-8ace-32e0826870ba",
"enddate": "2026-05-21T20:59:59-0300",
"quotaconsumed": 1.42880073,
"startdate": "2026-05-20T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 52.70616739,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(dr) 🐱 > quota resourcestatement
id=e4e91818-cbb5-401a-bb42-35d976ea4e01 startdate=2026-01-01 enddate=2027-01-01
usagetype=1 isrecursive=false
{
"quotaresourcestatement": {
"items": [
{
"accountid": "f684da1a-f84b-11f0-8ace-32e0826870ba",
"enddate": "2026-05-21T20:59:59-0300",
"quotaconsumed": 1.42880073,
"startdate": "2026-05-20T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 33.79573569,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
```
---
### Test 3 (root admins)
- `id`: returns the statement of any resource without limiting.
```sh
(admin) 🐱 > quota resourcestatement
id=e4e91818-cbb5-401a-bb42-35d976ea4e01 startdate=2026-01-01 enddate=2027-01-01
usagetype=1
{
"quotaresourcestatement": {
"items": [
{
"accountid": "f684da1a-f84b-11f0-8ace-32e0826870ba",
"enddate": "2026-05-21T20:59:59-0300",
"quotaconsumed": 1.42880073,
"startdate": "2026-05-20T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 39.76534465,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(admin) 🐱 > quota resourcestatement
id=ab6b1ced-d36e-4436-aad2-e78e06005350 startdate=2026-01-01 enddate=2027-01-01
usagetype=1
{
"quotaresourcestatement": {
"items": [
{
"accountid": "feaffae2-7ba4-45dc-b46f-20ae86192685",
"enddate": "2026-05-21T20:59:59-0300",
"quotaconsumed": 1.42801677,
"startdate": "2026-05-20T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 39.76291791,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(admin) 🐱 > quota resourcestatement
id=db0db635-df4d-42bb-9aca-19cc3d986ca0 startdate=2026-01-01 enddate=2027-01-01
usagetype=1
{
"quotaresourcestatement": {
"items": [
{
"accountid": "2f49212d-d6d5-437b-800d-a7bb4a8def4b",
"enddate": "2026-05-21T20:59:59-0300",
"quotaconsumed": 1.42775528,
"startdate": "2026-05-20T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 39.75638356,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(admin) 🐱 > quota resourcestatement
id=53c791d2-ac8f-4acb-9246-3a2b9eb354ea startdate=2026-01-01 enddate=2027-01-01
usagetype=1
{
"quotaresourcestatement": {
"items": [
{
"accountid": "b029e8b8-e539-4d1a-906d-3d4f2fb36b82",
"enddate": "2026-05-21T20:59:59-0300",
"quotaconsumed": 1.42670996,
"startdate": "2026-05-20T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 39.7583256,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
```
- `accountid`: returns the statement scoped to the provided account.
```sh
(admin) 🐱 > quota resourcestatement
id=53c791d2-ac8f-4acb-9246-3a2b9eb354ea startdate=2026-01-01 enddate=2027-01-01
usagetype=1 accountid=2f49212d-d6d5-437b-800d-a7bb4a8def4b
{
"quotaresourcestatement": {
"items": [
{
"accountid": "2f49212d-d6d5-437b-800d-a7bb4a8def4b",
"enddate": "2026-05-24T20:59:59-0300",
"quotaconsumed": 2.46531524,
"startdate": "2026-05-23T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 11.44631141,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(admin) 🐱 > quota resourcestatement
id=53c791d2-ac8f-4acb-9246-3a2b9eb354ea startdate=2026-01-01 enddate=2027-01-01
usagetype=1 accountid=feaffae2-7ba4-45dc-b46f-20ae86192685
{
"quotaresourcestatement": {
"items": [
{
"accountid": "feaffae2-7ba4-45dc-b46f-20ae86192685",
"enddate": "2026-05-26T20:59:59-0300",
"quotaconsumed": 3.16106627,
"startdate": "2026-05-25T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
}
],
"totalquota": 3.16106627,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(admin) 🐱 > quota resourcestatement
id=53c791d2-ac8f-4acb-9246-3a2b9eb354ea startdate=2026-01-01 enddate=2027-01-01
usagetype=1 accountid=f684da1a-f84b-11f0-8ace-32e0826870ba
{
"quotaresourcestatement": {
"items": [],
"totalquota": 0,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
```
- `projectid`: returns the statement scoped to the provided project.
```sh
(admin) 🐱 > quota resourcestatement
id=6d7b3c73-7f06-4f23-9210-3af5889790d1 startdate=2026-01-01 enddate=2027-01-01
usagetype=1 projectid=c1ce41c4-7b01-4386-8264-479db5ace0bc
{
"quotaresourcestatement": {
"items": [
{
"accountid": "b14100c6-d9f6-450e-87a2-0833bb45e5f8",
"enddate": "2026-05-21T20:59:59-0300",
"quotaconsumed": 1.42573923,
"startdate": "2026-05-20T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 39.76108809,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
```
- `isrecursive`: allows admins to generate the statement including usage
records of subdomains.
```sh
(admin) 🐱 > quota resourcestatement
id=e4e91818-cbb5-401a-bb42-35d976ea4e01 startdate=2026-01-01 enddate=2027-01-01
usagetype=1
{
"quotaresourcestatement": {
"items": [
{
"accountid": "f684da1a-f84b-11f0-8ace-32e0826870ba",
"enddate": "2026-05-21T20:59:59-0300",
"quotaconsumed": 1.42880073,
"startdate": "2026-05-20T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 33.79573569,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(admin) 🐱 > quota resourcestatement
id=e4e91818-cbb5-401a-bb42-35d976ea4e01 startdate=2026-01-01 enddate=2027-01-01
usagetype=1 isrecursive=true
{
"quotaresourcestatement": {
"items": [
{
"accountid": "f684da1a-f84b-11f0-8ace-32e0826870ba",
"enddate": "2026-05-21T20:59:59-0300",
"quotaconsumed": 1.42880073,
"startdate": "2026-05-20T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 52.70616739,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
(admin) 🐱 > quota resourcestatement
id=e4e91818-cbb5-401a-bb42-35d976ea4e01 startdate=2026-01-01 enddate=2027-01-01
usagetype=1 isrecursive=false
{
"quotaresourcestatement": {
"items": [
{
"accountid": "f684da1a-f84b-11f0-8ace-32e0826870ba",
"enddate": "2026-05-21T20:59:59-0300",
"quotaconsumed": 1.42880073,
"startdate": "2026-05-20T21:00:00-0300",
"tariffid": "2b9671f8-a0ec-4127-bcc8-69413375c3c6",
"tariffname": "RUNNING_VM"
},
...
],
"totalquota": 33.79573569,
"unit": "Compute*Month",
"usagename": "RUNNING_VM"
}
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]