From 8446f245b5f0793dc7e37cf4f59a9119061a0a2c Mon Sep 17 00:00:00 2001 From: wanghao Date: Tue, 26 May 2015 15:32:42 +0800 Subject: [PATCH] Notify the transfer volume action in cinder Now when we transfer a volume, there is not corresponding action notification that is sent to ceilometer. Include the actions of create, accept and delete. The bp that this patch implements, proposes adding those action to enrich the notification in cinder. Notify is added in Create, Accept, and Delete actions. Change-Id: I9d71c55d103cc501f60585b64902d364af21d4d9 Implements: blueprint notify-the-transfer-volume-action-in-cinder --- cinder/tests/unit/test_volume_transfer.py | 39 +++++++++++++++++++++-- cinder/transfer/api.py | 13 ++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/cinder/tests/unit/test_volume_transfer.py b/cinder/tests/unit/test_volume_transfer.py index 524cb6ab0..cf45cb9ce 100644 --- a/cinder/tests/unit/test_volume_transfer.py +++ b/cinder/tests/unit/test_volume_transfer.py @@ -15,6 +15,7 @@ import datetime +import mock from oslo_log import log as logging from cinder import context @@ -36,7 +37,8 @@ class VolumeTransferTestCase(test.TestCase): project_id='project_id') self.updated_at = datetime.datetime(1, 1, 1, 1, 1, 1) - def test_transfer_volume_create_delete(self): + @mock.patch('cinder.volume.utils.notify_about_volume_usage') + def test_transfer_volume_create_delete(self, mock_notify): tx_api = transfer_api.API() utils.create_volume(self.ctxt, id='1', updated_at=self.updated_at) @@ -44,10 +46,18 @@ class VolumeTransferTestCase(test.TestCase): volume = db.volume_get(self.ctxt, '1') self.assertEqual('awaiting-transfer', volume['status'], 'Unexpected state') + calls = [mock.call(self.ctxt, mock.ANY, "transfer.create.start"), + mock.call(self.ctxt, mock.ANY, "transfer.create.end")] + mock_notify.assert_has_calls(calls) + self.assertEqual(2, mock_notify.call_count) tx_api.delete(self.ctxt, response['id']) volume = db.volume_get(self.ctxt, '1') self.assertEqual('available', volume['status'], 'Unexpected state') + calls = [mock.call(self.ctxt, mock.ANY, "transfer.delete.start"), + mock.call(self.ctxt, mock.ANY, "transfer.delete.end")] + mock_notify.assert_has_calls(calls) + self.assertEqual(4, mock_notify.call_count) def test_transfer_invalid_volume(self): tx_api = transfer_api.API() @@ -59,7 +69,8 @@ class VolumeTransferTestCase(test.TestCase): volume = db.volume_get(self.ctxt, '1') self.assertEqual('in-use', volume['status'], 'Unexpected state') - def test_transfer_accept(self): + @mock.patch('cinder.volume.utils.notify_about_volume_usage') + def test_transfer_accept(self, mock_notify): svc = self.start_service('volume', host='test_host') tx_api = transfer_api.API() utils.create_volume(self.ctxt, id='1', @@ -77,12 +88,23 @@ class VolumeTransferTestCase(test.TestCase): tx_api.accept, self.ctxt, transfer['id'], 'wrong') + calls = [mock.call(self.ctxt, mock.ANY, "transfer.create.start"), + mock.call(self.ctxt, mock.ANY, "transfer.create.end")] + mock_notify.assert_has_calls(calls) + self.assertEqual(2, mock_notify.call_count) + db.volume_update(self.ctxt, '1', {'status': 'wrong'}) self.assertRaises(exception.InvalidVolume, tx_api.accept, self.ctxt, transfer['id'], transfer['auth_key']) db.volume_update(self.ctxt, '1', {'status': 'awaiting-transfer'}) + # Because the InvalidVolume exception is raised in tx_api, so there is + # only transfer.accept.start called and missing transfer.accept.end. + calls = [mock.call(self.ctxt, mock.ANY, "transfer.accept.start")] + mock_notify.assert_has_calls(calls) + self.assertEqual(3, mock_notify.call_count) + self.ctxt.user_id = 'new_user_id' self.ctxt.project_id = 'new_project_id' response = tx_api.accept(self.ctxt, @@ -99,6 +121,11 @@ class VolumeTransferTestCase(test.TestCase): self.assertEqual(transfer['id'], response['id'], 'Unexpected transfer id in response.') + calls = [mock.call(self.ctxt, mock.ANY, "transfer.accept.start"), + mock.call(self.ctxt, mock.ANY, "transfer.accept.end")] + mock_notify.assert_has_calls(calls) + self.assertEqual(5, mock_notify.call_count) + svc.stop() def test_transfer_get(self): @@ -123,7 +150,8 @@ class VolumeTransferTestCase(test.TestCase): ts = tx_api.get_all(nctxt) self.assertEqual(len(ts), 0, 'Unexpected transfers listed.') - def test_delete_transfer_with_deleted_volume(self): + @mock.patch('cinder.volume.utils.notify_about_volume_usage') + def test_delete_transfer_with_deleted_volume(self, mock_notify): # create a volume volume = utils.create_volume(self.ctxt, id='1', updated_at=self.updated_at) @@ -132,6 +160,11 @@ class VolumeTransferTestCase(test.TestCase): transfer = tx_api.create(self.ctxt, volume['id'], 'Description') t = tx_api.get(self.ctxt, transfer['id']) self.assertEqual(t['id'], transfer['id'], 'Unexpected transfer id') + + calls = [mock.call(self.ctxt, mock.ANY, "transfer.create.start"), + mock.call(self.ctxt, mock.ANY, "transfer.create.end")] + mock_notify.assert_has_calls(calls) + self.assertEqual(2, mock_notify.call_count) # force delete volume db.volume_destroy(context.get_admin_context(), volume['id']) # Make sure transfer has been deleted. diff --git a/cinder/transfer/api.py b/cinder/transfer/api.py index 0ad3fccf3..e29dee773 100644 --- a/cinder/transfer/api.py +++ b/cinder/transfer/api.py @@ -31,6 +31,7 @@ from cinder import exception from cinder.i18n import _, _LE, _LI, _LW from cinder import quota from cinder.volume import api as volume_api +from cinder.volume import utils as volume_utils volume_transfer_opts = [ @@ -64,9 +65,13 @@ class API(base.Base): transfer = self.db.transfer_get(context, transfer_id) volume_ref = self.db.volume_get(context, transfer.volume_id) + volume_utils.notify_about_volume_usage(context, volume_ref, + "transfer.delete.start") if volume_ref['status'] != 'awaiting-transfer': LOG.error(_LE("Volume in unexpected state")) self.db.transfer_destroy(context, transfer_id) + volume_utils.notify_about_volume_usage(context, volume_ref, + "transfer.delete.end") def get_all(self, context, filters=None): filters = filters or {} @@ -105,6 +110,8 @@ class API(base.Base): if volume_ref['status'] != "available": raise exception.InvalidVolume(reason=_("status must be available")) + volume_utils.notify_about_volume_usage(context, volume_ref, + "transfer.create.start") # The salt is just a short random string. salt = self._get_random_string(CONF.volume_transfer_salt_length) auth_key = self._get_random_string(CONF.volume_transfer_key_length) @@ -123,6 +130,8 @@ class API(base.Base): LOG.error(_LE("Failed to create transfer record " "for %s"), volume_id) raise + volume_utils.notify_about_volume_usage(context, volume_ref, + "transfer.create.end") return {'id': transfer['id'], 'volume_id': transfer['volume_id'], 'display_name': transfer['display_name'], @@ -145,6 +154,8 @@ class API(base.Base): volume_id = transfer['volume_id'] vol_ref = self.db.volume_get(context.elevated(), volume_id) + volume_utils.notify_about_volume_usage(context, vol_ref, + "transfer.accept.start") try: reservations = QUOTAS.reserve(context, volumes=1, @@ -210,6 +221,8 @@ class API(base.Base): project_id=donor_id) vol_ref = self.db.volume_get(context, volume_id) + volume_utils.notify_about_volume_usage(context, vol_ref, + "transfer.accept.end") return {'id': transfer_id, 'display_name': transfer['display_name'], 'volume_id': vol_ref['id']} -- 2.45.2