Port update will trigger less notifications to the DHCP agents
After port update, DHCP agent will be notified about changes only if one of the port's attributes related somehow to the DHCP will change. Such fields are: * fixed_ips, * MAC address, * dns_domain, * dns_name, * dns_assignment, * extra_dhcp_opts. In other cases there is no reason to send notifications to the agent. This will results with less notifications to the DHCP agent and less possibilities to race condition between DHCP and L2 agents while switching ports from the DOWN to ACTIVE status and sending notifications to nova. Closes-Bug: #1982367 Change-Id: If7990bdec435af76ad2e88fd4ea2bc24a255fd5a
This commit is contained in:
parent
c53a951450
commit
06ddcaf436
|
@ -298,26 +298,23 @@ class DhcpAgentNotifyAPI(object):
|
||||||
method_name = '.'.join((resource, action, 'end'))
|
method_name = '.'.join((resource, action, 'end'))
|
||||||
data = {resource: payload.latest_state}
|
data = {resource: payload.latest_state}
|
||||||
if resource == resources.PORT and event == events.AFTER_UPDATE:
|
if resource == resources.PORT and event == events.AFTER_UPDATE:
|
||||||
if self._only_status_changed(payload.states[0],
|
if not self._notification_is_needed(payload.states[0],
|
||||||
payload.latest_state):
|
payload.latest_state):
|
||||||
# don't waste time updating the DHCP agent for status updates
|
# don't waste time updating the DHCP agent for status updates
|
||||||
return
|
return
|
||||||
self.notify(payload.context, data, method_name)
|
self.notify(payload.context, data, method_name)
|
||||||
|
|
||||||
def _only_status_changed(self, orig, new):
|
def _notification_is_needed(self, orig, new):
|
||||||
# a status change will manifest as a bumped revision number, a new
|
# notification to the DHCP agent should be send only if DHCP related
|
||||||
# updated_at timestamp, and a new status. If that's all that changed,
|
# attributes of the port were changed, like: fixed_ips, mac_address,
|
||||||
# return True, else False
|
# extra_dhcp_opts, dns_name, dns_assignment or dns_domain.
|
||||||
|
# Otherwise there is no need to waste DHCP agent's time for doing
|
||||||
|
# updates.
|
||||||
if not orig or not new:
|
if not orig or not new:
|
||||||
return False
|
return True
|
||||||
if set(orig.keys()) != set(new.keys()):
|
return any(orig.get(k) != new.get(k) for k in (
|
||||||
return False
|
'fixed_ips', 'mac_address', 'extra_dhcp_opts',
|
||||||
for k in orig.keys():
|
'dns_name', 'dns_assignment', 'dns_domain'))
|
||||||
if k in ('status', 'updated_at', 'revision_number'):
|
|
||||||
continue
|
|
||||||
if orig[k] != new[k]:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _send_dhcp_notification(self, resource, event, trigger, payload=None):
|
def _send_dhcp_notification(self, resource, event, trigger, payload=None):
|
||||||
action = payload.action.split('_')[0]
|
action = payload.action.split('_')[0]
|
||||||
|
|
|
@ -284,17 +284,41 @@ class TestDhcpAgentNotifyAPI(base.BaseTestCase):
|
||||||
payload=events.DBEventPayload(mock.Mock()))
|
payload=events.DBEventPayload(mock.Mock()))
|
||||||
self.assertEqual([res], self.notifier._unsubscribed_resources)
|
self.assertEqual([res], self.notifier._unsubscribed_resources)
|
||||||
|
|
||||||
def test__only_status_changed(self):
|
def test__notification_is_needed(self):
|
||||||
p1 = {'id': 1, 'status': 'DOWN', 'updated_at': '10:00:00',
|
p1 = {'id': 1, 'status': 'DOWN', 'updated_at': '10:00:00',
|
||||||
'revision_number': 1}
|
'revision_number': 1,
|
||||||
|
'fixed_ips': [{'ip_address': '10.0.0.10', 'subnet_id': 'aaa'}],
|
||||||
|
'mac_address': 'aa:bb:cc:dd:ee:ff'}
|
||||||
p2 = dict(p1)
|
p2 = dict(p1)
|
||||||
p2['status'] = 'ACTIVE'
|
p2['status'] = 'ACTIVE'
|
||||||
p2['revision_number'] = 2
|
p2['revision_number'] = 2
|
||||||
p2['updated_at'] = '10:00:01'
|
p2['updated_at'] = '10:00:01'
|
||||||
self.assertTrue(self.notifier._only_status_changed(p1, p2))
|
self.assertFalse(self.notifier._notification_is_needed(p1, p2))
|
||||||
|
|
||||||
p2['name'] = 'test'
|
p2['name'] = 'test'
|
||||||
self.assertFalse(self.notifier._only_status_changed(p1, p2))
|
self.assertFalse(self.notifier._notification_is_needed(p1, p2))
|
||||||
p1['name'] = 'test'
|
p2.pop('name')
|
||||||
self.assertTrue(self.notifier._only_status_changed(p1, p2))
|
|
||||||
p1['name'] = 'test1'
|
p2['mac_address'] = '11:22:33:44:55:66'
|
||||||
self.assertFalse(self.notifier._only_status_changed(p1, p2))
|
self.assertTrue(self.notifier._notification_is_needed(p1, p2))
|
||||||
|
p2['mac_address'] = p1['mac_address']
|
||||||
|
|
||||||
|
p2['fixed_ips'] = [{'ip_address': '10.0.0.11', 'subnet_id': 'aaa'}]
|
||||||
|
self.assertTrue(self.notifier._notification_is_needed(p1, p2))
|
||||||
|
p2['fixed_ips'] = p1['fixed_ips']
|
||||||
|
|
||||||
|
p2['extra_dhcp_opts'] = 'some-test-opt'
|
||||||
|
self.assertTrue(self.notifier._notification_is_needed(p1, p2))
|
||||||
|
p2.pop('extra_dhcp_opts')
|
||||||
|
|
||||||
|
p2['dns_name'] = 'test-dns-name'
|
||||||
|
self.assertTrue(self.notifier._notification_is_needed(p1, p2))
|
||||||
|
p2.pop('dns_name')
|
||||||
|
|
||||||
|
p2['dns_assignment'] = 'test-dns-assignment'
|
||||||
|
self.assertTrue(self.notifier._notification_is_needed(p1, p2))
|
||||||
|
p2.pop('dns_assignment')
|
||||||
|
|
||||||
|
p2['dns_domain'] = 'test-dns-domain'
|
||||||
|
self.assertTrue(self.notifier._notification_is_needed(p1, p2))
|
||||||
|
p2.pop('dns_domain')
|
||||||
|
|
Loading…
Reference in New Issue