Add count info in /shares and /shares/detail response
Added support for display count info in share list&detail APIs: 1. /v2/{project_id}/shares?with_count=True 2. /v2/{project_id}/shares/detail?with_count=True Partially-Implements bp add-amount-info-in-list-api Change-Id: I12c41a46140b04f26565d8934e0326480477c612
This commit is contained in:
parent
db8b63c139
commit
6dac83660d
@ -112,13 +112,14 @@ REST_API_VERSION_HISTORY = """
|
||||
* 2.39 - Added share-type quotas.
|
||||
* 2.40 - Added share group and share group snapshot quotas.
|
||||
* 2.41 - Added 'description' in share type create/list APIs.
|
||||
* 2.42 - Added ``with_count`` in share list API to get total count info.
|
||||
"""
|
||||
|
||||
# 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 = "2.0"
|
||||
_MAX_API_VERSION = "2.41"
|
||||
_MAX_API_VERSION = "2.42"
|
||||
DEFAULT_API_VERSION = _MIN_API_VERSION
|
||||
|
||||
|
||||
|
@ -230,3 +230,7 @@ user documentation.
|
||||
2.41
|
||||
----
|
||||
Added 'description' in share type create/list APIs.
|
||||
|
||||
2.42
|
||||
----
|
||||
Added ``with_count`` in share list API to get total count info.
|
||||
|
@ -34,6 +34,7 @@ from manila import exception
|
||||
from manila.i18n import _
|
||||
from manila import share
|
||||
from manila.share import share_types
|
||||
from manila import utils
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
@ -105,6 +106,7 @@ class ShareMixin(object):
|
||||
req.GET.pop('name~', None)
|
||||
req.GET.pop('description~', None)
|
||||
req.GET.pop('description', None)
|
||||
req.GET.pop('with_count', None)
|
||||
return self._get_shares(req, is_detail=False)
|
||||
|
||||
def detail(self, req):
|
||||
@ -114,6 +116,7 @@ class ShareMixin(object):
|
||||
req.GET.pop('name~', None)
|
||||
req.GET.pop('description~', None)
|
||||
req.GET.pop('description', None)
|
||||
req.GET.pop('with_count', None)
|
||||
return self._get_shares(req, is_detail=True)
|
||||
|
||||
def _get_shares(self, req, is_detail):
|
||||
@ -129,6 +132,12 @@ class ShareMixin(object):
|
||||
sort_key = search_opts.pop('sort_key', 'created_at')
|
||||
sort_dir = search_opts.pop('sort_dir', 'desc')
|
||||
|
||||
show_count = False
|
||||
if 'with_count' in search_opts:
|
||||
show_count = utils.get_bool_from_api_params(
|
||||
'with_count', search_opts)
|
||||
search_opts.pop('with_count')
|
||||
|
||||
# Deserialize dicts
|
||||
if 'metadata' in search_opts:
|
||||
search_opts['metadata'] = ast.literal_eval(search_opts['metadata'])
|
||||
@ -160,13 +169,18 @@ class ShareMixin(object):
|
||||
shares = self.share_api.get_all(
|
||||
context, search_opts=search_opts, sort_key=sort_key,
|
||||
sort_dir=sort_dir)
|
||||
total_count = None
|
||||
if show_count:
|
||||
total_count = len(shares)
|
||||
|
||||
limited_list = common.limited(shares, req)
|
||||
|
||||
if is_detail:
|
||||
shares = self._view_builder.detail_list(req, limited_list)
|
||||
shares = self._view_builder.detail_list(req, limited_list,
|
||||
total_count)
|
||||
else:
|
||||
shares = self._view_builder.summary_list(req, limited_list)
|
||||
shares = self._view_builder.summary_list(req, limited_list,
|
||||
total_count)
|
||||
return shares
|
||||
|
||||
def _get_share_search_options(self):
|
||||
|
@ -429,6 +429,9 @@ class ShareController(shares.ShareMixin,
|
||||
req.GET.pop('description~', None)
|
||||
req.GET.pop('description', None)
|
||||
|
||||
if req.api_version_request < api_version.APIVersionRequest("2.42"):
|
||||
req.GET.pop('with_count', None)
|
||||
|
||||
return self._get_shares(req, is_detail=False)
|
||||
|
||||
@wsgi.Controller.api_version("2.0")
|
||||
|
@ -36,13 +36,13 @@ class ViewBuilder(common.ViewBuilder):
|
||||
"add_mount_snapshot_support_field",
|
||||
]
|
||||
|
||||
def summary_list(self, request, shares):
|
||||
def summary_list(self, request, shares, count=None):
|
||||
"""Show a list of shares without many details."""
|
||||
return self._list_view(self.summary, request, shares)
|
||||
return self._list_view(self.summary, request, shares, count)
|
||||
|
||||
def detail_list(self, request, shares):
|
||||
def detail_list(self, request, shares, count=None):
|
||||
"""Detailed view of a list of shares."""
|
||||
return self._list_view(self.detail, request, shares)
|
||||
return self._list_view(self.detail, request, shares, count)
|
||||
|
||||
def summary(self, request, share):
|
||||
"""Generic, non-detailed view of a share."""
|
||||
@ -170,7 +170,7 @@ class ViewBuilder(common.ViewBuilder):
|
||||
share_dict['mount_snapshot_support'] = share.get(
|
||||
'mount_snapshot_support')
|
||||
|
||||
def _list_view(self, func, request, shares):
|
||||
def _list_view(self, func, request, shares, count=None):
|
||||
"""Provide a view for a list of shares."""
|
||||
shares_list = [func(request, share)['share'] for share in shares]
|
||||
shares_links = self._get_collection_links(request,
|
||||
@ -178,6 +178,8 @@ class ViewBuilder(common.ViewBuilder):
|
||||
self._collection_name)
|
||||
shares_dict = dict(shares=shares_list)
|
||||
|
||||
if count:
|
||||
shares_dict['count'] = count
|
||||
if shares_links:
|
||||
shares_dict['shares_links'] = shares_links
|
||||
|
||||
|
@ -1502,7 +1502,9 @@ class ShareAPITest(test.TestCase):
|
||||
{'use_admin_context': True, 'version': '2.35'},
|
||||
{'use_admin_context': False, 'version': '2.35'},
|
||||
{'use_admin_context': True, 'version': '2.36'},
|
||||
{'use_admin_context': False, 'version': '2.36'})
|
||||
{'use_admin_context': False, 'version': '2.36'},
|
||||
{'use_admin_context': True, 'version': '2.42'},
|
||||
{'use_admin_context': False, 'version': '2.42'})
|
||||
@ddt.unpack
|
||||
def test_share_list_summary_with_search_opts(self, use_admin_context,
|
||||
version):
|
||||
@ -1528,6 +1530,9 @@ class ShareAPITest(test.TestCase):
|
||||
search_opts.update(
|
||||
{'display_name~': 'fake',
|
||||
'display_description~': 'fake'})
|
||||
if (api_version.APIVersionRequest(version) >=
|
||||
api_version.APIVersionRequest('2.42')):
|
||||
search_opts.update({'with_count': 'true'})
|
||||
if use_admin_context:
|
||||
search_opts['host'] = 'fake_host'
|
||||
# fake_key should be filtered for non-admin
|
||||
@ -1583,6 +1588,9 @@ class ShareAPITest(test.TestCase):
|
||||
self.assertEqual(shares[1]['id'], result['shares'][0]['id'])
|
||||
self.assertEqual(
|
||||
shares[1]['display_name'], result['shares'][0]['name'])
|
||||
if (api_version.APIVersionRequest(version) >=
|
||||
api_version.APIVersionRequest('2.42')):
|
||||
self.assertEqual(3, result['count'])
|
||||
|
||||
def test_share_list_summary(self):
|
||||
self.mock_object(share_api.API, 'get_all',
|
||||
@ -1612,7 +1620,9 @@ class ShareAPITest(test.TestCase):
|
||||
@ddt.data({'use_admin_context': False, 'version': '2.4'},
|
||||
{'use_admin_context': True, 'version': '2.4'},
|
||||
{'use_admin_context': True, 'version': '2.35'},
|
||||
{'use_admin_context': False, 'version': '2.35'})
|
||||
{'use_admin_context': False, 'version': '2.35'},
|
||||
{'use_admin_context': True, 'version': '2.42'},
|
||||
{'use_admin_context': False, 'version': '2.42'})
|
||||
@ddt.unpack
|
||||
def test_share_list_detail_with_search_opts(self, use_admin_context,
|
||||
version):
|
||||
@ -1633,6 +1643,9 @@ class ShareAPITest(test.TestCase):
|
||||
'export_location_id': 'fake_export_location_id',
|
||||
'export_location_path': 'fake_export_location_path',
|
||||
}
|
||||
if (api_version.APIVersionRequest(version) >=
|
||||
api_version.APIVersionRequest('2.42')):
|
||||
search_opts.update({'with_count': 'true'})
|
||||
if use_admin_context:
|
||||
search_opts['host'] = 'fake_host'
|
||||
# fake_key should be filtered for non-admin
|
||||
@ -1710,6 +1723,9 @@ class ShareAPITest(test.TestCase):
|
||||
self.assertEqual(
|
||||
shares[1]['instance']['share_network_id'],
|
||||
result['shares'][0]['share_network_id'])
|
||||
if (api_version.APIVersionRequest(version) >=
|
||||
api_version.APIVersionRequest('2.42')):
|
||||
self.assertEqual(3, result['count'])
|
||||
|
||||
def _list_detail_common_expected(self, admin=False):
|
||||
share_dict = {
|
||||
|
@ -30,7 +30,7 @@ ShareGroup = [
|
||||
help="The minimum api microversion is configured to be the "
|
||||
"value of the minimum microversion supported by Manila."),
|
||||
cfg.StrOpt("max_api_microversion",
|
||||
default="2.41",
|
||||
default="2.42",
|
||||
help="The maximum api microversion is configured to be the "
|
||||
"value of the latest microversion supported by Manila."),
|
||||
cfg.StrOpt("region",
|
||||
|
@ -389,6 +389,14 @@ class SharesActionsTest(base.BaseSharesTest):
|
||||
for share in shares:
|
||||
self.assertEqual(project_id, share["project_id"])
|
||||
|
||||
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
|
||||
@base.skip_if_microversion_lt("2.42")
|
||||
def test_list_shares_with_detail_with_count(self):
|
||||
# list shares by name, at least one share is expected
|
||||
params = {"with_count": 'true'}
|
||||
shares = self.shares_v2_client.list_shares_with_detail(params)
|
||||
self.assertGreater(shares["count"], 0)
|
||||
|
||||
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
|
||||
def test_list_shares_public_with_detail(self):
|
||||
public_share = self.create_share(
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Added total count info in Manila's /shares and /shares/detail APIs.
|
Loading…
Reference in New Issue
Block a user