Separate port status update from getting details

This is a small refactor to separate updating the port status
from the method retrieving device details. This is in preparation
for patch I99c2b77b35e6eabb6e4f633c4e8e2533594c6b55 which will allow
updating ports' status in bulk.

Change-Id: Ifa78f6911cfbbd3e982807122bddc898613f323f
Partial-Bug: #1665215
(cherry picked from commit a04332ca4a)
This commit is contained in:
Kevin Benton 2017-04-27 11:56:56 -07:00 committed by Swaminathan Vasudevan
parent 18c4bc9888
commit 912b25f3d8
2 changed files with 36 additions and 18 deletions

View File

@ -57,6 +57,14 @@ class RpcCallbacks(type_tunnel.TunnelRpcCallbackMixin):
self.setup_tunnel_callback_mixin(notifier, type_manager)
super(RpcCallbacks, self).__init__()
def _get_new_status(self, host, port_context):
port = port_context.current
if not host or host == port_context.host:
new_status = (n_const.PORT_STATUS_BUILD if port['admin_state_up']
else n_const.PORT_STATUS_DOWN)
if port['status'] != new_status:
return new_status
def get_device_details(self, rpc_context, **kwargs):
"""Agent requests device details."""
agent_id = kwargs.get('agent_id')
@ -87,16 +95,24 @@ class RpcCallbacks(type_tunnel.TunnelRpcCallbackMixin):
if port['network_id'] not in cached_networks:
cached_networks[port['network_id']] = (
port_context.network.current)
return self._get_device_details(rpc_context, agent_id=agent_id,
host=host, device=device,
port_context=port_context)
result = self._get_device_details(rpc_context, agent_id=agent_id,
host=host, device=device,
port_context=port_context)
if 'network_id' in result:
# success so we update status
new_status = self._get_new_status(host, port_context)
if new_status:
plugin.update_port_status(rpc_context,
port_id,
new_status,
host,
port_context.network.current)
return result
def _get_device_details(self, rpc_context, agent_id, host, device,
port_context):
segment = port_context.bottom_bound_segment
port = port_context.current
plugin = directory.get_plugin()
port_id = port_context.current['id']
if not segment:
LOG.warning(_LW("Device %(device)s requested by agent "
@ -108,16 +124,6 @@ class RpcCallbacks(type_tunnel.TunnelRpcCallbackMixin):
'vif_type': port_context.vif_type})
return {'device': device}
if (not host or host == port_context.host):
new_status = (n_const.PORT_STATUS_BUILD if port['admin_state_up']
else n_const.PORT_STATUS_DOWN)
if port['status'] != new_status:
plugin.update_port_status(rpc_context,
port_id,
new_status,
host,
port_context.network.current)
network_qos_policy_id = port_context.network._network.get(
qos_consts.QOS_POLICY_ID)
entry = {'device': device,
@ -183,6 +189,18 @@ class RpcCallbacks(type_tunnel.TunnelRpcCallbackMixin):
LOG.exception(_LE("Failed to get details for device %s"),
device)
failed_devices.append(device)
new_status_map = {ctxt.current['id']: self._get_new_status(host, ctxt)
for ctxt in bound_contexts.values() if ctxt}
# filter out any without status changes
new_status_map = {p: s for p, s in new_status_map.items() if s}
try:
for port_id, new_status in new_status_map.items():
plugin.update_port_status(rpc_context, port_id,
new_status, host)
except Exception:
LOG.exception(_LE("Failure updating statuses, retrying all"))
failed_devices = devices_to_fetch
devices = []
return {'devices': devices,
'failed_devices': failed_devices}

View File

@ -179,10 +179,10 @@ class RpcCallbacksTestCase(base.BaseTestCase):
f.assert_has_calls(calls)
def test_get_devices_details_list(self):
devices = [1, 2, 3, 4, 5]
expected = devices
results = [{'device': [v]} for v in [1, 2, 3, 4, 5]]
expected = results
callback = self.callbacks.get_devices_details_list
self._test_get_devices_list(callback, devices, expected)
self._test_get_devices_list(callback, results, expected)
def test_get_devices_details_list_with_empty_devices(self):
with mock.patch.object(self.callbacks, 'get_device_details') as f: