Introduces MV to add volume type ID in volumes details
Introduces microversion (MV) 3.63 to add volume type ID in the volume details. This change comes to fix a problem we found in Gnocchi concerning volumes monitored data. When a volume event is created, Cinder uses the volume type as the volume type ID. On the other hand, Ceilometer pollsters are always updating the volume_type value in Gnocchi with the volume type from volume details API (which uses the volume type name value). That situation creates a massive number of resource revisions in Gnocchi. This MV along with the Dynamic pollster system in Ceilometer enables operators to overcome the issue. Closes-Bug: https://bugs.launchpad.net/cinder/+bug/1911660 Change-Id: Icb88faeb00040250a25a5630aeb312a8434ed3c8 Signed-off-by: Rafael Weingärtner <rafael@apache.org>
This commit is contained in:
@@ -3121,6 +3121,13 @@ volume_type_detail:
|
|||||||
in: body
|
in: body
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
|
volume_type_id_363:
|
||||||
|
description: |
|
||||||
|
The associated volume type ID for the volume.
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
type: object
|
||||||
|
min_version: 3.63
|
||||||
volume_type_id_body:
|
volume_type_id_body:
|
||||||
description: |
|
description: |
|
||||||
The UUID of the volume type.
|
The UUID of the volume type.
|
||||||
@@ -3129,7 +3136,7 @@ volume_type_id_body:
|
|||||||
type: string
|
type: string
|
||||||
volume_type_vol:
|
volume_type_vol:
|
||||||
description: |
|
description: |
|
||||||
The associated volume type for the volume.
|
The associated volume type name for the volume.
|
||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
|
|||||||
@@ -21,8 +21,8 @@
|
|||||||
],
|
],
|
||||||
"min_version": "3.0",
|
"min_version": "3.0",
|
||||||
"status": "CURRENT",
|
"status": "CURRENT",
|
||||||
"updated": "2018-07-17T00:00:00Z",
|
"updated": "2020-11-19T08:56:00Z",
|
||||||
"version": "3.62"
|
"version": "3.63"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,8 +45,8 @@
|
|||||||
],
|
],
|
||||||
"min_version": "3.0",
|
"min_version": "3.0",
|
||||||
"status": "CURRENT",
|
"status": "CURRENT",
|
||||||
"updated": "2018-07-17T00:00:00Z",
|
"updated": "2020-11-19T08:56:00Z",
|
||||||
"version": "3.62"
|
"version": "3.63"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,13 @@
|
|||||||
"status": "creating",
|
"status": "creating",
|
||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
|
"user_id": "c853ca26-e8ea-4797-8a52-ee124a013d0e",
|
||||||
"volume_type": "__DEFAULT__"
|
"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
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -130,6 +130,7 @@ Response Parameters
|
|||||||
- created_at: created_at
|
- created_at: created_at
|
||||||
- volumes: volumes
|
- volumes: volumes
|
||||||
- volume_type: volume_type_vol
|
- volume_type: volume_type_vol
|
||||||
|
- volume_type_id: volume_type_id_363
|
||||||
- group_id: group_id_optional
|
- group_id: group_id_optional
|
||||||
- volumes_links: links_vol_optional
|
- volumes_links: links_vol_optional
|
||||||
- count: count
|
- count: count
|
||||||
@@ -375,6 +376,7 @@ Response Parameters
|
|||||||
- bootable: bootable_response
|
- bootable: bootable_response
|
||||||
- created_at: created_at
|
- created_at: created_at
|
||||||
- volume_type: volume_type_vol
|
- volume_type: volume_type_vol
|
||||||
|
- volume_type_id: volume_type_id_363
|
||||||
- service_uuid: service_uuid
|
- service_uuid: service_uuid
|
||||||
- shared_targets: shared_targets
|
- shared_targets: shared_targets
|
||||||
- cluster_name: cluster_name
|
- cluster_name: cluster_name
|
||||||
|
|||||||
@@ -165,6 +165,8 @@ VOLUME_CLUSTER_NAME = '3.61'
|
|||||||
|
|
||||||
DEFAULT_TYPE_OVERRIDES = '3.62'
|
DEFAULT_TYPE_OVERRIDES = '3.62'
|
||||||
|
|
||||||
|
VOLUME_TYPE_ID_IN_VOLUME_DETAIL = '3.63'
|
||||||
|
|
||||||
|
|
||||||
def get_mv_header(version):
|
def get_mv_header(version):
|
||||||
"""Gets a formatted HTTP microversion header.
|
"""Gets a formatted HTTP microversion header.
|
||||||
|
|||||||
@@ -142,6 +142,11 @@ REST_API_VERSION_HISTORY = """
|
|||||||
* 3.61 - Add ``cluster_name`` attribute to response body of volume details
|
* 3.61 - Add ``cluster_name`` attribute to response body of volume details
|
||||||
for admin.
|
for admin.
|
||||||
* 3.62 - Default volume type overrides
|
* 3.62 - Default volume type overrides
|
||||||
|
* 3.63 - Include volume type ID in the volume details JSON response. Before
|
||||||
|
this microversion (MV), Cinder returns only the volume type name
|
||||||
|
in the volume details. This MV affects the volume detail list
|
||||||
|
("GET /v3/{project_id}/volumes/detail") and volume-show
|
||||||
|
("GET /v3/{project_id}/volumes/{volume_id}") calls.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# The minimum and maximum versions of the API supported
|
# The minimum and maximum versions of the API supported
|
||||||
@@ -149,9 +154,9 @@ REST_API_VERSION_HISTORY = """
|
|||||||
# minimum version of the API supported.
|
# minimum version of the API supported.
|
||||||
# Explicitly using /v2 endpoints will still work
|
# Explicitly using /v2 endpoints will still work
|
||||||
_MIN_API_VERSION = "3.0"
|
_MIN_API_VERSION = "3.0"
|
||||||
_MAX_API_VERSION = "3.62"
|
_MAX_API_VERSION = "3.63"
|
||||||
_LEGACY_API_VERSION2 = "2.0"
|
_LEGACY_API_VERSION2 = "2.0"
|
||||||
UPDATED = "2020-10-14T00:00:00Z"
|
UPDATED = "2020-11-19T08:56:00Z"
|
||||||
|
|
||||||
|
|
||||||
# NOTE(cyeoh): min and max versions declared as functions so we can
|
# NOTE(cyeoh): min and max versions declared as functions so we can
|
||||||
|
|||||||
@@ -479,3 +479,9 @@ Active/Active HA mode.
|
|||||||
Add support for set, get, and unset a default volume type for a specific
|
Add support for set, get, and unset a default volume type for a specific
|
||||||
project. Setting this default overrides the configured default_volume_type
|
project. Setting this default overrides the configured default_volume_type
|
||||||
value.
|
value.
|
||||||
|
|
||||||
|
3.63
|
||||||
|
----
|
||||||
|
Includes volume type ID in the volume-show and volume-detail-list JSON
|
||||||
|
responses. Before this microversion, Cinder returns only the volume type name
|
||||||
|
in the volume details.
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
'updated_at': volume.get('updated_at'),
|
'updated_at': volume.get('updated_at'),
|
||||||
'name': volume.get('display_name'),
|
'name': volume.get('display_name'),
|
||||||
'description': volume.get('display_description'),
|
'description': volume.get('display_description'),
|
||||||
'volume_type': self._get_volume_type(volume),
|
'volume_type': self._get_volume_type(request, volume),
|
||||||
'snapshot_id': volume.get('snapshot_id'),
|
'snapshot_id': volume.get('snapshot_id'),
|
||||||
'source_volid': volume.get('source_volid'),
|
'source_volid': volume.get('source_volid'),
|
||||||
'metadata': self._get_volume_metadata(volume),
|
'metadata': self._get_volume_metadata(volume),
|
||||||
@@ -138,8 +138,8 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
"""Retrieve the metadata of the volume object."""
|
"""Retrieve the metadata of the volume object."""
|
||||||
return volume.metadata
|
return volume.metadata
|
||||||
|
|
||||||
def _get_volume_type(self, volume):
|
def _get_volume_type(self, request, volume):
|
||||||
"""Retrieve the type the volume object."""
|
"""Retrieve the type of the volume object."""
|
||||||
if volume['volume_type_id'] and volume.get('volume_type'):
|
if volume['volume_type_id'] and volume.get('volume_type'):
|
||||||
return volume['volume_type']['name']
|
return volume['volume_type']['name']
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ class ViewBuilder(views_v2.ViewBuilder):
|
|||||||
volume_ref['volume']['cluster_name'] = volume.get(
|
volume_ref['volume']['cluster_name'] = volume.get(
|
||||||
'cluster_name', None)
|
'cluster_name', None)
|
||||||
|
|
||||||
|
if req_version.matches(mv.VOLUME_TYPE_ID_IN_VOLUME_DETAIL, None):
|
||||||
|
volume_ref[
|
||||||
|
'volume']["volume_type_id"] = volume['volume_type'].get('id')
|
||||||
|
|
||||||
return volume_ref
|
return volume_ref
|
||||||
|
|
||||||
def _list_view(self, func, request, volumes, volume_count,
|
def _list_view(self, func, request, volumes, volume_count,
|
||||||
@@ -96,3 +100,18 @@ class ViewBuilder(views_v2.ViewBuilder):
|
|||||||
volumes_dict['count'] = volume_count
|
volumes_dict['count'] = volume_count
|
||||||
|
|
||||||
return volumes_dict
|
return volumes_dict
|
||||||
|
|
||||||
|
def _get_volume_type(self, request, volume):
|
||||||
|
"""Returns the volume type of the volume.
|
||||||
|
|
||||||
|
Retrieves the volume type name for microversion 3.63.
|
||||||
|
Otherwise, it uses the default implementation from super.
|
||||||
|
"""
|
||||||
|
|
||||||
|
req_version = request.api_version_request
|
||||||
|
if req_version.matches(mv.VOLUME_TYPE_ID_IN_VOLUME_DETAIL):
|
||||||
|
if volume.get('volume_type'):
|
||||||
|
return volume['volume_type']['name']
|
||||||
|
return None
|
||||||
|
|
||||||
|
return super(ViewBuilder, self)._get_volume_type(request, volume)
|
||||||
|
|||||||
@@ -34,7 +34,13 @@
|
|||||||
"status": "creating",
|
"status": "creating",
|
||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"user_id": "%(uuid)s",
|
"user_id": "%(uuid)s",
|
||||||
"volume_type": "__DEFAULT__"
|
"volume_type": "%(name)s",
|
||||||
|
"volume_type_id": "%(uuid)s",
|
||||||
|
"service_uuid": null,
|
||||||
|
"provider_id": null,
|
||||||
|
"group_id": null,
|
||||||
|
"shared_targets": true,
|
||||||
|
"cluster_name": null
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
|
|
||||||
|
from cinder.api.microversions import VOLUME_TYPE_ID_IN_VOLUME_DETAIL
|
||||||
from cinder.tests.functional import api_samples_test_base
|
from cinder.tests.functional import api_samples_test_base
|
||||||
|
|
||||||
|
|
||||||
@@ -40,10 +41,15 @@ class VolumesSampleJsonTest(VolumesSampleBase):
|
|||||||
self.response = self._create_volume()
|
self.response = self._create_volume()
|
||||||
|
|
||||||
def test_volume_list_detail(self):
|
def test_volume_list_detail(self):
|
||||||
|
original_api_version = self.api.api_version
|
||||||
|
|
||||||
response = self._do_get('volumes/detail')
|
try:
|
||||||
self._verify_response('volumes-list-detailed-response',
|
self.api.api_version = VOLUME_TYPE_ID_IN_VOLUME_DETAIL
|
||||||
{}, response, 200)
|
response = self._do_get('volumes/detail')
|
||||||
|
self._verify_response('volumes-list-detailed-response',
|
||||||
|
{}, response, 200)
|
||||||
|
finally:
|
||||||
|
self.api.api_version = original_api_version
|
||||||
|
|
||||||
def test_volume_create(self):
|
def test_volume_create(self):
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Introduces microversion (MV) 3.63, which includes volume type ID in the
|
||||||
|
volume details JSON response. This MV affects the volume detail list
|
||||||
|
(``GET /v3/{project_id}/volumes/detail``), and volume-show
|
||||||
|
(``GET /v3/{project_id}/volumes/{volume_id}``) calls.
|
||||||
Reference in New Issue
Block a user