From 63aebb5dea06acbd54814287da70eabc4c7f065b Mon Sep 17 00:00:00 2001 From: "zhu.boxiang" Date: Fri, 26 Jul 2019 14:41:41 +0800 Subject: [PATCH] Fix issue of getting detail backups list info osapi_max_limit: The maximum number of items that a collection resource returns in a single response. If we have more than osapi_max_limit and want to list detail backups info, we will generate the next link, we must set detail for the url. Change-Id: I9499fcefd236e1fa0c7c980d3e40265a9a118bb3 Close-Bug: 1837967 --- cinder/api/views/backups.py | 8 ++-- cinder/tests/unit/api/contrib/test_backups.py | 39 +++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/cinder/api/views/backups.py b/cinder/api/views/backups.py index b69a1479714..a27f860d52d 100644 --- a/cinder/api/views/backups.py +++ b/cinder/api/views/backups.py @@ -31,7 +31,8 @@ class ViewBuilder(common.ViewBuilder): def detail_list(self, request, backups, backup_count=None): """Detailed view of a list of backups .""" - return self._list_view(self.detail, request, backups, backup_count) + return self._list_view(self.detail, request, backups, backup_count, + self._collection_name + '/detail') def summary(self, request, backup): """Generic, non-detailed view of a backup.""" @@ -80,12 +81,13 @@ class ViewBuilder(common.ViewBuilder): return backup_dict - def _list_view(self, func, request, backups, backup_count): + def _list_view(self, func, request, backups, backup_count, + coll_name=_collection_name): """Provide a view for a list of backups.""" backups_list = [func(request, backup)['backup'] for backup in backups] backups_links = self._get_collection_links(request, backups, - self._collection_name, + coll_name, backup_count) backups_dict = dict(backups=backups_list) diff --git a/cinder/tests/unit/api/contrib/test_backups.py b/cinder/tests/unit/api/contrib/test_backups.py index f43c5b2664e..97d3b29dd54 100644 --- a/cinder/tests/unit/api/contrib/test_backups.py +++ b/cinder/tests/unit/api/contrib/test_backups.py @@ -257,6 +257,45 @@ class BackupsAPITestCase(test.TestCase): backup2.destroy() backup1.destroy() + def test_list_all_backups_detail_json_over_limit(self): + self.override_config('osapi_max_limit', 2) + backup1 = utils.create_backup(self.context, availability_zone='az1', + container='volumebackups', size=1) + backup2 = utils.create_backup(self.context, availability_zone='az1', + container='volumebackups', size=1) + backup3 = utils.create_backup(self.context, availability_zone='az1', + container='volumebackups', size=1) + + req = webob.Request.blank('/v2/%s/backups/detail' % fake.PROJECT_ID) + req.method = 'GET' + req.headers['Content-Type'] = 'application/json' + req.headers['Accept'] = 'application/json' + res = req.get_response(fakes.wsgi_app( + fake_auth_context=self.user_context)) + res_dict = jsonutils.loads(res.body) + + self.assertEqual(http_client.OK, res.status_int) + self.assertEqual(NUM_ELEMENTS_IN_BACKUP, len(res_dict['backups'][0])) + self.assertEqual(NUM_ELEMENTS_IN_BACKUP, len(res_dict['backups'][1])) + self.assertEqual(2, len(res_dict['backups'])) + + self.assertIn('backups_links', res_dict) + links = res_dict['backups_links'] + next_url = links[0]['href'] + req = webob.Request.blank(next_url) + req.method = 'GET' + req.headers['Content-Type'] = 'application/json' + req.headers['Accept'] = 'application/json' + res = req.get_response(fakes.wsgi_app( + fake_auth_context=self.user_context)) + res_dict = jsonutils.loads(res.body) + + self.assertEqual(NUM_ELEMENTS_IN_BACKUP, len(res_dict['backups'][0])) + + backup3.destroy() + backup2.destroy() + backup1.destroy() + def test_list_backups_detail_json(self): backup1 = utils.create_backup(self.context, availability_zone='az1', container='volumebackups', size=1)