Add count info in 'snapshot list' API
Added support for display count info in share snapshot list&detail APIs: 1. /v2/snapshots?with_count=True 2. /v2/snapshots/detail?with_count=True New microversion added 2.79 Closes-bug: #2024556 Change-Id: I37d8ca9022e2ea2c107c6695e20e951d7950043a
This commit is contained in:
parent
e31be16130
commit
0e7812657b
@ -653,11 +653,18 @@ user_id_query:
|
|||||||
type: string
|
type: string
|
||||||
with_count_query:
|
with_count_query:
|
||||||
description: |
|
description: |
|
||||||
Whether to show ``count`` in API response or not, default is ``False``.
|
Whether to show ``count`` in share list API response or not, default is ``False``.
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
type: boolean
|
type: boolean
|
||||||
min_version: 2.42
|
min_version: 2.42
|
||||||
|
with_count_snapshot_query:
|
||||||
|
description: |
|
||||||
|
Whether to show ``count`` in share snapshot list API response or not, default is ``False``.
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
min_version: 2.79
|
||||||
|
|
||||||
# variables in body
|
# variables in body
|
||||||
accepted:
|
accepted:
|
||||||
|
@ -70,6 +70,7 @@ Request
|
|||||||
- all_tenants: all_tenants_query
|
- all_tenants: all_tenants_query
|
||||||
- name~: name_inexact_query
|
- name~: name_inexact_query
|
||||||
- description~: description_inexact_query
|
- description~: description_inexact_query
|
||||||
|
- with_count: with_count_snapshot_query
|
||||||
|
|
||||||
Response parameters
|
Response parameters
|
||||||
-------------------
|
-------------------
|
||||||
@ -114,6 +115,7 @@ Request
|
|||||||
- all_tenants: all_tenants_query
|
- all_tenants: all_tenants_query
|
||||||
- name~: name_inexact_query
|
- name~: name_inexact_query
|
||||||
- description~: description_inexact_query
|
- description~: description_inexact_query
|
||||||
|
- with_count: with_count_snapshot_query
|
||||||
|
|
||||||
Response parameters
|
Response parameters
|
||||||
-------------------
|
-------------------
|
||||||
|
@ -195,6 +195,8 @@ REST_API_VERSION_HISTORY = """
|
|||||||
* 2.76 - Added 'default_ad_site' field in security service object.
|
* 2.76 - Added 'default_ad_site' field in security service object.
|
||||||
* 2.77 - Added support for share transfer between different projects.
|
* 2.77 - Added support for share transfer between different projects.
|
||||||
* 2.78 - Added Share Network Subnet Metadata to Metadata API.
|
* 2.78 - Added Share Network Subnet Metadata to Metadata API.
|
||||||
|
* 2.79 - Added ``with_count`` in share snapshot list API to get total
|
||||||
|
count info.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -202,7 +204,7 @@ REST_API_VERSION_HISTORY = """
|
|||||||
# The default api version request is defined to be the
|
# The default api version request is defined to be the
|
||||||
# minimum version of the API supported.
|
# minimum version of the API supported.
|
||||||
_MIN_API_VERSION = "2.0"
|
_MIN_API_VERSION = "2.0"
|
||||||
_MAX_API_VERSION = "2.78"
|
_MAX_API_VERSION = "2.79"
|
||||||
DEFAULT_API_VERSION = _MIN_API_VERSION
|
DEFAULT_API_VERSION = _MIN_API_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
@ -427,3 +427,7 @@ ____
|
|||||||
---------------------------------
|
---------------------------------
|
||||||
Added Metadata API methods (GET, PUT, POST, DELETE)
|
Added Metadata API methods (GET, PUT, POST, DELETE)
|
||||||
to Share Network Subnets.
|
to Share Network Subnets.
|
||||||
|
|
||||||
|
2.79
|
||||||
|
------------------------
|
||||||
|
Added ``with_count`` in share snapshot list API to get total count info.
|
||||||
|
@ -30,6 +30,7 @@ from manila import db
|
|||||||
from manila import exception
|
from manila import exception
|
||||||
from manila.i18n import _
|
from manila.i18n import _
|
||||||
from manila import share
|
from manila import share
|
||||||
|
from manila import utils
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
@ -100,6 +101,13 @@ class ShareSnapshotMixin(object):
|
|||||||
# Remove keys that are not related to share attrs
|
# Remove keys that are not related to share attrs
|
||||||
search_opts.pop('limit', None)
|
search_opts.pop('limit', None)
|
||||||
search_opts.pop('offset', None)
|
search_opts.pop('offset', None)
|
||||||
|
|
||||||
|
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')
|
||||||
|
|
||||||
sort_key, sort_dir = common.get_sort_params(search_opts)
|
sort_key, sort_dir = common.get_sort_params(search_opts)
|
||||||
key_dict = {"name": "display_name",
|
key_dict = {"name": "display_name",
|
||||||
"description": "display_description"}
|
"description": "display_description"}
|
||||||
@ -137,19 +145,23 @@ class ShareSnapshotMixin(object):
|
|||||||
common.remove_invalid_options(context, search_opts,
|
common.remove_invalid_options(context, search_opts,
|
||||||
self._get_snapshots_search_options())
|
self._get_snapshots_search_options())
|
||||||
|
|
||||||
snapshots = self.share_api.get_all_snapshots(
|
total_count = None
|
||||||
context,
|
if show_count:
|
||||||
search_opts=search_opts,
|
count, snapshots = self.share_api.get_all_snapshots_with_count(
|
||||||
limit=limit,
|
context, search_opts=search_opts, limit=limit, offset=offset,
|
||||||
offset=offset,
|
sort_key=sort_key, sort_dir=sort_dir)
|
||||||
sort_key=sort_key,
|
total_count = count
|
||||||
sort_dir=sort_dir,
|
else:
|
||||||
)
|
snapshots = self.share_api.get_all_snapshots(
|
||||||
|
context, search_opts=search_opts, limit=limit, offset=offset,
|
||||||
|
sort_key=sort_key, sort_dir=sort_dir)
|
||||||
|
|
||||||
if is_detail:
|
if is_detail:
|
||||||
snapshots = self._view_builder.detail_list(req, snapshots)
|
snapshots = self._view_builder.detail_list(
|
||||||
|
req, snapshots, total_count)
|
||||||
else:
|
else:
|
||||||
snapshots = self._view_builder.summary_list(req, snapshots)
|
snapshots = self._view_builder.summary_list(
|
||||||
|
req, snapshots, total_count)
|
||||||
return snapshots
|
return snapshots
|
||||||
|
|
||||||
def _get_snapshots_search_options(self):
|
def _get_snapshots_search_options(self):
|
||||||
|
@ -336,6 +336,10 @@ class ShareSnapshotsController(share_snapshots.ShareSnapshotMixin,
|
|||||||
req.GET.pop('name~', None)
|
req.GET.pop('name~', None)
|
||||||
req.GET.pop('description~', None)
|
req.GET.pop('description~', None)
|
||||||
req.GET.pop('description', None)
|
req.GET.pop('description', None)
|
||||||
|
|
||||||
|
if req.api_version_request < api_version.APIVersionRequest("2.79"):
|
||||||
|
req.GET.pop('with_count', None)
|
||||||
|
|
||||||
return self._get_snapshots(req, is_detail=False)
|
return self._get_snapshots(req, is_detail=False)
|
||||||
|
|
||||||
@wsgi.Controller.api_version("2.0")
|
@wsgi.Controller.api_version("2.0")
|
||||||
|
@ -26,13 +26,13 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
"add_metadata"
|
"add_metadata"
|
||||||
]
|
]
|
||||||
|
|
||||||
def summary_list(self, request, snapshots):
|
def summary_list(self, request, snapshots, count=None):
|
||||||
"""Show a list of share snapshots without many details."""
|
"""Show a list of share snapshots without many details."""
|
||||||
return self._list_view(self.summary, request, snapshots)
|
return self._list_view(self.summary, request, snapshots, count)
|
||||||
|
|
||||||
def detail_list(self, request, snapshots):
|
def detail_list(self, request, snapshots, count=None):
|
||||||
"""Detailed view of a list of share snapshots."""
|
"""Detailed view of a list of share snapshots."""
|
||||||
return self._list_view(self.detail, request, snapshots)
|
return self._list_view(self.detail, request, snapshots, count)
|
||||||
|
|
||||||
def summary(self, request, snapshot):
|
def summary(self, request, snapshot):
|
||||||
"""Generic, non-detailed view of an share snapshot."""
|
"""Generic, non-detailed view of an share snapshot."""
|
||||||
@ -84,7 +84,7 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
metadata = {}
|
metadata = {}
|
||||||
snapshot_dict['metadata'] = metadata
|
snapshot_dict['metadata'] = metadata
|
||||||
|
|
||||||
def _list_view(self, func, request, snapshots):
|
def _list_view(self, func, request, snapshots, count=None):
|
||||||
"""Provide a view for a list of share snapshots."""
|
"""Provide a view for a list of share snapshots."""
|
||||||
snapshots_list = [func(request, snapshot)['snapshot']
|
snapshots_list = [func(request, snapshot)['snapshot']
|
||||||
for snapshot in snapshots]
|
for snapshot in snapshots]
|
||||||
@ -93,6 +93,8 @@ class ViewBuilder(common.ViewBuilder):
|
|||||||
self._collection_name)
|
self._collection_name)
|
||||||
snapshots_dict = {self._collection_name: snapshots_list}
|
snapshots_dict = {self._collection_name: snapshots_list}
|
||||||
|
|
||||||
|
if count is not None:
|
||||||
|
snapshots_dict['count'] = count
|
||||||
if snapshots_links:
|
if snapshots_links:
|
||||||
snapshots_dict['share_snapshots_links'] = snapshots_links
|
snapshots_dict['share_snapshots_links'] = snapshots_links
|
||||||
|
|
||||||
|
@ -692,6 +692,15 @@ def share_snapshot_get_all(context, filters=None, limit=None, offset=None,
|
|||||||
sort_key=sort_key, sort_dir=sort_dir)
|
sort_key=sort_key, sort_dir=sort_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def share_snapshot_get_all_with_count(context, filters=None, limit=None,
|
||||||
|
offset=None, sort_key=None,
|
||||||
|
sort_dir=None):
|
||||||
|
"""Get all snapshots."""
|
||||||
|
return IMPL.share_snapshot_get_all_with_count(
|
||||||
|
context, filters=filters, limit=limit, offset=offset,
|
||||||
|
sort_key=sort_key, sort_dir=sort_dir)
|
||||||
|
|
||||||
|
|
||||||
def share_snapshot_get_all_by_project(context, project_id, filters=None,
|
def share_snapshot_get_all_by_project(context, project_id, filters=None,
|
||||||
limit=None, offset=None, sort_key=None,
|
limit=None, offset=None, sort_key=None,
|
||||||
sort_dir=None):
|
sort_dir=None):
|
||||||
@ -701,6 +710,16 @@ def share_snapshot_get_all_by_project(context, project_id, filters=None,
|
|||||||
sort_key=sort_key, sort_dir=sort_dir)
|
sort_key=sort_key, sort_dir=sort_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def share_snapshot_get_all_by_project_with_count(context, project_id,
|
||||||
|
filters=None, limit=None,
|
||||||
|
offset=None, sort_key=None,
|
||||||
|
sort_dir=None):
|
||||||
|
"""Get all snapshots belonging to a project."""
|
||||||
|
return IMPL.share_snapshot_get_all_by_project_with_count(
|
||||||
|
context, project_id, filters=filters, limit=limit, offset=offset,
|
||||||
|
sort_key=sort_key, sort_dir=sort_dir)
|
||||||
|
|
||||||
|
|
||||||
def share_snapshot_get_all_for_share(context, share_id, filters=None,
|
def share_snapshot_get_all_for_share(context, share_id, filters=None,
|
||||||
sort_key=None, sort_dir=None):
|
sort_key=None, sort_dir=None):
|
||||||
"""Get all snapshots for a share."""
|
"""Get all snapshots for a share."""
|
||||||
|
@ -3319,7 +3319,8 @@ def share_snapshot_get(context, snapshot_id, project_only=True, session=None):
|
|||||||
def _share_snapshot_get_all_with_filters(context, project_id=None,
|
def _share_snapshot_get_all_with_filters(context, project_id=None,
|
||||||
share_id=None, filters=None,
|
share_id=None, filters=None,
|
||||||
limit=None, offset=None,
|
limit=None, offset=None,
|
||||||
sort_key=None, sort_dir=None):
|
sort_key=None, sort_dir=None,
|
||||||
|
show_count=False):
|
||||||
"""Retrieves all snapshots.
|
"""Retrieves all snapshots.
|
||||||
|
|
||||||
If no sorting parameters are specified then returned snapshots are sorted
|
If no sorting parameters are specified then returned snapshots are sorted
|
||||||
@ -3389,13 +3390,25 @@ def _share_snapshot_get_all_with_filters(context, project_id=None,
|
|||||||
query = exact_filter(query, models.ShareSnapshot,
|
query = exact_filter(query, models.ShareSnapshot,
|
||||||
filters, legal_filter_keys)
|
filters, legal_filter_keys)
|
||||||
|
|
||||||
query = utils.paginate_query(query, models.ShareSnapshot, limit,
|
query = apply_sorting(models.ShareSnapshot, query, sort_key, sort_dir)
|
||||||
sort_key=sort_key,
|
|
||||||
sort_dir=sort_dir,
|
|
||||||
offset=offset)
|
|
||||||
|
|
||||||
# Returns list of shares that satisfy filters
|
count = None
|
||||||
return query.all()
|
if show_count:
|
||||||
|
count = query.count()
|
||||||
|
|
||||||
|
if limit is not None:
|
||||||
|
query = query.limit(limit)
|
||||||
|
|
||||||
|
if offset:
|
||||||
|
query = query.offset(offset)
|
||||||
|
|
||||||
|
# Returns list of share snapshots that satisfy filters
|
||||||
|
query = query.all()
|
||||||
|
|
||||||
|
if show_count:
|
||||||
|
return count, query
|
||||||
|
|
||||||
|
return query
|
||||||
|
|
||||||
|
|
||||||
@require_admin_context
|
@require_admin_context
|
||||||
@ -3406,6 +3419,17 @@ def share_snapshot_get_all(context, filters=None, limit=None, offset=None,
|
|||||||
offset=offset, sort_key=sort_key, sort_dir=sort_dir)
|
offset=offset, sort_key=sort_key, sort_dir=sort_dir)
|
||||||
|
|
||||||
|
|
||||||
|
@require_admin_context
|
||||||
|
def share_snapshot_get_all_with_count(context, filters=None, limit=None,
|
||||||
|
offset=None, sort_key=None,
|
||||||
|
sort_dir=None):
|
||||||
|
count, query = _share_snapshot_get_all_with_filters(
|
||||||
|
context, filters=filters, limit=limit,
|
||||||
|
offset=offset, sort_key=sort_key, sort_dir=sort_dir,
|
||||||
|
show_count=True)
|
||||||
|
return count, query
|
||||||
|
|
||||||
|
|
||||||
@require_context
|
@require_context
|
||||||
def share_snapshot_get_all_by_project(context, project_id, filters=None,
|
def share_snapshot_get_all_by_project(context, project_id, filters=None,
|
||||||
limit=None, offset=None,
|
limit=None, offset=None,
|
||||||
@ -3416,6 +3440,19 @@ def share_snapshot_get_all_by_project(context, project_id, filters=None,
|
|||||||
offset=offset, sort_key=sort_key, sort_dir=sort_dir)
|
offset=offset, sort_key=sort_key, sort_dir=sort_dir)
|
||||||
|
|
||||||
|
|
||||||
|
@require_context
|
||||||
|
def share_snapshot_get_all_by_project_with_count(context, project_id,
|
||||||
|
filters=None, limit=None,
|
||||||
|
offset=None, sort_key=None,
|
||||||
|
sort_dir=None):
|
||||||
|
authorize_project_context(context, project_id)
|
||||||
|
count, query = _share_snapshot_get_all_with_filters(
|
||||||
|
context, project_id=project_id, filters=filters, limit=limit,
|
||||||
|
offset=offset, sort_key=sort_key, sort_dir=sort_dir,
|
||||||
|
show_count=True)
|
||||||
|
return count, query
|
||||||
|
|
||||||
|
|
||||||
@require_context
|
@require_context
|
||||||
def share_snapshot_get_all_for_share(context, share_id, filters=None,
|
def share_snapshot_get_all_for_share(context, share_id, filters=None,
|
||||||
sort_key=None, sort_dir=None):
|
sort_key=None, sort_dir=None):
|
||||||
|
@ -2177,6 +2177,21 @@ class API(base.Base):
|
|||||||
|
|
||||||
def get_all_snapshots(self, context, search_opts=None, limit=None,
|
def get_all_snapshots(self, context, search_opts=None, limit=None,
|
||||||
offset=None, sort_key='share_id', sort_dir='desc'):
|
offset=None, sort_key='share_id', sort_dir='desc'):
|
||||||
|
return self._get_all_snapshots(context, search_opts=search_opts,
|
||||||
|
limit=limit, offset=offset,
|
||||||
|
sort_key=sort_key, sort_dir=sort_dir)
|
||||||
|
|
||||||
|
def get_all_snapshots_with_count(self, context, search_opts=None,
|
||||||
|
limit=None, offset=None,
|
||||||
|
sort_key='share_id', sort_dir='desc'):
|
||||||
|
return self._get_all_snapshots(context, search_opts=search_opts,
|
||||||
|
limit=limit, offset=offset,
|
||||||
|
sort_key=sort_key, sort_dir=sort_dir,
|
||||||
|
show_count=True)
|
||||||
|
|
||||||
|
def _get_all_snapshots(self, context, search_opts=None, limit=None,
|
||||||
|
offset=None, sort_key='share_id', sort_dir='desc',
|
||||||
|
show_count=False):
|
||||||
policy.check_policy(context, 'share_snapshot', 'get_all_snapshots')
|
policy.check_policy(context, 'share_snapshot', 'get_all_snapshots')
|
||||||
|
|
||||||
search_opts = search_opts or {}
|
search_opts = search_opts or {}
|
||||||
@ -2193,17 +2208,32 @@ class API(base.Base):
|
|||||||
"'%(v)s'.") % {'k': k, 'v': string_args[k]}
|
"'%(v)s'.") % {'k': k, 'v': string_args[k]}
|
||||||
raise exception.InvalidInput(reason=msg)
|
raise exception.InvalidInput(reason=msg)
|
||||||
|
|
||||||
|
get_methods = {
|
||||||
|
'get_all': (
|
||||||
|
self.db.share_snapshot_get_all_with_count
|
||||||
|
if show_count else self.db.share_snapshot_get_all),
|
||||||
|
'get_all_by_project': (
|
||||||
|
self.db.share_snapshot_get_all_by_project_with_count
|
||||||
|
if show_count else self.db.share_snapshot_get_all_by_project)}
|
||||||
|
|
||||||
if context.is_admin and all_tenants:
|
if context.is_admin and all_tenants:
|
||||||
snapshots = self.db.share_snapshot_get_all(
|
result = get_methods['get_all'](
|
||||||
context, filters=search_opts, limit=limit, offset=offset,
|
context, filters=search_opts, limit=limit, offset=offset,
|
||||||
sort_key=sort_key, sort_dir=sort_dir)
|
sort_key=sort_key, sort_dir=sort_dir)
|
||||||
else:
|
else:
|
||||||
snapshots = self.db.share_snapshot_get_all_by_project(
|
result = get_methods['get_all_by_project'](
|
||||||
context, context.project_id, filters=search_opts,
|
context, context.project_id, filters=search_opts,
|
||||||
limit=limit, offset=offset, sort_key=sort_key,
|
limit=limit, offset=offset, sort_key=sort_key,
|
||||||
sort_dir=sort_dir)
|
sort_dir=sort_dir)
|
||||||
|
|
||||||
return snapshots
|
if show_count:
|
||||||
|
count = result[0]
|
||||||
|
snapshots = result[1]
|
||||||
|
else:
|
||||||
|
snapshots = result
|
||||||
|
|
||||||
|
result = (count, snapshots) if show_count else snapshots
|
||||||
|
return result
|
||||||
|
|
||||||
def get_latest_snapshot_for_share(self, context, share_id):
|
def get_latest_snapshot_for_share(self, context, share_id):
|
||||||
"""Get the newest snapshot of a share."""
|
"""Get the newest snapshot of a share."""
|
||||||
|
@ -196,6 +196,10 @@ class ShareSnapshotAPITest(test.TestCase):
|
|||||||
api_version.APIVersionRequest('2.36')):
|
api_version.APIVersionRequest('2.36')):
|
||||||
search_opts.pop('name')
|
search_opts.pop('name')
|
||||||
search_opts['display_name~'] = 'fake_name'
|
search_opts['display_name~'] = 'fake_name'
|
||||||
|
if (api_version.APIVersionRequest(version) >=
|
||||||
|
api_version.APIVersionRequest('2.79')):
|
||||||
|
search_opts.update({'with_count': 'true'})
|
||||||
|
|
||||||
# fake_key should be filtered for non-admin
|
# fake_key should be filtered for non-admin
|
||||||
url = '/v2/fake/snapshots?fake_key=fake_value'
|
url = '/v2/fake/snapshots?fake_key=fake_value'
|
||||||
for k, v in search_opts.items():
|
for k, v in search_opts.items():
|
||||||
@ -203,14 +207,21 @@ class ShareSnapshotAPITest(test.TestCase):
|
|||||||
req = fakes.HTTPRequest.blank(
|
req = fakes.HTTPRequest.blank(
|
||||||
url, use_admin_context=use_admin_context, version=version)
|
url, use_admin_context=use_admin_context, version=version)
|
||||||
|
|
||||||
|
method = 'get_all_snapshots'
|
||||||
db_snapshots = [
|
db_snapshots = [
|
||||||
{'id': 'id1', 'display_name': 'n1', 'status': 'fake_status', },
|
{'id': 'id1', 'display_name': 'n1', 'status': 'fake_status', },
|
||||||
{'id': 'id2', 'display_name': 'n2', 'status': 'fake_status', },
|
{'id': 'id2', 'display_name': 'n2', 'status': 'fake_status', },
|
||||||
{'id': 'id3', 'display_name': 'n3', 'status': 'fake_status', },
|
{'id': 'id3', 'display_name': 'n3', 'status': 'fake_status', },
|
||||||
]
|
]
|
||||||
snapshots = [db_snapshots[1]]
|
|
||||||
self.mock_object(share_api.API, 'get_all_snapshots',
|
mock_action = {'return_value': [db_snapshots[1]]}
|
||||||
mock.Mock(return_value=snapshots))
|
if (api_version.APIVersionRequest(version) >=
|
||||||
|
api_version.APIVersionRequest('2.79')):
|
||||||
|
method = 'get_all_snapshots_with_count'
|
||||||
|
mock_action = {'side_effect': [(1, [db_snapshots[1]])]}
|
||||||
|
|
||||||
|
mock_get_all_snapshots = (
|
||||||
|
self.mock_object(share_api.API, method, mock.Mock(**mock_action)))
|
||||||
|
|
||||||
result = self.controller.index(req)
|
result = self.controller.index(req)
|
||||||
|
|
||||||
@ -225,7 +236,8 @@ class ShareSnapshotAPITest(test.TestCase):
|
|||||||
search_opts_expected['display_name'] = search_opts['name']
|
search_opts_expected['display_name'] = search_opts['name']
|
||||||
if use_admin_context:
|
if use_admin_context:
|
||||||
search_opts_expected.update({'fake_key': 'fake_value'})
|
search_opts_expected.update({'fake_key': 'fake_value'})
|
||||||
share_api.API.get_all_snapshots.assert_called_once_with(
|
|
||||||
|
mock_get_all_snapshots.assert_called_once_with(
|
||||||
req.environ['manila.context'],
|
req.environ['manila.context'],
|
||||||
limit=int(search_opts['limit']),
|
limit=int(search_opts['limit']),
|
||||||
offset=int(search_opts['offset']),
|
offset=int(search_opts['offset']),
|
||||||
@ -234,14 +246,19 @@ class ShareSnapshotAPITest(test.TestCase):
|
|||||||
search_opts=search_opts_expected,
|
search_opts=search_opts_expected,
|
||||||
)
|
)
|
||||||
self.assertEqual(1, len(result['snapshots']))
|
self.assertEqual(1, len(result['snapshots']))
|
||||||
self.assertEqual(snapshots[0]['id'], result['snapshots'][0]['id'])
|
self.assertEqual(db_snapshots[1]['id'], result['snapshots'][0]['id'])
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
snapshots[0]['display_name'], result['snapshots'][0]['name'])
|
db_snapshots[1]['display_name'], result['snapshots'][0]['name'])
|
||||||
|
if (api_version.APIVersionRequest(version) >=
|
||||||
|
api_version.APIVersionRequest('2.79')):
|
||||||
|
self.assertEqual(1, result['count'])
|
||||||
|
|
||||||
@ddt.data({'version': '2.35', 'use_admin_context': True},
|
@ddt.data({'version': '2.35', 'use_admin_context': True},
|
||||||
{'version': '2.36', 'use_admin_context': True},
|
{'version': '2.36', 'use_admin_context': True},
|
||||||
|
{'version': '2.79', 'use_admin_context': True},
|
||||||
{'version': '2.35', 'use_admin_context': False},
|
{'version': '2.35', 'use_admin_context': False},
|
||||||
{'version': '2.36', 'use_admin_context': False})
|
{'version': '2.36', 'use_admin_context': False},
|
||||||
|
{'version': '2.79', 'use_admin_context': False})
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_snapshot_list_summary_with_search_opts(self, version,
|
def test_snapshot_list_summary_with_search_opts(self, version,
|
||||||
use_admin_context):
|
use_admin_context):
|
||||||
@ -288,14 +305,20 @@ class ShareSnapshotAPITest(test.TestCase):
|
|||||||
self.assertEqual(1, len(result['snapshots']))
|
self.assertEqual(1, len(result['snapshots']))
|
||||||
self.assertEqual(snapshots[0]['id'], result['snapshots'][0]['id'])
|
self.assertEqual(snapshots[0]['id'], result['snapshots'][0]['id'])
|
||||||
|
|
||||||
def _snapshot_list_detail_with_search_opts(self, use_admin_context):
|
def _snapshot_list_detail_with_search_opts(self, version,
|
||||||
|
use_admin_context):
|
||||||
search_opts = fake_share.search_opts()
|
search_opts = fake_share.search_opts()
|
||||||
|
if (api_version.APIVersionRequest(version) >=
|
||||||
|
api_version.APIVersionRequest('2.79')):
|
||||||
|
search_opts.update({'with_count': 'true'})
|
||||||
|
|
||||||
# fake_key should be filtered for non-admin
|
# fake_key should be filtered for non-admin
|
||||||
url = '/v2/fake/shares/detail?fake_key=fake_value'
|
url = '/v2/fake/shares/detail?fake_key=fake_value'
|
||||||
for k, v in search_opts.items():
|
for k, v in search_opts.items():
|
||||||
url = url + '&' + k + '=' + v
|
url = url + '&' + k + '=' + v
|
||||||
req = fakes.HTTPRequest.blank(url, use_admin_context=use_admin_context)
|
req = fakes.HTTPRequest.blank(url, use_admin_context=use_admin_context)
|
||||||
|
|
||||||
|
method = 'get_all_snapshots'
|
||||||
db_snapshots = [
|
db_snapshots = [
|
||||||
{
|
{
|
||||||
'id': 'id1',
|
'id': 'id1',
|
||||||
@ -317,10 +340,14 @@ class ShareSnapshotAPITest(test.TestCase):
|
|||||||
'aggregate_status': 'fake_status',
|
'aggregate_status': 'fake_status',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
snapshots = [db_snapshots[1]]
|
mock_action = {'return_value': [db_snapshots[1]]}
|
||||||
|
if (api_version.APIVersionRequest(version) >=
|
||||||
|
api_version.APIVersionRequest('2.79')):
|
||||||
|
method = 'get_all_snapshots_with_count'
|
||||||
|
mock_action = {'side_effect': [(1, [db_snapshots[1]])]}
|
||||||
|
|
||||||
self.mock_object(share_api.API, 'get_all_snapshots',
|
mock_get_all_snapshots = (
|
||||||
mock.Mock(return_value=snapshots))
|
self.mock_object(share_api.API, method, mock.Mock(**mock_action)))
|
||||||
|
|
||||||
result = self.controller.detail(req)
|
result = self.controller.detail(req)
|
||||||
|
|
||||||
@ -331,7 +358,7 @@ class ShareSnapshotAPITest(test.TestCase):
|
|||||||
}
|
}
|
||||||
if use_admin_context:
|
if use_admin_context:
|
||||||
search_opts_expected.update({'fake_key': 'fake_value'})
|
search_opts_expected.update({'fake_key': 'fake_value'})
|
||||||
share_api.API.get_all_snapshots.assert_called_once_with(
|
mock_get_all_snapshots.assert_called_once_with(
|
||||||
req.environ['manila.context'],
|
req.environ['manila.context'],
|
||||||
limit=int(search_opts['limit']),
|
limit=int(search_opts['limit']),
|
||||||
offset=int(search_opts['offset']),
|
offset=int(search_opts['offset']),
|
||||||
@ -340,19 +367,27 @@ class ShareSnapshotAPITest(test.TestCase):
|
|||||||
search_opts=search_opts_expected,
|
search_opts=search_opts_expected,
|
||||||
)
|
)
|
||||||
self.assertEqual(1, len(result['snapshots']))
|
self.assertEqual(1, len(result['snapshots']))
|
||||||
self.assertEqual(snapshots[0]['id'], result['snapshots'][0]['id'])
|
self.assertEqual(db_snapshots[1]['id'], result['snapshots'][0]['id'])
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
snapshots[0]['display_name'], result['snapshots'][0]['name'])
|
db_snapshots[1]['display_name'], result['snapshots'][0]['name'])
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
snapshots[0]['aggregate_status'], result['snapshots'][0]['status'])
|
db_snapshots[1]['aggregate_status'],
|
||||||
|
result['snapshots'][0]['status'])
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
snapshots[0]['share_id'], result['snapshots'][0]['share_id'])
|
db_snapshots[1]['share_id'], result['snapshots'][0]['share_id'])
|
||||||
|
if (api_version.APIVersionRequest(version) >=
|
||||||
|
api_version.APIVersionRequest('2.79')):
|
||||||
|
self.assertEqual(1, result['count'])
|
||||||
|
|
||||||
def test_snapshot_list_detail_with_search_opts_by_non_admin(self):
|
@ddt.data({'version': '2.78', 'use_admin_context': True},
|
||||||
self._snapshot_list_detail_with_search_opts(use_admin_context=False)
|
{'version': '2.78', 'use_admin_context': False},
|
||||||
|
{'version': '2.79', 'use_admin_context': True},
|
||||||
def test_snapshot_list_detail_with_search_opts_by_admin(self):
|
{'version': '2.79', 'use_admin_context': False})
|
||||||
self._snapshot_list_detail_with_search_opts(use_admin_context=True)
|
@ddt.unpack
|
||||||
|
def test_snapshot_list_detail_with_search_opts(self, version,
|
||||||
|
use_admin_context):
|
||||||
|
self._snapshot_list_detail_with_search_opts(
|
||||||
|
version=version, use_admin_context=use_admin_context)
|
||||||
|
|
||||||
@ddt.data('2.0', '2.16', '2.17')
|
@ddt.data('2.0', '2.16', '2.17')
|
||||||
def test_snapshot_list_detail(self, version):
|
def test_snapshot_list_detail(self, version):
|
||||||
|
@ -1732,6 +1732,42 @@ class ShareSnapshotDatabaseAPITestCase(test.TestCase):
|
|||||||
self.assertEqual(1, len(actual_result.instances))
|
self.assertEqual(1, len(actual_result.instances))
|
||||||
self.assertSubDictMatch(values, actual_result.to_dict())
|
self.assertSubDictMatch(values, actual_result.to_dict())
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
({'with_count': True}, 3, 3),
|
||||||
|
({'with_count': True, 'limit': 2}, 3, 2)
|
||||||
|
)
|
||||||
|
@ddt.unpack
|
||||||
|
def test_share_snapshot_get_all_with_count(self, filters,
|
||||||
|
amount_of_share_snapshots,
|
||||||
|
expected_share_snapshots_len):
|
||||||
|
share = db_utils.create_share(size=1)
|
||||||
|
values = {
|
||||||
|
'share_id': share['id'],
|
||||||
|
'size': share['size'],
|
||||||
|
'user_id': share['user_id'],
|
||||||
|
'project_id': share['project_id'],
|
||||||
|
'status': constants.STATUS_CREATING,
|
||||||
|
'progress': '0%',
|
||||||
|
'share_size': share['size'],
|
||||||
|
'display_description': 'fake_count_test',
|
||||||
|
'share_proto': share['share_proto'],
|
||||||
|
}
|
||||||
|
|
||||||
|
# consider only shares created in this function
|
||||||
|
filters.update({'share_id': share['id']})
|
||||||
|
|
||||||
|
for i in range(amount_of_share_snapshots):
|
||||||
|
tmp_values = copy.deepcopy(values)
|
||||||
|
tmp_values['display_name'] = 'fake_name_%s' % str(i)
|
||||||
|
db_api.share_snapshot_create(self.ctxt, tmp_values)
|
||||||
|
|
||||||
|
limit = filters.get('limit')
|
||||||
|
count, share_snapshots = db_api.share_snapshot_get_all_with_count(
|
||||||
|
self.ctxt, filters=filters, limit=limit)
|
||||||
|
|
||||||
|
self.assertEqual(count, amount_of_share_snapshots)
|
||||||
|
self.assertEqual(expected_share_snapshots_len, len(share_snapshots))
|
||||||
|
|
||||||
def test_share_snapshot_get_all_with_filters_some(self):
|
def test_share_snapshot_get_all_with_filters_some(self):
|
||||||
expected_status = constants.STATUS_AVAILABLE
|
expected_status = constants.STATUS_AVAILABLE
|
||||||
filters = {
|
filters = {
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Added total count info in Manila's /snapshots and /snapshots/detail APIs.
|
Loading…
Reference in New Issue
Block a user