Merge "Add create/delete/extend/shrink share notifications"

This commit is contained in:
Jenkins 2017-07-03 11:27:13 +00:00 committed by Gerrit Code Review
commit 0921ea5285
5 changed files with 179 additions and 6 deletions

View File

@ -1549,7 +1549,12 @@ class ShareManager(manager.SchedulerDependentManager):
context = context.elevated() context = context.elevated()
share_instance = self._get_share_instance(context, share_instance_id) share_instance = self._get_share_instance(context, share_instance_id)
share_network_id = share_instance.get('share_network_id', None) share_id = share_instance.get('share_id')
share_network_id = share_instance.get('share_network_id')
share = self.db.share_get(context, share_id)
self._notify_about_share_usage(context, share,
share_instance, "create.start")
if not share_instance['availability_zone']: if not share_instance['availability_zone']:
share_instance = self.db.share_instance_update( share_instance = self.db.share_instance_update(
@ -1641,7 +1646,6 @@ class ShareManager(manager.SchedulerDependentManager):
else: else:
LOG.info("Share instance %s created successfully.", LOG.info("Share instance %s created successfully.",
share_instance_id) share_instance_id)
share = self.db.share_get(context, share_instance['share_id'])
updates = { updates = {
'status': constants.STATUS_AVAILABLE, 'status': constants.STATUS_AVAILABLE,
'launched_at': timeutils.utcnow(), 'launched_at': timeutils.utcnow(),
@ -1651,6 +1655,9 @@ class ShareManager(manager.SchedulerDependentManager):
self.db.share_instance_update(context, share_instance_id, updates) self.db.share_instance_update(context, share_instance_id, updates)
self._notify_about_share_usage(context, share,
share_instance, "create.end")
def _update_share_replica_access_rules_state(self, context, def _update_share_replica_access_rules_state(self, context,
share_replica_id, state): share_replica_id, state):
"""Update the access_rules_status for the share replica.""" """Update the access_rules_status for the share replica."""
@ -2544,7 +2551,12 @@ class ShareManager(manager.SchedulerDependentManager):
"""Delete a share instance.""" """Delete a share instance."""
context = context.elevated() context = context.elevated()
share_instance = self._get_share_instance(context, share_instance_id) share_instance = self._get_share_instance(context, share_instance_id)
share_id = share_instance.get('share_id')
share_server = self._get_share_server(context, share_instance) share_server = self._get_share_server(context, share_instance)
share = self.db.share_get(context, share_id)
self._notify_about_share_usage(context, share,
share_instance, "delete.start")
try: try:
self.access_helper.update_access_rules( self.access_helper.update_access_rules(
@ -2598,6 +2610,9 @@ class ShareManager(manager.SchedulerDependentManager):
self._check_delete_share_server(context, share_instance) self._check_delete_share_server(context, share_instance)
self._notify_about_share_usage(context, share,
share_instance, "delete.end")
def _check_delete_share_server(self, context, share_instance): def _check_delete_share_server(self, context, share_instance):
if CONF.delete_share_server_with_last_share: if CONF.delete_share_server_with_last_share:
@ -3336,6 +3351,9 @@ class ShareManager(manager.SchedulerDependentManager):
project_id = share['project_id'] project_id = share['project_id']
user_id = share['user_id'] user_id = share['user_id']
self._notify_about_share_usage(context, share,
share_instance, "extend.start")
try: try:
self.driver.extend_share( self.driver.extend_share(
share_instance, new_size, share_server=share_server) share_instance, new_size, share_server=share_server)
@ -3369,6 +3387,9 @@ class ShareManager(manager.SchedulerDependentManager):
LOG.info("Extend share completed successfully.", resource=share) LOG.info("Extend share completed successfully.", resource=share)
self._notify_about_share_usage(context, share,
share_instance, "extend.end")
@add_hooks @add_hooks
@utils.require_driver_initialized @utils.require_driver_initialized
def shrink_share(self, context, share_id, new_size): def shrink_share(self, context, share_id, new_size):
@ -3380,6 +3401,9 @@ class ShareManager(manager.SchedulerDependentManager):
user_id = share['user_id'] user_id = share['user_id']
new_size = int(new_size) new_size = int(new_size)
self._notify_about_share_usage(context, share,
share_instance, "shrink.start")
def error_occurred(exc, msg, status=constants.STATUS_SHRINKING_ERROR): def error_occurred(exc, msg, status=constants.STATUS_SHRINKING_ERROR):
LOG.exception(msg, resource=share) LOG.exception(msg, resource=share)
self.db.share_update(context, share['id'], {'status': status}) self.db.share_update(context, share['id'], {'status': status})
@ -3433,6 +3457,9 @@ class ShareManager(manager.SchedulerDependentManager):
LOG.info("Shrink share completed successfully.", resource=share) LOG.info("Shrink share completed successfully.", resource=share)
self._notify_about_share_usage(context, share,
share_instance, "shrink.end")
@utils.require_driver_initialized @utils.require_driver_initialized
def create_share_group(self, context, share_group_id): def create_share_group(self, context, share_group_id):
context = context.elevated() context = context.elevated()
@ -3816,3 +3843,9 @@ class ShareManager(manager.SchedulerDependentManager):
self.snapshot_access_helper.update_access_rules( self.snapshot_access_helper.update_access_rules(
context, snapshot_instance['id'], share_server=share_server) context, snapshot_instance['id'], share_server=share_server)
def _notify_about_share_usage(self, context, share, share_instance,
event_suffix, extra_usage_info=None):
share_utils.notify_about_share_usage(
context, share, share_instance, event_suffix,
extra_usage_info=extra_usage_info, host=self.host)

View File

@ -16,10 +16,13 @@
"""Share-related Utilities and helpers.""" """Share-related Utilities and helpers."""
from manila.common import constants from oslo_config import cfg
from manila.common import constants
from manila import rpc
DEFAULT_POOL_NAME = '_pool0' DEFAULT_POOL_NAME = '_pool0'
CONF = cfg.CONF
def extract_host(host, level='backend', use_default_pool_name=False): def extract_host(host, level='backend', use_default_pool_name=False):
@ -104,3 +107,41 @@ def cast_access_object_to_dict_in_readonly(rules):
'access_to': rule['access_to'] 'access_to': rule['access_to']
}) })
return dict_rules return dict_rules
def notify_about_share_usage(context, share, share_instance,
event_suffix, extra_usage_info=None, host=None):
if not host:
host = CONF.host
if not extra_usage_info:
extra_usage_info = {}
usage_info = _usage_from_share(share, share_instance, **extra_usage_info)
rpc.get_notifier("share", host).info(context, 'share.%s' % event_suffix,
usage_info)
def _usage_from_share(share_ref, share_instance_ref, **extra_usage_info):
usage_info = {
'share_id': share_ref['id'],
'user_id': share_ref['user_id'],
'project_id': share_ref['project_id'],
'snapshot_id': share_ref['snapshot_id'],
'share_group_id': share_ref['share_group_id'],
'size': share_ref['size'],
'name': share_ref['display_name'],
'description': share_ref['display_description'],
'proto': share_ref['share_proto'],
'is_public': share_ref['is_public'],
'availability_zone': share_instance_ref['availability_zone'],
'host': share_instance_ref['host'],
'status': share_instance_ref['status'],
}
usage_info.update(extra_usage_info)
return usage_info

View File

@ -363,3 +363,13 @@ class TestCase(base_test.BaseTestCase):
def is_microversion_ge(self, left, right): def is_microversion_ge(self, left, right):
return (api_version.APIVersionRequest(left) >= return (api_version.APIVersionRequest(left) >=
api_version.APIVersionRequest(right)) api_version.APIVersionRequest(right))
def assert_notify_called(self, mock_notify, calls):
for i in range(0, len(calls)):
mock_call = mock_notify.call_args_list[i]
call = calls[i]
posargs = mock_call[0]
self.assertEqual(call[0], posargs[0])
self.assertEqual(call[1], posargs[2])

View File

@ -1933,6 +1933,29 @@ class ShareManagerTestCase(test.TestCase):
utils.IsAMatcher(context.RequestContext), fake_server, utils.IsAMatcher(context.RequestContext), fake_server,
metadata={'request_host': 'fake_host'}) metadata={'request_host': 'fake_host'})
@mock.patch('manila.tests.fake_notifier.FakeNotifier._notify')
def test_create_delete_share_instance(self, mock_notify):
"""Test share can be created and deleted."""
share = db_utils.create_share()
mock_notify.assert_not_called()
self.share_manager.create_share_instance(
self.context, share.instance['id'])
self.assert_notify_called(mock_notify,
(['INFO', 'share.create.start'],
['INFO', 'share.create.end']))
self.share_manager.delete_share_instance(
self.context, share.instance['id'])
self.assert_notify_called(mock_notify,
(['INFO', 'share.create.start'],
['INFO', 'share.create.end'],
['INFO', 'share.delete.start'],
['INFO', 'share.delete.end']))
@ddt.data(True, False) @ddt.data(True, False)
def test_create_delete_share_instance_error(self, exception_update_access): def test_create_delete_share_instance_error(self, exception_update_access):
"""Test share can be created and deleted with error.""" """Test share can be created and deleted with error."""
@ -2993,11 +3016,14 @@ class ShareManagerTestCase(test.TestCase):
'server1') 'server1')
timeutils.utcnow.assert_called_once_with() timeutils.utcnow.assert_called_once_with()
def test_extend_share_invalid(self): @mock.patch('manila.tests.fake_notifier.FakeNotifier._notify')
def test_extend_share_invalid(self, mock_notify):
share = db_utils.create_share() share = db_utils.create_share()
share_id = share['id'] share_id = share['id']
reservations = {} reservations = {}
mock_notify.assert_not_called()
self.mock_object(self.share_manager, 'driver') self.mock_object(self.share_manager, 'driver')
self.mock_object(self.share_manager.db, 'share_update') self.mock_object(self.share_manager.db, 'share_update')
self.mock_object(quota.QUOTAS, 'rollback') self.mock_object(quota.QUOTAS, 'rollback')
@ -3015,7 +3041,8 @@ class ShareManagerTestCase(test.TestCase):
user_id=six.text_type(share['user_id']) user_id=six.text_type(share['user_id'])
) )
def test_extend_share(self): @mock.patch('manila.tests.fake_notifier.FakeNotifier._notify')
def test_extend_share(self, mock_notify):
share = db_utils.create_share() share = db_utils.create_share()
share_id = share['id'] share_id = share['id']
new_size = 123 new_size = 123
@ -3026,6 +3053,8 @@ class ShareManagerTestCase(test.TestCase):
reservations = {} reservations = {}
fake_share_server = 'fake' fake_share_server = 'fake'
mock_notify.assert_not_called()
manager = self.share_manager manager = self.share_manager
self.mock_object(manager, 'driver') self.mock_object(manager, 'driver')
self.mock_object(manager.db, 'share_get', self.mock_object(manager.db, 'share_get',
@ -3052,6 +3081,10 @@ class ShareManagerTestCase(test.TestCase):
mock.ANY, share_id, shr_update mock.ANY, share_id, shr_update
) )
self.assert_notify_called(mock_notify,
(['INFO', 'share.extend.start'],
['INFO', 'share.extend.end']))
def test_shrink_share_quota_error(self): def test_shrink_share_quota_error(self):
size = 5 size = 5
new_size = 1 new_size = 1
@ -3115,7 +3148,8 @@ class ShareManagerTestCase(test.TestCase):
) )
self.assertTrue(self.share_manager.db.share_get.called) self.assertTrue(self.share_manager.db.share_get.called)
def test_shrink_share(self): @mock.patch('manila.tests.fake_notifier.FakeNotifier._notify')
def test_shrink_share(self, mock_notify):
share = db_utils.create_share() share = db_utils.create_share()
share_id = share['id'] share_id = share['id']
new_size = 123 new_size = 123
@ -3126,6 +3160,8 @@ class ShareManagerTestCase(test.TestCase):
fake_share_server = 'fake' fake_share_server = 'fake'
size_decrease = int(share['size']) - new_size size_decrease = int(share['size']) - new_size
mock_notify.assert_not_called()
manager = self.share_manager manager = self.share_manager
self.mock_object(manager, 'driver') self.mock_object(manager, 'driver')
self.mock_object(manager.db, 'share_get', self.mock_object(manager.db, 'share_get',
@ -3158,6 +3194,10 @@ class ShareManagerTestCase(test.TestCase):
mock.ANY, share_id, shr_update mock.ANY, share_id, shr_update
) )
self.assert_notify_called(mock_notify,
(['INFO', 'share.shrink.start'],
['INFO', 'share.shrink.end']))
def test_report_driver_status_driver_handles_ss_false(self): def test_report_driver_status_driver_handles_ss_false(self):
fake_stats = {'field': 'val'} fake_stats = {'field': 'val'}
fake_pool = {'name': 'pool1'} fake_pool = {'name': 'pool1'}

View File

@ -16,6 +16,8 @@
"""Tests For miscellaneous util methods used with share.""" """Tests For miscellaneous util methods used with share."""
import mock
from manila.common import constants from manila.common import constants
from manila.share import utils as share_utils from manila.share import utils as share_utils
from manila import test from manila import test
@ -159,3 +161,50 @@ class ShareUtilsTestCase(test.TestCase):
] ]
replica = share_utils.get_active_replica(replica_list) replica = share_utils.get_active_replica(replica_list)
self.assertIsNone(replica) self.assertIsNone(replica)
class NotifyUsageTestCase(test.TestCase):
@mock.patch('manila.share.utils._usage_from_share')
@mock.patch('manila.share.utils.CONF')
@mock.patch('manila.share.utils.rpc')
def test_notify_about_share_usage(self, mock_rpc, mock_conf, mock_usage):
mock_conf.host = 'host1'
output = share_utils.notify_about_share_usage(mock.sentinel.context,
mock.sentinel.share,
mock.sentinel.
share_instance,
'test_suffix')
self.assertIsNone(output)
mock_usage.assert_called_once_with(mock.sentinel.share,
mock.sentinel.share_instance)
mock_rpc.get_notifier.assert_called_once_with('share',
'host1')
mock_rpc.get_notifier.return_value.info.assert_called_once_with(
mock.sentinel.context,
'share.test_suffix',
mock_usage.return_value)
@mock.patch('manila.share.utils._usage_from_share')
@mock.patch('manila.share.utils.CONF')
@mock.patch('manila.share.utils.rpc')
def test_notify_about_share_usage_with_kwargs(self, mock_rpc, mock_conf,
mock_usage):
mock_conf.host = 'host1'
output = share_utils.notify_about_share_usage(mock.sentinel.context,
mock.sentinel.share,
mock.sentinel.
share_instance,
'test_suffix',
extra_usage_info={
'a': 'b', 'c': 'd'},
host='host2')
self.assertIsNone(output)
mock_usage.assert_called_once_with(mock.sentinel.share,
mock.sentinel.share_instance,
a='b', c='d')
mock_rpc.get_notifier.assert_called_once_with('share',
'host2')
mock_rpc.get_notifier.return_value.info.assert_called_once_with(
mock.sentinel.context,
'share.test_suffix',
mock_usage.return_value)