Merge "Ignore cinder notifications if the Storage model is empty" into stable/2025.2

This commit is contained in:
Zuul
2026-01-29 23:18:30 +00:00
committed by Gerrit Code Review
3 changed files with 171 additions and 0 deletions

View File

@@ -258,6 +258,10 @@ class CapacityNotificationEndpoint(CinderNotification):
publisher=publisher_id,
metadata=metadata))
LOG.debug(payload)
if not self.cluster_data_model:
LOG.debug('Storage CDM has not yet been built; ignoring '
'notifications until an audit is performed.')
return
name = payload['name_to_id']
try:
pool = self.get_or_create_pool(name)
@@ -289,6 +293,10 @@ class VolumeCreateEnd(VolumeNotificationEndpoint):
publisher=publisher_id,
metadata=metadata))
LOG.debug(payload)
if not self.cluster_data_model:
LOG.debug('Storage CDM has not yet been built; ignoring '
'notifications until an audit is performed.')
return
volume_id = payload['volume_id']
poolname = payload['host']
volume = self.get_or_create_volume(volume_id, poolname)
@@ -314,6 +322,10 @@ class VolumeUpdateEnd(VolumeNotificationEndpoint):
publisher=publisher_id,
metadata=metadata))
LOG.debug(payload)
if not self.cluster_data_model:
LOG.debug('Storage CDM has not yet been built; ignoring '
'notifications until an audit is performed.')
return
volume_id = payload['volume_id']
poolname = payload['host']
volume = self.get_or_create_volume(volume_id, poolname)
@@ -372,6 +384,10 @@ class VolumeDeleteEnd(VolumeNotificationEndpoint):
publisher=publisher_id,
metadata=metadata))
LOG.debug(payload)
if not self.cluster_data_model:
LOG.debug('Storage CDM has not yet been built; ignoring '
'notifications until an audit is performed.')
return
volume_id = payload['volume_id']
poolname = payload['host']
volume = self.get_or_create_volume(volume_id, poolname)

View File

@@ -365,3 +365,21 @@ class FakerBaremetalModelCollector(base.BaseClusterDataModelCollector):
def generate_scenario_1(self):
return self.load_model('ironic_scenario_1.xml')
class FakerEmptyModelCollector(base.BaseClusterDataModelCollector):
def __init__(self, config=None, osc=None):
if config is None:
config = mock.Mock(period=777)
super(FakerEmptyModelCollector, self).__init__(config)
@property
def notification_endpoints(self):
return []
def get_audit_scope_handler(self, audit_scope):
return None
def execute(self):
return None

View File

@@ -605,3 +605,140 @@ class TestCinderNotifications(NotificationTestCase):
self.assertEqual(460, pool_0.free_capacity_gb)
self.assertEqual(40, pool_0.allocated_capacity_gb)
self.assertEqual(40, pool_0.provisioned_capacity_gb)
class TestCinderNotificationsEmptyModel(NotificationTestCase):
FAKE_METADATA = {'message_id': None, 'timestamp': None}
def setUp(self):
super(TestCinderNotificationsEmptyModel, self).setUp()
self.fake_cdmc = faker_cluster_state.FakerEmptyModelCollector()
@mock.patch.object(cnotification.CapacityNotificationEndpoint,
'update_pool')
def test_cinder_capacity_empty_model(self, m_update_pool):
"""test consuming capacity"""
handler = cnotification.CapacityNotificationEndpoint(self.fake_cdmc)
message = self.load_message('scenario_1_capacity.json')
handler.info(
ctxt=self.context,
publisher_id=message['publisher_id'],
event_type=message['event_type'],
payload=message['payload'],
metadata=self.FAKE_METADATA,
)
m_update_pool.assert_not_called()
@mock.patch.object(cnotification.VolumeCreateEnd, 'update_volume')
@mock.patch.object(cinder_helper, 'CinderHelper')
def test_cinder_volume_create_empty_model(self, m_update_volume,
m_cinder_helper):
"""test creating volume in existing pool and node"""
# create storage_pool_by_name mock
return_pool_mock = mock.Mock()
return_pool_mock.configure_mock(
name='host_0@backend_0#pool_0',
total_volumes='3',
total_capacity_gb='500',
free_capacity_gb='380',
provisioned_capacity_gb='120',
allocated_capacity_gb='120')
m_get_storage_pool_by_name = mock.Mock(
side_effect=lambda name: return_pool_mock)
m_cinder_helper.return_value = mock.Mock(
get_storage_pool_by_name=m_get_storage_pool_by_name)
handler = cnotification.VolumeCreateEnd(self.fake_cdmc)
message = self.load_message('scenario_1_volume-create.json')
handler.info(
ctxt=self.context,
publisher_id=message['publisher_id'],
event_type=message['event_type'],
payload=message['payload'],
metadata=self.FAKE_METADATA,
)
# check that create_volume is not called
m_cinder_helper.assert_not_called()
m_update_volume.assert_not_called()
@mock.patch.object(cnotification.VolumeUpdateEnd, 'update_volume')
@mock.patch.object(cinder_helper, 'CinderHelper')
def test_cinder_volume_update_empty_model(self, m_update_volume,
m_cinder_helper):
"""test updating volume in existing pool and node"""
handler = cnotification.VolumeUpdateEnd(self.fake_cdmc)
# create storage_pool_by name mock
return_pool_mock = mock.Mock()
return_pool_mock.configure_mock(
name='host_0@backend_0#pool_0',
total_volumes='2',
total_capacity_gb='500',
free_capacity_gb='420',
provisioned_capacity_gb='80',
allocated_capacity_gb='80')
m_get_storage_pool_by_name = mock.Mock(
side_effect=lambda name: return_pool_mock)
m_cinder_helper.return_value = mock.Mock(
get_storage_pool_by_name=m_get_storage_pool_by_name)
message = self.load_message('scenario_1_volume-update.json')
handler.info(
ctxt=self.context,
publisher_id=message['publisher_id'],
event_type=message['event_type'],
payload=message['payload'],
metadata=self.FAKE_METADATA,
)
# check that update_volume is not called
m_cinder_helper.assert_not_called()
m_update_volume.assert_not_called()
@mock.patch.object(cinder_helper, 'CinderHelper')
@mock.patch.object(cnotification.VolumeDeleteEnd, 'delete_volume')
def test_cinder_volume_delete_empty_model(self, m_delete_volume,
m_cinder_helper):
"""test deleting volume when model is empty"""
# create storage_pool_by name mock
return_pool_mock = mock.Mock()
return_pool_mock.configure_mock(
name='host_0@backend_0#pool_0',
total_volumes='1',
total_capacity_gb='500',
free_capacity_gb='460',
provisioned_capacity_gb='40',
allocated_capacity_gb='40')
m_get_storage_pool_by_name = mock.Mock(
side_effect=lambda name: return_pool_mock)
m_cinder_helper.return_value = mock.Mock(
get_storage_pool_by_name=m_get_storage_pool_by_name)
handler = cnotification.VolumeDeleteEnd(self.fake_cdmc)
message = self.load_message('scenario_1_volume-delete.json')
handler.info(
ctxt=self.context,
publisher_id=message['publisher_id'],
event_type=message['event_type'],
payload=message['payload'],
metadata=self.FAKE_METADATA,
)
# check that delete_volume is not called
m_cinder_helper.assert_not_called()
m_delete_volume.assert_not_called()