Browse Source

Bind DVR ports when DOWN to workaround upstream issue

When two DVR bindings go to ACTIVE simultaneously, one of the
updates will hit a stale data exception when commit to the DB.
This will ultimately result in update_port_postcommit not getting
called when the second binding's status goes to ACTIVE on retry.

In order to workaround this issue, we now bind DVR ports even
in a DOWN state.

Change-Id: I4811c8ce398a5a95a446c68ed81af550f6ea394f
(cherry picked from commit f2e081e7fa)
changes/01/765401/1
Mitchell Jameson 6 months ago
parent
commit
fe2bc9d512
3 changed files with 19 additions and 7 deletions
  1. +1
    -4
      networking_arista/common/db_lib.py
  2. +11
    -2
      networking_arista/ml2/mechanism_arista.py
  3. +7
    -1
      networking_arista/tests/unit/ml2/test_mechanism_arista.py

+ 1
- 4
networking_arista/common/db_lib.py View File

@ -363,10 +363,7 @@ def get_port_bindings(binding_key=None):
binding_level_model.port_id,
dist_binding_model.host ==
binding_level_model.host))
.filter_unnecessary_ports()
.filter(dist_binding_model.status.in_([
n_const.PORT_STATUS_BUILD,
n_const.PORT_STATUS_ACTIVE]))
.filter_unnecessary_ports(active=False)
.join(aliased_blm,
and_(dist_binding_model.port_id ==
aliased_blm.port_id,


+ 11
- 2
networking_arista/ml2/mechanism_arista.py View File

@ -275,14 +275,23 @@ class AristaDriver(driver_api.MechanismDriver):
log_context("update_port_postcommit: port", port)
log_context("update_port_postcommit: orig", orig_port)
log_context("update_port_postcommit: status", context.status)
log_context("update_port_postcommit: host", context.host)
# Device id can change without a port going DOWN, but the new device
# id may not be supported
if orig_port and port['device_id'] != orig_port['device_id']:
self.delete_port_binding(orig_port, context.original_host)
if context.status in [n_const.PORT_STATUS_ACTIVE,
n_const.PORT_STATUS_BUILD]:
# DVR port bindings are provisioned even when they are DOWN as two
# bindings coming up simultaneously causes a race that results in
# update_port_postcommit being called only for the first binding to
# commit. The second binding does get set to ACTIVE, but due to the
# logic in _update_individual_port_db_status, update_port_postcommit
# never gets called on the retry
if (context.status in [n_const.PORT_STATUS_ACTIVE,
n_const.PORT_STATUS_BUILD] or
port['device_owner'] == n_const.DEVICE_OWNER_DVR_INTERFACE):
if context.binding_levels:
segments = [
level['bound_segment'] for level in context.binding_levels]


+ 7
- 1
networking_arista/tests/unit/ml2/test_mechanism_arista.py View File

@ -178,7 +178,13 @@ class BasicMechDriverTestCase(ml2_test_base.MechTestBase):
# Removed the second host
self.unbind_dvr_from_host(port, port_host_2)
self.assertPortBindingDeleted((port['id'], port_host_2))
# Due to an upstream issue, wherein if two DVR port bindings
# go to ACTIVE simultaneously, we only get a single
# update_port_postcommit, we provision DVR port bindings
# even in the DOWN state. If this gets fixed, we should update
# this test case to reflect that
# self.assertPortBindingDeleted((port['id'], port_host_2))
self.assertPortBindingCreated((port['id'], port_host_2))
self.assertTenantCreated(port_tenant)
self.assertRouterCreated(device_id)
self.assertRouterPortCreated(port['id'])


Loading…
Cancel
Save