Skip to content

feat: PUC-1758: remove physical_network fallback lookup - #2145

Open
haseebsyed12 wants to merge 1 commit into
mainfrom
remove_physical_network_fallback_lookup_bind_port
Open

feat: PUC-1758: remove physical_network fallback lookup#2145
haseebsyed12 wants to merge 1 commit into
mainfrom
remove_physical_network_fallback_lookup_bind_port

Conversation

@haseebsyed12

@haseebsyed12 haseebsyed12 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

What does this change do?

Ironic requires a physical_network on the baremetal port to attach a vif and passes it through in the binding_profile, so the fallback that queried Ironic for the port matching local_link_information was only ever a workaround. This removes it, which also drops a synchronous Ironic API call from the port bind path.

With the fallback gone a missing physical_network is a hard error, enforced on the precommit hooks:

  • SUBPORTS/TRUNK PRECOMMIT_CREATE raise BadRequest, aborting the transaction and surfacing the error to the API caller.
  • New SUBPORTS/TRUNK PRECOMMIT_DELETE handlers validate the parent port before the teardown commits, since the AFTER_DELETE hook that does the switchport cleanup cannot roll anything back. Only a still-bound parent port blocks the delete; an unbound one tears down as before.
  • The AFTER_CREATE/AFTER_DELETE hooks log instead of raising. They run after the rows are committed, where an exception cannot undo the change and — the subscriptions being cancellable — would surface as a 500. The delete path still releases its segments so their VLANs do not leak, and only skips the undersync call.
  • bind_port_segment still refuses the bind and logs, now including the port and network ids.

Also drops the helpers the fallback was the only caller of: IronicClient.baremetal_port_physical_network, its _port_by_local_link helper, and utils.local_link_from_binding_profile.

Upgrade impact

  • This change requires operator action to upgrade. If checked, add the
    upgrade-impact label and a release note: run scriv create from the
    repository root and describe the required action in the generated
    changelog.d/ file. See RELEASING.md.

Operator action means anything a deployment has to do beyond a normal resync:
deploy repo or values changes, new or removed secrets, enabling or disabling a
component, or a manual one-time step.

@haseebsyed12
haseebsyed12 force-pushed the remove_physical_network_fallback_lookup_bind_port branch 16 times, most recently from 3d18f99 to 1d25276 Compare July 20, 2026 10:16
@haseebsyed12
haseebsyed12 marked this pull request as ready for review July 20, 2026 13:41
@haseebsyed12
haseebsyed12 force-pushed the remove_physical_network_fallback_lookup_bind_port branch from 1d25276 to 5babf60 Compare July 20, 2026 14:48
@cardoe

cardoe commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Rebase: rebased onto current main (was 113 commits behind) — clean, no conflicts. ruff check clean, 184 tests pass. The one ruff format complaint is in l3_router/understack_vni_db.py, pre-existing on main and untouched here.

Re: physical_network availability — the backfill migration has been run and the data is present where available, so the hard requirement is fine in principle. Remaining comments are about how it's enforced.

1. Move the enforcement to PRECOMMIT

Two of the three new raise exc.BadRequest sites are in postcommit hooks, where the DB change is already committed:

Site Method Hook Registered
trunk.py:183 _add_subports_networks_to_parent_port_switchport PRECOMMIT_CREATE — correct :73, :91
trunk.py:212 _clean_parent_port_switchport_config AFTER_DELETE :85, :97
trunk.py:279 subports_added_post AFTER_CREATE :79

Neutron publishes AFTER_* outside the writer context (neutron/services/trunk/plugin.py:385, :443). Since all subscriptions are cancellable=True the exception does propagate — but nothing rolls back: the trunk/subport rows stand, switch config is never pushed, and on the delete path it aborts before undersync.sync(). BadRequest is also the wrong signal, since it tells the caller their request was invalid after it already succeeded.

Please convert this protection to a PRECOMMIT trigger:

  • subports_added_post (:279): this raise is already unreachable. subports_added_handle_tenant_vlan_id_and_switchport_config (:110) and subports_added_post (:276) guard on the same utils.parent_port_is_bound() condition against the same parent port, so PRECOMMIT_CREATE at :183 fires first. Just drop the raise here.
  • _clean_parent_port_switchport_config (:212): move the check to a PRECOMMIT_DELETE subscription for both resources.SUBPORTS and resources.TRUNK (neutron publishes these inside the writer context — plugin.py:435 and :324), and leave the AFTER_DELETE path to log and return. Worth considering whether a missing physnet should block a delete at all — failing teardown can wedge cleanup of resources that are already gone.

Also note configure_trunk (:144) calls the raising method unconditionally and isn't a registry callback at all, so it needs its own thought about how a BadRequest surfaces from there.

2. Add tests

None of the three new raise paths are currently exercised — 184 tests pass without touching them. Also, conftest.py now injects physical_network: "physnet" into every binding profile, so the missing-physnet case is no longer covered by default anywhere. And test_fails_when_physical_network_missing only asserts continue_binding.assert_not_called(), which can't distinguish "refused for the right reason" from any other non-binding path — please assert on the logged error, and prefer parametrizing the binding_profile fixture over copy-and-pop mutation of port_context.current.

Notes

  • components/images-openstack.yaml: all 12 neutron images are pinned to neutron:pr-2145. Needs reverting to 2026.1 before merge.
  • scripts/openstack_cli_commands.sh is 840 of the 907 added lines, headed Session: 2026-07-16_Remove_Physical_Network_Fallback, and isn't registered in docs/operator-guide/scripts.md. It also overlaps the existing scripts/audit_ports_missing_physical_network.py. Suggest dropping it, or splitting it into its own PR with docs.
  • Dead code now unreferenced: utils.local_link_from_binding_profile (utils.py:469), IronicClient.baremetal_port_physical_network (ironic.py:64), its sole helper _port_by_local_link (ironic.py:68), and trunk.py:49 self.ironic_client. Worth removing in a PR named "remove fallback lookup" — keep the IronicClient class, still used by utils.py:173 and l3_router/palo_alto.py:85.
  • All four new messages say "contains physical_network in local_link_information" — it's a sibling key of local_link_information, not nested inside it. Sends operators to the wrong place.
  • is Nonenot vlan_group_name in trunk.py is a good catch for empty-string physnets.

@cardoe
cardoe force-pushed the remove_physical_network_fallback_lookup_bind_port branch from 5babf60 to 618ae76 Compare August 17, 2026 20:08
@cardoe

cardoe commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Pushed a rebase onto current main with the review feedback applied, squashed into your original commit (authorship preserved).

  • Enforcement moved to precommit: PRECOMMIT_CREATE still raises, plus new subports_deleted_precommit / trunk_deleted_precommit on SUBPORTS/TRUNK PRECOMMIT_DELETE. The AFTER_CREATE/AFTER_DELETE hooks now log instead of raising, and the delete path still releases its segments so their VLANs don't leak — the old raise happened before deallocation.
  • A missing physnet only blocks a delete when the parent port is still bound as baremetal; unbound parents tear down freely (_validate_parent_port_physnet).
  • Reverted the neutron:pr-2145 image pins to 2026.1 and dropped scripts/openstack_cli_commands.sh, which overlapped the existing scripts/audit_ports_missing_physical_network.py.
  • Removed the helpers the fallback was the only caller of, corrected the error messages (physnet is a sibling of local_link_information, not nested in it), and added tests for the raise/log paths — 190 pass, ruff clean.

@cardoe
cardoe force-pushed the remove_physical_network_fallback_lookup_bind_port branch from 618ae76 to 034a505 Compare August 17, 2026 20:14
Ironic requires a physical_network on the baremetal port to attach a vif and
passes it through in the binding_profile, so the fallback that queried Ironic
for the port matching local_link_information was only ever a workaround. Drop
it, along with the synchronous Ironic API call it made on the bind path.

With the fallback gone, a missing physical_network is a hard error. Enforce
it on the precommit hooks only:

  * subports/trunk PRECOMMIT_CREATE raise BadRequest, aborting the
    transaction and surfacing the error to the API caller.
  * New subports/trunk PRECOMMIT_DELETE handlers validate the parent port
    before the teardown commits, since the AFTER_DELETE hook that does the
    switchport cleanup cannot roll anything back. Only a still-bound parent
    port blocks the delete; an unbound one tears down as before.
  * The AFTER_CREATE and AFTER_DELETE hooks log instead of raising. They run
    after the rows are committed, where an exception cannot undo the change
    and, because the subscriptions are cancellable, would surface as a 500.
    The delete path still releases its segments so their VLANs do not leak,
    and only skips the undersync call.

bind_port_segment keeps refusing the bind and logging, now including the
port and network ids.

Also drops the helpers the fallback was the only caller of:
IronicClient.baremetal_port_physical_network, its _port_by_local_link
helper, and utils.local_link_from_binding_profile.

Co-Authored-By: Doug Goldstein <doug.goldstein@rackspace.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@cardoe
cardoe force-pushed the remove_physical_network_fallback_lookup_bind_port branch from 034a505 to 3468dea Compare August 17, 2026 20:24
@cardoe cardoe added the upgrade-impact Requires operator action to upgrade; needs a changelog.d/ release note fragment label Aug 17, 2026
@haseebsyed12

Copy link
Copy Markdown
Contributor Author

LGTM.

@mfencik mfencik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may consider removing the vlan_group check when deleting ports at some point as we should only bind the ports that have vlan_group present. But for the moment let's leave it there obviously.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

upgrade-impact Requires operator action to upgrade; needs a changelog.d/ release note fragment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants