diff --git a/api-ref/source/v3/ext-backups.inc b/api-ref/source/v3/ext-backups.inc index 41b2b5f1eea..be003de743d 100644 --- a/api-ref/source/v3/ext-backups.inc +++ b/api-ref/source/v3/ext-backups.inc @@ -97,6 +97,7 @@ Response Parameters - os-backup-project-attr:project_id: os-backup-project-attr:project_id - count: count - metadata: metadata_backup + - user_id: user_id_backup Response Example ---------------- @@ -155,6 +156,7 @@ Response Parameters - snapshot_id: snapshot_id_source_vol - os-backup-project-attr:project_id: os-backup-project-attr:project_id - metadata: metadata_backup + - user_id: user_id_backup Response Example ---------------- diff --git a/api-ref/source/v3/parameters.yaml b/api-ref/source/v3/parameters.yaml index 54d051122a3..7288b757714 100644 --- a/api-ref/source/v3/parameters.yaml +++ b/api-ref/source/v3/parameters.yaml @@ -2766,6 +2766,13 @@ user_id: in: body required: true type: string +user_id_backup: + description: | + The UUID of the project owner. + in: body + required: true + type: string + min_version: 3.56 user_id_min: description: | The UUID of the user. diff --git a/api-ref/source/v3/samples/backup-show-response.json b/api-ref/source/v3/samples/backup-show-response.json index 8b112f51171..e400ada9b9c 100644 --- a/api-ref/source/v3/samples/backup-show-response.json +++ b/api-ref/source/v3/samples/backup-show-response.json @@ -19,6 +19,7 @@ "name": "backup001", "object_count": 22, "os-backup-project-attr:project_id": "2c67a14be9314c5dae2ee6c4ec90cf0b", + "user_id": "515ba0dd59f84f25a6a084a45d8d93b2", "size": 1, "updated_at": "2013-04-20T05:30:19.000000", "data_timestamp": "2013-04-20T05:30:19.000000", diff --git a/api-ref/source/v3/samples/backups-list-detailed-response.json b/api-ref/source/v3/samples/backups-list-detailed-response.json index 6cf72cf9e51..16acc8d8329 100644 --- a/api-ref/source/v3/samples/backups-list-detailed-response.json +++ b/api-ref/source/v3/samples/backups-list-detailed-response.json @@ -20,6 +20,7 @@ "name": "backup001", "object_count": 22, "os-backup-project-attr:project_id": "2c67a14be9314c5dae2ee6c4ec90cf0b", + "user_id": "515ba0dd59f84f25a6a084a45d8d93b2", "size": 1, "status": "available", "updated_at": "2013-04-02T10:35:27.000000", @@ -49,6 +50,7 @@ "name": "backup002", "object_count": 22, "os-backup-project-attr:project_id": "2c67a14be9314c5dae2ee6c4ec90cf0b", + "user_id": "515ba0dd59f84f25a6a084a45d8d93b2", "size": 1, "status": "available", "updated_at": "2013-04-02T10:21:48.000000", diff --git a/cinder/api/microversions.py b/cinder/api/microversions.py index 620aa9f7ee3..bdbf0966166 100644 --- a/cinder/api/microversions.py +++ b/cinder/api/microversions.py @@ -151,6 +151,8 @@ ATTACHMENT_CREATE_MODE_ARG = '3.54' TRANSFER_WITH_SNAPSHOTS = '3.55' +BACKUP_PROJECT_USER_ID = '3.56' + 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 a72111fb16f..05abf4160f3 100644 --- a/cinder/api/openstack/api_version_request.py +++ b/cinder/api/openstack/api_version_request.py @@ -127,6 +127,8 @@ REST_API_VERSION_HISTORY = """ Also, additional parameters will not be allowed. * 3.54 - Add ``mode`` argument to attachment-create. * 3.55 - Support transfer volume with snapshots + * 3.56 - Add ``user_id`` attribute to response body of list backup with + detail and show backup detail APIs. """ # The minimum and maximum versions of the API supported @@ -134,7 +136,7 @@ REST_API_VERSION_HISTORY = """ # minimum version of the API supported. # Explicitly using /v2 endpoints will still work _MIN_API_VERSION = "3.0" -_MAX_API_VERSION = "3.55" +_MAX_API_VERSION = "3.56" _LEGACY_API_VERSION2 = "2.0" UPDATED = "2018-07-17T00:00:00Z" diff --git a/cinder/api/openstack/rest_api_version_history.rst b/cinder/api/openstack/rest_api_version_history.rst index 237f4adde2e..a4fa8a5b2ee 100644 --- a/cinder/api/openstack/rest_api_version_history.rst +++ b/cinder/api/openstack/rest_api_version_history.rst @@ -441,3 +441,8 @@ Add ``mode`` argument to attachment-create. 3.55 (Maximum in Rocky) ----------------------- Support ability to transfer snapshots along with their parent volume. + +3.56 +---- +Add ``user_id`` attribute to response body of list backup with detail and show +backup detail APIs. diff --git a/cinder/api/v3/backups.py b/cinder/api/v3/backups.py index e31d0c3ac62..83dc713f2e7 100644 --- a/cinder/api/v3/backups.py +++ b/cinder/api/v3/backups.py @@ -65,6 +65,11 @@ class BackupsController(backups_v2.BackupsController): key = "os-backup-project-attr:project_id" backup[key] = db_backup['project_id'] + def _add_backup_user_attribute(self, req, backup): + db_backup = req.get_db_backup(backup['id']) + key = "user_id" + backup[key] = db_backup['user_id'] + def show(self, req, id): """Return data about the given backup.""" LOG.debug('Show backup with id %s.', id) @@ -79,6 +84,10 @@ class BackupsController(backups_v2.BackupsController): if req_version.matches(mv.BACKUP_PROJECT): if context.authorize(policy.BACKUP_ATTRIBUTES_POLICY, fatal=False): self._add_backup_project_attribute(req, resp_backup['backup']) + + if req_version.matches(mv.BACKUP_PROJECT_USER_ID): + if context.authorize(policy.BACKUP_ATTRIBUTES_POLICY, fatal=False): + self._add_backup_user_attribute(req, resp_backup['backup']) return resp_backup def detail(self, req): @@ -90,6 +99,11 @@ class BackupsController(backups_v2.BackupsController): if context.authorize(policy.BACKUP_ATTRIBUTES_POLICY, fatal=False): for bak in resp_backup['backups']: self._add_backup_project_attribute(req, bak) + + if req_version.matches(mv.BACKUP_PROJECT_USER_ID): + if context.authorize(policy.BACKUP_ATTRIBUTES_POLICY, fatal=False): + for bak in resp_backup['backups']: + self._add_backup_user_attribute(req, bak) return resp_backup def _convert_sort_name(self, req_version, sort_keys): diff --git a/cinder/tests/unit/api/contrib/test_backup_project_attribute.py b/cinder/tests/unit/api/contrib/test_backup_project_attribute.py index e48295c5e45..b3c1974a0b3 100644 --- a/cinder/tests/unit/api/contrib/test_backup_project_attribute.py +++ b/cinder/tests/unit/api/contrib/test_backup_project_attribute.py @@ -33,6 +33,7 @@ def fake_backup_get(*args, **kwargs): bak = { 'id': fake.BACKUP_ID, 'project_id': fake.PROJECT_ID, + 'user_id': fake.USER_ID, } return fake_backup.fake_backup_obj(ctx, **bak) @@ -101,3 +102,30 @@ class BackupProjectAttributeTest(test.TestCase): bak = self._send_backup_request( ctx, version=mv.get_prior_version(mv.BACKUP_PROJECT)) self.assertNotIn('os-backup-project-attr:project_id', bak) + + @ddt.data(True, False) + def test_get_backup_with_user_id(self, is_admin): + ctx = context.RequestContext(fake.USER_ID, fake.PROJECT_ID, is_admin) + bak = self._send_backup_request(ctx, + version=mv.BACKUP_PROJECT_USER_ID) + if is_admin: + self.assertEqual(fake.USER_ID, bak['user_id']) + else: + self.assertNotIn('user_id', bak) + + @ddt.data(True, False) + def test_list_detail_backups_with_user_id(self, is_admin): + ctx = context.RequestContext(fake.USER_ID, fake.PROJECT_ID, is_admin) + baks = self._send_backup_request(ctx, detail=True, + version=mv.BACKUP_PROJECT_USER_ID) + if is_admin: + self.assertEqual(fake.USER_ID, + baks[0]['user_id']) + else: + self.assertNotIn('user_id', baks[0]) + + def test_get_backup_user_id_before_microversion_v356(self): + ctx = context.RequestContext(fake.USER_ID, fake.PROJECT_ID, True) + bak = self._send_backup_request( + ctx, version=mv.get_prior_version(mv.BACKUP_PROJECT_USER_ID)) + self.assertNotIn('user_id', bak) diff --git a/cinder/tests/unit/backup/fake_backup.py b/cinder/tests/unit/backup/fake_backup.py index 41379095c30..314b95b4712 100644 --- a/cinder/tests/unit/backup/fake_backup.py +++ b/cinder/tests/unit/backup/fake_backup.py @@ -34,6 +34,10 @@ def fake_db_backup(**updates): 'service': 'fake_service', 'object_count': 5, 'num_dependent_backups': 0, + 'backup_metadata': [ + {'key': 'key1', 'value': 'value1'}, + {'key': 'key2', 'value': 'value2'} + ], } for name, field in objects.Backup.fields.items(): @@ -54,4 +58,5 @@ def fake_db_backup(**updates): def fake_backup_obj(context, **updates): return objects.Backup._from_db_object(context, objects.Backup(), - fake_db_backup(**updates)) + fake_db_backup(**updates), + expected_attrs=['metadata']) diff --git a/releasenotes/notes/add-user-id-attribute-to-backup-response-ce27364680c895f7.yaml b/releasenotes/notes/add-user-id-attribute-to-backup-response-ce27364680c895f7.yaml new file mode 100644 index 00000000000..12c90b8a6a1 --- /dev/null +++ b/releasenotes/notes/add-user-id-attribute-to-backup-response-ce27364680c895f7.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Add ``user_id`` attribute to response body of list backup with detail + and show backup detail APIs.