Skip to content

Fix vPC pair physical interface deployment#338

Open
sivakasi-cisco wants to merge 15 commits into
developfrom
fix/nd_manage_vpc_pair_physical_peerlink_335
Open

Fix vPC pair physical interface deployment#338
sivakasi-cisco wants to merge 15 commits into
developfrom
fix/nd_manage_vpc_pair_physical_peerlink_335

Conversation

@sivakasi-cisco

@sivakasi-cisco sivakasi-cisco commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Related Issue(s)

Problem Statement

The nd_manage_vpc_pair was failing when creating a vPC pair with a physical peer-link.
The vpc_pair module was able to tell ND what vPC pair we wanted, but the final deploy step failed before the configuration could actually be pushed to the switches. This only happened for physical peer-links with member interfaces. Virtual peer-links were working fine.

Root cause

The module was using the fabric-level deploy flow: actions/configSave + actions/deploy

That path fails in ND for physical vPC peer-link creation because ND tries to generate the configuration fabric-wide and incorrectly reports that the peer-link member port is already part of the vPC pair.

The same configuration works when deployed directly at the switch level using switchActions/deploy So the problem was the deploy API path being used.

Proposed Changes

Updated nd_manage_vpc_pair so the default switch-scoped deployment uses switchActions/deploy with the affected switch serial numbers.

This means the module now asks ND to deploy only to the switches involved in the vPC pair, which avoids the failing fabric-level config-save path and allows physical peer-link vPC pair creation to complete successfully.

The fabric-level deploy path is still kept for global deployment mode or fallback cases.

Test Notes

Updated the vPC pair integration task assertions for merge, replace, override, and delete flows to verify that switch-level deployment uses /switchActions/deploy instead of the fabric-level /actions/configSave path.

@sivakasi-cisco
sivakasi-cisco marked this pull request as ready for review July 2, 2026 16:46
@sivakasi-cisco sivakasi-cisco added the ready for review Submitter is requesting a PR review label Jul 2, 2026

@allenrobel allenrobel left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Code review

Reviewed the switch-scoped deploy refactor for correctness and CLAUDE.md compliance. Three findings inline: a missing workaround marker (CLAUDE.md-mandated), an unchecked 207 multi-status response that can mask per-switch deploy failures, and a now-stale custom_vpc_deploy docstring. No issues found in the integration-test or unit-test changes.

🤖 Generated with Claude Code

Comment thread plugins/module_utils/manage_vpc_pair/deploy.py Outdated
Comment thread plugins/module_utils/manage_vpc_pair/deploy.py Outdated
Comment thread plugins/module_utils/manage_vpc_pair/deploy.py
@mikewiebe mikewiebe self-assigned this Jul 9, 2026
@sivakasi-cisco

Copy link
Copy Markdown
Collaborator Author

Hi Allen,

Thanks for the review. I rechecked the physical vPC pair behavior against ND/UI.

The earlier assumption was that physical peer-link vPC creation needed a different deploy path. After checking the actual UI/API behavior, that is not the real issue.

The issue is not that physical peer-link vPC pairing needs a switch-level deploy workaround. The issue is that for VXLAN iBGP/eBGP fabrics, ND/UI only supports the simple pair payload with switchId, peerSwitchId, and useVirtualPeerLink=false. It does not accept vpcPairDetails for that scenario. It accepts only the below.
{
"vpcAction": "pair",
"switchId": "",
"peerSwitchId": "",
"useVirtualPeerLink": false
}

The UI itself does not send or accept vpcPairDetails for this scenario. If we send extra details like domain ID, keepalive IPs, peer-link port-channel, member interfaces, VLANs, etc., ND rejects it / can hit the HTTP 500 path.

I removed the switch deploy workaround from the PR. The PR now only blocks unsupported vpc_pair_details on VXLAN iBGP/eBGP fabrics and keeps those details allowed for supported fabric types.

So the earlier comments on _switch_level_deploy, HTTP 207 handling, and the deploy docstring should be obsolete for the current diff. Please take another look at the updated PR.

So the original switch-level deploy workaround is no longer needed. I removed that change from the PR. The PR now focuses only on validating the input earlier:

  • block vpc_pair_details for VXLAN iBGP/eBGP fabrics
  • keep allowing vpc_pair_details for fabrics where those details are supported
  • add integration coverage for both cases

Kindly re-review the updated diff when you get a chance and also share your comments on this

@allenrobel

Copy link
Copy Markdown
Collaborator

Kindly re-review the updated diff when you get a chance and also share your comments on this

Have re-reviewed based on your analysis of the root cause and this looks good. Thank you @sivakasi-cisco!

@allenrobel allenrobel left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

Comment thread plugins/module_utils/manage_vpc_pair/actions.py Outdated
Comment thread plugins/module_utils/manage_vpc_pair/actions.py Outdated
Comment thread plugins/module_utils/manage_vpc_pair/actions.py Outdated
Comment thread plugins/module_utils/manage_vpc_pair/actions.py Outdated
Comment thread plugins/module_utils/manage_vpc_pair/actions.py
@sivakasi-cisco
sivakasi-cisco requested a review from oborys July 15, 2026 05:42
@sivakasi-cisco
sivakasi-cisco removed the request for review from oborys July 15, 2026 05:43

@sivakasi-cisco sivakasi-cisco left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed the comments

Comment thread plugins/module_utils/manage_vpc_pair/actions.py Outdated
@sivakasi-cisco
sivakasi-cisco force-pushed the fix/nd_manage_vpc_pair_physical_peerlink_335 branch from 60e52b5 to 2c055e1 Compare July 15, 2026 10:02
Comment thread plugins/module_utils/manage_vpc_pair/actions.py Outdated
Comment thread plugins/module_utils/manage_vpc_pair/actions.py Outdated
Comment thread plugins/module_utils/manage_vpc_pair/actions.py Outdated
Comment thread plugins/module_utils/manage_vpc_pair/actions.py
Comment thread plugins/module_utils/manage_vpc_pair/actions.py Outdated
Comment thread plugins/module_utils/manage_vpc_pair/actions.py Outdated
Comment thread plugins/module_utils/manage_vpc_pair/actions.py Outdated
Comment thread plugins/module_utils/manage_vpc_pair/actions.py Outdated
@akinross
akinross self-requested a review July 20, 2026 09:04
@mikewiebe

Copy link
Copy Markdown
Collaborator

High: config_actions.type: switch still uses fabric-scoped deployment

Issue

The supported VXLAN workflow is now clear: iBGP/eBGP fabrics correctly reject vpc_pair_details, and with use_virtual_peer_link: false ND automatically discovers the physical interfaces between the pair. That does not make config_actions.type advisory, however. The current implementation sends both type: switch and type: global through the fabric-level actions/configSave and actions/deploy flow instead of selecting switchActions/deploy for switch scope.

Evidence

  • deploy.py lines 204-257 always calls FabricUtils.save_config() and FabricUtils.deploy_config() after reading config_actions.type; there is no branch to switchActions/deploy.
  • The current PR description still says the default switch-scoped path uses switchActions/deploy with the affected switch serials, but deploy.py is not changed in the current eight-file diff because commit c9aacd9 reverted that implementation.
  • The author's scope-update comment confirms that switch deployment was removed in favor of VXLAN input validation. Live testing confirms that validation and ND-managed physical-interface discovery are correct, while captured action paths still show fabric-level save/deploy for type: switch.

Existing PR overlap

Related to the author's scope-update comment above, which explains why the earlier switch-deploy workaround was removed. It does not address the separate public contract that config_actions.type: switch selects switch-level deployment, and it conflicts with the PR description that still claims this dispatch is implemented.

Existing open issue overlap

Related open issue #368 tracks the collection-wide config_actions contract. The PR-specific delta is actionable here because this PR advertises switch-scoped deployment as its fix while the current head does not implement it.

Impact

Users cannot select the documented deployment scope: switch and global execute the same fabric operation. This makes the module contract misleading and leaves switch-targeted runs with fabric-wide save/deploy behavior even though ND correctly handles the physical VXLAN pair itself through interface auto-discovery.

Suggested fix

Keep the new VXLAN validation and auto-discovery workflow unchanged. Route config_actions.type: switch to POST .../switchActions/deploy with the affected peer switch IDs, retain actions/configSave plus actions/deploy for type: global, and add unit/integration assertions for both endpoint and payload selections. Update the PR description if switch-scoped dispatch is intentionally deferred to #368.

Comment thread tests/integration/targets/nd_vpc_pair/tasks/nd_vpc_pair_merge.yaml Outdated
Comment thread tests/integration/targets/nd_vpc_pair/tasks/base_tasks.yaml Outdated
Comment thread plugins/module_utils/manage_vpc_pair/actions.py
Comment thread plugins/module_utils/manage_vpc_pair/actions.py Outdated
… strip inherited details on blocked fabrics, gate detail-bearing integration cases and TC23b assertions
@sivakasi-cisco

Copy link
Copy Markdown
Collaborator Author

High: config_actions.type: switch still uses fabric-scoped deployment

Issue

The supported VXLAN workflow is now clear: iBGP/eBGP fabrics correctly reject vpc_pair_details, and with use_virtual_peer_link: false ND automatically discovers the physical interfaces between the pair. That does not make config_actions.type advisory, however. The current implementation sends both type: switch and type: global through the fabric-level actions/configSave and actions/deploy flow instead of selecting switchActions/deploy for switch scope.

Evidence

  • deploy.py lines 204-257 always calls FabricUtils.save_config() and FabricUtils.deploy_config() after reading config_actions.type; there is no branch to switchActions/deploy.
  • The current PR description still says the default switch-scoped path uses switchActions/deploy with the affected switch serials, but deploy.py is not changed in the current eight-file diff because commit c9aacd9 reverted that implementation.
  • The author's scope-update comment confirms that switch deployment was removed in favor of VXLAN input validation. Live testing confirms that validation and ND-managed physical-interface discovery are correct, while captured action paths still show fabric-level save/deploy for type: switch.

Existing PR overlap

Related to the author's scope-update comment above, which explains why the earlier switch-deploy workaround was removed. It does not address the separate public contract that config_actions.type: switch selects switch-level deployment, and it conflicts with the PR description that still claims this dispatch is implemented.

Existing open issue overlap

Related open issue #368 tracks the collection-wide config_actions contract. The PR-specific delta is actionable here because this PR advertises switch-scoped deployment as its fix while the current head does not implement it.

Impact

Users cannot select the documented deployment scope: switch and global execute the same fabric operation. This makes the module contract misleading and leaves switch-targeted runs with fabric-wide save/deploy behavior even though ND correctly handles the physical VXLAN pair itself through interface auto-discovery.

Suggested fix

Keep the new VXLAN validation and auto-discovery workflow unchanged. Route config_actions.type: switch to POST .../switchActions/deploy with the affected peer switch IDs, retain actions/configSave plus actions/deploy for type: global, and add unit/integration assertions for both endpoint and payload selections. Update the PR description if switch-scoped dispatch is intentionally deferred to #368.

Changed failed_when: false → ignore_errors: true so the failure is actually captured; gated the fabric-detail test cases TC1, 7, 8, 12, 13 and 23b so they only run on fabrics that support them.

For example, on an eBGP VXLAN fabric, when it was senidng the whole vpc_pair_details which is rejected by module and gets aborted. Now, it is skipped there and asserts with the rejection message.

@sivakasi-cisco

Copy link
Copy Markdown
Collaborator Author

High: config_actions.type: switch still uses fabric-scoped deployment

Issue

The supported VXLAN workflow is now clear: iBGP/eBGP fabrics correctly reject vpc_pair_details, and with use_virtual_peer_link: false ND automatically discovers the physical interfaces between the pair. That does not make config_actions.type advisory, however. The current implementation sends both type: switch and type: global through the fabric-level actions/configSave and actions/deploy flow instead of selecting switchActions/deploy for switch scope.

Evidence

  • deploy.py lines 204-257 always calls FabricUtils.save_config() and FabricUtils.deploy_config() after reading config_actions.type; there is no branch to switchActions/deploy.
  • The current PR description still says the default switch-scoped path uses switchActions/deploy with the affected switch serials, but deploy.py is not changed in the current eight-file diff because commit c9aacd9 reverted that implementation.
  • The author's scope-update comment confirms that switch deployment was removed in favor of VXLAN input validation. Live testing confirms that validation and ND-managed physical-interface discovery are correct, while captured action paths still show fabric-level save/deploy for type: switch.

Existing PR overlap

Related to the author's scope-update comment above, which explains why the earlier switch-deploy workaround was removed. It does not address the separate public contract that config_actions.type: switch selects switch-level deployment, and it conflicts with the PR description that still claims this dispatch is implemented.

Existing open issue overlap

Related open issue #368 tracks the collection-wide config_actions contract. The PR-specific delta is actionable here because this PR advertises switch-scoped deployment as its fix while the current head does not implement it.

Impact

Users cannot select the documented deployment scope: switch and global execute the same fabric operation. This makes the module contract misleading and leaves switch-targeted runs with fabric-wide save/deploy behavior even though ND correctly handles the physical VXLAN pair itself through interface auto-discovery.

Suggested fix

Keep the new VXLAN validation and auto-discovery workflow unchanged. Route config_actions.type: switch to POST .../switchActions/deploy with the affected peer switch IDs, retain actions/configSave plus actions/deploy for type: global, and add unit/integration assertions for both endpoint and payload selections. Update the PR description if switch-scoped dispatch is intentionally deferred to #368.

Fixed them up to use respective deploy method. Now, we look up the fabric and only deploy the switches that are actually out of sync via ../switchActions/deploy for type:switch. The global still does the whole-fabric deploy. Save stays on configSave for both. Added unit tests for the endpoint + payload of each scope. Not deferred to #368 anymore

@sivakasi-cisco

Copy link
Copy Markdown
Collaborator Author

Verified the changes with IT on the latest changes

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

Labels

NaC-CapSet1 ready for review Submitter is requesting a PR review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants