Trigger port status DOWN on VIF replug

Now with the merge of push notifications, processing a port update
no longer automatically implies a transition from ACTIVE to BUILD
to ACTIVE again.

This resulted in a bug where Nova would unplug and replug an interface
quickly during rebuild and it would never get a vif-plugged event.
Nothing in the data model was actually being updated that resulted in
the status being set to DOWN or BUILD and the port would return before
the agent would process it as a removed port to mark it as DOWN.

This fixes the bug by making the agent force the port to DOWN whenever
it loses its VLAN. Watching for the VLAN loss was already introduced
to detect these fast unplug/plug events before so this just adds the
status update.

Closes-Bug: #1694371
Change-Id: Ice24eea2534fd6f3b103ec014218a65a45492b1f
(cherry picked from commit 0d7952400b)
This commit is contained in:
Kevin Benton 2017-06-12 21:56:09 -07:00 committed by Swaminathan Vasudevan
parent d9eccad736
commit e38fb9be8d
2 changed files with 19 additions and 2 deletions

View File

@ -1366,7 +1366,7 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
return self._get_port_info(registered_ports, cur_ports, sync)
def check_changed_vlans(self):
"""Return ports which have lost their vlan tag.
"""Check for changed VLAN tags. If changes, notify server and return.
The returned value is a set of port ids of the ports concerned by a
vlan tag loss.
@ -1386,6 +1386,18 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin,
'vlan_tag': lvm.vlan}
)
changed_ports.add(port.vif_id)
if changed_ports:
# explicitly mark these DOWN on the server since they have been
# manipulated (likely a nova unplug/replug) and need to be rewired
devices_down = self.plugin_rpc.update_device_list(self.context,
[],
changed_ports,
self.agent_id,
self.conf.host)
failed_devices = set(devices_down.get('failed_devices_down'))
if failed_devices:
LOG.debug("Status updated failed for %s", failed_devices)
return changed_ports
def treat_vif_port(self, vif_port, port_id, network_id, network_type,

View File

@ -620,10 +620,15 @@ class TestOvsNeutronAgent(object):
added=set([3]), current=vif_port_set,
removed=set([2]), updated=set([1])
)
with mock.patch.object(self.agent, 'tun_br', autospec=True):
with mock.patch.object(self.agent, 'tun_br', autospec=True), \
mock.patch.object(self.agent.plugin_rpc,
'update_device_list') as upd_l:
actual = self.mock_scan_ports(
vif_port_set, registered_ports, port_tags_dict=port_tags_dict)
self.assertEqual(expected, actual)
upd_l.assert_called_once_with(mock.ANY, [], set([1]),
self.agent.agent_id,
self.agent.conf.host)
def test_update_retries_map_and_remove_devs_not_to_retry(self):
failed_devices_retries_map = {