Skip to content

Resolving dcnm vpc pair keyError with ipAddress #460

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions playbooks/roles/dcnm_vpc_pair/dcnm_hosts.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
all:
vars:
ansible_user: "admin"
ansible_password: "password-secret"
ansible_python_interpreter: python
ansible_httpapi_validate_certs: False
ansible_httpapi_use_ssl: True
children:
dcnm:
vars:
ansible_it_fabric: fabric-stage
ansible_connection: ansible.netcommon.httpapi
ansible_network_os: cisco.dcnm.dcnm
ansible_httpapi_validate_certs: no
hosts:
nac-ndfc1:
ansible_host: 10.10.5.1

78 changes: 78 additions & 0 deletions playbooks/roles/dcnm_vpc_pair/dcnm_tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
# This playbook can be used to execute integration tests for
# the role located in:
#
# tests/integration/targets/dcnm_image_policy
#
# Modify the hosts and vars sections with details for your testing
# setup and uncomment the testcase you want to run.
#
- hosts: dcnm
gather_facts: no
connection: ansible.netcommon.httpapi

vars:
switch_username: admin
switch_password: "password-secret"
ansible_it_fabric: fabric-stage
ansible_switch1: 192.168.1.1
ansible_switch2: 192.168.1.2
ansible_peer1_ip: 192.168.1.1
ansible_peer2_ip: 192.168.1.2
ansible_vxlan_vpc_domain_id: 1000

config:
- peerOneId: "{{ ansible_switch1 }}"
peerTwoId: "{{ ansible_switch2 }}"
templateName: "vpc_pair" # Using the correct template name
profile:
# Required fields for VPC template
ADMIN_STATE: true
ALLOWED_VLANS: "all"
DOMAIN_ID: "{{ ansible_vxlan_vpc_domain_id }}"
FABRIC_NAME: "{{ ansible_it_fabric }}"
KEEP_ALIVE_HOLD_TIMEOUT: 3
KEEP_ALIVE_VRF: "management"
PC_MODE: "active"
PEER1_KEEP_ALIVE_LOCAL_IP: "{{ ansible_peer1_ip }}"
PEER1_MEMBER_INTERFACES: "eth1/1"
PEER1_PCID: 1
PEER2_KEEP_ALIVE_LOCAL_IP: "{{ ansible_peer2_ip }}"
PEER2_MEMBER_INTERFACES: "eth1/1"
PEER2_PCID: 2

# Additional required fields
peer1Ip: "{{ ansible_peer1_ip }}"
peer2Ip: "{{ ansible_peer2_ip }}"
vpcDomainId: "{{ ansible_vxlan_vpc_domain_id }}"
adminState: true
keepAliveVrf: "management"
keepAliveHoldTimeout: 3
keepAliveLocalIp: "{{ ansible_peer1_ip }}"
keepAliveRemoteIp: "{{ ansible_peer2_ip }}"

# Template specific fields
templateName: "vpc_pair"
templatePropId: ""
templatePropName: "vpc_pair"
templatePropDescription: "VPC Template"
templatePropDataType: "JSON"
templatePropDefaultValue: ""
templatePropDisplayName: "VPC Configuration"
templatePropIsMandatory: true
templatePropIsMultiSelect: false
templatePropIsPassword: false
templatePropIsReadOnly: false
templatePropIsRequired: true
templatePropIsSecure: false
templatePropIsSortable: false
templatePropIsVisible: true
templatePropOptions: []
templatePropRange: []
templatePropValue: ""
templatePropValueType: "STRING"
templateIPAddress: "{{ ansible_peer1_ip }}"


roles:
- dcnm_vpc_pair
1 change: 1 addition & 0 deletions plugins/module_utils/network/dcnm/dcnm.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"long": "int",
"ipV4Address": "ipv4",
"ipV6Address": "ipv6",
"ipAddress": "ipv4",
"interfaceRange": "list",
"boolean": "bool",
"enum": "str",
Expand Down
61 changes: 39 additions & 22 deletions plugins/module_utils/network/dcnm/dcnm_vpc_pair_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,14 +393,21 @@ def dcnm_vpc_pair_compare_vpc_pair_objects(self, wobj, hobj):
if "_defaulted" in key:
continue

if str(hobj.get(key, None)).lower() != str(wobj[key]).lower():
if key == "nvPairs":
continue

# We found an object that matched all other key values, but differs in one of the params.
mismatch_reasons.append(
{key.upper() + "_MISMATCH": [wobj[key], hobj.get(key, None)]}
)
# Special handling for useVirtualPeerlink to treat None and False as equivalent
if key == "useVirtualPeerlink":
hval = hobj.get(key, None)
wval = wobj[key]
if not ((hval is None and wval is False) or (hval is False and wval is None)):
if str(hval).lower() != str(wval).lower():
mismatch_reasons.append(
{key.upper() + "_MISMATCH": [wval, hval]}
)
elif key != "nvPairs": # Skip nvPairs here as it's handled separately
if str(hobj.get(key, None)).lower() != str(wobj[key]).lower():
# We found an object that matched all other key values, but differs in one of the params.
mismatch_reasons.append(
{key.upper() + "_MISMATCH": [wobj[key], hobj.get(key, None)]}
)

if wobj.get("nvPairs", None) is not None:

Expand All @@ -409,20 +416,30 @@ def dcnm_vpc_pair_compare_vpc_pair_objects(self, wobj, hobj):
if "_defaulted" in key:
continue

if (
str(hobj["nvPairs"].get(key, None)).lower()
!= str(wobj["nvPairs"][key]).lower()
):
# We found an object that matched all other key values, but differs in one of the params.
mismatch_reasons.append(
{
key.upper()
+ "_MISMATCH": [
wobj["nvPairs"][key],
hobj["nvPairs"].get(key, None),
]
}
)
# Special handling for useVirtualPeerlink in nvPairs to treat None and False as equivalent
if key == "useVirtualPeerlink":
hval = hobj["nvPairs"].get(key, None)
wval = wobj["nvPairs"][key]
if not ((hval is None and wval is False) or (hval is False and wval is None)):
if str(hval).lower() != str(wval).lower():
mismatch_reasons.append(
{key.upper() + "_MISMATCH": [wval, hval]}
)
else:
if (
str(hobj["nvPairs"].get(key, None)).lower()
!= str(wobj["nvPairs"][key]).lower()
):
# We found an object that matched all other key values, but differs in one of the params.
mismatch_reasons.append(
{
key.upper()
+ "_MISMATCH": [
wobj["nvPairs"][key],
hobj["nvPairs"].get(key, None),
]
}
)

if mismatch_reasons != []:
return "DCNM_VPC_PAIR_MERGE", mismatch_reasons, hobj
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@
"peerOneId": "SAL1820SDPP",
"peerTwoId": "SAL1819S6K3",
"templateName": "vpc_pair",
"useVirtualPeerLink": "None"
"useVirtualPeerLink": false
},

"vpc_pair_want":
{
"peerOneId": "SAL1820SDPP",
"peerTwoId": "SAL1819S6K3",
"templateName": "vpc_pair",
"useVirtualPeerLink": "None",
"useVirtualPeerLink": false,
"nvPairs": {
"PEER2_MEMBER_INTERFACES_defaulted": false,
"PEER1_MEMBER_INTERFACES_defaulted": false,
Expand Down Expand Up @@ -110,7 +110,7 @@
"peerOneId": "SAL1820SDPP",
"peerTwoId": "SAL1819S6K3",
"templateName": "vpc_pair",
"useVirtualPeerLink": "None",
"useVirtualPeerLink": false,
"nvPairs": {
"PEER2_MEMBER_INTERFACES_defaulted": false,
"PEER1_MEMBER_INTERFACES_defaulted": false,
Expand Down Expand Up @@ -205,7 +205,7 @@
"peerOneId": "SAL1820SDPP",
"peerTwoId": "SAL1819S6K3",
"templateName": "vpc_pair",
"useVirtualPeerLink": "None"
"useVirtualPeerLink": false
},

"vpc_pair_query_cfg_00003_11":[
Expand Down Expand Up @@ -246,7 +246,7 @@
"peerOneId": "SAL1820SDPP",
"peerTwoId": "SAL1819S6K3",
"templateName": "vpc_pair",
"useVirtualPeerLink": "None",
"useVirtualPeerLink": false,
"nvPairs": {
"PEER2_MEMBER_INTERFACES_defaulted": false,
"PEER1_MEMBER_INTERFACES_defaulted": false,
Expand Down Expand Up @@ -289,7 +289,7 @@
"peerOneId": "SAL1820SDPP",
"peerTwoId": "SAL1819S6K3",
"templateName": "vpc_pair",
"useVirtualPeerLink": "None"
"useVirtualPeerLink": false
},

"vpc_pair_vpc_info_00005":
Expand All @@ -298,7 +298,7 @@
"peerOneId": "10.122.84.174",
"peerTwoId": "10.122.84.175",
"templateName": "vpc_pair",
"useVirtualPeerLink": "None",
"useVirtualPeerLink": false,
"profile": {
"ADMIN_STATE": true,
"ALLOWED_VLANS": "",
Expand Down Expand Up @@ -339,7 +339,7 @@
"peerOneId": "10.122.85.174",
"peerTwoId": "10.122.85.175",
"templateName": "vpc_pair",
"useVirtualPeerLink": "None",
"useVirtualPeerLink": false,
"profile": {
"ADMIN_STATE": true,
"ALLOWED_VLANS": "",
Expand Down Expand Up @@ -380,7 +380,7 @@
"peerOneId": "10.122.86.174",
"peerTwoId": "10.122.86.175",
"templateName": "vpc_pair",
"useVirtualPeerLink": "None",
"useVirtualPeerLink": false,
"profile": {
"ADMIN_STATE": true,
"ALLOWED_VLANS": "",
Expand Down Expand Up @@ -497,7 +497,7 @@
"peerOneId": "SAL1820SDPP",
"peerTwoId": "SAL1819S6K3",
"templateName": "vpc_pair",
"useVirtualPeerLink": "None",
"useVirtualPeerLink": false,
"nvPairs": {
"PEER2_MEMBER_INTERFACES_defaulted": false,
"PEER1_MEMBER_INTERFACES_defaulted": false,
Expand Down Expand Up @@ -538,7 +538,7 @@
"peerOneId": "SAL1820SDPP",
"peerTwoId": "SAL1819S6K3",
"templateName": "vpc_pair",
"useVirtualPeerLink": "None",
"useVirtualPeerLink": false,
"nvPairs": {
"PEER2_MEMBER_INTERFACES_defaulted": false,
"PEER1_MEMBER_INTERFACES_defaulted": false,
Expand Down Expand Up @@ -579,7 +579,7 @@
"peerOneId": "SAL1820SDPQ",
"peerTwoId": "SAL1819S6K4",
"templateName": "vpc_pair",
"useVirtualPeerLink": "None",
"useVirtualPeerLink": false,
"profile": {
"PEER2_MEMBER_INTERFACES_defaulted": false,
"PEER1_MEMBER_INTERFACES_defaulted": false,
Expand Down Expand Up @@ -620,7 +620,7 @@
"peerOneId": "SAL1820SDPR",
"peerTwoId": "SAL1819S6K5",
"templateName": "vpc_pair",
"useVirtualPeerLink": "None",
"useVirtualPeerLink": false,
"profile": {
"PEER2_MEMBER_INTERFACES_defaulted": false,
"PEER1_MEMBER_INTERFACES_defaulted": false,
Expand Down Expand Up @@ -1001,7 +1001,7 @@
"peerOneId": "SAL1820SDPP",
"peerTwoId": "SAL1819S6K3",
"templateName": "vpc_pair",
"useVirtualPeerLink": null
"useVirtualPeerLink": false
},

"vpc_pair_del_list_1": [
Expand All @@ -1025,7 +1025,7 @@
"peerOneId": "SAL1820SDPP",
"peerTwoId": "SAL1819S6K3",
"templateName": "vpc_pair",
"useVirtualPeerLink":null,
"useVirtualPeerLink": false,
"nvPairs": {
"ADMIN_STATE": true,
"ALLOWED_VLANS": "all",
Expand Down Expand Up @@ -1062,7 +1062,7 @@
"peerOneId": "SAL1820SDPQ",
"peerTwoId": "SAL1819S6K4",
"templateName": "vpc_pair",
"useVirtualPeerLink":null,
"useVirtualPeerLink": false,
"nvPairs": {
"ADMIN_STATE": true,
"ALLOWED_VLANS": "all",
Expand Down Expand Up @@ -1099,7 +1099,7 @@
"peerOneId": "SAL1820SDPR",
"peerTwoId": "SAL1819S6K5",
"templateName": "vpc_pair",
"useVirtualPeerLink":null,
"useVirtualPeerLink": false,
"nvPairs": {
"ADMIN_STATE": true,
"ALLOWED_VLANS": "all",
Expand Down Expand Up @@ -1138,7 +1138,7 @@
"peerOneId": "SAL1820SDPP",
"peerTwoId": "SAL1819S6K3",
"templateName": "vpc_pair",
"useVirtualPeerLink":null,
"useVirtualPeerLink": false,
"nvPairs": {
"ADMIN_STATE": true,
"ALLOWED_VLANS": "all",
Expand Down Expand Up @@ -1175,7 +1175,7 @@
"peerOneId": "SAL1820SDPQ",
"peerTwoId": "SAL1819S6K4",
"templateName": "vpc_pair",
"useVirtualPeerLink":null,
"useVirtualPeerLink": false,
"nvPairs": {
"ADMIN_STATE": true,
"ALLOWED_VLANS": "all",
Expand Down Expand Up @@ -1212,7 +1212,7 @@
"peerOneId": "SAL1820SDPR",
"peerTwoId": "SAL1819S6K5",
"templateName": "vpc_pair",
"useVirtualPeerLink":null,
"useVirtualPeerLink": false,
"nvPairs": {
"ADMIN_STATE": true,
"ALLOWED_VLANS": "all",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1208,7 +1208,7 @@
"recommendationReason": "Switches have same role and support Virtual Fabric Peering",
"recommended": "True",
"serialNumber": "FDO24020JMT",
"useVirtualPeerlink": "False",
"useVirtualPeerlink": false,
"uuid": "None",
"vdcId": 0,
"vdcName": "None"
Expand Down