Skip native DHCP notifications on status change

On profiling the get_devices_details communications between
the agent and the server, a significant amount of time
(60% in my dev env) is being spent in the AFTER_UPDATE events
for the port updates resulting from the port status changes.

One of the major offenders is the native DHCP agent notifier.
On each port update it ends up retrieving the network for the
port, the DHCP agents for the network, and the segments.

This patch addresses this particular issue by adding logic to
skip a DHCP notification if the only thing that changed on the
port was the status. The DHCP agent doesn't do anything based on
the status field so there is no need to update it when this is
the only change.

Change-Id: I948132924ec5021a9db78cf17efbba96b2500e8e
Partial-Bug: #1665215
This commit is contained in:
Kevin Benton 2017-02-15 20:49:45 -08:00
parent f9e5c2a726
commit 840e04b6f1
2 changed files with 35 additions and 0 deletions

View File

@ -241,8 +241,28 @@ class DhcpAgentNotifyAPI(object):
method_name = '.'.join((resource, action, 'end'))
payload = kwargs[resource]
data = {resource: payload}
if resource == resources.PORT:
if self._only_status_changed(kwargs.get('original_port'),
kwargs.get('port')):
# don't waste time updating the DHCP agent for status updates
return
self.notify(context, data, method_name)
def _only_status_changed(self, orig, new):
# a status change will manifest as a bumped revision number, a new
# updated_at timestamp, and a new status. If that's all that changed,
# return True, else False
if not orig or not new:
return False
if set(orig.keys()) != set(new.keys()):
return False
for k in orig.keys():
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, context=None,
data=None, method_name=None, collection=None,
action='', **kwargs):

View File

@ -238,3 +238,18 @@ class TestDhcpAgentNotifyAPI(base.BaseTestCase):
registry.notify(res, events.AFTER_CREATE, self,
context=mock.Mock(), **kwargs)
self.assertEqual([res], self.notifier._unsubscribed_resources)
def test__only_status_changed(self):
p1 = {'id': 1, 'status': 'DOWN', 'updated_at': '10:00:00',
'revision_number': 1}
p2 = dict(p1)
p2['status'] = 'ACTIVE'
p2['revision_number'] = 2
p2['updated_at'] = '10:00:01'
self.assertTrue(self.notifier._only_status_changed(p1, p2))
p2['name'] = 'test'
self.assertFalse(self.notifier._only_status_changed(p1, p2))
p1['name'] = 'test'
self.assertTrue(self.notifier._only_status_changed(p1, p2))
p1['name'] = 'test1'
self.assertFalse(self.notifier._only_status_changed(p1, p2))