summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api-ref/source/v3/parameters.yaml21
-rw-r--r--api-ref/source/v3/resource-filters.inc2
-rw-r--r--api-ref/source/v3/samples/snapshots/snapshot-create-response.json2
-rw-r--r--api-ref/source/v3/samples/snapshots/snapshot-show-response.json2
-rw-r--r--api-ref/source/v3/samples/snapshots/snapshot-update-response.json2
-rw-r--r--api-ref/source/v3/samples/snapshots/snapshots-list-detailed-response.json2
-rw-r--r--api-ref/source/v3/samples/snapshots/v3.65/snapshot-create-response.json18
-rw-r--r--api-ref/source/v3/samples/snapshots/v3.65/snapshot-show-response.json20
-rw-r--r--api-ref/source/v3/samples/snapshots/v3.65/snapshot-update-response.json18
-rw-r--r--api-ref/source/v3/samples/snapshots/v3.65/snapshots-list-detailed-response.json22
-rw-r--r--api-ref/source/v3/samples/versions/version-show-response.json4
-rw-r--r--api-ref/source/v3/samples/versions/versions-response.json4
-rw-r--r--api-ref/source/v3/samples/volumes/v3.65/volume-create-response.json41
-rw-r--r--api-ref/source/v3/samples/volumes/v3.65/volume-show-response.json45
-rw-r--r--api-ref/source/v3/samples/volumes/v3.65/volume-update-response.json43
-rw-r--r--api-ref/source/v3/samples/volumes/v3.65/volumes-list-detailed-response.json47
-rw-r--r--api-ref/source/v3/samples/volumes/volume-create-response.json2
-rw-r--r--api-ref/source/v3/samples/volumes/volume-show-response.json2
-rw-r--r--api-ref/source/v3/samples/volumes/volume-update-response.json2
-rw-r--r--api-ref/source/v3/volumes-v3-snapshots.inc22
-rw-r--r--api-ref/source/v3/volumes-v3-volumes.inc22
-rw-r--r--cinder/api/common.py3
-rw-r--r--cinder/api/microversions.py2
-rw-r--r--cinder/api/openstack/api_version_request.py7
-rw-r--r--cinder/api/v3/snapshots.py20
-rw-r--r--cinder/api/v3/views/snapshots.py8
-rw-r--r--cinder/api/v3/views/volumes.py3
-rw-r--r--cinder/api/v3/volumes.py26
-rw-r--r--cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshot-create-response.json.tpl18
-rw-r--r--cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshot-show-response.json.tpl20
-rw-r--r--cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshot-update-response.json.tpl18
-rw-r--r--cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshots-list-detailed-response.json.tpl22
-rw-r--r--cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volume-create-response.json.tpl41
-rw-r--r--cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volume-show-response.json.tpl45
-rw-r--r--cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volume-update-response.json.tpl43
-rw-r--r--cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volumes-list-detailed-response.json.tpl47
-rw-r--r--cinder/tests/functional/api_sample_tests/test_snapshots.py3
-rw-r--r--cinder/tests/functional/api_sample_tests/test_volumes.py3
-rw-r--r--cinder/tests/unit/api/test_common.py5
-rw-r--r--cinder/tests/unit/api/v3/test_snapshots.py37
-rw-r--r--cinder/tests/unit/api/v3/test_volumes.py60
-rw-r--r--etc/cinder/resource_filters.json5
-rw-r--r--releasenotes/notes/mv-use_quota-b8e010f8f68a1eaa.yaml14
43 files changed, 733 insertions, 60 deletions
diff --git a/api-ref/source/v3/parameters.yaml b/api-ref/source/v3/parameters.yaml
index 3551f3301..cf806829d 100644
--- a/api-ref/source/v3/parameters.yaml
+++ b/api-ref/source/v3/parameters.yaml
@@ -214,6 +214,18 @@ detail:
in: query
required: false
type: boolean
+filter_consumes_quota:
+ description: |
+ Filters results by ``consumes_quota`` field. Resources that don't use
+ quotas are usually temporary internal resources created to perform an
+ operation. Default is to not filter by it. Filtering by this option may
+ not be always possible in a cloud, see
+ :ref:`List Resource Filters <resource-filters>` to determine whether this
+ filter is available in your cloud.
+ in: query
+ required: false
+ type: boolean
+ min_version: 3.65
filter_created_at:
description: |
Filters reuslts by a time that resources are created at with time
@@ -841,6 +853,15 @@ consumer:
in: body
required: false
type: string
+consumes_quota:
+ description: |
+ Whether this resource consumes quota or not. Resources that not counted
+ for quota usage are usually temporary internal resources created to perform
+ an operation.
+ in: body
+ required: false
+ type: boolean
+ min_version: 3.65
container:
description: |
The container name or null.
diff --git a/api-ref/source/v3/resource-filters.inc b/api-ref/source/v3/resource-filters.inc
index b5064e965..37f662c75 100644
--- a/api-ref/source/v3/resource-filters.inc
+++ b/api-ref/source/v3/resource-filters.inc
@@ -1,5 +1,7 @@
.. -*- rst -*-
+.. _resource-filters:
+
Resource Filters (resource_filters)
===================================
diff --git a/api-ref/source/v3/samples/snapshots/snapshot-create-response.json b/api-ref/source/v3/samples/snapshots/snapshot-create-response.json
index 8819dd94a..e19e407c8 100644
--- a/api-ref/source/v3/samples/snapshots/snapshot-create-response.json
+++ b/api-ref/source/v3/samples/snapshots/snapshot-create-response.json
@@ -12,4 +12,4 @@
"updated_at": null,
"volume_id": "d291b81c-6e40-4525-8231-90aa1588121e"
}
-} \ No newline at end of file
+}
diff --git a/api-ref/source/v3/samples/snapshots/snapshot-show-response.json b/api-ref/source/v3/samples/snapshots/snapshot-show-response.json
index da7e68da1..b4979f368 100644
--- a/api-ref/source/v3/samples/snapshots/snapshot-show-response.json
+++ b/api-ref/source/v3/samples/snapshots/snapshot-show-response.json
@@ -14,4 +14,4 @@
"updated_at": null,
"volume_id": "b72c48f1-64b7-4cd8-9745-b12e0be82d37"
}
-} \ No newline at end of file
+}
diff --git a/api-ref/source/v3/samples/snapshots/snapshot-update-response.json b/api-ref/source/v3/samples/snapshots/snapshot-update-response.json
index 5d9c9bb4d..d69a8aedc 100644
--- a/api-ref/source/v3/samples/snapshots/snapshot-update-response.json
+++ b/api-ref/source/v3/samples/snapshots/snapshot-update-response.json
@@ -12,4 +12,4 @@
"updated_at": null,
"volume_id": "070c942d-9909-42e9-a467-7a781f150c58"
}
-} \ No newline at end of file
+}
diff --git a/api-ref/source/v3/samples/snapshots/snapshots-list-detailed-response.json b/api-ref/source/v3/samples/snapshots/snapshots-list-detailed-response.json
index 9c452f387..a73af2094 100644
--- a/api-ref/source/v3/samples/snapshots/snapshots-list-detailed-response.json
+++ b/api-ref/source/v3/samples/snapshots/snapshots-list-detailed-response.json
@@ -16,4 +16,4 @@
"volume_id": "7acd675e-4e06-4653-af9f-2ecd546342d6"
}
]
-} \ No newline at end of file
+}
diff --git a/api-ref/source/v3/samples/snapshots/v3.65/snapshot-create-response.json b/api-ref/source/v3/samples/snapshots/v3.65/snapshot-create-response.json
new file mode 100644
index 000000000..b38d66242
--- /dev/null
+++ b/api-ref/source/v3/samples/snapshots/v3.65/snapshot-create-response.json
@@ -0,0 +1,18 @@
+{
+ "snapshot": {
+ "created_at": "2019-03-11T16:24:34.469003",
+ "description": "Daily backup",
+ "id": "b36476e5-d18b-47f9-ac69-4818cb43ee21",
+ "metadata": {
+ "key": "v3"
+ },
+ "name": "snap-001",
+ "size": 10,
+ "status": "creating",
+ "updated_at": null,
+ "volume_id": "d291b81c-6e40-4525-8231-90aa1588121e",
+ "group_snapshot_id": null,
+ "user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
+ "consumes_quota": true
+ }
+}
diff --git a/api-ref/source/v3/samples/snapshots/v3.65/snapshot-show-response.json b/api-ref/source/v3/samples/snapshots/v3.65/snapshot-show-response.json
new file mode 100644
index 000000000..69be72e98
--- /dev/null
+++ b/api-ref/source/v3/samples/snapshots/v3.65/snapshot-show-response.json
@@ -0,0 +1,20 @@
+{
+ "snapshot": {
+ "created_at": "2019-03-12T04:42:00.809352",
+ "description": "Daily backup",
+ "id": "4a584cae-e4ce-429b-9154-d4c9eb8fda4c",
+ "metadata": {
+ "key": "v3"
+ },
+ "name": "snap-001",
+ "os-extended-snapshot-attributes:progress": "0%",
+ "os-extended-snapshot-attributes:project_id": "89afd400-b646-4bbc-b12b-c0a4d63e5bd3",
+ "size": 10,
+ "status": "creating",
+ "updated_at": null,
+ "volume_id": "b72c48f1-64b7-4cd8-9745-b12e0be82d37",
+ "group_snapshot_id": null,
+ "user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
+ "consumes_quota": true
+ }
+}
diff --git a/api-ref/source/v3/samples/snapshots/v3.65/snapshot-update-response.json b/api-ref/source/v3/samples/snapshots/v3.65/snapshot-update-response.json
new file mode 100644
index 000000000..c097889d2
--- /dev/null
+++ b/api-ref/source/v3/samples/snapshots/v3.65/snapshot-update-response.json
@@ -0,0 +1,18 @@
+{
+ "snapshot": {
+ "created_at": "2019-03-12T04:53:53.426591",
+ "description": "This is yet, another snapshot.",
+ "id": "43666194-8e72-451a-b7bb-54fef763b2b8",
+ "metadata": {
+ "key": "v3"
+ },
+ "name": "snap-002",
+ "size": 10,
+ "status": "creating",
+ "updated_at": null,
+ "volume_id": "070c942d-9909-42e9-a467-7a781f150c58",
+ "group_snapshot_id": null,
+ "user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
+ "consumes_quota": true
+ }
+}
diff --git a/api-ref/source/v3/samples/snapshots/v3.65/snapshots-list-detailed-response.json b/api-ref/source/v3/samples/snapshots/v3.65/snapshots-list-detailed-response.json
new file mode 100644
index 000000000..7c9e8d476
--- /dev/null
+++ b/api-ref/source/v3/samples/snapshots/v3.65/snapshots-list-detailed-response.json
@@ -0,0 +1,22 @@
+{
+ "snapshots": [
+ {
+ "created_at": "2019-03-11T16:24:36.464445",
+ "description": "Daily backup",
+ "id": "d0083dc5-8795-4c1a-bc9c-74f70006c205",
+ "metadata": {
+ "key": "v3"
+ },
+ "name": "snap-001",
+ "os-extended-snapshot-attributes:progress": "0%",
+ "os-extended-snapshot-attributes:project_id": "89afd400-b646-4bbc-b12b-c0a4d63e5bd3",
+ "size": 10,
+ "status": "creating",
+ "updated_at": null,
+ "volume_id": "7acd675e-4e06-4653-af9f-2ecd546342d6",
+ "group_snapshot_id": null,
+ "user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
+ "consumes_quota": true
+ }
+ ]
+}
diff --git a/api-ref/source/v3/samples/versions/version-show-response.json b/api-ref/source/v3/samples/versions/version-show-response.json
index 5e34efae7..1d79bf38f 100644
--- a/api-ref/source/v3/samples/versions/version-show-response.json
+++ b/api-ref/source/v3/samples/versions/version-show-response.json
@@ -21,8 +21,8 @@
],
"min_version": "3.0",
"status": "CURRENT",
- "updated": "2021-05-30T00:00:00Z",
- "version": "3.64"
+ "updated": "2021-08-25T00:00:00Z",
+ "version": "3.65"
}
]
}
diff --git a/api-ref/source/v3/samples/versions/versions-response.json b/api-ref/source/v3/samples/versions/versions-response.json
index 529ca5d21..dd7b843d1 100644
--- a/api-ref/source/v3/samples/versions/versions-response.json
+++ b/api-ref/source/v3/samples/versions/versions-response.json
@@ -21,8 +21,8 @@
],
"min_version": "3.0",
"status": "CURRENT",
- "updated": "2021-05-30T00:00:00Z",
- "version": "3.64"
+ "updated": "2021-08-25T00:00:00Z",
+ "version": "3.65"
}
]
}
diff --git a/api-ref/source/v3/samples/volumes/v3.65/volume-create-response.json b/api-ref/source/v3/samples/volumes/v3.65/volume-create-response.json
new file mode 100644
index 000000000..4dc4775ff
--- /dev/null
+++ b/api-ref/source/v3/samples/volumes/v3.65/volume-create-response.json
@@ -0,0 +1,41 @@
+{
+ "volume": {
+ "attachments": [],
+ "availability_zone": "nova",
+ "bootable": "false",
+ "consistencygroup_id": null,
+ "created_at": "2018-11-28T06:21:12.715987",
+ "description": null,
+ "encrypted": false,
+ "id": "2b955850-f177-45f7-9f49-ecb2c256d161",
+ "links": [
+ {
+ "href": "http://127.0.0.1:33951/v3/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/2b955850-f177-45f7-9f49-ecb2c256d161",
+ "rel": "self"
+ },
+ {
+ "href": "http://127.0.0.1:33951/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/2b955850-f177-45f7-9f49-ecb2c256d161",
+ "rel": "bookmark"
+ }
+ ],
+ "metadata": {},
+ "migration_status": null,
+ "multiattach": false,
+ "name": null,
+ "replication_status": null,
+ "size": 10,
+ "snapshot_id": null,
+ "source_volid": null,
+ "status": "creating",
+ "updated_at": null,
+ "user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
+ "volume_type": "__DEFAULT__",
+ "group_id": null,
+ "provider_id": null,
+ "service_uuid": null,
+ "shared_targets": true,
+ "cluster_name": null,
+ "volume_type_id": "5fed9d7c-401d-46e2-8e80-f30c70cb7e1d",
+ "consumes_quota": true
+ }
+}
diff --git a/api-ref/source/v3/samples/volumes/v3.65/volume-show-response.json b/api-ref/source/v3/samples/volumes/v3.65/volume-show-response.json
new file mode 100644
index 000000000..690bb228b
--- /dev/null
+++ b/api-ref/source/v3/samples/volumes/v3.65/volume-show-response.json
@@ -0,0 +1,45 @@
+{
+ "volume": {
+ "attachments": [],
+ "availability_zone": "nova",
+ "bootable": "false",
+ "consistencygroup_id": null,
+ "created_at": "2018-11-29T06:50:07.770785",
+ "description": null,
+ "encrypted": false,
+ "id": "f7223234-1afc-4d19-bfa3-d19deb6235ef",
+ "links": [
+ {
+ "href": "http://127.0.0.1:45839/v3/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/f7223234-1afc-4d19-bfa3-d19deb6235ef",
+ "rel": "self"
+ },
+ {
+ "href": "http://127.0.0.1:45839/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/f7223234-1afc-4d19-bfa3-d19deb6235ef",
+ "rel": "bookmark"
+ }
+ ],
+ "metadata": {},
+ "migration_status": null,
+ "multiattach": false,
+ "name": null,
+ "os-vol-host-attr:host": null,
+ "os-vol-mig-status-attr:migstat": null,
+ "os-vol-mig-status-attr:name_id": null,
+ "os-vol-tenant-attr:tenant_id": "89afd400-b646-4bbc-b12b-c0a4d63e5bd3",
+ "replication_status": null,
+ "size": 10,
+ "snapshot_id": null,
+ "source_volid": null,
+ "status": "creating",
+ "updated_at": null,
+ "user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
+ "volume_type": "__DEFAULT__",
+ "provider_id": null,
+ "group_id": null,
+ "service_uuid": null,
+ "shared_targets": true,
+ "cluster_name": null,
+ "volume_type_id": "5fed9d7c-401d-46e2-8e80-f30c70cb7e1d",
+ "consumes_quota": true
+ }
+}
diff --git a/api-ref/source/v3/samples/volumes/v3.65/volume-update-response.json b/api-ref/source/v3/samples/volumes/v3.65/volume-update-response.json
new file mode 100644
index 000000000..3d8f20926
--- /dev/null
+++ b/api-ref/source/v3/samples/volumes/v3.65/volume-update-response.json
@@ -0,0 +1,43 @@
+{
+ "volume": {
+ "attachments": [],
+ "availability_zone": "nova",
+ "bootable": "false",
+ "consistencygroup_id": null,
+ "created_at": "2018-11-29T06:59:23.679903",
+ "description": "This is yet, another volume.",
+ "encrypted": false,
+ "id": "8b2459d1-0059-4e14-a89f-dfa73a452af6",
+ "links": [
+ {
+ "href": "http://127.0.0.1:41467/v3/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/8b2459d1-0059-4e14-a89f-dfa73a452af6",
+ "rel": "self"
+ },
+ {
+ "href": "http://127.0.0.1:41467/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/8b2459d1-0059-4e14-a89f-dfa73a452af6",
+ "rel": "bookmark"
+ }
+ ],
+ "metadata": {
+ "name": "metadata0"
+ },
+ "migration_status": null,
+ "multiattach": false,
+ "name": "vol-003",
+ "replication_status": null,
+ "size": 10,
+ "snapshot_id": null,
+ "source_volid": null,
+ "status": "creating",
+ "updated_at": null,
+ "user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
+ "volume_type": "__DEFAULT__",
+ "group_id": null,
+ "provider_id": null,
+ "service_uuid": null,
+ "shared_targets": true,
+ "cluster_name": null,
+ "volume_type_id": "5fed9d7c-401d-46e2-8e80-f30c70cb7e1d",
+ "consumes_quota": true
+ }
+}
diff --git a/api-ref/source/v3/samples/volumes/v3.65/volumes-list-detailed-response.json b/api-ref/source/v3/samples/volumes/v3.65/volumes-list-detailed-response.json
new file mode 100644
index 000000000..ceaa39c79
--- /dev/null
+++ b/api-ref/source/v3/samples/volumes/v3.65/volumes-list-detailed-response.json
@@ -0,0 +1,47 @@
+{
+ "volumes": [
+ {
+ "attachments": [],
+ "availability_zone": "nova",
+ "bootable": "false",
+ "consistencygroup_id": null,
+ "created_at": "2018-11-28T06:25:15.288987",
+ "description": null,
+ "encrypted": false,
+ "id": "cb49b381-9012-40cb-b8ee-80c19a4801b5",
+ "links": [
+ {
+ "href": "http://127.0.0.1:43543/v3/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/cb49b381-9012-40cb-b8ee-80c19a4801b5",
+ "rel": "self"
+ },
+ {
+ "href": "http://127.0.0.1:43543/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/cb49b381-9012-40cb-b8ee-80c19a4801b5",
+ "rel": "bookmark"
+ }
+ ],
+ "metadata": {},
+ "migration_status": null,
+ "multiattach": false,
+ "name": null,
+ "os-vol-host-attr:host": null,
+ "os-vol-mig-status-attr:migstat": null,
+ "os-vol-mig-status-attr:name_id": null,
+ "os-vol-tenant-attr:tenant_id": "89afd400-b646-4bbc-b12b-c0a4d63e5bd3",
+ "replication_status": null,
+ "size": 10,
+ "snapshot_id": null,
+ "source_volid": null,
+ "status": "creating",
+ "updated_at": null,
+ "user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
+ "volume_type": "__DEFAULT__",
+ "volume_type_id": "5fed9d7c-401d-46e2-8e80-f30c70cb7e1d",
+ "provider_id": null,
+ "group_id": null,
+ "service_uuid": null,
+ "shared_targets": true,
+ "cluster_name": null,
+ "consumes_quota": true
+ }
+ ]
+}
diff --git a/api-ref/source/v3/samples/volumes/volume-create-response.json b/api-ref/source/v3/samples/volumes/volume-create-response.json
index 30feb2ac6..4bd8a6e0f 100644
--- a/api-ref/source/v3/samples/volumes/volume-create-response.json
+++ b/api-ref/source/v3/samples/volumes/volume-create-response.json
@@ -31,4 +31,4 @@
"user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
"volume_type": "__DEFAULT__"
}
-} \ No newline at end of file
+}
diff --git a/api-ref/source/v3/samples/volumes/volume-show-response.json b/api-ref/source/v3/samples/volumes/volume-show-response.json
index 186411e90..faf9be288 100644
--- a/api-ref/source/v3/samples/volumes/volume-show-response.json
+++ b/api-ref/source/v3/samples/volumes/volume-show-response.json
@@ -35,4 +35,4 @@
"user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
"volume_type": "__DEFAULT__"
}
-} \ No newline at end of file
+}
diff --git a/api-ref/source/v3/samples/volumes/volume-update-response.json b/api-ref/source/v3/samples/volumes/volume-update-response.json
index 4a587f679..a41d41fba 100644
--- a/api-ref/source/v3/samples/volumes/volume-update-response.json
+++ b/api-ref/source/v3/samples/volumes/volume-update-response.json
@@ -33,4 +33,4 @@
"user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
"volume_type": "__DEFAULT__"
}
-} \ No newline at end of file
+}
diff --git a/api-ref/source/v3/volumes-v3-snapshots.inc b/api-ref/source/v3/volumes-v3-snapshots.inc
index c7a63793f..f3d660857 100644
--- a/api-ref/source/v3/volumes-v3-snapshots.inc
+++ b/api-ref/source/v3/volumes-v3-snapshots.inc
@@ -67,6 +67,7 @@ Request
- offset: offset
- marker: marker
- with_count: with_count
+ - consumes_quota: filter_consumes_quota
Response Parameters
@@ -89,11 +90,12 @@ Response Parameters
- updated_at: updated_at
- snapshots_links: links_snap
- group_snapshot_id: group_snapshot_id_3_14
+ - consumes_quota: consumes_quota
-Response Example (v3.41)
+Response Example (v3.65)
------------------------
-.. literalinclude:: ./samples/snapshots/v3.41/snapshots-list-detailed-response.json
+.. literalinclude:: ./samples/snapshots/v3.65/snapshots-list-detailed-response.json
:language: javascript
@@ -149,11 +151,12 @@ Response Parameters
- size: size
- updated_at: updated_at
- group_snapshot_id: group_snapshot_id_3_14
+ - consumes_quota: consumes_quota
-Response Example (v3.41)
+Response Example (v3.65)
------------------------
-.. literalinclude:: ./samples/snapshots/v3.41/snapshot-create-response.json
+.. literalinclude:: ./samples/snapshots/v3.65/snapshot-create-response.json
:language: javascript
@@ -189,6 +192,7 @@ Request
- limit: limit
- offset: offset
- marker: marker
+ - consumes_quota: filter_consumes_quota
- with_count: with_count
@@ -388,11 +392,12 @@ Response Parameters
- metadata: metadata
- updated_at: updated_at
- group_snapshot_id: group_snapshot_id_3_14
+ - consumes_quota: consumes_quota
-Response Example (v3.41)
+Response Example (v3.65)
------------------------
-.. literalinclude:: ./samples/snapshots/v3.41/snapshot-show-response.json
+.. literalinclude:: ./samples/snapshots/v3.65/snapshot-show-response.json
:language: javascript
@@ -446,11 +451,12 @@ Response Parameters
- user_id: user_id_min
- metadata: metadata
- group_snapshot_id: group_snapshot_id_3_14
+ - consumes_quota: consumes_quota
-Response Example (v3.41)
+Response Example (v3.65)
------------------------
-.. literalinclude:: ./samples/snapshots/v3.41/snapshot-update-response.json
+.. literalinclude:: ./samples/snapshots/v3.65/snapshot-update-response.json
:language: javascript
diff --git a/api-ref/source/v3/volumes-v3-volumes.inc b/api-ref/source/v3/volumes-v3-volumes.inc
index f40b38606..2d7d8f4d3 100644
--- a/api-ref/source/v3/volumes-v3-volumes.inc
+++ b/api-ref/source/v3/volumes-v3-volumes.inc
@@ -98,6 +98,7 @@ Request
- with_count: with_count
- created_at: filter_created_at
- updated_at: filter_updated_at
+ - consumes_quota: filter_consumes_quota
Response Parameters
@@ -140,13 +141,14 @@ Response Parameters
- service_uuid: service_uuid
- shared_targets: shared_targets
- cluster_name: cluster_name
+ - consumes_quota: consumes_quota
- count: count
-Response Example (v3.63)
+Response Example (v3.65)
------------------------
-.. literalinclude:: ./samples/volumes/v3.63/volumes-list-detailed-response.json
+.. literalinclude:: ./samples/volumes/v3.65/volumes-list-detailed-response.json
:language: javascript
@@ -258,11 +260,12 @@ Response Parameters
- service_uuid: service_uuid
- shared_targets: shared_targets
- cluster_name: cluster_name
+ - consumes_quota: consumes_quota
-Response Example (v3.63)
+Response Example (v3.65)
------------------------
-.. literalinclude:: ./samples/volumes/v3.63/volume-create-response.json
+.. literalinclude:: ./samples/volumes/v3.65/volume-create-response.json
:language: javascript
@@ -301,6 +304,7 @@ Request
- marker: marker
- with_count: with_count
- created_at: filter_created_at
+ - consumes_quota: filter_consumes_quota
- updated_at: filter_updated_at
@@ -394,12 +398,13 @@ Response Parameters
- cluster_name: cluster_name
- provider_id: provider_id
- group_id: group_id_optional
+ - consumes_quota: consumes_quota
-Response Example (v3.63)
+Response Example (v3.65)
------------------------
-.. literalinclude:: ./samples/volumes/v3.63/volume-show-response.json
+.. literalinclude:: ./samples/volumes/v3.65/volume-show-response.json
:language: javascript
@@ -473,12 +478,13 @@ Response Parameters
- service_uuid: service_uuid
- shared_targets: shared_targets
- cluster_name: cluster_name
+ - consumes_quota: consumes_quota
-Response Example (v3.63)
+Response Example (v3.65)
------------------------
-.. literalinclude:: ./samples/volumes/v3.63/volume-update-response.json
+.. literalinclude:: ./samples/volumes/v3.65/volume-update-response.json
:language: javascript
diff --git a/cinder/api/common.py b/cinder/api/common.py
index 432052786..7479237ee 100644
--- a/cinder/api/common.py
+++ b/cinder/api/common.py
@@ -49,7 +49,8 @@ LOG = logging.getLogger(__name__)
_FILTERS_COLLECTION = None
ATTRIBUTE_CONVERTERS = {'name~': 'display_name~',
- 'description~': 'display_description~'}
+ 'description~': 'display_description~',
+ 'consumes_quota': 'use_quota'}
METADATA_TYPES = enum.Enum('METADATA_TYPES', 'user image')
diff --git a/cinder/api/microversions.py b/cinder/api/microversions.py
index e72c76c07..909dcd875 100644
--- a/cinder/api/microversions.py
+++ b/cinder/api/microversions.py
@@ -167,6 +167,8 @@ VOLUME_TYPE_ID_IN_VOLUME_DETAIL = '3.63'
ENCRYPTION_KEY_ID_IN_DETAILS = '3.64'
+USE_QUOTA = '3.65'
+
def get_mv_header(version):
"""Gets a formatted HTTP microversion header.
diff --git a/cinder/api/openstack/api_version_request.py b/cinder/api/openstack/api_version_request.py
index b6597346d..7f0769e9b 100644
--- a/cinder/api/openstack/api_version_request.py
+++ b/cinder/api/openstack/api_version_request.py
@@ -148,14 +148,17 @@ REST_API_VERSION_HISTORY = """
("GET /v3/{project_id}/volumes/detail") and volume-show
("GET /v3/{project_id}/volumes/{volume_id}") calls.
* 3.64 - Include 'encryption_key_id' in volume and backup details
+ * 3.65 - Include 'consumes_quota' in volume and snapshot details
+ - Accept 'consumes_quota' filter in volume and snapshot list
+ operation.
"""
# The minimum and maximum versions of the API supported
# The default api version request is defined to be the
# minimum version of the API supported.
_MIN_API_VERSION = "3.0"
-_MAX_API_VERSION = "3.64"
-UPDATED = "2021-05-30T00:00:00Z"
+_MAX_API_VERSION = "3.65"
+UPDATED = "2021-08-25T00:00:00Z"
# NOTE(cyeoh): min and max versions declared as functions so we can
diff --git a/cinder/api/v3/snapshots.py b/cinder/api/v3/snapshots.py
index 9debfcebc..d5c1a47ba 100644
--- a/cinder/api/v3/snapshots.py
+++ b/cinder/api/v3/snapshots.py
@@ -53,16 +53,24 @@ class SnapshotsController(snapshots_v2.SnapshotsController):
LOG.debug('Could not evaluate value %s, assuming string',
search_opts['metadata'])
+ if 'use_quota' in search_opts:
+ search_opts['use_quota'] = utils.get_bool_param('use_quota',
+ search_opts)
+
+ MV_ADDED_FILTERS = (
+ (mv.get_prior_version(mv.SNAPSHOT_LIST_METADATA_FILTER), 'metadata'),
+ # REST API receives consumes_quota, but process_general_filtering
+ # transforms it into use_quota
+ (mv.get_prior_version(mv.USE_QUOTA), 'use_quota'),
+ )
+
@common.process_general_filtering('snapshot')
def _process_snapshot_filtering(self, context=None, filters=None,
req_version=None):
"""Formats allowed filters"""
-
- # if the max version is less than SNAPSHOT_LIST_METADATA_FILTER
- # metadata based filtering is not supported
- if req_version.matches(
- None, mv.get_prior_version(mv.SNAPSHOT_LIST_METADATA_FILTER)):
- filters.pop('metadata', None)
+ for version, field in self.MV_ADDED_FILTERS:
+ if req_version.matches(None, version):
+ filters.pop(field, None)
# Filter out invalid options
allowed_search_options = self._get_snapshot_filter_options()
diff --git a/cinder/api/v3/views/snapshots.py b/cinder/api/v3/views/snapshots.py
index 857df059c..cd09f9cd5 100644
--- a/cinder/api/v3/views/snapshots.py
+++ b/cinder/api/v3/views/snapshots.py
@@ -27,9 +27,11 @@ class ViewBuilder(views_v2.ViewBuilder):
req_version = request.api_version_request
# Add group_snapshot_id if min version is greater than or equal
# to GROUP_SNAPSHOTS.
+ snap = snapshot_ref['snapshot']
if req_version.matches(mv.GROUP_SNAPSHOTS, None):
- snapshot_ref['snapshot']['group_snapshot_id'] = (
- snapshot.get('group_snapshot_id'))
+ snap['group_snapshot_id'] = snapshot.get('group_snapshot_id')
if req_version.matches(mv.SNAPSHOT_LIST_USER_ID, None):
- snapshot_ref['snapshot']['user_id'] = snapshot.get('user_id')
+ snap['user_id'] = snapshot.get('user_id')
+ if req_version.matches(mv.USE_QUOTA):
+ snap['consumes_quota'] = snapshot.get('use_quota')
return snapshot_ref
diff --git a/cinder/api/v3/views/volumes.py b/cinder/api/v3/views/volumes.py
index ed171c7bd..ded603a4f 100644
--- a/cinder/api/v3/views/volumes.py
+++ b/cinder/api/v3/views/volumes.py
@@ -77,6 +77,9 @@ class ViewBuilder(views_v2.ViewBuilder):
encryption_key_id != cinder_constants.FIXED_KEY_ID):
volume_ref['volume']['encryption_key_id'] = encryption_key_id
+ if req_version.matches(mv.USE_QUOTA):
+ volume_ref['volume']['consumes_quota'] = volume.get('use_quota')
+
return volume_ref
def _list_view(self, func, request, volumes, volume_count,
diff --git a/cinder/api/v3/volumes.py b/cinder/api/v3/volumes.py
index e5c5f18ef..0d2841c4f 100644
--- a/cinder/api/v3/volumes.py
+++ b/cinder/api/v3/volumes.py
@@ -80,18 +80,23 @@ class VolumeController(volumes_v2.VolumeController):
return webob.Response(status_int=HTTPStatus.ACCEPTED)
+ MV_ADDED_FILTERS = (
+ (mv.get_prior_version(mv.VOLUME_LIST_GLANCE_METADATA),
+ 'glance_metadata'),
+ (mv.get_prior_version(mv.VOLUME_LIST_GROUP), 'group_id'),
+ (mv.get_prior_version(mv.VOLUME_TIME_COMPARISON_FILTER), 'created_at'),
+ (mv.get_prior_version(mv.VOLUME_TIME_COMPARISON_FILTER), 'updated_at'),
+ # REST API receives consumes_quota, but process_general_filtering
+ # transforms it into use_quota
+ (mv.get_prior_version(mv.USE_QUOTA), 'use_quota'),
+ )
+
@common.process_general_filtering('volume')
def _process_volume_filtering(self, context=None, filters=None,
req_version=None):
- if req_version.matches(None, mv.MESSAGES):
- filters.pop('glance_metadata', None)
-
- if req_version.matches(None, mv.BACKUP_UPDATE):
- filters.pop('group_id', None)
-
- if req_version.matches(None, mv.SUPPORT_TRANSFER_PAGINATION):
- filters.pop('created_at', None)
- filters.pop('updated_at', None)
+ for version, field in self.MV_ADDED_FILTERS:
+ if req_version.matches(None, version):
+ filters.pop(field, None)
api_utils.remove_invalid_filter_options(
context, filters,
@@ -155,6 +160,9 @@ class VolumeController(volumes_v2.VolumeController):
if 'name' in filters:
filters['display_name'] = filters.pop('name')
+ if 'use_quota' in filters:
+ filters['use_quota'] = utils.get_bool_param('use_quota', filters)
+
self._handle_time_comparison_filters(filters)
strict = req.api_version_request.matches(
diff --git a/cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshot-create-response.json.tpl b/cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshot-create-response.json.tpl
new file mode 100644
index 000000000..e2f6f55de
--- /dev/null
+++ b/cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshot-create-response.json.tpl
@@ -0,0 +1,18 @@
+{
+ "snapshot": {
+ "created_at": "%(strtime)s",
+ "description": "Daily backup",
+ "id": "%(uuid)s",
+ "metadata": {
+ "key": "v3"
+ },
+ "name": "snap-001",
+ "size": 10,
+ "status": "creating",
+ "updated_at": null,
+ "volume_id": "%(uuid)s",
+ "group_snapshot_id": null,
+ "user_id": "%(uuid)s",
+ "consumes_quota": true
+ }
+}
diff --git a/cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshot-show-response.json.tpl b/cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshot-show-response.json.tpl
new file mode 100644
index 000000000..2656017af
--- /dev/null
+++ b/cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshot-show-response.json.tpl
@@ -0,0 +1,20 @@
+{
+ "snapshot": {
+ "created_at": "%(strtime)s",
+ "description": "Daily backup",
+ "id": "%(uuid)s",
+ "metadata": {
+ "key": "v3"
+ },
+ "name": "snap-001",
+ "os-extended-snapshot-attributes:progress": "0%",
+ "os-extended-snapshot-attributes:project_id": "%(uuid)s",
+ "size": 10,
+ "status": "creating",
+ "updated_at": null,
+ "volume_id": "%(uuid)s",
+ "group_snapshot_id": null,
+ "user_id": "%(uuid)s",
+ "consumes_quota": true
+ }
+}
diff --git a/cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshot-update-response.json.tpl b/cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshot-update-response.json.tpl
new file mode 100644
index 000000000..fb5285c6e
--- /dev/null
+++ b/cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshot-update-response.json.tpl
@@ -0,0 +1,18 @@
+{
+ "snapshot": {
+ "created_at": "%(strtime)s",
+ "description": "This is yet, another snapshot.",
+ "id": "%(uuid)s",
+ "metadata": {
+ "key": "v3"
+ },
+ "name": "snap-002",
+ "size": 10,
+ "status": "creating",
+ "updated_at": null,
+ "volume_id": "%(uuid)s",
+ "group_snapshot_id": null,
+ "user_id": "%(uuid)s",
+ "consumes_quota": true
+ }
+}
diff --git a/cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshots-list-detailed-response.json.tpl b/cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshots-list-detailed-response.json.tpl
new file mode 100644
index 000000000..a521bc85c
--- /dev/null
+++ b/cinder/tests/functional/api_sample_tests/samples/snapshots/v3.65/snapshots-list-detailed-response.json.tpl
@@ -0,0 +1,22 @@
+{
+ "snapshots": [
+ {
+ "created_at": "%(strtime)s",
+ "description": "Daily backup",
+ "id": "%(uuid)s",
+ "metadata": {
+ "key": "v3"
+ },
+ "name": "snap-001",
+ "os-extended-snapshot-attributes:progress": "0%",
+ "os-extended-snapshot-attributes:project_id": "%(uuid)s",
+ "size": 10,
+ "status": "creating",
+ "updated_at": null,
+ "volume_id": "%(uuid)s",
+ "group_snapshot_id": null,
+ "user_id": "%(uuid)s",
+ "consumes_quota": true
+ }
+ ]
+}
diff --git a/cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volume-create-response.json.tpl b/cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volume-create-response.json.tpl
new file mode 100644
index 000000000..ecfa16b1f
--- /dev/null
+++ b/cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volume-create-response.json.tpl
@@ -0,0 +1,41 @@
+{
+ "volume": {
+ "attachments": [],
+ "availability_zone": "nova",
+ "bootable": "false",
+ "consistencygroup_id": null,
+ "created_at": "%(strtime)s",
+ "description": null,
+ "encrypted": false,
+ "id": "%(uuid)s",
+ "links": [
+ {
+ "href": "%(host)s/v3/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/%(uuid)s",
+ "rel": "self"
+ },
+ {
+ "href": "%(host)s/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/%(uuid)s",
+ "rel": "bookmark"
+ }
+ ],
+ "metadata": {},
+ "migration_status": null,
+ "multiattach": false,
+ "name": null,
+ "replication_status": null,
+ "size": 10,
+ "snapshot_id": null,
+ "source_volid": null,
+ "status": "creating",
+ "updated_at": null,
+ "user_id": "%(uuid)s",
+ "volume_type": "__DEFAULT__",
+ "group_id": null,
+ "provider_id": null,
+ "service_uuid": null,
+ "shared_targets": true,
+ "cluster_name": null,
+ "volume_type_id": "%(uuid)s",
+ "consumes_quota": true
+ }
+}
diff --git a/cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volume-show-response.json.tpl b/cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volume-show-response.json.tpl
new file mode 100644
index 000000000..4fc2ab447
--- /dev/null
+++ b/cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volume-show-response.json.tpl
@@ -0,0 +1,45 @@
+{
+ "volume": {
+ "attachments": [],
+ "availability_zone": "nova",
+ "bootable": "false",
+ "consistencygroup_id": null,
+ "created_at": "%(strtime)s",
+ "description": null,
+ "encrypted": false,
+ "id": "%(uuid)s",
+ "links": [
+ {
+ "href": "%(host)s/v3/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/%(uuid)s",
+ "rel": "self"
+ },
+ {
+ "href": "%(host)s/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/%(uuid)s",
+ "rel": "bookmark"
+ }
+ ],
+ "metadata": {},
+ "migration_status": null,
+ "multiattach": false,
+ "name": null,
+ "os-vol-host-attr:host": null,
+ "os-vol-mig-status-attr:migstat": null,
+ "os-vol-mig-status-attr:name_id": null,
+ "os-vol-tenant-attr:tenant_id": "%(uuid)s",
+ "replication_status": null,
+ "size": 10,
+ "snapshot_id": null,
+ "source_volid": null,
+ "status": "creating",
+ "updated_at": null,
+ "user_id": "%(uuid)s",
+ "volume_type": "__DEFAULT__",
+ "provider_id": null,
+ "group_id": null,
+ "service_uuid": null,
+ "shared_targets": true,
+ "cluster_name": null,
+ "volume_type_id": "%(uuid)s",
+ "consumes_quota": true
+ }
+}
diff --git a/cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volume-update-response.json.tpl b/cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volume-update-response.json.tpl
new file mode 100644
index 000000000..bc2723504
--- /dev/null
+++ b/cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volume-update-response.json.tpl
@@ -0,0 +1,43 @@
+{
+ "volume": {
+ "attachments": [],
+ "availability_zone": "nova",
+ "bootable": "false",
+ "consistencygroup_id": null,
+ "created_at": "%(strtime)s",
+ "description": "This is yet, another volume.",
+ "encrypted": false,
+ "id": "%(uuid)s",
+ "links": [
+ {
+ "href": "%(host)s/v3/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/%(uuid)s",
+ "rel": "self"
+ },
+ {
+ "href": "%(host)s/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/%(uuid)s",
+ "rel": "bookmark"
+ }
+ ],
+ "metadata": {
+ "name": "metadata0"
+ },
+ "migration_status": null,
+ "multiattach": false,
+ "name": "vol-003",
+ "replication_status": null,
+ "size": 10,
+ "snapshot_id": null,
+ "source_volid": null,
+ "status": "creating",
+ "updated_at": null,
+ "user_id": "%(uuid)s",
+ "volume_type": "__DEFAULT__",
+ "group_id": null,
+ "provider_id": null,
+ "service_uuid": null,
+ "shared_targets": true,
+ "cluster_name": null,
+ "volume_type_id": "%(uuid)s",
+ "consumes_quota": true
+ }
+}
diff --git a/cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volumes-list-detailed-response.json.tpl b/cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volumes-list-detailed-response.json.tpl
new file mode 100644
index 000000000..3aff1e884
--- /dev/null
+++ b/cinder/tests/functional/api_sample_tests/samples/volumes/v3.65/volumes-list-detailed-response.json.tpl
@@ -0,0 +1,47 @@
+{
+ "volumes": [
+ {
+ "attachments": [],
+ "availability_zone": "nova",
+ "bootable": "false",
+ "consistencygroup_id": null,
+ "created_at": "%(strtime)s",
+ "description": null,
+ "encrypted": false,
+ "id": "%(uuid)s",
+ "links": [
+ {
+ "href": "%(host)s/v3/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/%(uuid)s",
+ "rel": "self"
+ },
+ {
+ "href": "%(host)s/89afd400-b646-4bbc-b12b-c0a4d63e5bd3/volumes/%(uuid)s",
+ "rel": "bookmark"
+ }
+ ],
+ "metadata": {},
+ "migration_status": null,
+ "multiattach": false,
+ "name": null,
+ "os-vol-host-attr:host": null,
+ "os-vol-mig-status-attr:migstat": null,
+ "os-vol-mig-status-attr:name_id": null,
+ "os-vol-tenant-attr:tenant_id": "%(uuid)s",
+ "replication_status": null,
+ "size": 10,
+ "snapshot_id": null,
+ "source_volid": null,
+ "status": "creating",
+ "updated_at": null,
+ "user_id": "%(uuid)s",
+ "volume_type": "%(name)s",
+ "volume_type_id": "%(uuid)s",
+ "service_uuid": null,
+ "provider_id": null,
+ "group_id": null,
+ "shared_targets": true,
+ "cluster_name": null,
+ "consumes_quota": true
+ }
+ ]
+}
diff --git a/cinder/tests/functional/api_sample_tests/test_snapshots.py b/cinder/tests/functional/api_sample_tests/test_snapshots.py
index abec1251a..14200ff01 100644
--- a/cinder/tests/functional/api_sample_tests/test_snapshots.py
+++ b/cinder/tests/functional/api_sample_tests/test_snapshots.py
@@ -39,7 +39,8 @@ class SnapshotBaseTest(test_base.VolumesSampleBase):
@test_base.VolumesSampleBase.use_versions(
mv.BASE_VERSION, # 3.0
mv.GROUP_SNAPSHOTS, # 3.14
- mv.SNAPSHOT_LIST_USER_ID) # 3.41
+ mv.SNAPSHOT_LIST_USER_ID, # 3.41
+ mv.USE_QUOTA) # 3.65
class SnapshotDetailTests(SnapshotBaseTest):
"""Test snapshot details returned for operations with different MVs.
diff --git a/cinder/tests/functional/api_sample_tests/test_volumes.py b/cinder/tests/functional/api_sample_tests/test_volumes.py
index a80d3ef1c..24ef1d5da 100644
--- a/cinder/tests/functional/api_sample_tests/test_volumes.py
+++ b/cinder/tests/functional/api_sample_tests/test_volumes.py
@@ -22,7 +22,8 @@ from cinder.tests.functional import api_samples_test_base as test_base
mv.VOLUME_DETAIL_PROVIDER_ID, # 3.21
mv.VOLUME_SHARED_TARGETS_AND_SERVICE_FIELDS, # 3.48
mv.VOLUME_CLUSTER_NAME, # 3.61
- mv.VOLUME_TYPE_ID_IN_VOLUME_DETAIL) # 3.63
+ mv.VOLUME_TYPE_ID_IN_VOLUME_DETAIL, # 3.63
+ mv.USE_QUOTA) # 3.65
class VolumeDetailTests(test_base.VolumesSampleBase):
"""Test volume details returned for operations with different MVs.
diff --git a/cinder/tests/unit/api/test_common.py b/cinder/tests/unit/api/test_common.py
index ecd389340..e18bb24cc 100644
--- a/cinder/tests/unit/api/test_common.py
+++ b/cinder/tests/unit/api/test_common.py
@@ -487,12 +487,13 @@ class GeneralFiltersTest(test.TestCase):
'expected': ["name", "status", "metadata",
"bootable", "migration_status",
"availability_zone", "group_id",
- "size", "created_at", "updated_at"]},
+ "size", "created_at", "updated_at",
+ "consumes_quota"]},
{'resource': 'backup',
'expected': ["name", "status", "volume_id"]},
{'resource': 'snapshot',
'expected': ["name", "status", "volume_id", "metadata",
- "availability_zone"]},
+ "availability_zone", "consumes_quota"]},
{'resource': 'group_snapshot',
'expected': ["name", "status", "group_id"]},
{'resource': 'attachment',
diff --git a/cinder/tests/unit/api/v3/test_snapshots.py b/cinder/tests/unit/api/v3/test_snapshots.py
index d984c8c53..473ae5b89 100644
--- a/cinder/tests/unit/api/v3/test_snapshots.py
+++ b/cinder/tests/unit/api/v3/test_snapshots.py
@@ -115,6 +115,28 @@ class SnapshotApiTest(test.TestCase):
self.assertNotIn('group_snapshot_id', resp_dict['snapshot'])
self.assertNotIn('user_id', resp_dict['snapshot'])
+ @ddt.data(
+ (True, True, mv.USE_QUOTA),
+ (True, False, mv.USE_QUOTA),
+ (False, True, mv.get_prior_version(mv.USE_QUOTA)),
+ (False, False, mv.get_prior_version(mv.USE_QUOTA)),
+ )
+ @ddt.unpack
+ def test_snapshot_show_with_use_quota(self, present, value, microversion):
+ volume = test_utils.create_volume(self.ctx, host='test_host1',
+ cluster_name='cluster1',
+ availability_zone='nova1')
+ snapshot = test_utils.create_snapshot(self.ctx, volume.id,
+ use_quota=value)
+
+ url = '/v3/snapshots?%s' % snapshot.id
+ req = fakes.HTTPRequest.blank(url, version=microversion)
+ res_dict = self.controller.show(req, snapshot.id)['snapshot']
+ if present:
+ self.assertIs(value, res_dict['consumes_quota'])
+ else:
+ self.assertNotIn('consumes_quota', res_dict)
+
def test_snapshot_show_invalid_id(self):
snapshot_id = INVALID_UUID
req = fakes.HTTPRequest.blank('/v3/snapshots/%s' % snapshot_id)
@@ -133,25 +155,28 @@ class SnapshotApiTest(test.TestCase):
body = {"snapshot": snap}
self.controller.create(req, body=body)
- @ddt.data(('host', 'test_host1', True), ('cluster_name', 'cluster1', True),
- ('availability_zone', 'nova1', False))
+ @ddt.data(('host', 'test_host1', True, mv.RESOURCE_FILTER),
+ ('cluster_name', 'cluster1', True, mv.RESOURCE_FILTER),
+ ('availability_zone', 'nova1', False, mv.RESOURCE_FILTER),
+ ('consumes_quota', 'true', False, mv.USE_QUOTA))
@ddt.unpack
def test_snapshot_list_with_filter(self, filter_name, filter_value,
- is_admin_user):
+ is_admin_user, microversion):
volume1 = test_utils.create_volume(self.ctx, host='test_host1',
cluster_name='cluster1',
availability_zone='nova1')
volume2 = test_utils.create_volume(self.ctx, host='test_host2',
cluster_name='cluster2',
availability_zone='nova2')
- snapshot1 = test_utils.create_snapshot(self.ctx, volume1.id)
- test_utils.create_snapshot(self.ctx, volume2.id)
+ snapshot1 = test_utils.create_snapshot(self.ctx, volume1.id,
+ use_quota=True)
+ test_utils.create_snapshot(self.ctx, volume2.id, use_quota=False)
url = '/v3/snapshots?%s=%s' % (filter_name, filter_value)
# Generic filtering is introduced since '3,31' and we add
# 'availability_zone' support by using generic filtering.
req = fakes.HTTPRequest.blank(url, use_admin_context=is_admin_user,
- version=mv.RESOURCE_FILTER)
+ version=microversion)
res_dict = self.controller.detail(req)
self.assertEqual(1, len(res_dict['snapshots']))
diff --git a/cinder/tests/unit/api/v3/test_volumes.py b/cinder/tests/unit/api/v3/test_volumes.py
index c2f787021..18e313527 100644
--- a/cinder/tests/unit/api/v3/test_volumes.py
+++ b/cinder/tests/unit/api/v3/test_volumes.py
@@ -343,6 +343,45 @@ class VolumeApiTest(test.TestCase):
volumes = res_dict['volumes']
self.assertEqual(2, len(volumes))
+ @ddt.data(('true', 0), ('false', 1))
+ @ddt.unpack
+ def test_volume_list_with_quota_filter(self, use_quota, expected_index):
+ volumes = (test_utils.create_volume(self.ctxt, host='test_host1',
+ cluster_name='cluster1',
+ volume_type_id=None,
+ use_quota=True,
+ availability_zone='nova1'),
+ test_utils.create_volume(self.ctxt, host='test_host2',
+ cluster_name='cluster2',
+ volume_type_id=None,
+ use_quota=False,
+ availability_zone='nova2'))
+ req = fakes.HTTPRequest.blank(
+ '/v3/volumes?consumes_quota=%s' % use_quota, version=mv.USE_QUOTA)
+ res_dict = self.controller.detail(req)
+ self.assertEqual(1, len(res_dict['volumes']))
+ self.assertEqual(volumes[expected_index].id,
+ res_dict['volumes'][0]['id'])
+
+ def test_volume_list_without_quota_filter(self):
+ num_vols = 4
+ vol_ids = set()
+ # Half of the volumes will use quota, the other half won't
+ for i in range(num_vols):
+ vol = test_utils.create_volume(self.ctxt,
+ use_quota=bool(i % 2),
+ host='test_host',
+ cluster_name='cluster',
+ volume_type_id=None,
+ availability_zone='nova1')
+ vol_ids.add(vol.id)
+ req = fakes.HTTPRequest.blank('/v3/volumes', version=mv.USE_QUOTA)
+ res_dict = self.controller.detail(req)
+
+ res_vol_ids = {v['id'] for v in res_dict['volumes']}
+ self.assertEqual(num_vols, len(res_vol_ids))
+ self.assertEqual(vol_ids, res_vol_ids)
+
def _fake_volumes_summary_request(self,
version=mv.VOLUME_SUMMARY,
all_tenant=False,
@@ -900,6 +939,27 @@ class VolumeApiTest(test.TestCase):
else:
self.assertNotIn('encryption_key_id', volume_details)
+ @ddt.data(
+ (True, True, mv.USE_QUOTA),
+ (True, False, mv.USE_QUOTA),
+ (False, True, mv.get_prior_version(mv.USE_QUOTA)),
+ (False, False, mv.get_prior_version(mv.USE_QUOTA)),
+ )
+ @ddt.unpack
+ def test_volume_show_with_use_quota(self, present, value, microversion):
+ volume = test_utils.create_volume(self.ctxt,
+ volume_type_id=None,
+ use_quota=value)
+
+ req = fakes.HTTPRequest.blank('/v3/volumes/%s' % volume.id,
+ version=microversion)
+ volume_details = self.controller.show(req, volume.id)['volume']
+
+ if present:
+ self.assertIs(value, volume_details['consumes_quota'])
+ else:
+ self.assertNotIn('consumes_quota', volume_details)
+
def _fake_create_volume(self, size=1):
vol = {
'display_name': 'fake_volume1',
diff --git a/etc/cinder/resource_filters.json b/etc/cinder/resource_filters.json
index 967361e69..e9335ab14 100644
--- a/etc/cinder/resource_filters.json
+++ b/etc/cinder/resource_filters.json
@@ -1,10 +1,11 @@
{
"volume": ["name", "status", "metadata",
"bootable", "migration_status", "availability_zone",
- "group_id", "size", "created_at", "updated_at"],
+ "group_id", "size", "created_at", "updated_at",
+ "consumes_quota"],
"backup": ["name", "status", "volume_id"],
"snapshot": ["name", "status", "volume_id", "metadata",
- "availability_zone"],
+ "availability_zone", "consumes_quota"],
"group": ["name"],
"group_snapshot": ["name", "status", "group_id"],
"attachment": ["volume_id", "status", "instance_id", "attach_status"],
diff --git a/releasenotes/notes/mv-use_quota-b8e010f8f68a1eaa.yaml b/releasenotes/notes/mv-use_quota-b8e010f8f68a1eaa.yaml
new file mode 100644
index 000000000..e5c494e81
--- /dev/null
+++ b/releasenotes/notes/mv-use_quota-b8e010f8f68a1eaa.yaml
@@ -0,0 +1,14 @@
+---
+features:
+ - |
+ Starting with API microversion 3.65, a ``consumes_quota`` field
+ is included in the response body of volumes and snapshots to indicate
+ whether the volume is using quota or not.
+
+ Additionally, ``consumes_quota`` can be used as a listing filter for
+ volumes and snapshots. Its availability is controlled by its inclusion in
+ ``etc/cinder/resource_filters.json``, where it is included by default. The
+ default listing behavior is not to use this filter.
+
+ Only temporary resources created internally by cinder will have the value
+ set to ``false``.