Skip to content

nd_manage_vpc_pair: physical vPC peer-link creation fails (deploys via fabric actions/configSave; switchActions/deploy works) #335

Description

@allenrobel

Summary

nd_manage_vpc_pair (added in #197) cannot create a vPC pair with a physical peer-link. The intent PUT .../vpcPair succeeds (HTTP 204), but the deploy step — fabric-level POST .../actions/configSave — returns HTTP 500 and the pair never forms:

[<sn>/<host>] - Unexpected error generating vPC configuration. Last Status [Peer Link Interface]
Switch [<host>/<sn>]: Member port Ethernet1/2 is a member of VPC_PAIR, remove Ethernet1/2 from VPC_PAIR first.

A virtual peer-link (use_virtual_peer_link: true) works fine through the same module. The failure is specific to physical peer-links (i.e. configs that set switch_member_interfaces / peer_switch_member_interfaces / switch_po_id under vpc_pair_details).

Root cause

It's the deploy mechanism, not the intent. The config-generation succeeds via the switch-scoped deploy and fails via the fabric-scoped config-save — same intent, same switches, only the endpoint differs (lab-verified via the raw ND API, independent of any module):

Path Endpoint(s) Physical peer-link
Switch-level POST .../switchActions/deploy {"switchIds":[le1,le2]} ✅ works — switchActions/preview shows the generated CLI; deploy returns "Deployed Successfully"; pair forms (vpcConfigured: true on both, roles elected)
Fabric-level POST .../actions/configSave then .../actions/deploy ❌ HTTP 500 "Member port … is a member of VPC_PAIR"

nd_manage_vpc_pair deploys via the fabric-level actions/configSave + actions/deploy path (plugins/module_utils/manage_vpc_pair/deploy.pyEpFabricConfigSavePost / EpFabricDeployPost). The peer-link member interface is a clean trunkHost when unpaired, so this is ND's config generator self-conflicting on the peer-link member through the fabric path — not a pre-existing claim on the interface.

(There is no switch-level config-save endpoint; switchActions/deploy itself generates+pushes. So the fabric configSave is the only path nd_manage_vpc_pair currently uses, and it's the broken one for physical peer-links.)

Why it wasn't caught

The nd_manage_vpc_pair integration suite (tests/integration/targets/nd_vpc_pair/) only exercises use_virtual_peer_link: true/false and never sets switch_member_interfaces / peer_switch_member_interfaces / switch_po_id — so a physical peer-link with member ports (the failing config) was never run.

Secondary: even when configSave 500s, deploy.py::_is_non_fatal_config_save_error does not catch it, because it matches against error.msg, which is the top-level "Internal Server Error", not the nested "Unexpected error generating vPC configuration …" message. (And even if it matched, the config still wouldn't generate.)

Steps to reproduce

- cisco.nd.nd_manage_vpc_pair:
    fabric_name: SITE1
    state: merged
    config:
      - peer1_switch_id: "<le1 mgmt ip or serial>"
        peer2_switch_id: "<le2 mgmt ip or serial>"
        use_virtual_peer_link: false
        vpc_pair_details:
          type: default
          domain_id: 1
          keep_alive_vrf: management
          switch_keep_alive_local_ip: "<le1 mgmt ip>"
          peer_switch_keep_alive_local_ip: "<le2 mgmt ip>"
          switch_po_id: 1
          peer_switch_po_id: 1
          switch_member_interfaces: ["Ethernet1/2"]
          peer_switch_member_interfaces: ["Ethernet1/2"]

Result: task fails at config save with the HTTP 500 above. Switching to use_virtual_peer_link: true (no member interfaces) succeeds.

Expected behavior

Creating a vPC pair with a physical peer-link should generate and deploy the peer-link config, as it does via switchActions/deploy and as the former nd_vpc_pair module did.

Recommended fix

Deploy vPC pairs via the switch-scoped POST .../switchActions/deploy {"switchIds":[le1, le2]} instead of the fabric-level actions/configSave + actions/deploy. This is exactly what the (now-closed) nd_vpc_pair implementation did — see PR #278 / the nd_vpc_pair branch (plugins/module_utils/orchestrators/vpc_pair.py, which queues both peer serials and flushes via EpManageFabricSwitchActionsDeployPost). It fixes physical peer-link and continues to work for virtual.

Environment

Impact on dependent work

Blocks physical-peer-link vPC pair creation. The nd_interface_vpc_access / nd_interface_vpc_trunk_host modules (PRs #279/#280, on base #334) work around it by using a virtual peer-link substrate in their integration tests, with a TODO to revert to physical once this is fixed.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions