Add request_ids attribute to resource objects

Added request_ids attribute to resource object for all the
volume_backups, volume_encryption_types and volume_transfers
APIs by updating following APIs:

volume_backups: reset_state, delete, export_record, import_record
volume_transfers: delete
volume_encryption_types: list

Returning list with request_ids as attribute in case of 'list' API
for volume_encryption_types.

These changes are required to return 'request_id' from client to log
request_id mappings of cross projects.

For more details on how request_id will be returned to the caller,
please refer to the approved blueprint [1] discussed with the
cross-project team.
[1] http://specs.openstack.org/openstack/openstack-specs/specs/return-request-id.html

DocImpact
'request-ids' will be returned as an attribute with response object.
User can access it using 'res.request_ids' where 'res' is a
response object.

Change-Id: I2197ca38f6c9a8b0ced5c82d29676b49c9700b09
Partial-Implements: blueprint return-request-id-to-caller
This commit is contained in:
Ankit Agrawal 2015-12-13 23:48:33 -08:00
parent b2fc77f731
commit c49fce3909
6 changed files with 72 additions and 35 deletions

View File

@ -24,23 +24,27 @@ cs = fakes.FakeClient()
class VolumeBackupsTest(utils.TestCase):
def test_create(self):
cs.backups.create('2b695faf-b963-40c8-8464-274008fbcef4')
vol = cs.backups.create('2b695faf-b963-40c8-8464-274008fbcef4')
cs.assert_called('POST', '/backups')
self._assert_request_id(vol)
def test_create_full(self):
cs.backups.create('2b695faf-b963-40c8-8464-274008fbcef4',
None, None, False)
vol = cs.backups.create('2b695faf-b963-40c8-8464-274008fbcef4',
None, None, False)
cs.assert_called('POST', '/backups')
self._assert_request_id(vol)
def test_create_incremental(self):
cs.backups.create('2b695faf-b963-40c8-8464-274008fbcef4',
None, None, True)
vol = cs.backups.create('2b695faf-b963-40c8-8464-274008fbcef4',
None, None, True)
cs.assert_called('POST', '/backups')
self._assert_request_id(vol)
def test_create_force(self):
cs.backups.create('2b695faf-b963-40c8-8464-274008fbcef4',
None, None, False, True)
vol = cs.backups.create('2b695faf-b963-40c8-8464-274008fbcef4',
None, None, False, True)
cs.assert_called('POST', '/backups')
self._assert_request_id(vol)
def test_create_snapshot(self):
cs.backups.create('2b695faf-b963-40c8-8464-274008fbcef4',
@ -50,32 +54,39 @@ class VolumeBackupsTest(utils.TestCase):
def test_get(self):
backup_id = '76a17945-3c6f-435c-975b-b5685db10b62'
cs.backups.get(backup_id)
back = cs.backups.get(backup_id)
cs.assert_called('GET', '/backups/%s' % backup_id)
self._assert_request_id(back)
def test_list(self):
cs.backups.list()
lst = cs.backups.list()
cs.assert_called('GET', '/backups/detail')
self._assert_request_id(lst)
def test_list_with_pagination(self):
cs.backups.list(limit=2, marker=100)
lst = cs.backups.list(limit=2, marker=100)
cs.assert_called('GET', '/backups/detail?limit=2&marker=100')
self._assert_request_id(lst)
def test_sorted_list(self):
cs.backups.list(sort="id")
lst = cs.backups.list(sort="id")
cs.assert_called('GET', '/backups/detail?sort=id')
self._assert_request_id(lst)
def test_delete(self):
b = cs.backups.list()[0]
b.delete()
del_back = b.delete()
cs.assert_called('DELETE',
'/backups/76a17945-3c6f-435c-975b-b5685db10b62')
cs.backups.delete('76a17945-3c6f-435c-975b-b5685db10b62')
self._assert_request_id(del_back)
del_back = cs.backups.delete('76a17945-3c6f-435c-975b-b5685db10b62')
cs.assert_called('DELETE',
'/backups/76a17945-3c6f-435c-975b-b5685db10b62')
cs.backups.delete(b)
self._assert_request_id(del_back)
del_back = cs.backups.delete(b)
cs.assert_called('DELETE',
'/backups/76a17945-3c6f-435c-975b-b5685db10b62')
self._assert_request_id(del_back)
def test_restore(self):
backup_id = '76a17945-3c6f-435c-975b-b5685db10b62'
@ -83,28 +94,34 @@ class VolumeBackupsTest(utils.TestCase):
cs.assert_called('POST', '/backups/%s/restore' % backup_id)
self.assertIsInstance(info,
volume_backups_restore.VolumeBackupsRestore)
self._assert_request_id(info)
def test_reset_state(self):
b = cs.backups.list()[0]
api = '/backups/76a17945-3c6f-435c-975b-b5685db10b62/action'
b.reset_state(state='error')
st = b.reset_state(state='error')
cs.assert_called('POST', api)
cs.backups.reset_state('76a17945-3c6f-435c-975b-b5685db10b62',
state='error')
self._assert_request_id(st)
st = cs.backups.reset_state('76a17945-3c6f-435c-975b-b5685db10b62',
state='error')
cs.assert_called('POST', api)
cs.backups.reset_state(b, state='error')
self._assert_request_id(st)
st = cs.backups.reset_state(b, state='error')
cs.assert_called('POST', api)
self._assert_request_id(st)
def test_record_export(self):
backup_id = '76a17945-3c6f-435c-975b-b5685db10b62'
cs.backups.export_record(backup_id)
export = cs.backups.export_record(backup_id)
cs.assert_called('GET',
'/backups/%s/export_record' % backup_id)
self._assert_request_id(export)
def test_record_import(self):
backup_service = 'fake-backup-service'
backup_url = 'fake-backup-url'
expected_body = {'backup-record': {'backup_service': backup_service,
'backup_url': backup_url}}
cs.backups.import_record(backup_service, backup_url)
impt = cs.backups.import_record(backup_service, backup_url)
cs.assert_called('POST', '/backups/import_record', expected_body)
self._assert_request_id(impt)

View File

@ -41,6 +41,7 @@ class VolumeEncryptionTypesTest(utils.TestCase):
cs.assert_called_anytime('GET', '/types/1/encryption')
for encryption_type in encryption_types:
self.assertIsInstance(encryption_type, VolumeEncryptionType)
self._assert_request_id(encryption_type)
def test_get(self):
"""
@ -53,6 +54,7 @@ class VolumeEncryptionTypesTest(utils.TestCase):
encryption_type = cs.volume_encryption_types.get(1)
cs.assert_called('GET', '/types/1/encryption')
self.assertIsInstance(encryption_type, VolumeEncryptionType)
self._assert_request_id(encryption_type)
def test_get_no_encryption(self):
"""
@ -65,6 +67,7 @@ class VolumeEncryptionTypesTest(utils.TestCase):
self.assertIsInstance(encryption_type, VolumeEncryptionType)
self.assertFalse(hasattr(encryption_type, 'id'),
'encryption type has an id')
self._assert_request_id(encryption_type)
def test_create(self):
"""
@ -80,6 +83,7 @@ class VolumeEncryptionTypesTest(utils.TestCase):
None})
cs.assert_called('POST', '/types/2/encryption')
self.assertIsInstance(result, VolumeEncryptionType)
self._assert_request_id(result)
def test_update(self):
"""
@ -96,6 +100,7 @@ class VolumeEncryptionTypesTest(utils.TestCase):
cs.assert_called('PUT', '/types/1/encryption/provider')
self.assertEqual(expected, result,
"empty update must yield original data")
self._assert_request_id(result)
def test_delete(self):
"""
@ -108,3 +113,4 @@ class VolumeEncryptionTypesTest(utils.TestCase):
cs.assert_called('DELETE', '/types/1/encryption/provider')
self.assertIsInstance(result, tuple)
self.assertEqual(202, result[0].status_code)
self._assert_request_id(result)

View File

@ -14,7 +14,7 @@
# under the License.
from cinderclient.tests.unit import utils
from cinderclient.tests.unit.v1 import fakes
from cinderclient.tests.unit.v2 import fakes
cs = fakes.FakeClient()
@ -23,29 +23,36 @@ cs = fakes.FakeClient()
class VolumeTransfersTest(utils.TestCase):
def test_create(self):
cs.transfers.create('1234')
vol = cs.transfers.create('1234')
cs.assert_called('POST', '/os-volume-transfer')
self._assert_request_id(vol)
def test_get(self):
transfer_id = '5678'
cs.transfers.get(transfer_id)
vol = cs.transfers.get(transfer_id)
cs.assert_called('GET', '/os-volume-transfer/%s' % transfer_id)
self._assert_request_id(vol)
def test_list(self):
cs.transfers.list()
lst = cs.transfers.list()
cs.assert_called('GET', '/os-volume-transfer/detail')
self._assert_request_id(lst)
def test_delete(self):
b = cs.transfers.list()[0]
b.delete()
vol = b.delete()
cs.assert_called('DELETE', '/os-volume-transfer/5678')
cs.transfers.delete('5678')
self._assert_request_id(vol)
vol = cs.transfers.delete('5678')
self._assert_request_id(vol)
cs.assert_called('DELETE', '/os-volume-transfer/5678')
cs.transfers.delete(b)
vol = cs.transfers.delete(b)
cs.assert_called('DELETE', '/os-volume-transfer/5678')
self._assert_request_id(vol)
def test_accept(self):
transfer_id = '5678'
auth_key = '12345'
cs.transfers.accept(transfer_id, auth_key)
vol = cs.transfers.accept(transfer_id, auth_key)
cs.assert_called('POST', '/os-volume-transfer/%s/accept' % transfer_id)
self._assert_request_id(vol)

View File

@ -17,6 +17,7 @@
Volume Backups interface (1.1 extension).
"""
from cinderclient import base
from cinderclient.openstack.common.apiclient import base as common_base
class VolumeBackup(base.Resource):
@ -30,7 +31,7 @@ class VolumeBackup(base.Resource):
return self.manager.delete(self)
def reset_state(self, state):
self.manager.reset_state(self, state)
return self.manager.reset_state(self, state)
class VolumeBackupManager(base.ManagerWithFind):
@ -85,7 +86,7 @@ class VolumeBackupManager(base.ManagerWithFind):
:param backup: The :class:`VolumeBackup` to delete.
"""
self._delete("/backups/%s" % base.getid(backup))
return self._delete("/backups/%s" % base.getid(backup))
def reset_state(self, backup, state):
"""Update the specified volume backup with the provided state."""
@ -96,7 +97,8 @@ class VolumeBackupManager(base.ManagerWithFind):
body = {action: info}
self.run_hooks('modify_body_for_action', body, **kwargs)
url = '/backups/%s/action' % base.getid(backup)
return self.api.client.post(url, body=body)
resp, body = self.api.client.post(url, body=body)
return common_base.TupleWithMeta((resp, body), resp)
def export_record(self, backup_id):
"""Export volume backup metadata record.
@ -106,7 +108,7 @@ class VolumeBackupManager(base.ManagerWithFind):
"""
resp, body = \
self.api.client.get("/backups/%s/export_record" % backup_id)
return body['backup-record']
return common_base.DictWithMeta(body['backup-record'], resp)
def import_record(self, backup_service, backup_url):
"""Export volume backup metadata record.
@ -119,4 +121,4 @@ class VolumeBackupManager(base.ManagerWithFind):
'backup_url': backup_url}}
self.run_hooks('modify_body_for_update', body, 'backup-record')
resp, body = self.api.client.post("/backups/import_record", body=body)
return body['backup']
return common_base.DictWithMeta(body['backup'], resp)

View File

@ -19,6 +19,7 @@ Volume Encryption Type interface
"""
from cinderclient import base
from cinderclient.openstack.common.apiclient import base as common_base
class VolumeEncryptionType(base.Resource):
@ -47,12 +48,16 @@ class VolumeEncryptionTypeManager(base.ManagerWithFind):
# all encryption types without going through all volume types.
volume_types = self.api.volume_types.list()
encryption_types = []
list_of_resp = []
for volume_type in volume_types:
encryption_type = self._get("/types/%s/encryption"
% base.getid(volume_type))
if hasattr(encryption_type, 'volume_type_id'):
encryption_types.append(encryption_type)
return encryption_types
list_of_resp.extend(encryption_type.request_ids)
return common_base.ListWithMeta(encryption_types, list_of_resp)
def get(self, volume_type):
"""

View File

@ -98,4 +98,4 @@ class VolumeTransferManager(base.ManagerWithFind):
:param transfer_id: The :class:`VolumeTransfer` to delete.
"""
self._delete("/os-volume-transfer/%s" % base.getid(transfer_id))
return self._delete("/os-volume-transfer/%s" % base.getid(transfer_id))