From 360474974dd07fe01264a2e4240fe1fc442eab47 Mon Sep 17 00:00:00 2001 From: Jan Provaznik Date: Wed, 29 Mar 2017 13:15:09 +0000 Subject: [PATCH] Extend usage of user messages Instead of creating a user message only from scheduler during resource creation, a message is created directly by share manager which allows more detailed error reporting. Partially-implements: blueprint user-messages Change-Id: Ic7d25a144905a39c56ababe8bd666b01bc0d0aef --- manila/message/message_field.py | 45 +++++++-- manila/scheduler/manager.py | 23 ++++- manila/share/manager.py | 151 ++++++++++++++++++++++++++--- manila/tests/share/test_manager.py | 116 +++++++++++++++++++++- 4 files changed, 312 insertions(+), 23 deletions(-) diff --git a/manila/message/message_field.py b/manila/message/message_field.py index 8e3cd8ab..a415babb 100644 --- a/manila/message/message_field.py +++ b/manila/message/message_field.py @@ -16,24 +16,57 @@ from manila.i18n import _ class Resource(object): SHARE = 'SHARE' + SHARE_GROUP = 'SHARE_GROUP' + SHARE_REPLICA = 'SHARE_REPLICA' + SHARE_SNAPSHOT = 'SHARE_SNAPSHOT' class Action(object): ALLOCATE_HOST = ('001', _('allocate host')) - - ALL = (ALLOCATE_HOST,) + CREATE = ('002', _('create')) + DELETE_ACCESS_RULES = ('003', _('delete access rules')) + PROMOTE = ('004', _('promote')) + UPDATE = ('005', _('update')) + REVERT_TO_SNAPSHOT = ('006', _('revert to snapshot')) + DELETE = ('007', _('delete')) + ALL = (ALLOCATE_HOST, + CREATE, + DELETE_ACCESS_RULES, + PROMOTE, + UPDATE, + REVERT_TO_SNAPSHOT, + DELETE) class Detail(object): UNKNOWN_ERROR = ('001', _('An unknown error occurred.')) - NO_VALID_HOST = ('002', _("No storage could be allocated for this share " - "request. Trying again with a different size " - "or share type may succeed.")) + NO_VALID_HOST = ( + '002', _("No storage could be allocated for this share request. " + "Trying again with a different size or share type may " + "succeed.")) + UNEXPECTED_NETWORK = ( + '003', _("Driver does not expect share-network to be provided with " + "current configuration.")) + NO_SHARE_SERVER = ( + '004', _("Could not find an existing share server or allocate one on " + "the share network provided. You may use a different share " + "network, or verify the network details in the share network " + "and retry your request. If this doesn't work, contact your " + "administrator to troubleshoot issues with your network.")) + NO_ACTIVE_AVAILABLE_REPLICA = ( + '005', _("An 'active' replica must exist in 'available' state to " + "create a new replica for share.")) + NO_ACTIVE_REPLICA = ( + '006', _("Share has no replica with 'replica_state' set to 'active'.")) ALL = (UNKNOWN_ERROR, - NO_VALID_HOST) + NO_VALID_HOST, + UNEXPECTED_NETWORK, + NO_SHARE_SERVER, + NO_ACTIVE_AVAILABLE_REPLICA, + NO_ACTIVE_REPLICA,) # Exception and detail mappings EXCEPTION_DETAIL_MAPPINGS = { diff --git a/manila/scheduler/manager.py b/manila/scheduler/manager.py index 0c4f6c6c..f6cfeb17 100644 --- a/manila/scheduler/manager.py +++ b/manila/scheduler/manager.py @@ -221,7 +221,8 @@ class SchedulerManager(manager.Manager): def request_service_capabilities(self, context): share_rpcapi.ShareAPI().publish_service_capabilities(context) - def _set_share_group_error_state(self, method, context, ex, request_spec): + def _set_share_group_error_state(self, method, context, ex, + request_spec, action=None): LOG.warning("Failed to schedule_%(method)s: %(ex)s", {"method": method, "ex": ex}) @@ -232,6 +233,12 @@ class SchedulerManager(manager.Manager): if share_group_id: db.share_group_update(context, share_group_id, share_group_state) + if action: + self.message_api.create( + context, action, context.project_id, + resource_type=message_field.Resource.SHARE_GROUP, + resource_id=share_group_id, exception=ex) + @periodic_task.periodic_task(spacing=600, run_immediately=True) def _expire_reservations(self, context): quota.QUOTAS.expire(context) @@ -243,14 +250,15 @@ class SchedulerManager(manager.Manager): context, share_group_id, request_spec, filter_properties) except exception.NoValidHost as ex: self._set_share_group_error_state( - 'create_share_group', context, ex, request_spec) + 'create_share_group', context, ex, request_spec, + message_field.Action.ALLOCATE_HOST) except Exception as ex: with excutils.save_and_reraise_exception(): self._set_share_group_error_state( 'create_share_group', context, ex, request_spec) def _set_share_replica_error_state(self, context, method, exc, - request_spec): + request_spec, action=None): LOG.warning("Failed to schedule_%(method)s: %(exc)s", {'method': method, 'exc': exc}) @@ -271,6 +279,12 @@ class SchedulerManager(manager.Manager): db.share_replica_update(context, share_replica_id, status_updates) + if action: + self.message_api.create( + context, action, context.project_id, + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=share_replica_id, exception=exc) + def create_share_replica(self, context, request_spec=None, filter_properties=None): try: @@ -279,7 +293,8 @@ class SchedulerManager(manager.Manager): except exception.NoValidHost as exc: self._set_share_replica_error_state( - context, 'create_share_replica', exc, request_spec) + context, 'create_share_replica', exc, request_spec, + message_field.Action.ALLOCATE_HOST) except Exception as exc: with excutils.save_and_reraise_exception(): diff --git a/manila/share/manager.py b/manila/share/manager.py index ec6e47bc..3b1b213b 100644 --- a/manila/share/manager.py +++ b/manila/share/manager.py @@ -40,6 +40,8 @@ from manila.data import rpcapi as data_rpcapi from manila import exception from manila.i18n import _ from manila import manager +from manila.message import api as message_api +from manila.message import message_field from manila import quota from manila.share import access from manila.share import api @@ -227,6 +229,7 @@ class ShareManager(manager.SchedulerDependentManager): self.migration_wait_access_rules_timeout = ( CONF.migration_wait_access_rules_timeout) + self.message_api = message_api.API() self.hooks = [] self._init_hook_drivers() @@ -423,7 +426,6 @@ class ShareManager(manager.SchedulerDependentManager): def error(msg, *args): LOG.error(msg, *args) - self.db.share_instance_update(context, share_instance['id'], {'status': constants.STATUS_ERROR}) @@ -1566,6 +1568,13 @@ class ShareManager(manager.SchedulerDependentManager): if share_network_id and not self.driver.driver_handles_share_servers: self.db.share_instance_update( context, share_instance_id, {'status': constants.STATUS_ERROR}) + self.message_api.create( + context, + message_field.Action.CREATE, + share['project_id'], + resource_type=message_field.Resource.SHARE, + resource_id=share_id, + detail=message_field.Detail.UNEXPECTED_NETWORK) raise exception.ManilaException(_( "Creation of share instance %s failed: driver does not expect " "share-network to be provided with current " @@ -1602,6 +1611,14 @@ class ShareManager(manager.SchedulerDependentManager): context, share_instance_id, {'status': constants.STATUS_ERROR} ) + self.message_api.create( + context, + message_field.Action.CREATE, + share['project_id'], + resource_type=message_field.Resource.SHARE, + resource_id=share_id, + detail=message_field.Detail.NO_SHARE_SERVER) + else: share_server = None @@ -1643,6 +1660,13 @@ class ShareManager(manager.SchedulerDependentManager): context, share_instance_id, {'status': constants.STATUS_ERROR} ) + self.message_api.create( + context, + message_field.Action.CREATE, + share['project_id'], + resource_type=message_field.Resource.SHARE, + resource_id=share_id, + exception=e) else: LOG.info("Share instance %s created successfully.", share_instance_id) @@ -1726,6 +1750,13 @@ class ShareManager(manager.SchedulerDependentManager): context, share_replica['id'], {'status': constants.STATUS_ERROR, 'replica_state': constants.STATUS_ERROR}) + self.message_api.create( + context, + message_field.Action.CREATE, + share_replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=share_replica['id'], + detail=message_field.Detail.NO_ACTIVE_REPLICA) msg = _("An 'active' replica must exist in 'available' " "state to create a new replica for share %s.") raise exception.ReplicationException( @@ -1741,6 +1772,13 @@ class ShareManager(manager.SchedulerDependentManager): context, share_replica['id'], {'status': constants.STATUS_ERROR, 'replica_state': constants.STATUS_ERROR}) + self.message_api.create( + context, + message_field.Action.CREATE, + share_replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=share_replica['id'], + detail=message_field.Detail.UNEXPECTED_NETWORK) raise exception.InvalidDriverMode( "Driver does not expect share-network to be provided " "with current configuration.") @@ -1759,6 +1797,13 @@ class ShareManager(manager.SchedulerDependentManager): context, share_replica['id'], {'status': constants.STATUS_ERROR, 'replica_state': constants.STATUS_ERROR}) + self.message_api.create( + context, + message_field.Action.CREATE, + share_replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=share_replica['id'], + detail=message_field.Detail.NO_SHARE_SERVER) else: share_server = None @@ -1794,7 +1839,7 @@ class ShareManager(manager.SchedulerDependentManager): share_access_rules, available_share_snapshots, share_server=share_server) or {} - except Exception: + except Exception as excep: with excutils.save_and_reraise_exception(): LOG.error("Share replica %s failed on creation.", share_replica['id']) @@ -1804,6 +1849,13 @@ class ShareManager(manager.SchedulerDependentManager): 'replica_state': constants.STATUS_ERROR}) self._update_share_replica_access_rules_state( context, share_replica['id'], constants.STATUS_ERROR) + self.message_api.create( + context, + message_field.Action.CREATE, + share_replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=share_replica['id'], + exception=excep) if replica_ref.get('export_locations'): if isinstance(replica_ref.get('export_locations'), list): @@ -1871,13 +1923,20 @@ class ShareManager(manager.SchedulerDependentManager): delete_all_rules=True, share_server=share_server ) - except Exception: + except Exception as excep: with excutils.save_and_reraise_exception() as exc_context: # Set status to 'error' from 'deleting' since # access_rules_status has been set to 'error'. self.db.share_replica_update( context, share_replica['id'], {'status': constants.STATUS_ERROR}) + self.message_api.create( + context, + message_field.Action.DELETE_ACCESS_RULES, + share_replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=share_replica['id'], + exception=excep) if force: msg = _("The driver was unable to delete access rules " "for the replica: %s. Will attempt to delete " @@ -1889,7 +1948,7 @@ class ShareManager(manager.SchedulerDependentManager): self.driver.delete_replica( context, replica_list, replica_snapshots, share_replica, share_server=share_server) - except Exception: + except Exception as excep: with excutils.save_and_reraise_exception() as exc_context: if force: msg = _("The driver was unable to delete the share " @@ -1904,6 +1963,13 @@ class ShareManager(manager.SchedulerDependentManager): context, share_replica['id'], {'status': constants.STATUS_ERROR_DELETING, 'replica_state': constants.STATUS_ERROR}) + self.message_api.create( + context, + message_field.Action.DELETE, + share_replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=share_replica['id'], + exception=excep) for replica_snapshot in replica_snapshots: self.db.share_snapshot_instance_delete( @@ -1948,6 +2014,13 @@ class ShareManager(manager.SchedulerDependentManager): msg = _("Share %(share)s has no replica with 'replica_state' " "set to %(state)s. Promoting %(replica)s is not " "possible.") + self.message_api.create( + context, + message_field.Action.PROMOTE, + share_replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=share_replica['id'], + detail=message_field.Detail.NO_ACTIVE_REPLICA) raise exception.ReplicationException( reason=msg % {'share': share_replica['share_id'], 'state': constants.REPLICA_STATE_ACTIVE, @@ -1966,7 +2039,7 @@ class ShareManager(manager.SchedulerDependentManager): context, replica_list, share_replica, access_rules, share_server=share_server) ) - except Exception: + except Exception as excep: with excutils.save_and_reraise_exception(): # (NOTE) gouthamr: If the driver throws an exception at # this stage, there is a good chance that the replicas are @@ -1981,6 +2054,13 @@ class ShareManager(manager.SchedulerDependentManager): for replica_ref in replica_list: self.db.share_replica_update( context, replica_ref['id'], updates) + self.message_api.create( + context, + message_field.Action.PROMOTE, + replica_ref['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=replica_ref['id'], + exception=excep) # Set any 'creating' snapshots on the currently active replica to # 'error' since we cannot guarantee they will finish 'creating'. @@ -2145,7 +2225,7 @@ class ShareManager(manager.SchedulerDependentManager): replica_state = self.driver.update_replica_state( context, replica_list, share_replica, access_rules, available_share_snapshots, share_server=share_server) - except Exception: + except Exception as excep: msg = ("Driver error when updating replica " "state for replica %s.") LOG.exception(msg, share_replica['id']) @@ -2153,6 +2233,13 @@ class ShareManager(manager.SchedulerDependentManager): context, share_replica['id'], {'replica_state': constants.STATUS_ERROR, 'status': constants.STATUS_ERROR}) + self.message_api.create( + context, + message_field.Action.UPDATE, + share_replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=share_replica['id'], + exception=excep) return if replica_state in (constants.REPLICA_STATE_IN_SYNC, @@ -2510,7 +2597,7 @@ class ShareManager(manager.SchedulerDependentManager): snapshot_instance_dict, access_rules, share_server=share_server) - except Exception: + except Exception as excep: with excutils.save_and_reraise_exception(): msg = ('Share %(share)s could not be reverted ' @@ -2529,6 +2616,13 @@ class ShareManager(manager.SchedulerDependentManager): self.db.share_snapshot_update( context, snapshot_id, {'status': constants.STATUS_AVAILABLE}) + self.message_api.create( + context, + message_field.Action.REVERT_TO_SNAPSHOT, + share['project_id'], + resource_type=message_field.Resource.SHARE, + resource_id=share_id, + exception=excep) if reservations: QUOTAS.commit( @@ -2568,7 +2662,7 @@ class ShareManager(manager.SchedulerDependentManager): except exception.ShareResourceNotFound: LOG.warning("Share instance %s does not exist in the " "backend.", share_instance_id) - except Exception: + except Exception as excep: with excutils.save_and_reraise_exception() as exc_context: if force: msg = ("The driver was unable to delete access rules " @@ -2581,6 +2675,13 @@ class ShareManager(manager.SchedulerDependentManager): context, share_instance_id, {'status': constants.STATUS_ERROR_DELETING}) + self.message_api.create( + context, + message_field.Action.DELETE_ACCESS_RULES, + share_instance['project_id'], + resource_type=message_field.Resource.SHARE, + resource_id=share_instance_id, + exception=excep) try: self.driver.delete_share(context, share_instance, @@ -2588,7 +2689,7 @@ class ShareManager(manager.SchedulerDependentManager): except exception.ShareResourceNotFound: LOG.warning("Share instance %s does not exist in the " "backend.", share_instance_id) - except Exception: + except Exception as excep: with excutils.save_and_reraise_exception() as exc_context: if force: msg = ("The driver was unable to delete the share " @@ -2603,6 +2704,13 @@ class ShareManager(manager.SchedulerDependentManager): context, share_instance_id, {'status': constants.STATUS_ERROR_DELETING}) + self.message_api.create( + context, + message_field.Action.DELETE, + share_instance['project_id'], + resource_type=message_field.Resource.SHARE, + resource_id=share_instance_id, + exception=excep) self.db.share_instance_delete(context, share_instance_id) LOG.info("Share instance %s: deleted successfully.", @@ -2658,12 +2766,19 @@ class ShareManager(manager.SchedulerDependentManager): model_update = self.driver.create_snapshot( context, snapshot_instance, share_server=share_server) or {} - except Exception: + except Exception as excep: with excutils.save_and_reraise_exception(): self.db.share_snapshot_instance_update( context, snapshot_instance_id, {'status': constants.STATUS_ERROR}) + self.message_api.create( + context, + message_field.Action.CREATE, + snapshot_ref['project_id'], + resource_type=message_field.Resource.SHARE_SNAPSHOT, + resource_id=snapshot_instance_id, + exception=excep) snapshot_export_locations = model_update.pop('export_locations', []) @@ -2725,7 +2840,7 @@ class ShareManager(manager.SchedulerDependentManager): try: self.driver.delete_snapshot(context, snapshot_instance, share_server=share_server) - except Exception: + except Exception as excep: with excutils.save_and_reraise_exception() as exc: if force: msg = _("The driver was unable to delete the " @@ -2740,6 +2855,13 @@ class ShareManager(manager.SchedulerDependentManager): context, snapshot_instance_id, {'status': constants.STATUS_ERROR_DELETING}) + self.message_api.create( + context, + message_field.Action.DELETE, + snapshot_ref['project_id'], + resource_type=message_field.Resource.SHARE_SNAPSHOT, + resource_id=snapshot_instance_id, + exception=excep) self.db.share_snapshot_instance_delete(context, snapshot_instance_id) @@ -3514,6 +3636,13 @@ class ShareManager(manager.SchedulerDependentManager): self.db.share_group_update( context, share_group_id, {'status': constants.STATUS_ERROR}) + self.message_api.create( + context, + message_field.Action.CREATE, + share_group_ref['project_id'], + resource_type=message_field.Resource.SHARE_GROUP, + resource_id=share_group_id, + detail=message_field.Detail.NO_SHARE_SERVER) try: # TODO(ameade): Add notification for create.start diff --git a/manila/tests/share/test_manager.py b/manila/tests/share/test_manager.py index 1ade84b0..fa3c6e95 100644 --- a/manila/tests/share/test_manager.py +++ b/manila/tests/share/test_manager.py @@ -32,6 +32,7 @@ from manila.data import rpcapi as data_rpc from manila import db from manila.db.sqlalchemy import models from manila import exception +from manila.message import message_field from manila import quota from manila.share import api from manila.share import drivers_private_data @@ -96,6 +97,7 @@ class ShareManagerTestCase(test.TestCase): self.share_manager.driver._stats = { 'share_group_stats': {'consistent_snapshot_support': None}, } + self.mock_object(self.share_manager.message_api, 'create') self.context = context.get_admin_context() self.share_manager.driver.initialized = True mock.patch.object( @@ -584,6 +586,13 @@ class ShareManagerTestCase(test.TestCase): mock.ANY, replica['id'], {'status': constants.STATUS_ERROR, 'replica_state': constants.STATUS_ERROR}) self.assertFalse(mock_driver_replica_call.called) + self.share_manager.message_api.create.assert_called_once_with( + utils.IsAMatcher(context.RequestContext), + message_field.Action.CREATE, + replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=replica['id'], + detail=message_field.Detail.NO_ACTIVE_REPLICA) def test_create_share_replica_with_share_network_id_and_not_dhss(self): replica = fake_replica() @@ -605,6 +614,13 @@ class ShareManagerTestCase(test.TestCase): mock.ANY, replica['id'], {'status': constants.STATUS_ERROR, 'replica_state': constants.STATUS_ERROR}) self.assertFalse(mock_driver_replica_call.called) + self.share_manager.message_api.create.assert_called_once_with( + utils.IsAMatcher(context.RequestContext), + message_field.Action.CREATE, + replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=replica['id'], + detail=message_field.Detail.UNEXPECTED_NETWORK) def test_create_share_replica_with_share_server_exception(self): replica = fake_replica() @@ -626,6 +642,13 @@ class ShareManagerTestCase(test.TestCase): mock.ANY, replica['id'], {'status': constants.STATUS_ERROR, 'replica_state': constants.STATUS_ERROR}) self.assertFalse(mock_driver_replica_call.called) + self.share_manager.message_api.create.assert_called_once_with( + utils.IsAMatcher(context.RequestContext), + message_field.Action.CREATE, + replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=replica['id'], + detail=message_field.Detail.NO_SHARE_SERVER) def test_create_share_replica_driver_error_on_creation(self): fake_access_rules = [{'id': '1'}, {'id': '2'}, {'id': '3'}] @@ -676,6 +699,13 @@ class ShareManagerTestCase(test.TestCase): self.assertTrue(mock_log_error.called) self.assertFalse(mock_log_info.called) self.assertTrue(driver_call.called) + self.share_manager.message_api.create.assert_called_once_with( + utils.IsAMatcher(context.RequestContext), + message_field.Action.CREATE, + replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=replica['id'], + exception=mock.ANY) def test_create_share_replica_invalid_locations_state(self): driver_retval = { @@ -896,6 +926,13 @@ class ShareManagerTestCase(test.TestCase): self.assertFalse(mock_drv_delete_replica_call.called) self.assertFalse(mock_replica_delete_call.called) self.assertFalse(mock_exception_log.called) + self.share_manager.message_api.create.assert_called_once_with( + utils.IsAMatcher(context.RequestContext), + message_field.Action.DELETE_ACCESS_RULES, + replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=replica['id'], + exception=mock.ANY) def test_delete_share_replica_drv_misbehavior_ignored_with_the_force(self): replica = fake_replica() @@ -1097,6 +1134,18 @@ class ShareManagerTestCase(test.TestCase): mock_replica_update.assert_has_calls(expected_update_calls) self.assertFalse(mock_info_log.called) + expected_message_calls = [ + mock.call( + utils.IsAMatcher(context.RequestContext), + message_field.Action.PROMOTE, + r['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=r['id'], + exception=mock.ANY) + for r in (replica, active_replica)] + self.share_manager.message_api.create.assert_has_calls( + expected_message_calls) + @ddt.data([], None) def test_promote_share_replica_driver_update_nothing_has_snaps(self, retval): @@ -1288,6 +1337,13 @@ class ShareManagerTestCase(test.TestCase): 'status': constants.STATUS_ERROR} ) self.assertEqual(1, mock_debug_log.call_count) + self.share_manager.message_api.create.assert_called_once_with( + utils.IsAMatcher(context.RequestContext), + message_field.Action.UPDATE, + replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=replica['id'], + exception=mock.ANY) def test__share_replica_update_driver_exception_ignored(self): mock_debug_log = self.mock_object(manager.LOG, 'debug') @@ -1314,6 +1370,13 @@ class ShareManagerTestCase(test.TestCase): 'status': constants.STATUS_ERROR} ) self.assertEqual(1, mock_debug_log.call_count) + self.share_manager.message_api.create.assert_called_once_with( + utils.IsAMatcher(context.RequestContext), + message_field.Action.UPDATE, + replica['project_id'], + resource_type=message_field.Resource.SHARE_REPLICA, + resource_id=replica['id'], + exception=mock.ANY) @ddt.data({'status': constants.STATUS_AVAILABLE, 'replica_state': constants.REPLICA_STATE_ACTIVE, }, @@ -1487,6 +1550,13 @@ class ShareManagerTestCase(test.TestCase): self.share_manager.driver.create_snapshot.assert_called_once_with( self.context, expected_snapshot_instance_dict, share_server=None) + self.share_manager.message_api.create.assert_called_once_with( + utils.IsAMatcher(context.RequestContext), + message_field.Action.CREATE, + snapshot['project_id'], + resource_type=message_field.Resource.SHARE_SNAPSHOT, + resource_id=snapshot_instance['id'], + exception=mock.ANY) @ddt.data({'model_update': {}, 'mount_snapshot_support': True}, {'model_update': {}, 'mount_snapshot_support': False}, @@ -1601,6 +1671,13 @@ class ShareManagerTestCase(test.TestCase): snapshot_instance['id'], delete_all_rules=True, share_server=None) self.assertFalse(db_destroy_call.called) self.assertFalse(mock_exception_log.called) + self.share_manager.message_api.create.assert_called_once_with( + utils.IsAMatcher(context.RequestContext), + message_field.Action.DELETE, + snapshot['project_id'], + resource_type=message_field.Resource.SHARE_SNAPSHOT, + resource_id=snapshot_instance['id'], + exception=mock.ANY) @ddt.data(True, False) def test_delete_snapshot_with_quota_error(self, quota_error): @@ -1695,6 +1772,13 @@ class ShareManagerTestCase(test.TestCase): mock.ANY, snapshot_instance['id']) self.assertFalse(quota_commit_call.called) self.assertFalse(db_update_call.called) + self.share_manager.message_api.create.assert_called_once_with( + utils.IsAMatcher(context.RequestContext), + message_field.Action.DELETE, + snapshot['project_id'], + resource_type=message_field.Resource.SHARE_SNAPSHOT, + resource_id=snapshot_instance['id'], + exception=mock.ANY) def test_create_share_instance_with_share_network_dhss_false(self): manager.CONF.set_default('driver_handles_share_servers', False) @@ -1702,8 +1786,8 @@ class ShareManagerTestCase(test.TestCase): self.share_manager.driver.configuration, 'safe_get', mock.Mock(return_value=False)) share_network_id = 'fake_sn' - share_instance = db_utils.create_share( - share_network_id=share_network_id).instance + share = db_utils.create_share(share_network_id=share_network_id) + share_instance = share.instance self.mock_object( self.share_manager.db, 'share_instance_get', mock.Mock(return_value=share_instance)) @@ -1722,6 +1806,13 @@ class ShareManagerTestCase(test.TestCase): self.share_manager.db.share_instance_update.assert_called_once_with( utils.IsAMatcher(context.RequestContext), share_instance['id'], {'status': constants.STATUS_ERROR}) + self.share_manager.message_api.create.assert_called_once_with( + utils.IsAMatcher(context.RequestContext), + message_field.Action.CREATE, + six.text_type(share.project_id), + resource_type=message_field.Resource.SHARE, + resource_id=share['id'], + detail=mock.ANY) def test_create_share_instance_with_share_network_server_not_exists(self): """Test share can be created without share server.""" @@ -1800,6 +1891,13 @@ class ShareManagerTestCase(test.TestCase): metadata={'request_host': 'fake_host'}) manager.LOG.error.assert_called_with(mock.ANY, fake_share.instance['id']) + self.share_manager.message_api.create.assert_called_once_with( + utils.IsAMatcher(context.RequestContext), + message_field.Action.CREATE, + six.text_type(fake_share.project_id), + resource_type=message_field.Resource.SHARE, + resource_id=fake_share['id'], + detail=message_field.Detail.NO_SHARE_SERVER) def test_create_share_instance_with_share_network_not_found(self): """Test creation fails if share network not found.""" @@ -1817,6 +1915,13 @@ class ShareManagerTestCase(test.TestCase): manager.LOG.error.assert_called_with(mock.ANY, share.instance['id']) shr = db.share_get(self.context, share_id) self.assertEqual(constants.STATUS_ERROR, shr['status']) + self.share_manager.message_api.create.assert_called_once_with( + utils.IsAMatcher(context.RequestContext), + message_field.Action.CREATE, + six.text_type(shr.project_id), + resource_type=message_field.Resource.SHARE, + resource_id=shr['id'], + detail=message_field.Detail.NO_SHARE_SERVER) def test_create_share_instance_with_share_network_server_exists(self): """Test share can be created with existing share server.""" @@ -1865,6 +1970,13 @@ class ShareManagerTestCase(test.TestCase): self.assertTrue(self.share_manager.driver.create_share.called) shr = db.share_get(self.context, share_id) self.assertEqual(some_data, shr['export_location']) + self.share_manager.message_api.create.assert_called_once_with( + utils.IsAMatcher(context.RequestContext), + message_field.Action.CREATE, + six.text_type(share.project_id), + resource_type=message_field.Resource.SHARE, + resource_id=share['id'], + exception=mock.ANY) def test_create_share_instance_with_server_created(self): """Test share can be created and share server is created."""