...
if utils.is_extension_supported( self.plugin, constants.PORT_BINDING_EXT_ALIAS):
# ensures the right port binding self._ensure_host_set_on_ports(context, host, routers)
...
# the same data structure returned as after list_active_sync_routers_on_active_l3_agent without being refreshed
return routers
_populate_mtu_and_subnets_for_ports is eventually called on a code path from list_active_sync_routers_on_active_l3_agent and this depends on a binding being other than "unbound".
It seems that we need to do list_active_sync_routers_on_active_l3_agent twice - I confirmed that routes get created if routers variable is refreshed after _ensure_host_set_on_ports before returning from sync_routers.
I think it's this portion of code that results in an issue:
https:/ /github. com/openstack/ neutron/ blob/fbe308bdc1 2191c187343b5ef 103dea9af738380 /neutron/ api/rpc/ handlers/ l3_rpc. py#L119- L129
# this populates "routers"
self. l3plugin. list_active_ sync_routers_ on_active_ l3_agent(
context, host, router_ids))
routers = (
... extension_ supported(
self. plugin, constants. PORT_BINDING_ EXT_ALIAS) :
self. _ensure_ host_set_ on_ports( context, host, routers) sync_routers_ on_active_ l3_agent without being refreshed
if utils.is_
# ensures the right port binding
...
# the same data structure returned as after list_active_
return routers
_populate_ mtu_and_ subnets_ for_ports is eventually called on a code path from list_active_ sync_routers_ on_active_ l3_agent and this depends on a binding being other than "unbound".
It seems that we need to do list_active_ sync_routers_ on_active_ l3_agent twice - I confirmed that routes get created if routers variable is refreshed after _ensure_ host_set_ on_ports before returning from sync_routers.