diff --git a/components/images-openstack.yaml b/components/images-openstack.yaml index d63aa6968..35a60adda 100644 --- a/components/images-openstack.yaml +++ b/components/images-openstack.yaml @@ -34,18 +34,18 @@ images: ironic_retrive_swift_config: "ghcr.io/rackerlabs/understack/openstack-client:2025.2" # neutron - neutron_db_sync: "ghcr.io/rackerlabs/understack/neutron:2026.1" - neutron_dhcp: "ghcr.io/rackerlabs/understack/neutron:2026.1" - neutron_l3: "ghcr.io/rackerlabs/understack/neutron:2026.1" - neutron_l2gw: "ghcr.io/rackerlabs/understack/neutron:2026.1" - neutron_linuxbridge_agent: "ghcr.io/rackerlabs/understack/neutron:2026.1" - neutron_metadata: "ghcr.io/rackerlabs/understack/neutron:2026.1" - neutron_ovn_metadata: "ghcr.io/rackerlabs/understack/neutron:2026.1" - neutron_openvswitch_agent: "ghcr.io/rackerlabs/understack/neutron:2026.1" - neutron_server: "ghcr.io/rackerlabs/understack/neutron:2026.1" - neutron_rpc_server: "ghcr.io/rackerlabs/understack/neutron:2026.1" - neutron_bagpipe_bgp: "ghcr.io/rackerlabs/understack/neutron:2026.1" - neutron_netns_cleanup_cron: "ghcr.io/rackerlabs/understack/neutron:2026.1" + neutron_db_sync: "ghcr.io/rackerlabs/understack/neutron:pr-2148" + neutron_dhcp: "ghcr.io/rackerlabs/understack/neutron:pr-2148" + neutron_l3: "ghcr.io/rackerlabs/understack/neutron:pr-2148" + neutron_l2gw: "ghcr.io/rackerlabs/understack/neutron:pr-2148" + neutron_linuxbridge_agent: "ghcr.io/rackerlabs/understack/neutron:pr-2148" + neutron_metadata: "ghcr.io/rackerlabs/understack/neutron:pr-2148" + neutron_ovn_metadata: "ghcr.io/rackerlabs/understack/neutron:pr-2148" + neutron_openvswitch_agent: "ghcr.io/rackerlabs/understack/neutron:pr-2148" + neutron_server: "ghcr.io/rackerlabs/understack/neutron:pr-2148" + neutron_rpc_server: "ghcr.io/rackerlabs/understack/neutron:pr-2148" + neutron_bagpipe_bgp: "ghcr.io/rackerlabs/understack/neutron:pr-2148" + neutron_netns_cleanup_cron: "ghcr.io/rackerlabs/understack/neutron:pr-2148" # nova nova_api: "ghcr.io/rackerlabs/understack/nova:2026.1" diff --git a/containers/neutron/Dockerfile b/containers/neutron/Dockerfile index da7fd1a0c..16df730d1 100644 --- a/containers/neutron/Dockerfile +++ b/containers/neutron/Dockerfile @@ -21,6 +21,9 @@ ARG OPENSTACK_VERSION="required_argument" ADD https://releases.openstack.org/constraints/upper/${OPENSTACK_VERSION} /upper-constraints.txt RUN sed -i '/^neutron-lib==.*/d' /upper-constraints.txt +COPY containers/neutron/patches /tmp/patches/ +RUN cd /src/neutron && git apply /tmp/patches/*.patch + RUN --mount=type=cache,target=/root/.cache/uv \ uv pip install \ --upgrade \ diff --git a/containers/neutron/patches/fix-ovn-ghost-chassis-agent.patch b/containers/neutron/patches/fix-ovn-ghost-chassis-agent.patch new file mode 100644 index 000000000..96f40d618 --- /dev/null +++ b/containers/neutron/patches/fix-ovn-ghost-chassis-agent.patch @@ -0,0 +1,35 @@ +--- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovsdb_monitor.py ++++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovsdb_monitor.py +@@ -362,7 +362,11 @@ + def match_fn(self, event, row, old=None): + # On updates to Chassis_Private because the Chassis has been deleted, + # don't update the AgentCache. We use chassis_private.chassis to return +- # data about the agent. ++ # data about the agent. Require a valid chassis reference for all ++ # events including ROW_CREATE: an orphaned Chassis_Private (where the ++ # Chassis row was already deleted) must not create a ghost agent entry. ++ if not row.chassis: ++ return False + return (event == self.ROW_CREATE or + (hasattr(old, 'nb_cfg') and row.chassis)) + +@@ -428,14 +432,13 @@ + if not self.agent_id(row): + # Don't create a cached object with an agent_id of 'None' + return False +- if event == self.ROW_CREATE: +- return True +- +- # On updates to Chassis_Private because the Chassis has been +- # deleted, don't update the AgentCache. We use +- # chassis_private.chassis to return data about the agent. ++ # Require a valid chassis reference for all events including ++ # ROW_CREATE: an orphaned Chassis_Private (where the Chassis row ++ # was already deleted) must not create a ghost agent entry. + if not getattr(row, 'chassis', None): + return False ++ if event == self.ROW_CREATE: ++ return True + + # Check if both rows have external_ids before comparing nb_cfg + if not (hasattr(old, 'external_ids') and row.external_ids):