From 970d120ad208359fe55de4b28d84577daf931d4a Mon Sep 17 00:00:00 2001
From: praveenramoorthy <62758226+praveenramoorthy@users.noreply.github.com>
Date: Fri, 28 Apr 2023 10:05:38 +0530
Subject: [PATCH 1/8] Vrf lite enhancements (#219)
* vrf lite enhancements and fixes
* vrf lite enhancements and fixes
* vrf lite doc update
* vrf lite enhancements
* vrf lite enhancements
* vrf lite enhancements
* vrf lite enhancements
* vrf lite enhancements - Review comments addressed
---
docs/cisco.dcnm.dcnm_vrf_module.rst | 15 +-
plugins/action/dcnm_vrf.py | 16 +
plugins/modules/dcnm_inventory.py | 3 -
plugins/modules/dcnm_links.py | 2 -
plugins/modules/dcnm_network.py | 1 -
plugins/modules/dcnm_resource_manager.py | 1 -
plugins/modules/dcnm_rest.py | 1 -
plugins/modules/dcnm_vrf.py | 342 ++++++++++------
.../targets/dcnm_vrf/tests/dcnm/deleted.yaml | 23 +-
.../targets/dcnm_vrf/tests/dcnm/merged.yaml | 36 +-
.../dcnm_vrf/tests/dcnm/overridden.yaml | 22 +-
.../targets/dcnm_vrf/tests/dcnm/query.yaml | 10 -
.../targets/dcnm_vrf/tests/dcnm/replaced.yaml | 25 +-
.../dcnm/self-contained-tests/vrf_lite.yaml | 383 ++++++++++++++++++
.../unit/modules/dcnm/fixtures/dcnm_vrf.json | 43 ++
tests/unit/modules/dcnm/test_dcnm_vrf.py | 18 +-
16 files changed, 730 insertions(+), 211 deletions(-)
create mode 100644 tests/integration/targets/dcnm_vrf/tests/dcnm/self-contained-tests/vrf_lite.yaml
diff --git a/docs/cisco.dcnm.dcnm_vrf_module.rst b/docs/cisco.dcnm.dcnm_vrf_module.rst
index b09eaa15e..48db1acb6 100644
--- a/docs/cisco.dcnm.dcnm_vrf_module.rst
+++ b/docs/cisco.dcnm.dcnm_vrf_module.rst
@@ -292,7 +292,6 @@ Parameters
string
- / required
@@ -1099,15 +1098,23 @@ Examples
- ip_address: 192.168.1.224
- ip_address: 192.168.1.225
vrf_lite:
- # All parameters under vrf_lite except peer_vrf are optional and
- # will be supplied by DCNM when omitted in the playbook
- - peer_vrf: test_vrf_1 # peer_vrf is mandatory
+ # All parameters under vrf_lite are optional
+ # For best results in VRF LITE idempotence checks and
+ # configurations specify all possible vrf_lite parameters
+ - peer_vrf: test_vrf_1 # optional
interface: Ethernet1/16 # optional
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
neighbor_ipv6: 2010::10:34:0:3 # optional
dot1q: 2 # dot1q can be got from dcnm/optional
+ - peer_vrf: test_vrf_2 # optional
+ interface: Ethernet1/17 # optional
+ ipv4_addr: 20.33.0.2/30 # optional
+ neighbor_ipv4: 20.33.0.1 # optional
+ ipv6_addr: 3010::10:34:0:7/64 # optional
+ neighbor_ipv6: 3010::10:34:0:3 # optional
+ dot1q: 3 # dot1q can be got from dcnm/optional
# The two VRFs below will be replaced in the target fabric.
- name: Replace vrfs
diff --git a/plugins/action/dcnm_vrf.py b/plugins/action/dcnm_vrf.py
index 00bb9695f..4c0ade744 100644
--- a/plugins/action/dcnm_vrf.py
+++ b/plugins/action/dcnm_vrf.py
@@ -38,6 +38,22 @@ def run(self, tmp=None, task_vars=None):
if "vlan_id" in at:
msg = "Playbook parameter vlan_id should not be specified under the attach: block. Please specify this under the config: block instead" # noqa
return {"failed": True, "msg": msg}
+ if "vrf_lite" in at:
+ try:
+ for vl in at["vrf_lite"]:
+ if (
+ not vl.get("interface")
+ ):
+ msg = (
+ "'interface' parameter is not specified in playbook under 'vrf_lite' config. "
+ "Idempotence check will happen based on first available best match. "
+ "While attaching, first available extension will be attached for VRF LITE. "
+ "For best results specify all possible vrf_lite parameters."
+ )
+ display.warning(msg)
+ except TypeError:
+ msg = "Please specifiy at least one VRF LITE parameter in attach"
+ return {"failed": True, "msg": msg}
self.result = super(ActionModule, self).run(task_vars=task_vars)
return self.result
diff --git a/plugins/modules/dcnm_inventory.py b/plugins/modules/dcnm_inventory.py
index 0550c27a3..f7a576ea7 100644
--- a/plugins/modules/dcnm_inventory.py
+++ b/plugins/modules/dcnm_inventory.py
@@ -1316,7 +1316,6 @@ def set_lancred_switch(self, set_lan):
def lancred_all_switches(self):
- want_list = []
# Get Fabric Inventory Details
method = "GET"
path = "/fm/fmrest/lanConfig/getLanSwitchCredentials"
@@ -1356,7 +1355,6 @@ def lancred_all_switches(self):
def assign_role(self):
- want_list = []
method = "GET"
path = "/rest/control/fabrics/{0}/inventory".format(self.fabric)
if self.nd:
@@ -1484,7 +1482,6 @@ def config_save(self):
def config_deploy(self):
# config-deploy
- sernos = []
method = "POST"
path = "/rest/control/fabrics/{0}".format(self.fabric)
if self.nd:
diff --git a/plugins/modules/dcnm_links.py b/plugins/modules/dcnm_links.py
index 41567ab71..d3d28814c 100644
--- a/plugins/modules/dcnm_links.py
+++ b/plugins/modules/dcnm_links.py
@@ -776,8 +776,6 @@
dcnm_get_ip_addr_info,
)
-from datetime import datetime
-
# Resource Class object which includes all the required methods and data to configure and maintain Links
class DcnmLinks:
diff --git a/plugins/modules/dcnm_network.py b/plugins/modules/dcnm_network.py
index 4dd00b7a8..6c33c50aa 100644
--- a/plugins/modules/dcnm_network.py
+++ b/plugins/modules/dcnm_network.py
@@ -470,7 +470,6 @@
dcnm_version_supported,
dcnm_get_url,
)
-from ansible.module_utils.connection import Connection
from ansible.module_utils.basic import AnsibleModule
diff --git a/plugins/modules/dcnm_resource_manager.py b/plugins/modules/dcnm_resource_manager.py
index f953d1a7f..5cb774540 100644
--- a/plugins/modules/dcnm_resource_manager.py
+++ b/plugins/modules/dcnm_resource_manager.py
@@ -278,7 +278,6 @@
"""
-import time
import json
import copy
import ipaddress
diff --git a/plugins/modules/dcnm_rest.py b/plugins/modules/dcnm_rest.py
index 9ef0a0a51..84eda8ed1 100644
--- a/plugins/modules/dcnm_rest.py
+++ b/plugins/modules/dcnm_rest.py
@@ -90,7 +90,6 @@
import json
from json.decoder import JSONDecodeError
-from ansible.module_utils.connection import Connection
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.cisco.dcnm.plugins.module_utils.network.dcnm.dcnm import (
dcnm_send,
diff --git a/plugins/modules/dcnm_vrf.py b/plugins/modules/dcnm_vrf.py
index cf92a2a05..744a87acd 100644
--- a/plugins/modules/dcnm_vrf.py
+++ b/plugins/modules/dcnm_vrf.py
@@ -309,7 +309,7 @@
description:
- VRF Name to which this extension is attached
type: str
- required: true
+ required: false
interface:
description:
- Interface of the switch which is connected to the edge router
@@ -448,15 +448,23 @@
- ip_address: 192.168.1.224
- ip_address: 192.168.1.225
vrf_lite:
- # All parameters under vrf_lite except peer_vrf are optional and
- # will be supplied by DCNM when omitted in the playbook
- - peer_vrf: test_vrf_1 # peer_vrf is mandatory
+ # All parameters under vrf_lite are optional
+ # For best results in VRF LITE idempotence checks and
+ # configurations specify all possible vrf_lite parameters
+ - peer_vrf: test_vrf_1 # optional
interface: Ethernet1/16 # optional
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
neighbor_ipv6: 2010::10:34:0:3 # optional
dot1q: 2 # dot1q can be got from dcnm/optional
+ - peer_vrf: test_vrf_2 # optional
+ interface: Ethernet1/17 # optional
+ ipv4_addr: 20.33.0.2/30 # optional
+ neighbor_ipv4: 20.33.0.1 # optional
+ ipv6_addr: 3010::10:34:0:7/64 # optional
+ neighbor_ipv6: 3010::10:34:0:3 # optional
+ dot1q: 3 # dot1q can be got from dcnm/optional
# The two VRFs below will be replaced in the target fabric.
- name: Replace vrfs
@@ -643,7 +651,7 @@ def __init__(self, module):
self.failed_to_rollback = False
self.WAIT_TIME_FOR_DELETE_LOOP = 5 # in seconds
- def diff_for_attach_deploy(self, want_a, have_a):
+ def diff_for_attach_deploy(self, want_a, have_a, replace=False):
attach_list = []
@@ -668,51 +676,91 @@ def diff_for_attach_deploy(self, want_a, have_a):
want_e = ast.literal_eval(want_ext_values["VRF_LITE_CONN"])
have_e = ast.literal_eval(have_ext_values["VRF_LITE_CONN"])
- if (
- want_e["VRF_LITE_CONN"][0]["IF_NAME"]
- == have_e["VRF_LITE_CONN"][0]["IF_NAME"]
- ):
- if (
- want_e["VRF_LITE_CONN"][0]["DOT1Q_ID"]
- == have_e["VRF_LITE_CONN"][0]["DOT1Q_ID"]
- ):
- if (
- want_e["VRF_LITE_CONN"][0]["IP_MASK"]
- == have_e["VRF_LITE_CONN"][0]["IP_MASK"]
- ):
+ for wlite in want_e["VRF_LITE_CONN"]:
+ for hlite in have_e["VRF_LITE_CONN"]:
+ if wlite["IF_NAME"]:
+ if (
+ wlite["IF_NAME"]
+ == hlite["IF_NAME"]
+ ):
+ found = True
+ else:
+ found = False
+ continue
+
+ if wlite["DOT1Q_ID"]:
+ if (
+ wlite["DOT1Q_ID"]
+ == hlite["DOT1Q_ID"]
+ ):
+ found = True
+ else:
+ found = False
+ continue
+
+ if wlite["IP_MASK"]:
+ if (
+ wlite["IP_MASK"]
+ == hlite["IP_MASK"]
+ ):
+ found = True
+ else:
+ found = False
+ continue
+
+ if wlite["NEIGHBOR_IP"]:
+ if (
+ wlite["NEIGHBOR_IP"]
+ == hlite["NEIGHBOR_IP"]
+ ):
+ found = True
+ else:
+ found = False
+ continue
+
+ if wlite["IPV6_MASK"]:
+ if (
+ wlite["IPV6_MASK"]
+ == hlite["IPV6_MASK"]
+ ):
+ found = True
+ else:
+ found = False
+ continue
+
+ if wlite["IPV6_NEIGHBOR"]:
+ if (
+ wlite["IPV6_NEIGHBOR"]
+ == hlite["IPV6_NEIGHBOR"]
+ ):
+ found = True
+ else:
+ found = False
+ continue
+
+ if wlite["PEER_VRF_NAME"]:
if (
- want_e["VRF_LITE_CONN"][0]["NEIGHBOR_IP"]
- == have_e["VRF_LITE_CONN"][0]["NEIGHBOR_IP"]
+ wlite["PEER_VRF_NAME"]
+ == hlite["PEER_VRF_NAME"]
):
- if (
- want_e["VRF_LITE_CONN"][0]["IPV6_MASK"]
- == have_e["VRF_LITE_CONN"][0][
- "IPV6_MASK"
- ]
- ):
- if (
- want_e["VRF_LITE_CONN"][0][
- "IPV6_NEIGHBOR"
- ]
- == have_e["VRF_LITE_CONN"][0][
- "IPV6_NEIGHBOR"
- ]
- ):
- if (
- want_e["VRF_LITE_CONN"][0][
- "PEER_VRF_NAME"
- ]
- == have_e["VRF_LITE_CONN"][0][
- "PEER_VRF_NAME"
- ]
- ):
- found = True
+ found = True
+ else:
+ found = False
+ continue
elif (
want["extensionValues"] != ""
- or have["extensionValues"] != ""
+ and have["extensionValues"] == ""
):
found = False
+ elif (
+ want["extensionValues"] == ""
+ and have["extensionValues"] != ""
+ ):
+ if replace:
+ found = False
+ else:
+ found = True
else:
found = True
@@ -729,6 +777,9 @@ def diff_for_attach_deploy(self, want_a, have_a):
if bool(have["deployment"]) is not bool(want["deployment"]):
dep_vrf = True
+ if found:
+ break
+
if not found:
if bool(want["isAttached"]):
del want["isAttached"]
@@ -767,6 +818,11 @@ def update_attach_params(self, attach, vrf_name, deploy, vlanId):
self.module.fail_json(msg=msg)
ext_values = {}
+ ext_values["VRF_LITE_CONN"] = []
+ ms_con = {}
+ ms_con["MULTISITE_CONN"] = []
+ ext_values["MULTISITE_CONN"] = json.dumps(ms_con)
+
if attach["vrf_lite"]:
"""Before apply the vrf_lite config, need double check if the swtich role is started wth Border"""
r = re.search(r"\bborder\b", role.lower())
@@ -780,43 +836,70 @@ def update_attach_params(self, attach, vrf_name, deploy, vlanId):
for a_l in at_lite:
if (
a_l["interface"]
- and a_l["dot1q"]
- and a_l["ipv4_addr"]
- and a_l["neighbor_ipv4"]
- and a_l["ipv6_addr"]
- and a_l["neighbor_ipv6"]
- and a_l["peer_vrf"]
+ or a_l["dot1q"]
+ or a_l["ipv4_addr"]
+ or a_l["neighbor_ipv4"]
+ or a_l["ipv6_addr"]
+ or a_l["neighbor_ipv6"]
+ or a_l["peer_vrf"]
):
- """if all the elements are provided by the user in the playbook fill the extension values"""
+ """if vrf lite elements are provided by the user in the playbook fill the extension values"""
vrflite_con = {}
vrflite_con["VRF_LITE_CONN"] = []
vrflite_con["VRF_LITE_CONN"].append({})
- vrflite_con["VRF_LITE_CONN"][0]["IF_NAME"] = a_l["interface"]
- vrflite_con["VRF_LITE_CONN"][0]["DOT1Q_ID"] = str(a_l["dot1q"])
- vrflite_con["VRF_LITE_CONN"][0]["IP_MASK"] = a_l["ipv4_addr"]
- vrflite_con["VRF_LITE_CONN"][0]["NEIGHBOR_IP"] = a_l[
- "neighbor_ipv4"
- ]
- vrflite_con["VRF_LITE_CONN"][0]["NEIGHBOR_ASN"] = "65535"
- vrflite_con["VRF_LITE_CONN"][0]["IPV6_MASK"] = a_l["ipv6_addr"]
- vrflite_con["VRF_LITE_CONN"][0]["IPV6_NEIGHBOR"] = a_l[
- "neighbor_ipv6"
- ]
- vrflite_con["VRF_LITE_CONN"][0]["AUTO_VRF_LITE_FLAG"] = "false"
- vrflite_con["VRF_LITE_CONN"][0]["PEER_VRF_NAME"] = a_l["peer_vrf"]
+ if a_l["interface"]:
+ vrflite_con["VRF_LITE_CONN"][0]["IF_NAME"] = a_l["interface"]
+ else:
+ vrflite_con["VRF_LITE_CONN"][0]["IF_NAME"] = ""
+
+ if a_l["dot1q"]:
+ vrflite_con["VRF_LITE_CONN"][0]["DOT1Q_ID"] = str(a_l["dot1q"])
+ else:
+ vrflite_con["VRF_LITE_CONN"][0]["DOT1Q_ID"] = ""
+
+ if a_l["ipv4_addr"]:
+ vrflite_con["VRF_LITE_CONN"][0]["IP_MASK"] = a_l["ipv4_addr"]
+ else:
+ vrflite_con["VRF_LITE_CONN"][0]["IP_MASK"] = ""
+
+ if a_l["neighbor_ipv4"]:
+ vrflite_con["VRF_LITE_CONN"][0]["NEIGHBOR_IP"] = a_l[
+ "neighbor_ipv4"
+ ]
+ else:
+ vrflite_con["VRF_LITE_CONN"][0]["NEIGHBOR_IP"] = ""
+
+ if a_l["ipv6_addr"]:
+ vrflite_con["VRF_LITE_CONN"][0]["IPV6_MASK"] = a_l["ipv6_addr"]
+ else:
+ vrflite_con["VRF_LITE_CONN"][0]["IPV6_MASK"] = ""
+
+ if a_l["neighbor_ipv6"]:
+ vrflite_con["VRF_LITE_CONN"][0]["IPV6_NEIGHBOR"] = a_l[
+ "neighbor_ipv6"
+ ]
+ else:
+ vrflite_con["VRF_LITE_CONN"][0]["IPV6_NEIGHBOR"] = ""
+
+ if a_l["peer_vrf"]:
+ vrflite_con["VRF_LITE_CONN"][0]["PEER_VRF_NAME"] = a_l["peer_vrf"]
+ else:
+ vrflite_con["VRF_LITE_CONN"][0]["PEER_VRF_NAME"] = ""
+
vrflite_con["VRF_LITE_CONN"][0][
"VRF_LITE_JYTHON_TEMPLATE"
] = "Ext_VRF_Lite_Jython"
- ext_values["VRF_LITE_CONN"] = json.dumps(vrflite_con)
+ if (ext_values["VRF_LITE_CONN"]):
+ ext_values["VRF_LITE_CONN"]["VRF_LITE_CONN"].extend(vrflite_con["VRF_LITE_CONN"])
+ else:
+ ext_values["VRF_LITE_CONN"] = vrflite_con
- ms_con = {}
- ms_con["MULTISITE_CONN"] = []
- ext_values["MULTISITE_CONN"] = json.dumps(ms_con)
+ ext_values["VRF_LITE_CONN"] = json.dumps(ext_values["VRF_LITE_CONN"])
- self.vrflitevalues = ext_values
- self.vrf_ext = True
+ self.vrflitevalues = ext_values
+ self.vrf_ext = True
attach.update({"fabric": self.fabric})
attach.update({"vrfName": vrf_name})
@@ -831,7 +914,6 @@ def update_attach_params(self, attach, vrf_name, deploy, vlanId):
"instanceValues": '{"loopbackId":"","loopbackIpAddress":"","loopbackIpV6Address":""}'
}
)
- del attach["vrf_lite"]
else:
attach.update({"extensionValues": ""})
attach.update({"instanceValues": ""})
@@ -1247,8 +1329,10 @@ def get_have(self):
ext_values = ast.literal_eval(
ext_values["VRF_LITE_CONN"]
)
- for ev in ext_values["VRF_LITE_CONN"]:
- extension_values = {}
+ extension_values = {}
+ extension_values["VRF_LITE_CONN"] = []
+
+ for ev in ext_values.get("VRF_LITE_CONN"):
vrflite_con = {}
vrflite_con["VRF_LITE_CONN"] = []
@@ -1277,24 +1361,30 @@ def get_have(self):
] = "false"
vrflite_con["VRF_LITE_CONN"][0][
"PEER_VRF_NAME"
- ] = attach["vrfName"]
+ ] = ev["PEER_VRF_NAME"]
vrflite_con["VRF_LITE_CONN"][0][
"VRF_LITE_JYTHON_TEMPLATE"
] = "Ext_VRF_Lite_Jython"
- extension_values["VRF_LITE_CONN"] = json.dumps(
- vrflite_con
- )
- ms_con = {}
- ms_con["MULTISITE_CONN"] = []
- extension_values["MULTISITE_CONN"] = json.dumps(
- ms_con
- )
- e_values = json.dumps(extension_values).replace(
- " ", ""
- )
+ if (extension_values["VRF_LITE_CONN"]):
+ extension_values["VRF_LITE_CONN"]["VRF_LITE_CONN"].extend(vrflite_con["VRF_LITE_CONN"])
+ else:
+ extension_values["VRF_LITE_CONN"] = vrflite_con
+
+ extension_values["VRF_LITE_CONN"] = json.dumps(
+ extension_values["VRF_LITE_CONN"]
+ )
+
+ ms_con = {}
+ ms_con["MULTISITE_CONN"] = []
+ extension_values["MULTISITE_CONN"] = json.dumps(
+ ms_con
+ )
+ e_values = json.dumps(extension_values).replace(
+ " ", ""
+ )
- attach.update({"extensionValues": e_values})
+ attach.update({"extensionValues": e_values})
if dep_vrf:
upd_vrfs += dep_vrf + ","
@@ -1476,7 +1566,7 @@ def get_diff_replace(self):
all_vrfs = ""
- self.get_diff_merge()
+ self.get_diff_merge(replace=True)
diff_create = self.diff_create
diff_attach = self.diff_attach
diff_deploy = self.diff_deploy
@@ -1557,7 +1647,7 @@ def get_diff_replace(self):
self.diff_attach = diff_attach
self.diff_deploy = diff_deploy
- def get_diff_merge(self):
+ def get_diff_merge(self, replace=False):
# Special cases:
# 1. Auto generate vrfId if its not mentioned by user:
@@ -1709,7 +1799,7 @@ def get_diff_merge(self):
if want_a["vrfName"] == have_a["vrfName"]:
attach_found = True
diff, vrf = self.diff_for_attach_deploy(
- want_a["lanAttachList"], have_a["lanAttachList"]
+ want_a["lanAttachList"], have_a["lanAttachList"], replace
)
if diff:
base = want_a.copy()
@@ -2173,15 +2263,17 @@ def push_to_remote(self, is_rollback=False):
"""Before apply the vrf_lite config, need double check if the switch role is started wth Border"""
r = re.search(r"\bborder\b", self.role.lower())
if not r:
- msg = "VRF LITE cannot be attached to switch {0} with role {1}".format(
- v_a["ip_address"], self.role
- )
+ for ip, ser in self.ip_sn.items():
+ if ser == v_a["serialNumber"]:
+ msg = "VRF LITE cannot be attached to switch {0} with role {1}".format(
+ ip, self.role
+ )
self.module.fail_json(msg=msg)
"""Get the IP/Interface that is connected to edge router can be get from below query"""
method = "GET"
path = self.paths["GET_VRF_SWITCH"].format(
- self.fabric, self.diff_attach[0]["vrfName"], self.serial
+ self.fabric, v_a["vrfName"], v_a["serialNumber"]
)
lite_objects = dcnm_send(self.module, method, path)
@@ -2193,12 +2285,15 @@ def push_to_remote(self, is_rollback=False):
"extensionPrototypeValues"
]
ext_values = None
+ extension_values = {}
+ extension_values["VRF_LITE_CONN"] = []
+ extension_values["MULTISITE_CONN"] = []
+
for ext_l in lite:
if str(ext_l.get("extensionType")) == "VRF_LITE":
ext_values = ext_l["extensionValues"]
ext_values = ast.literal_eval(ext_values)
- extension_values = {}
- for ad_l in v_a["vrf_lite"]:
+ for ad_l in v_a.get("vrf_lite"):
vrflite_con = {}
vrflite_con["VRF_LITE_CONN"] = []
vrflite_con["VRF_LITE_CONN"].append({})
@@ -2263,15 +2358,23 @@ def push_to_remote(self, is_rollback=False):
vrflite_con["VRF_LITE_CONN"][0][
"AUTO_VRF_LITE_FLAG"
] = ext_values["AUTO_VRF_LITE_FLAG"]
- vrflite_con["VRF_LITE_CONN"][0][
- "PEER_VRF_NAME"
- ] = ad_l["peer_vrf"]
+
+ if ad_l["peer_vrf"]:
+ vrflite_con["VRF_LITE_CONN"][0][
+ "PEER_VRF_NAME"
+ ] = ad_l["peer_vrf"]
+ else:
+ vrflite_con["VRF_LITE_CONN"][0][
+ "PEER_VRF_NAME"
+ ] = ext_values["PEER_VRF_NAME"]
+
vrflite_con["VRF_LITE_CONN"][0][
"VRF_LITE_JYTHON_TEMPLATE"
] = "Ext_VRF_Lite_Jython"
- extension_values["VRF_LITE_CONN"] = json.dumps(
- vrflite_con
- )
+ if (extension_values["VRF_LITE_CONN"]):
+ extension_values["VRF_LITE_CONN"]["VRF_LITE_CONN"].extend(vrflite_con["VRF_LITE_CONN"])
+ else:
+ extension_values["VRF_LITE_CONN"] = vrflite_con
ms_con = {}
ms_con["MULTISITE_CONN"] = []
@@ -2279,19 +2382,27 @@ def push_to_remote(self, is_rollback=False):
ms_con
)
- v_a["extensionValues"] = json.dumps(
- extension_values
- ).replace(" ", "")
- v_a[
- "instanceValues"
- ] = '{"loopbackId":"","loopbackIpAddress":"","loopbackIpV6Address":""}'
- del v_a["vrf_lite"]
+ del v_a["vrf_lite"][0]
if ext_values is None:
- msg = "There is no VRF LITE capable interface on this witch {0}".format(
- v_a["ip_address"]
- )
+ for ip, ser in self.ip_sn.items():
+ if ser == v_a["serialNumber"]:
+ msg = "There is no VRF LITE capable interface on this switch {0}".format(
+ ip
+ )
self.module.fail_json(msg=msg)
+ else:
+ extension_values["VRF_LITE_CONN"] = json.dumps(
+ extension_values["VRF_LITE_CONN"]
+ )
+ v_a["extensionValues"] = json.dumps(
+ extension_values
+ ).replace(" ", "")
+ v_a[
+ "instanceValues"
+ ] = '{"loopbackId":"","loopbackIpAddress":"","loopbackIpV6Address":""}'
+ if v_a.get("vrf_lite", None) is not None:
+ del v_a["vrf_lite"]
else:
if v_a.get("vrf_lite", None) is not None:
@@ -2414,11 +2525,11 @@ def validate_input(self):
att_spec = dict(
ip_address=dict(required=True, type="str"),
deploy=dict(type="bool", default=True),
- vrf_lite=dict(type="list", default=[]),
+ vrf_lite=dict(type="list"),
)
lite_spec = dict(
interface=dict(type="str"),
- peer_vrf=dict(required=True, type="str"),
+ peer_vrf=dict(type="str"),
ipv4_addr=dict(type="ipv4_subnet"),
neighbor_ipv4=dict(type="ipv4"),
ipv6_addr=dict(type="ipv6"),
@@ -2444,11 +2555,6 @@ def validate_input(self):
# msg = "ip_address and vlan_id are mandatory under attach parameters"
if "ip_address" not in attach:
msg = "ip_address is mandatory under attach parameters"
- if attach.get("vrf_lite"):
- for vl in attach["vrf_lite"]:
- if not vl.get("peer_vrf"):
- msg = "peer_vrf is mandatory under attach VRF LITE parameters"
-
else:
if state == "merged" or state == "overridden" or state == "replaced":
msg = "config: element is mandatory for this state {0}".format(
@@ -2550,7 +2656,7 @@ def validate_input(self):
)
lite_spec = dict(
interface=dict(type="str"),
- peer_vrf=dict(required=True, type="str"),
+ peer_vrf=dict(type="str"),
ipv4_addr=dict(type="ipv4_subnet"),
neighbor_ipv4=dict(type="ipv4"),
ipv6_addr=dict(type="ipv6"),
diff --git a/tests/integration/targets/dcnm_vrf/tests/dcnm/deleted.yaml b/tests/integration/targets/dcnm_vrf/tests/dcnm/deleted.yaml
index 0f7b08217..8c120bbc4 100644
--- a/tests/integration/targets/dcnm_vrf/tests/dcnm/deleted.yaml
+++ b/tests/integration/targets/dcnm_vrf/tests/dcnm/deleted.yaml
@@ -35,8 +35,6 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
@@ -80,8 +78,6 @@
vrf_id: 9008011
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
- source: null
- service_vrf_template: null
register: result
- assert:
@@ -118,13 +114,11 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- - peer_vrf: ansible-vrf-int1 # peer_vrf is mandatory
+ - peer_vrf: ansible-vrf-int1 # optional
interface: "{{ ansible_int1 }}" # optional
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
@@ -168,13 +162,11 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- - peer_vrf: ansible-vrf-int1 # peer_vrf is mandatory
+ - peer_vrf: ansible-vrf-int1 # optional
interface: "{{ ansible_int1 }}" # optional
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
@@ -208,6 +200,13 @@
- 'result.response|length == 0'
- 'result.diff|length == 0'
+- name: QUERY - sleep for 40 seconds for DCNM to completely update the state
+ # The vrf lite profile removal returns ok for deployment, but the switch takes time to remove
+ # the profile so wait for some time before creating a new vrf, else the switch goes into
+ # OUT-OF-SYNC state
+ wait_for:
+ timeout: 40
+
- name: DELETED - Create, Attach and Deploy new VRF - VLAN/VRF LITE EXTENSION Provided by the User in one switch
cisco.dcnm.dcnm_vrf:
fabric: "{{ test_fabric }}"
@@ -218,13 +217,11 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- - peer_vrf: ansible-vrf-int1 # peer_vrf is mandatory
+ - peer_vrf: ansible-vrf-int1 # optional
interface: "{{ ansible_int1 }}" # optional
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
diff --git a/tests/integration/targets/dcnm_vrf/tests/dcnm/merged.yaml b/tests/integration/targets/dcnm_vrf/tests/dcnm/merged.yaml
index 7ee0dbd0c..5cc6de3e0 100644
--- a/tests/integration/targets/dcnm_vrf/tests/dcnm/merged.yaml
+++ b/tests/integration/targets/dcnm_vrf/tests/dcnm/merged.yaml
@@ -39,8 +39,6 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
@@ -94,8 +92,6 @@
vrf_id: 9008011
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
@@ -150,13 +146,11 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- - peer_vrf: ansible-vrf-int1 # peer_vrf is mandatory
+ - peer_vrf: ansible-vrf-int1 # optional
interface: "{{ ansible_int1 }}" # optional
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
@@ -204,7 +198,14 @@
fabric: "{{ test_fabric }}"
state: deleted
-- name: MERGED - Create, Attach and Deploy new VRF - VRF/VRF LITE EXTENSION Provided by the DCNM - Only Mandatory option - Rest are populated from DCNM
+- name: QUERY - sleep for 40 seconds for DCNM to completely remove lite profile
+ # The vrf lite profile removal returns ok for deployment, but the switch takes time to remove
+ # the profile so wait for some time before creating a new vrf, else the switch goes into
+ # OUT-OF-SYNC state
+ wait_for:
+ timeout: 40
+
+- name: MERGED - Create, Attach and Deploy new VRF - VRF/VRF LITE EXTENSION Provided by the DCNM - one optional - Rest are populated from DCNM
cisco.dcnm.dcnm_vrf:
fabric: "{{ test_fabric }}"
state: merged
@@ -214,13 +215,11 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- - peer_vrf: ansible-vrf-int1 # peer_vrf is mandatory
+ - peer_vrf: ansible-vrf-int1 # optional
deploy: true
register: result
@@ -257,8 +256,6 @@
vrf_id: 9008012
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
@@ -280,8 +277,6 @@
vrf_id: 9008012000000000
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
@@ -294,7 +289,7 @@
- 'result.changed == false'
- '"The item exceeds the allowed range of max" in result.msg'
-- name: MERGED - Create, Attach and Deploy new VRF - Try configuring VRF LITE without mandatory parameter
+- name: MERGED - Create, Attach and Deploy new VRF - Try configuring VRF LITE without any parameter
cisco.dcnm.dcnm_vrf:
fabric: "{{ test_fabric }}"
state: merged
@@ -304,13 +299,10 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- - interface: "{{ ansible_int1 }}"
deploy: true
register: result
ignore_errors: yes
@@ -318,7 +310,7 @@
- assert:
that:
- 'result.changed == false'
- - '"peer_vrf is mandatory under attach VRF LITE parameters" in result.msg'
+ - '"Please specifiy at least one VRF LITE parameter in attach" in result.msg'
- name: MERGED - Create, Attach and Deploy new VRF - Try configuring VRF LITE to a non border switch
cisco.dcnm.dcnm_vrf:
@@ -330,12 +322,10 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
vrf_lite:
- - peer_vrf: ansible-vrf-int1 # peer_vrf is mandatory
+ - peer_vrf: ansible-vrf-int1 # optional
interface: "{{ ansible_int1 }}" # optional
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
diff --git a/tests/integration/targets/dcnm_vrf/tests/dcnm/overridden.yaml b/tests/integration/targets/dcnm_vrf/tests/dcnm/overridden.yaml
index 31dc6f8ca..aae1432fb 100644
--- a/tests/integration/targets/dcnm_vrf/tests/dcnm/overridden.yaml
+++ b/tests/integration/targets/dcnm_vrf/tests/dcnm/overridden.yaml
@@ -35,8 +35,6 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
@@ -81,8 +79,6 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
@@ -143,15 +139,13 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 1500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- - peer_vrf: ansible-vrf-int2 # peer_vrf is mandatory
+ - peer_vrf: ansible-vrf-int2 # optional
interface: "{{ ansible_int1 }}" # optional
- ipv4_addr: 10.33.0.2/30 # optional
+ ipv4_addr: 10.33.0.2/24 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
neighbor_ipv6: 2010::10:34:0:3 # optional
@@ -193,15 +187,13 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 1500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- - peer_vrf: ansible-vrf-int2 # peer_vrf is mandatory
+ - peer_vrf: ansible-vrf-int2 # optional
interface: "{{ ansible_int1 }}" # optional
- ipv4_addr: 10.33.0.7/30 # optional
+ ipv4_addr: 10.33.0.6/24 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:10/64 # optional
neighbor_ipv6: 2010::10:34:0:7 # optional
@@ -247,15 +239,13 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- - peer_vrf: ansible-vrf-int1 # peer_vrf is mandatory
+ - peer_vrf: ansible-vrf-int1 # optional
interface: "{{ ansible_int1 }}" # optional
- ipv4_addr: 10.33.0.1/30 # optional
+ ipv4_addr: 10.33.0.3/24 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:1/64 # optional
neighbor_ipv6: 2010::10:34:0:2 # optional
diff --git a/tests/integration/targets/dcnm_vrf/tests/dcnm/query.yaml b/tests/integration/targets/dcnm_vrf/tests/dcnm/query.yaml
index f30d77e4d..f14cf6075 100644
--- a/tests/integration/targets/dcnm_vrf/tests/dcnm/query.yaml
+++ b/tests/integration/targets/dcnm_vrf/tests/dcnm/query.yaml
@@ -35,8 +35,6 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
@@ -81,8 +79,6 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
@@ -132,8 +128,6 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 1500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
@@ -182,8 +176,6 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 1500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
@@ -240,8 +232,6 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
diff --git a/tests/integration/targets/dcnm_vrf/tests/dcnm/replaced.yaml b/tests/integration/targets/dcnm_vrf/tests/dcnm/replaced.yaml
index 41132de15..ca01c4df9 100644
--- a/tests/integration/targets/dcnm_vrf/tests/dcnm/replaced.yaml
+++ b/tests/integration/targets/dcnm_vrf/tests/dcnm/replaced.yaml
@@ -35,8 +35,6 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
@@ -79,8 +77,6 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
register: result
- name: Query fabric state until vrfStatus transitions to DEPLOYED state
@@ -89,7 +85,7 @@
state: query
register: query_result
until:
- - "query_result.response[0].parent.vrfStatus is search('DEPLOYED')"
+ - "query_result.response[0].parent.vrfStatus is search('NA')"
retries: 30
delay: 2
@@ -122,8 +118,6 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
@@ -176,13 +170,11 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- - peer_vrf: ansible-vrf-int1 # peer_vrf is mandatory
+ - peer_vrf: ansible-vrf-int1 # optional
interface: "{{ ansible_int1 }}" # optional
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
@@ -216,6 +208,13 @@
- '"{{ ansible_switch2 }}" in result.diff[0].attach[1].ip_address'
- 'result.diff[0].vrf_name == "ansible-vrf-int1"'
+- name: QUERY - sleep for 40 seconds for DCNM to completely update the state
+ # The vrf lite profile removal returns ok for deployment, but the switch takes time to remove
+ # the profile so wait for some time before creating a new vrf, else the switch goes into
+ # OUT-OF-SYNC state
+ wait_for:
+ timeout: 40
+
- name: REPLACED - Update existing VRF LITE extensions using Replace - Delete VRF LITE Attachment Only
cisco.dcnm.dcnm_vrf: &conf3
fabric: "{{ test_fabric }}"
@@ -226,8 +225,6 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
deploy: true
@@ -270,13 +267,11 @@
vrf_template: Default_VRF_Universal
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
- source: null
- service_vrf_template: null
attach:
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- - peer_vrf: ansible-vrf-int1 # peer_vrf is mandatory
+ - peer_vrf: ansible-vrf-int1 # optional
interface: "{{ ansible_int1 }}" # optional
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
diff --git a/tests/integration/targets/dcnm_vrf/tests/dcnm/self-contained-tests/vrf_lite.yaml b/tests/integration/targets/dcnm_vrf/tests/dcnm/self-contained-tests/vrf_lite.yaml
new file mode 100644
index 000000000..fd198af3e
--- /dev/null
+++ b/tests/integration/targets/dcnm_vrf/tests/dcnm/self-contained-tests/vrf_lite.yaml
@@ -0,0 +1,383 @@
+##############################################
+## SETUP ##
+##############################################
+
+- set_fact:
+ rest_path: "/rest/control/fabrics/{{ test_fabric }}"
+ when: controller_version == "11"
+
+- set_fact:
+ rest_path: "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{{ test_fabric }}"
+ when: controller_version >= "12"
+
+- name: MERGED - Verify if fabric is deployed.
+ cisco.dcnm.dcnm_rest:
+ method: GET
+ path: "{{ rest_path }}"
+ register: result
+
+- assert:
+ that:
+ - 'result.response.DATA != None'
+
+- name: MERGED - Clean up any existing vrfs
+ cisco.dcnm.dcnm_vrf:
+ fabric: "{{ test_fabric }}"
+ state: deleted
+
+- name: VRF LITE - sleep for 40 seconds for DCNM to completely update the state
+ wait_for:
+ timeout: 40
+
+###############################################
+### TESTS ##
+###############################################
+
+- name: VRF LITE- Create, Attach and Deploy new VRF - VLAN/VRF LITE EXTENSION Provided by the User in one switch
+ cisco.dcnm.dcnm_vrf: &conf1
+ fabric: "{{ test_fabric }}"
+ state: merged
+ config:
+ - vrf_name: ansible-vrf-int1
+ vrf_id: 9008011
+ vrf_template: Default_VRF_Universal
+ vrf_extension_template: Default_VRF_Extension_Universal
+ vlan_id: 500
+ attach:
+ - ip_address: "{{ ansible_switch1 }}"
+ - ip_address: "{{ ansible_switch2 }}"
+ vrf_lite:
+ - peer_vrf: ansible-vrf-int1 # optional
+ interface: "{{ ansible_int1 }}" # optional
+ ipv4_addr: 10.33.0.2/24 # optional
+ neighbor_ipv4: 10.33.0.1 # optional
+ ipv6_addr: 2010::10:34:0:7/64 # optional
+ neighbor_ipv6: 2010::10:34:0:3 # optional
+ dot1q: 2 # dot1q can be got from dcnm
+ deploy: true
+ register: result
+
+- name: Query fabric state until vrfStatus transitions to DEPLOYED state
+ cisco.dcnm.dcnm_vrf:
+ fabric: "{{ test_fabric }}"
+ state: query
+ register: query_result
+ until:
+ - "query_result.response[0].parent.vrfStatus is search('DEPLOYED')"
+ retries: 30
+ delay: 2
+
+- assert:
+ that:
+ - 'result.changed == true'
+ - 'result.response[0].RETURN_CODE == 200'
+ - 'result.response[1].RETURN_CODE == 200'
+ - 'result.response[2].RETURN_CODE == 200'
+ - '(result.response[1].DATA|dict2items)[0].value == "SUCCESS"'
+ - '(result.response[1].DATA|dict2items)[1].value == "SUCCESS"'
+ - 'result.diff[0].attach[0].deploy == true'
+ - 'result.diff[0].attach[1].deploy == true'
+ - '"{{ ansible_switch1 }}" in result.diff[0].attach[0].ip_address'
+ - '"{{ ansible_switch2 }}" in result.diff[0].attach[1].ip_address'
+ - 'result.diff[0].vrf_name == "ansible-vrf-int1"'
+ - '"{{ ansible_int1 }}" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+ - '"ansible-vrf-int1" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+ - '"10.33.0.2/24" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+
+- name: MERGED - conf1 - Idempotence
+ cisco.dcnm.dcnm_vrf: *conf1
+ register: result
+
+- assert:
+ that:
+ - 'result.changed == false'
+ - 'result.response|length == 0'
+
+- name: VRF LITE- Attach and Deploy second VRF LITE EXTENSION Provided by the User in one switch
+ cisco.dcnm.dcnm_vrf: &conf2
+ fabric: "{{ test_fabric }}"
+ state: merged
+ config:
+ - vrf_name: ansible-vrf-int1
+ vrf_id: 9008011
+ vrf_template: Default_VRF_Universal
+ vrf_extension_template: Default_VRF_Extension_Universal
+ vlan_id: 500
+ attach:
+ - ip_address: "{{ ansible_switch1 }}"
+ - ip_address: "{{ ansible_switch2 }}"
+ vrf_lite:
+ - peer_vrf: ansible-vrf-int1 # optional
+ interface: "{{ ansible_int1 }}" # optional
+ ipv4_addr: 10.33.0.2/24 # optional
+ neighbor_ipv4: 10.33.0.1 # optional
+ ipv6_addr: 2010::10:34:0:7/64 # optional
+ neighbor_ipv6: 2010::10:34:0:3 # optional
+ dot1q: 2 # dot1q can be got from dcnm
+ - peer_vrf: ansible-vrf-int1 # optional
+ interface: "{{ ansible_int2 }}" # optional
+ ipv4_addr: 20.33.0.2/24 # optional
+ neighbor_ipv4: 20.33.0.1 # optional
+ ipv6_addr: 3010::10:34:0:7/64 # optional
+ neighbor_ipv6: 3010::10:34:0:3 # optional
+ dot1q: 21 # dot1q can be got from dcnm
+ deploy: true
+ register: result
+
+- name: Query fabric state until vrfStatus transitions to DEPLOYED state
+ cisco.dcnm.dcnm_vrf:
+ fabric: "{{ test_fabric }}"
+ state: query
+ register: query_result
+ until:
+ - "query_result.response[0].parent.vrfStatus is search('DEPLOYED')"
+ retries: 30
+ delay: 2
+
+- assert:
+ that:
+ - 'result.changed == true'
+ - 'result.response[0].RETURN_CODE == 200'
+ - 'result.response[1].RETURN_CODE == 200'
+ - '(result.response[0].DATA|dict2items)[0].value == "SUCCESS"'
+ - 'result.diff[0].attach[0].deploy == true'
+ - '"{{ ansible_switch2 }}" in result.diff[0].attach[0].ip_address'
+ - 'result.diff[0].vrf_name == "ansible-vrf-int1"'
+ - '"{{ ansible_int1 }}" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+ - '"ansible-vrf-int1" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+ - '"10.33.0.2/24" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+ - '"{{ ansible_int2 }}" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+ - '"20.33.0.2/24" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+
+- name: VRF LITE - conf2 - Idempotence
+ cisco.dcnm.dcnm_vrf: *conf2
+ register: result
+
+- assert:
+ that:
+ - 'result.changed == false'
+ - 'result.response|length == 0'
+
+- name: VRF LITE- Replace VRF LITE Attachment and Deploy by the User in one switch
+ cisco.dcnm.dcnm_vrf: &conf3
+ fabric: "{{ test_fabric }}"
+ state: replaced
+ config:
+ - vrf_name: ansible-vrf-int1
+ vrf_id: 9008011
+ vrf_template: Default_VRF_Universal
+ vrf_extension_template: Default_VRF_Extension_Universal
+ vlan_id: 500
+ attach:
+ - ip_address: "{{ ansible_switch1 }}"
+ - ip_address: "{{ ansible_switch2 }}"
+ vrf_lite:
+ - peer_vrf: ansible-vrf-int1 # optional
+ interface: "{{ ansible_int1 }}" # optional
+ ipv4_addr: 10.33.0.2/24 # optional
+ neighbor_ipv4: 10.33.0.1 # optional
+ ipv6_addr: 2010::10:34:0:7/64 # optional
+ neighbor_ipv6: 2010::10:34:0:3 # optional
+ dot1q: 2 # dot1q can be got from dcnm
+ deploy: true
+ register: result
+
+- name: Query fabric state until vrfStatus transitions to DEPLOYED state
+ cisco.dcnm.dcnm_vrf:
+ fabric: "{{ test_fabric }}"
+ state: query
+ register: query_result
+ until:
+ - "query_result.response[0].parent.vrfStatus is search('DEPLOYED')"
+ retries: 30
+ delay: 2
+
+- assert:
+ that:
+ - 'result.changed == true'
+ - 'result.response[0].RETURN_CODE == 200'
+ - 'result.response[1].RETURN_CODE == 200'
+ - '(result.response[0].DATA|dict2items)[0].value == "SUCCESS"'
+ - 'result.diff[0].attach[0].deploy == true'
+ - '"{{ ansible_switch2 }}" in result.diff[0].attach[0].ip_address'
+ - 'result.diff[0].vrf_name == "ansible-vrf-int1"'
+ - '"{{ ansible_int1 }}" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+ - '"ansible-vrf-int1" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+ - '"10.33.0.2/24" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+
+- name: MERGED - conf3 - Idempotence
+ cisco.dcnm.dcnm_vrf: *conf3
+ register: result
+
+- assert:
+ that:
+ - 'result.changed == false'
+ - 'result.response|length == 0'
+
+- name: VRF LITE- Override VRF and VRF LITE EXTENSION Provided by the User
+ cisco.dcnm.dcnm_vrf: &conf4
+ fabric: "{{ test_fabric }}"
+ state: overridden
+ config:
+ - vrf_name: ansible-vrf-int2
+ vrf_id: 9008013
+ vrf_template: Default_VRF_Universal
+ vrf_extension_template: Default_VRF_Extension_Universal
+ vlan_id: 400
+ attach:
+ - ip_address: "{{ ansible_switch2 }}"
+ vrf_lite:
+ - peer_vrf: ansible-vrf-int1 # optional
+ interface: "{{ ansible_int1 }}" # optional
+ ipv4_addr: 10.33.0.2/24 # optional
+ neighbor_ipv4: 10.33.0.1 # optional
+ ipv6_addr: 2010::10:34:0:7/64 # optional
+ neighbor_ipv6: 2010::10:34:0:3 # optional
+ dot1q: 2 # dot1q can be got from dcnm
+ - peer_vrf: ansible-vrf-int1 # optional
+ interface: "{{ ansible_int2 }}" # optional
+ ipv4_addr: 20.33.0.2/24 # optional
+ neighbor_ipv4: 20.33.0.1 # optional
+ ipv6_addr: 3010::10:34:0:7/64 # optional
+ neighbor_ipv6: 3010::10:34:0:3 # optional
+ dot1q: 21 # dot1q can be got from dcnm
+ deploy: true
+ register: result
+
+- name: Query fabric state until vrfStatus transitions to DEPLOYED state
+ cisco.dcnm.dcnm_vrf:
+ fabric: "{{ test_fabric }}"
+ state: query
+ register: query_result
+ until:
+ - "query_result.response[0].parent.vrfStatus is search('DEPLOYED')"
+ retries: 30
+ delay: 2
+
+- assert:
+ that:
+ - 'result.changed == true'
+ - 'result.response[0].RETURN_CODE == 200'
+ - 'result.response[1].RETURN_CODE == 200'
+ - 'result.response[2].RETURN_CODE == 200'
+ - 'result.response[3].RETURN_CODE == 200'
+ - 'result.response[4].RETURN_CODE == 200'
+ - 'result.response[5].RETURN_CODE == 200'
+ - '(result.response[0].DATA|dict2items)[0].value == "SUCCESS"'
+ - '(result.response[0].DATA|dict2items)[1].value == "SUCCESS"'
+ - 'result.diff[0].attach[0].deploy == true'
+ - 'result.diff[1].attach[0].deploy == false'
+ - 'result.diff[1].attach[1].deploy == false'
+ - '"{{ ansible_switch2 }}" in result.diff[0].attach[0].ip_address'
+ - '"{{ ansible_switch1 }}" in result.diff[1].attach[0].ip_address'
+ - '"{{ ansible_switch2 }}" in result.diff[1].attach[1].ip_address'
+ - 'result.diff[0].vrf_name == "ansible-vrf-int2"'
+ - 'result.diff[1].vrf_name == "ansible-vrf-int1"'
+ - '"{{ ansible_int1 }}" in query_result.response[0].attach[0].switchDetailsList[0].extensionValues'
+ - '"ansible-vrf-int1" in query_result.response[0].attach[0].switchDetailsList[0].extensionValues'
+ - '"10.33.0.2/24" in query_result.response[0].attach[0].switchDetailsList[0].extensionValues'
+ - '"{{ ansible_int2 }}" in query_result.response[0].attach[0].switchDetailsList[0].extensionValues'
+ - '"20.33.0.2/24" in query_result.response[0].attach[0].switchDetailsList[0].extensionValues'
+
+- name: VRF LITE - conf4 - Idempotence
+ cisco.dcnm.dcnm_vrf: *conf4
+ register: result
+
+- assert:
+ that:
+ - 'result.changed == false'
+ - 'result.response|length == 0'
+
+- name: VRF LITE - Clean up any existing vrfs
+ cisco.dcnm.dcnm_vrf:
+ fabric: "{{ test_fabric }}"
+ state: deleted
+
+- name: VRF LITE- Create, Attach and Deploy new VRF - VLAN/VRF LITE EXTENSION Provided by the User in multiple switch
+ cisco.dcnm.dcnm_vrf: &conf5
+ fabric: "{{ test_fabric }}"
+ state: merged
+ config:
+ - vrf_name: ansible-vrf-int2
+ vrf_id: 9008015
+ vrf_template: Default_VRF_Universal
+ vrf_extension_template: Default_VRF_Extension_Universal
+ vlan_id: 400
+ attach:
+ - ip_address: "{{ ansible_switch2 }}"
+ vrf_lite:
+ - peer_vrf: ansible-vrf-int1 # optional
+ interface: "{{ ansible_int1 }}" # optional
+ ipv4_addr: 10.33.0.2/24 # optional
+ neighbor_ipv4: 10.33.0.1 # optional
+ ipv6_addr: 2010::10:34:0:7/64 # optional
+ neighbor_ipv6: 2010::10:34:0:3 # optional
+ dot1q: 2 # dot1q can be got from dcnm
+ - peer_vrf: ansible-vrf-int1 # optional
+ interface: "{{ ansible_int2 }}" # optional
+ ipv4_addr: 20.33.0.2/24 # optional
+ neighbor_ipv4: 20.33.0.1 # optional
+ ipv6_addr: 3010::10:34:0:7/64 # optional
+ neighbor_ipv6: 3010::10:34:0:3 # optional
+ dot1q: 21 # dot1q can be got from dcnm
+ - ip_address: "{{ ansible_switch3 }}"
+ vrf_lite:
+ - peer_vrf: ansible-vrf-int3 # optional
+ interface: "{{ ansible_int3 }}" # optional
+ ipv4_addr: 40.33.0.2/24 # optional
+ neighbor_ipv4: 40.33.0.1 # optional
+ ipv6_addr: 5010::10:34:0:7/64 # optional
+ neighbor_ipv6: 5010::10:34:0:3 # optional
+ dot1q: 4 # dot1q can be got from dcnm
+ deploy: true
+ register: result
+
+- name: Query fabric state until vrfStatus transitions to DEPLOYED state
+ cisco.dcnm.dcnm_vrf:
+ fabric: "{{ test_fabric }}"
+ state: query
+ register: query_result
+ until:
+ - "query_result.response[0].parent.vrfStatus is search('DEPLOYED')"
+ retries: 30
+ delay: 2
+
+- assert:
+ that:
+ - 'result.changed == true'
+ - 'result.response[0].RETURN_CODE == 200'
+ - 'result.response[1].RETURN_CODE == 200'
+ - 'result.response[2].RETURN_CODE == 200'
+ - '(result.response[1].DATA|dict2items)[0].value == "SUCCESS"'
+ - '(result.response[1].DATA|dict2items)[1].value == "SUCCESS"'
+ - 'result.diff[0].attach[0].deploy == true'
+ - 'result.diff[0].attach[1].deploy == true'
+ - '"{{ ansible_switch2 }}" in result.diff[0].attach[0].ip_address'
+ - '"{{ ansible_switch3 }}" in result.diff[0].attach[1].ip_address'
+ - 'result.diff[0].vrf_name == "ansible-vrf-int2"'
+ - '"{{ ansible_int3 }}" in query_result.response[0].attach[0].switchDetailsList[0].extensionValues'
+ - '"ansible-vrf-int3" in query_result.response[0].attach[0].switchDetailsList[0].extensionValues'
+ - '"40.33.0.2/24" in query_result.response[0].attach[0].switchDetailsList[0].extensionValues'
+ - '"{{ ansible_int1 }}" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+ - '"ansible-vrf-int1" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+ - '"10.33.0.2/24" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+ - '"{{ ansible_int2 }}" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+ - '"20.33.0.2/24" in query_result.response[0].attach[1].switchDetailsList[0].extensionValues'
+
+- name: VRF LITE - conf5 - Idempotence
+ cisco.dcnm.dcnm_vrf: *conf5
+ register: result
+
+- assert:
+ that:
+ - 'result.changed == false'
+ - 'result.response|length == 0'
+
+###############################################
+### CLEAN-UP ##
+###############################################
+
+- name: VRF LITE - Clean up any existing vrfs
+ cisco.dcnm.dcnm_vrf:
+ fabric: "{{ test_fabric }}"
+ state: deleted
diff --git a/tests/unit/modules/dcnm/fixtures/dcnm_vrf.json b/tests/unit/modules/dcnm/fixtures/dcnm_vrf.json
index 74be2ddb7..ab9e4ea77 100644
--- a/tests/unit/modules/dcnm/fixtures/dcnm_vrf.json
+++ b/tests/unit/modules/dcnm/fixtures/dcnm_vrf.json
@@ -1075,5 +1075,48 @@
"vrfStatus": "DEPLOYED"
}
]
+ },
+ "mock_vrf_lite_obj": {
+ "RETURN_CODE":200,
+ "METHOD":"GET",
+ "MESSAGE":"OK",
+ "DATA": [
+ {
+ "vrfName":"test_vrf",
+ "templateName":"Default_VRF_Extension_Universal",
+ "switchDetailsList":[
+ {
+ "switchName":"poap_test",
+ "vlan":2001,
+ "serialNumber":"9D2DAUJJFQQ",
+ "peerSerialNumber":"None",
+ "extensionValues":"None",
+ "extensionPrototypeValues":[
+ {
+ "interfaceName":"Ethernet1/3",
+ "extensionType":"VRF_LITE",
+ "extensionValues":"{\"PEER_VRF_NAME\": \"\", \"NEIGHBOR_IP\": \"10.33.0.1\", \"VRF_LITE_JYTHON_TEMPLATE\": \"Ext_VRF_Lite_Jython\", \"enableBorderExtension\": \"VRF_LITE\", \"AUTO_VRF_LITE_FLAG\":\"false\", \"IP_MASK\": \"10.33.0.2/30\", \"MTU\": \"9216\", \"NEIGHBOR_ASN\": \"23132\", \"IF_NAME\": \"Ethernet1/3\", \"IPV6_NEIGHBOR\": \"\", \"IPV6_MASK\": \"\", \"DOT1Q_ID\": \"2\", \"asn\": \"52125\"}",
+ "destInterfaceName":"Ethernet1/1",
+ "destSwitchName":"poap-import-static"
+ },
+ {
+ "interfaceName":"Ethernet1/2",
+ "extensionType":"VRF_LITE",
+ "extensionValues":"{\"PEER_VRF_NAME\": \"\", \"NEIGHBOR_IP\": \"20.33.0.1\", \"VRF_LITE_JYTHON_TEMPLATE\": \"Ext_VRF_Lite_Jython\", \"enableBorderExtension\": \"VRF_LITE\", \"AUTO_VRF_LITE_FLAG\": \"false\", \"IP_MASK\": \"20.33.0.2/30\", \"MTU\": \"9216\", \"NEIGHBOR_ASN\": \"23132\", \"IF_NAME\": \"Ethernet1/2\", \"IPV6_NEIGHBOR\": \"\", \"IPV6_MASK\": \"\", \"DOT1Q_ID\": \"2\", \"asn\": \"52125\"}",
+ "destInterfaceName":"Ethernet1/2",
+ "destSwitchName":"poap-import-static"
+ }
+ ],
+ "islanAttached":false,
+ "lanAttachedState":"NA",
+ "errorMessage":"None",
+ "instanceValues":"None",
+ "freeformConfig":"None",
+ "role":"border gateway",
+ "vlanModifiable":true
+ }
+ ]
+ }
+ ]
}
}
diff --git a/tests/unit/modules/dcnm/test_dcnm_vrf.py b/tests/unit/modules/dcnm/test_dcnm_vrf.py
index 289e46aca..d63acbcf2 100644
--- a/tests/unit/modules/dcnm/test_dcnm_vrf.py
+++ b/tests/unit/modules/dcnm/test_dcnm_vrf.py
@@ -127,6 +127,7 @@ def init_data(self):
self.mock_vrf_attach_lite_object = copy.deepcopy(
self.test_data.get("mock_vrf_attach_lite_object")
)
+ self.mock_vrf_lite_obj = copy.deepcopy(self.test_data.get("mock_vrf_lite_obj"))
def setUp(self):
super(TestDcnmVrfModule, self).setUp()
@@ -199,9 +200,11 @@ def load_fixtures(self, response=None, device=""):
]
elif "_merged_lite_new" in self._testMethodName:
+ self.init_data()
self.run_dcnm_send.side_effect = [
self.blank_data,
self.blank_data,
+ self.mock_vrf_lite_obj,
self.attach_success_resp,
self.deploy_success_resp,
]
@@ -270,25 +273,27 @@ def load_fixtures(self, response=None, device=""):
self.deploy_success_resp,
]
- elif "_merged_lite_update_vlan" in self._testMethodName:
+ elif "_merged_lite_update" in self._testMethodName:
self.init_data()
self.run_dcnm_get_url.side_effect = [self.mock_vrf_attach_object]
self.run_dcnm_send.side_effect = [
self.mock_vrf_object,
self.mock_vrf_attach_get_ext_object_merge_att1_only,
self.mock_vrf_attach_get_ext_object_merge_att2_only,
- self.blank_data,
+ self.mock_vrf_lite_obj,
self.attach_success_resp,
self.deploy_success_resp,
]
- elif "_merged_lite_update" in self._testMethodName:
+ elif "_merged_lite_vlan_update" in self._testMethodName:
self.init_data()
self.run_dcnm_get_url.side_effect = [self.mock_vrf_attach_object]
self.run_dcnm_send.side_effect = [
self.mock_vrf_object,
self.mock_vrf_attach_get_ext_object_merge_att1_only,
self.mock_vrf_attach_get_ext_object_merge_att2_only,
+ self.blank_data,
+ self.mock_vrf_lite_obj,
self.attach_success_resp,
self.deploy_success_resp,
]
@@ -307,6 +312,7 @@ def load_fixtures(self, response=None, device=""):
self.init_data()
self.run_dcnm_send.side_effect = [
self.mock_vrf_object,
+ self.mock_vrf_lite_obj,
self.mock_vrf_attach_object_pending,
self.blank_data,
self.mock_vrf_attach_get_ext_object_merge_att1_only,
@@ -360,6 +366,7 @@ def load_fixtures(self, response=None, device=""):
self.mock_vrf_object,
self.mock_vrf_attach_get_ext_object_merge_att1_only,
self.mock_vrf_attach_get_ext_object_merge_att4_only,
+ self.mock_vrf_lite_obj,
self.attach_success_resp,
self.deploy_success_resp,
self.delete_success_resp,
@@ -384,9 +391,11 @@ def load_fixtures(self, response=None, device=""):
]
elif "lite_override_with_additions" in self._testMethodName:
+ self.init_data()
self.run_dcnm_send.side_effect = [
self.blank_data,
self.blank_data,
+ self.mock_vrf_lite_obj,
self.attach_success_resp,
self.deploy_success_resp,
]
@@ -406,6 +415,7 @@ def load_fixtures(self, response=None, device=""):
self.mock_vrf_object,
self.mock_vrf_attach_get_ext_object_merge_att1_only,
self.mock_vrf_attach_get_ext_object_merge_att4_only,
+ self.mock_vrf_lite_obj,
self.attach_success_resp,
self.deploy_success_resp,
self.mock_vrf_attach_object_del_not_ready,
@@ -772,7 +782,7 @@ def test_dcnm_vrf_merged_with_update_vlan(self):
self.assertEqual(result["response"][2]["DATA"]["status"], "")
self.assertEqual(result["response"][2]["RETURN_CODE"], self.SUCCESS_RETURN_CODE)
- def test_dcnm_vrf_merged_lite_update_vlan(self):
+ def test_dcnm_vrf_merged_lite_vlan_update(self):
set_module_args(
dict(
state="merged",
From 3075964157d9cbde2e3b484d72b80a7410f84ce9 Mon Sep 17 00:00:00 2001
From: mmudigon <62759545+mmudigon@users.noreply.github.com>
Date: Tue, 9 May 2023 19:03:54 +0530
Subject: [PATCH 2/8] Added checks for fabric monitoring status and switch's
managable attributes during deploy (#220)
---
plugins/module_utils/network/dcnm/dcnm.py | 41 +-
plugins/modules/dcnm_links.py | 337 ++++++-
.../tests/dcnm/dcnm_links_misc.yaml | 900 ++++++++++++++++++
.../dcnm/fixtures/dcnm_links_configs.json | 146 ++-
.../dcnm/fixtures/dcnm_links_payloads.json | 166 +++-
tests/unit/modules/dcnm/test_dcnm_links.py | 805 +++++++++++++++-
6 files changed, 2305 insertions(+), 90 deletions(-)
create mode 100644 tests/integration/targets/dcnm_links/tests/dcnm/dcnm_links_misc.yaml
diff --git a/plugins/module_utils/network/dcnm/dcnm.py b/plugins/module_utils/network/dcnm/dcnm.py
index 73ffcbed0..458199a69 100644
--- a/plugins/module_utils/network/dcnm/dcnm.py
+++ b/plugins/module_utils/network/dcnm/dcnm.py
@@ -42,11 +42,15 @@ def validate_ip_address_format(type, item, invalid_params):
subnet = item.split("/")[1]
if not subnet or int(subnet) > mask_len:
invalid_params.append(
- "{0} : Invalid {1} gw/subnet syntax".format(item, addr_type)
+ "{0} : Invalid {1} gw/subnet syntax".format(
+ item, addr_type
+ )
)
else:
invalid_params.append(
- "{0} : Invalid {1} gw/subnet syntax".format(item, addr_type)
+ "{0} : Invalid {1} gw/subnet syntax".format(
+ item, addr_type
+ )
)
try:
socket.inet_pton(addr_family, address)
@@ -138,7 +142,9 @@ def validate_list_of_dicts(param_list, spec, module=None):
module.no_log_values.add(item)
else:
msg = "\n\n'{0}' is a no_log parameter".format(param)
- msg += "\nAnsible module object must be passed to this "
+ msg += (
+ "\nAnsible module object must be passed to this "
+ )
msg += "\nfunction to ensure it is not logged\n\n"
raise Exception(msg)
@@ -158,6 +164,7 @@ def get_fabric_inventory_details(module, fabric):
conn = Connection(module._socket_path)
if conn.get_version() == 12:
path = "/appcenter/cisco/ndfc/api/v1/lan-fabric" + path
+ path += "/switchesByFabric"
count = 1
while rc is False:
@@ -188,10 +195,13 @@ def get_fabric_inventory_details(module, fabric):
raise Exception(response)
for device_data in response.get("DATA"):
- key = device_data.get("ipAddress")
+
+ if device_data.get("ipAddress", "") != "":
+ key = device_data.get("ipAddress")
+ else:
+ key = device_data.get("logicalName")
inventory_data[key] = device_data
rc = True
-
return inventory_data
@@ -204,7 +214,9 @@ def get_ip_sn_dict(inventory_data):
ip = inventory_data[device_key].get("ipAddress")
sn = inventory_data[device_key].get("serialNumber")
hn = inventory_data[device_key].get("logicalName")
- ip_sn.update({ip: sn})
+
+ if ip != "":
+ ip_sn.update({ip: sn})
hn_sn.update({hn: sn})
return ip_sn, hn_sn
@@ -247,9 +259,7 @@ def dcnm_get_ip_addr_info(module, sw_elem, ip_sn, hn_sn):
msg_dict = {"Error": ""}
msg = 'Given switch elem = "{}" is not a valid one for this fabric\n'
- msg1 = (
- 'Given switch elem = "{}" cannot be validated, provide a valid ip_sn object\n'
- )
+ msg1 = 'Given switch elem = "{}" cannot be validated, provide a valid ip_sn object\n'
# Check if the given sw_elem is a v4 ip_addr
try:
@@ -377,7 +387,9 @@ def dcnm_reset_connection(module):
conn = Connection(module._socket_path)
conn.logout()
- return conn.login(conn.get_option("remote_user"), conn.get_option("password"))
+ return conn.login(
+ conn.get_option("remote_user"), conn.get_option("password")
+ )
def dcnm_version_supported(module):
@@ -395,7 +407,10 @@ def dcnm_version_supported(module):
supported = None
data = None
- paths = ["/fm/fmrest/about/version", "/appcenter/cisco/ndfc/api/about/version"]
+ paths = [
+ "/fm/fmrest/about/version",
+ "/appcenter/cisco/ndfc/api/about/version",
+ ]
for path in paths:
response = dcnm_send(module, method, path)
if response["RETURN_CODE"] == 200:
@@ -476,7 +491,9 @@ def dcnm_get_url(module, fabric, path, items, module_name):
)
url = path.format(fabric, itemstr)
else:
- itemstr = ",".join(itemlist[iter * (len(itemlist) // send_count):])
+ itemstr = ",".join(
+ itemlist[iter * (len(itemlist) // send_count):]
+ )
url = path.format(fabric, itemstr)
att_objects = dcnm_send(module, method, url)
diff --git a/plugins/modules/dcnm_links.py b/plugins/modules/dcnm_links.py
index d3d28814c..885df3f00 100644
--- a/plugins/modules/dcnm_links.py
+++ b/plugins/modules/dcnm_links.py
@@ -788,6 +788,7 @@ class DcnmLinks:
"LINKS_GET_BY_FABRIC": "/rest/control/links/fabrics/{}",
"LINKS_CFG_DEPLOY": "/rest/control/fabrics/{}/config-deploy/",
"CONFIG_PREVIEW": "/rest/control/fabrics/{}/config-preview/",
+ "FABRIC_ACCESS_MODE": "/rest/control/fabrics/{}/accessmode",
},
12: {
"LINKS_GET_BY_SWITCH_PAIR": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/links",
@@ -797,6 +798,7 @@ class DcnmLinks:
"LINKS_GET_BY_FABRIC": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/links/fabrics/{}",
"LINKS_CFG_DEPLOY": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{}/config-deploy/",
"CONFIG_PREVIEW": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{}/config-preview/",
+ "FABRIC_ACCESS_MODE": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/control/fabrics/{}/accessmode",
},
}
@@ -863,6 +865,8 @@ def __init__(self, module):
self.diff_modify = []
self.diff_delete = []
self.diff_deploy = {}
+ self.monitoring = []
+ self.meta_switches = []
self.fd = None
self.changed_dict = [
{
@@ -899,6 +903,46 @@ def log_msg(self, msg):
self.fd.write("\n")
self.fd.flush()
+ def dcnm_dump_have_db(self):
+
+ lhave = []
+
+ for have in self.have:
+ lhave.append(
+ {
+ "UUID": have["link-uuid"],
+ "SRC FABRIC": have["sw1-info"]["fabric-name"],
+ "SRC IF NAME": have["sw1-info"]["if-name"],
+ "SRC SNO": have["sw1-info"]["sw-serial-number"],
+ "SRC SYS NAME": have["sw1-info"]["sw-sys-name"],
+ "DST FABRIC": have["sw2-info"]["fabric-name"],
+ "DST IF NAME": have["sw2-info"]["if-name"],
+ "DST SNO": have["sw2-info"]["sw-serial-number"],
+ "DST SYS NAME": have["sw2-info"]["sw-sys-name"],
+ }
+ )
+ self.log_msg(f"HAVE = {lhave}\n")
+
+ def dcnm_print_have(self, have):
+
+ lhave = []
+
+ lhave.append(
+ {
+ "UUID": have["link-uuid"],
+ "SRC FABRIC": have["sw1-info"]["fabric-name"],
+ "SRC IF NAME": have["sw1-info"]["if-name"],
+ "SRC SNO": have["sw1-info"]["sw-serial-number"],
+ "SRC SYS NAME": have["sw1-info"]["sw-sys-name"],
+ "DST FABRIC": have["sw2-info"]["fabric-name"],
+ "DST IF NAME": have["sw2-info"]["if-name"],
+ "DST SNO": have["sw2-info"]["sw-serial-number"],
+ "DST SYS NAME": have["sw2-info"]["sw-sys-name"],
+ }
+ )
+
+ self.log_msg(f"have = {lhave}\n")
+
def dcnm_links_compare_ip_addresses(self, addr1, addr2):
"""
@@ -1373,19 +1417,44 @@ def dcnm_links_get_links_payload(self, link):
"destinationFabric": link.get("dst_fabric"),
"sourceInterface": link.get("src_interface"),
"destinationInterface": link.get("dst_interface"),
- "sourceDevice": self.ip_sn[link.get("src_device")],
- "destinationDevice": self.ip_sn[link.get("dst_device")],
}
+ if link.get("src_device") in self.ip_sn:
+ link_payload["sourceDevice"] = self.ip_sn[link.get("src_device")]
+ else:
+ link_payload["sourceDevice"] = self.hn_sn.get(
+ link["src_device"], ""
+ )
+
+ if link.get("dst_device") in self.ip_sn:
+ link_payload["destinationDevice"] = self.ip_sn[
+ link.get("dst_device")
+ ]
+ else:
+ link_payload["destinationDevice"] = self.hn_sn.get(
+ link["dst_device"], ""
+ )
+
+ # At this point link_payload will have sourceDevice set to proper SNO and destinationDevice is either
+ # set to a proper SNO or "".
+
+ if link_payload["sourceDevice"] in self.sn_hn:
+ link_payload["sourceSwitchName"] = self.sn_hn.get(
+ link_payload["sourceDevice"], "Switch1"
+ )
+ else:
+ link_payload["sourceSwitchName"] = link.get("src_device")
+
+ if link_payload["destinationDevice"] in self.sn_hn:
+ link_payload["destinationSwitchName"] = self.sn_hn.get(
+ link_payload["destinationDevice"], "Switch2"
+ )
+ else:
+ link_payload["destinationSwitchName"] = link.get("dst_device")
+
if self.module.params["state"] == "deleted":
return link_payload
- link_payload["sourceSwitchName"] = self.sn_hn.get(
- link_payload["sourceDevice"], "Switch1"
- )
- link_payload["destinationSwitchName"] = self.sn_hn.get(
- link_payload["destinationDevice"], "Switch2"
- )
link_payload["templateName"] = link.get("template")
# Intra and Inter fabric payloads are different. Build them separately
@@ -1916,10 +1985,27 @@ def dcnm_links_update_want(self):
and (cfg["dst_fabric"] == want["destinationFabric"])
and (cfg["src_interface"] == want["sourceInterface"])
and (cfg["dst_interface"] == want["destinationInterface"])
- and (self.ip_sn[cfg["src_device"]] == want["sourceDevice"])
and (
- self.ip_sn[cfg["dst_device"]]
- == want["destinationDevice"]
+ cfg["src_device"] in self.ip_sn
+ and self.ip_sn[cfg["src_device"]]
+ == want["sourceDevice"]
+ )
+ or (
+ cfg["src_device"] in self.hn_sn
+ and self.hn_sn[cfg["src_device"]]
+ == want["sourceDevice"]
+ )
+ and (
+ (
+ cfg["dst_device"] in self.ip_sn
+ and self.ip_sn[cfg["dst_device"]]
+ == want["destinationDevice"]
+ )
+ or (
+ cfg["dst_device"] in self.hn_sn
+ and self.hn_sn[cfg["dst_device"]]
+ == want["destinationDevice"]
+ )
)
and (cfg["template"] == want["templateName"])
)
@@ -1976,14 +2062,22 @@ def dcnm_links_get_links_info_from_dcnm(self, link):
"""
# link object is from self.want. These objets would have translated devices to serial numbers already.
- path = self.paths[
- "LINKS_GET_BY_SWITCH_PAIR"
- ] + "?switch1Sn={0}&switch2Sn={1}".format(
- link["sourceDevice"], link["destinationDevice"]
- )
- path = path + "&switch1IfName={0}&switch2IfName={1}".format(
- link["sourceInterface"], link["destinationInterface"]
- )
+
+ if (
+ link["sourceDevice"] in self.ip_sn.values()
+ and link["destinationDevice"] in self.ip_sn.values()
+ ):
+ path = self.paths[
+ "LINKS_GET_BY_SWITCH_PAIR"
+ ] + "?switch1Sn={0}&switch2Sn={1}".format(
+ link["sourceDevice"], link["destinationDevice"]
+ )
+ path = path + "&switch1IfName={0}&switch2IfName={1}".format(
+ link["sourceInterface"], link["destinationInterface"]
+ )
+ else:
+ # If devices are not managable, the path should not include them
+ path = self.paths["LINKS_GET_BY_SWITCH_PAIR"]
resp = dcnm_send(self.module, "GET", path)
@@ -2013,6 +2107,31 @@ def dcnm_links_get_links_info_from_dcnm(self, link):
link_elem["sw2-info"]["fabric-name"]
== link["destinationFabric"]
)
+ and (
+ link["sourceDevice"]
+ == link_elem["sw1-info"]["sw-serial-number"]
+ )
+ and (
+ (
+ link["destinationDevice"] in self.ip_sn.values()
+ and link["destinationDevice"]
+ == link_elem["sw2-info"]["sw-serial-number"]
+ )
+ or (
+ link["destinationSwitchName"]
+ + "-"
+ + link["destinationFabric"]
+ == link_elem["sw2-info"]["sw-serial-number"]
+ )
+ )
+ and (
+ link["sourceInterface"]
+ == link_elem["sw1-info"]["if-name"]
+ )
+ and (
+ link["destinationInterface"]
+ == link_elem["sw2-info"]["if-name"]
+ )
)
]
@@ -2745,12 +2864,15 @@ def dcnm_links_compare_Links(self, want):
)
and (
have["sw2-info"]["sw-serial-number"]
- == want["destinationDevice"]
+ == want["destinationDevice"] or
+ have["sw2-info"]["sw-serial-number"]
+ == want["destinationSwitchName"] + "-" + want["destinationFabric"]
)
)
]
for mlink in match_have:
+
if want["sourceFabric"] == want["destinationFabric"]:
return self.dcnm_links_compare_intra_fabric_link_params(
want, mlink
@@ -2814,7 +2936,7 @@ def dcnm_links_update_diff_deploy(self, fabric, device):
if self.diff_deploy.get(fabric, "") == "":
self.diff_deploy[fabric] = []
- if device not in self.diff_deploy[fabric]:
+ if device != "" and device not in self.diff_deploy[fabric]:
self.diff_deploy[fabric].append(device)
def dcnm_links_get_diff_merge(self):
@@ -2865,12 +2987,37 @@ def dcnm_links_get_diff_merge(self):
# If "deploy" flag is set to "true", then all pending configurations on the source and
# destination devices will be deployed.
if self.deploy:
- self.dcnm_links_update_diff_deploy(
- self.fabric, link["sourceDevice"]
- )
- self.dcnm_links_update_diff_deploy(
- link["destinationFabric"], link["destinationDevice"]
- )
+
+ if (
+ self.fabric not in self.monitoring
+ and link["sourceDevice"] in self.managable.values()
+ ):
+ self.dcnm_links_update_diff_deploy(
+ self.fabric, link["sourceDevice"]
+ )
+ else:
+ self.dcnm_links_update_diff_deploy(self.fabric, "")
+
+ # If source swithces are not manageable, then do not deploy anything on destination fabric to
+ # avoid inconsitencies.
+ if link["sourceDevice"] in self.managable.values():
+ if (
+ link["destinationFabric"] not in self.monitoring
+ and link["destinationDevice"]
+ in self.managable.values()
+ ):
+ self.dcnm_links_update_diff_deploy(
+ link["destinationFabric"],
+ link["destinationDevice"],
+ )
+ else:
+ self.dcnm_links_update_diff_deploy(
+ link["destinationFabric"], ""
+ )
+ else:
+ self.dcnm_links_update_diff_deploy(
+ link["destinationFabric"], ""
+ )
if self.diff_deploy != {}:
self.changed_dict[0]["deploy"].append(
@@ -2891,6 +3038,7 @@ def dcnm_links_get_diff_deleted(self):
None
"""
+ match_links = []
for link in self.links_info:
match_links = [
@@ -2902,12 +3050,18 @@ def dcnm_links_get_diff_deleted(self):
and (have["sw1-info"]["if-name"] == link["src_interface"])
and (have["sw2-info"]["if-name"] == link["dst_interface"])
and (
- have["sw1-info"]["sw-serial-number"]
- == self.ip_sn[link["src_device"]]
+ link["src_device"] in self.ip_sn
+ and have["sw1-info"]["sw-serial-number"]
+ == self.ip_sn.get(link["src_device"], "")
+ or have["sw1-info"]["sw-serial-number"]
+ == self.hn_sn.get(link["src_device"], "")
)
and (
- have["sw2-info"]["sw-serial-number"]
- == self.ip_sn[link["dst_device"]]
+ link["dst_device"] in self.ip_sn
+ and have["sw2-info"]["sw-serial-number"]
+ == self.ip_sn.get(link["dst_device"], "")
+ or have["sw2-info"]["sw-serial-number"]
+ == self.hn_sn.get(link["dst_device"], "")
)
)
]
@@ -2926,12 +3080,28 @@ def dcnm_links_get_diff_deleted(self):
}
)
- self.dcnm_links_update_diff_deploy(
- self.fabric, self.ip_sn[link["src_device"]]
- )
- self.dcnm_links_update_diff_deploy(
- link["dst_fabric"], self.ip_sn[link["dst_device"]]
- )
+ if self.deploy:
+ if (
+ self.fabric not in self.monitoring
+ and link["src_device"] in self.managable
+ ):
+ self.dcnm_links_update_diff_deploy(
+ self.fabric, self.ip_sn[link["src_device"]]
+ )
+ else:
+ self.dcnm_links_update_diff_deploy(self.fabric, "")
+
+ if (
+ link["dst_fabric"] not in self.monitoring
+ and link["dst_device"] in self.managable
+ ):
+ self.dcnm_links_update_diff_deploy(
+ link["dst_fabric"], self.ip_sn[link["dst_device"]]
+ )
+ else:
+ self.dcnm_links_update_diff_deploy(
+ link["dst_fabric"], ""
+ )
if self.diff_deploy != {}:
self.changed_dict[0]["deploy"].append(
@@ -2996,16 +3166,28 @@ def dcnm_links_get_diff_query(self):
and (
(link["src_device"] == "")
or (
- rlink["sw1-info"]["sw-serial-number"]
+ link["src_device"] in self.ip_sn
+ and rlink["sw1-info"]["sw-serial-number"]
== self.ip_sn[link["src_device"]]
)
+ or (
+ link["src_device"] in self.hn_sn
+ and rlink["sw1-info"]["sw-serial-number"]
+ == self.hn_sn[link["src_device"]]
+ )
)
and (
(link["dst_device"] == "")
or (
- rlink["sw2-info"]["sw-serial-number"]
+ link["dst_device"] in self.ip_sn
+ and rlink["sw2-info"]["sw-serial-number"]
== self.ip_sn[link["dst_device"]]
)
+ or (
+ link["dst_device"] in self.hn_sn
+ and rlink["sw2-info"]["sw-serial-number"]
+ == self.hn_sn[link["dst_device"]]
+ )
)
and (
(link["template"] == "")
@@ -3026,7 +3208,7 @@ def dcnm_links_deploy_to_switches(self):
resp = {}
resp["RETURN_CODE"] = 200
- for fabric in self.diff_deploy.keys():
+ for fabric in self.diff_deploy:
if self.diff_deploy[fabric] != []:
deploy_path = self.paths["LINKS_CFG_DEPLOY"].format(fabric)
@@ -3046,7 +3228,7 @@ def dcnm_links_get_switch_sync_status(self):
retry = False
- for fabric in self.diff_deploy.keys():
+ for fabric in self.diff_deploy:
if self.diff_deploy[fabric] != []:
@@ -3196,7 +3378,6 @@ def dcnm_links_update_inventory_data(self):
processed_fabrics.append(self.fabric)
for cfg in self.config:
-
# For every fabric included in the playbook, get the inventory details. This info is required
# to get ip_sn, hn_sn and sn_hn details
if cfg.get("dst_fabric", "") != "":
@@ -3207,9 +3388,51 @@ def dcnm_links_update_inventory_data(self):
)
self.inventory_data.update(inv_data)
+ # Get all switches which are managable. Deploy must be avoided to all switches which are not part of this list
+ managable_ip = [
+ (key, self.inventory_data[key]["serialNumber"])
+ for key in self.inventory_data
+ if str(self.inventory_data[key]["managable"]).lower() == "true"
+ ]
+ managable_hosts = [
+ (
+ self.inventory_data[key]["logicalName"],
+ self.inventory_data[key]["serialNumber"],
+ )
+ for key in self.inventory_data
+ if str(self.inventory_data[key]["managable"]).lower() == "true"
+ ]
+ self.managable = dict(managable_ip + managable_hosts)
+
+ self.meta_switches = [
+ self.inventory_data[key]["logicalName"]
+ for key in self.inventory_data
+ if self.inventory_data[key]["switchRoleEnum"] is None
+ ]
+
+ # Get all fabrics which are in monitoring mode. Deploy must be avoided to all fabrics which are part of this list
+ for fabric in processed_fabrics:
+ path = self.paths["FABRIC_ACCESS_MODE"].format(fabric)
+ resp = dcnm_send(self.module, "GET", path)
+
+ if resp and resp["RETURN_CODE"] == 200:
+ if str(resp["DATA"]["readonly"]).lower() == "true":
+ self.monitoring.append(fabric)
+
+ # Checkif source fabric is in monitoring mode. If so return an error, since fabrics in monitoring mode do not allow
+ # create/modify/delete and deploy operations.
+ if self.fabric in self.monitoring:
+ self.module.fail_json(
+ msg="Error: Source Fabric '{0}' is in Monitoring mode, No changes are allowed on the fabric\n".format(
+ self.fabric
+ )
+ )
+
# Based on the updated inventory_data, update ip_sn, hn_sn and sn_hn objects
self.ip_sn, self.hn_sn = get_ip_sn_dict(self.inventory_data)
- self.sn_hn = dict([(value, key) for key, value in self.hn_sn.items()])
+ self.sn_hn = dict(
+ [(value, key) for key, value in self.hn_sn.items() if value != ""]
+ )
def dcnm_links_translate_playbook_info(self, config, ip_sn, hn_sn):
@@ -3234,13 +3457,22 @@ def dcnm_links_translate_playbook_info(self, config, ip_sn, hn_sn):
for cfg in config:
if cfg.get("src_device", "") != "":
- cfg["src_device"] = dcnm_get_ip_addr_info(
- self.module, cfg["src_device"], ip_sn, hn_sn
- )
+ if (
+ cfg["src_device"] in self.ip_sn
+ or cfg["src_device"] in self.hn_sn
+ ):
+ cfg["src_device"] = dcnm_get_ip_addr_info(
+ self.module, cfg["src_device"], ip_sn, hn_sn
+ )
if cfg.get("dst_device", "") != "":
- cfg["dst_device"] = dcnm_get_ip_addr_info(
- self.module, cfg["dst_device"], ip_sn, hn_sn
- )
+ if (
+ cfg["dst_device"] in self.ip_sn
+ or cfg["dst_device"] in self.hn_sn
+ and cfg["dst_device"] not in self.meta_switches
+ ):
+ cfg["dst_device"] = dcnm_get_ip_addr_info(
+ self.module, cfg["dst_device"], ip_sn, hn_sn
+ )
if cfg.get("template", None) is not None:
cfg["template"] = self.templates.get(
@@ -3280,7 +3512,6 @@ def main():
)
dcnm_links.dcnm_links_update_inventory_data()
-
dcnm_links.dcnm_links_translate_playbook_info(
dcnm_links.config, dcnm_links.ip_sn, dcnm_links.hn_sn
)
@@ -3310,6 +3541,12 @@ def main():
dcnm_links.dcnm_links_get_diff_query()
dcnm_links.result["diff"] = dcnm_links.changed_dict
+ dcnm_links.changed_dict[0]["debugs"].append(
+ {"Managable": dcnm_links.managable}
+ )
+ dcnm_links.changed_dict[0]["debugs"].append(
+ {"Monitoring": dcnm_links.monitoring}
+ )
if dcnm_links.diff_create or dcnm_links.diff_delete:
dcnm_links.result["changed"] = True
diff --git a/tests/integration/targets/dcnm_links/tests/dcnm/dcnm_links_misc.yaml b/tests/integration/targets/dcnm_links/tests/dcnm/dcnm_links_misc.yaml
new file mode 100644
index 000000000..3091b795e
--- /dev/null
+++ b/tests/integration/targets/dcnm_links/tests/dcnm/dcnm_links_misc.yaml
@@ -0,0 +1,900 @@
+##############################################
+## SETUP ##
+##############################################
+
+- name: Remove local log file
+ local_action: command rm -f dcnm_links.log
+
+- block:
+
+#############################################
+# DELETE ##
+#############################################
+
+ - name: Initial setup - Delete Links on numbered fabric
+ cisco.dcnm.dcnm_links: &links_delete
+ state: deleted # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_num_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_3 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_3 }}" # Interface on the Destination fabric
+ src_device: "dummy-switch-1" # Device on the Source fabric
+ dst_device: "{{ ansible_num_switch1 }}" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_3 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_3 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-test-sw3" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_4 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_4 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-test-sw100" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_5 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_5 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-svi1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_6 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_6 }}" # Interface on the Destination fabric
+ src_device: "n9kv-num-1" # Device on the Source fabric
+ dst_device: "n9kv-test-sw3" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_7 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_7 }}" # Interface on the Destination fabric
+ src_device: "n9kv-num-1" # Device on the Source fabric
+ dst_device: "n9kv-svi1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ - dst_fabric: "{{ ansible_ext_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_8 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_8 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-test-sw4" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ - dst_fabric: "{{ ansible_unnum_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_9 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_9 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-unnum-1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ - dst_fabric: "{{ ansible_ext_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_10 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_10 }}" # Interface on the Destination fabric
+ src_device: "n9kv-num-1" # Device on the Source fabric
+ dst_device: "n9kv-ext-sw1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ - dst_fabric: "{{ ansible_unnum_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_11 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_11 }}" # Interface on the Destination fabric
+ src_device: "n9kv-num-1" # Device on the Source fabric
+ dst_device: "n9kv-unnum-1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ register: result
+
+ - assert:
+ that:
+ - 'item["RETURN_CODE"] == 200'
+ loop: '{{ result.response }}'
+
+#############################################
+# MERGE ##
+#############################################
+
+ - name: Create Links - Source Fabric in Monitoring mode
+ cisco.dcnm.dcnm_links:
+ state: merged # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_extmon_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_num_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_3 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_3 }}" # Interface on the Destination fabric
+ src_device: "dummy-switch-1" # Device on the Source fabric
+ dst_device: "{{ ansible_num_switch1 }}" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ profile:
+ ipv4_subnet: 193.168.1.1/24 # IP address of interface in src fabric with mask
+ neighbor_ip: 193.168.1.2 # IP address of the interface in dst fabric
+ src_asn: "{{ ansible_extmon_asn }}" # BGP ASN in source fabric
+ dst_asn: "{{ ansible_num_asn }}" # BGP ASN in destination fabric
+ register: result
+ ignore_errors: yes
+
+ - assert:
+ that:
+ - '("Monitoring mode" in result["msg"])'
+ - '("No changes are allowed on the fabric" in result["msg"])'
+ - '("{{ ansible_extmon_fabric }}" in result["msg"])'
+
+ - name: Create Links - Destination Fabric - Monitoring, Source Switches Not Managable and Destination Switches Not Managable (in POAP)
+ cisco.dcnm.dcnm_links: &links_create1
+ state: merged # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_3 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_3 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-test-sw3" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ profile:
+ ipv4_subnet: 193.168.2.1/24 # IP address of interface in src fabric with mask
+ neighbor_ip: 193.168.2.2 # IP address of the interface in dst fabric
+ src_asn: "{{ ansible_num_asn }}" # BGP ASN in source fabric
+ dst_asn: "{{ ansible_svi_asn }}" # BGP ASN in destination fabric
+ register: result
+ ignore_errors: yes
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 1'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_svi_fabric }}" ] | length) == 0'
+
+############################################
+# IDEMPOTENCE #
+############################################
+
+ - name: Create Links - Idempotence
+ cisco.dcnm.dcnm_links: *links_create1
+ register: result
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 0'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_svi_fabric }}" ] | length) == 0'
+
+###############################################
+### QUERY ##
+###############################################
+
+ - name: Query Links
+ cisco.dcnm.dcnm_links:
+ state: query # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_3 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_3 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-test-sw3" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ register: result
+
+ - assert:
+ that:
+ '(result["response"] | length) >= 1'
+
+#############################################
+# MERGE ##
+#############################################
+
+ - name: Create Links - Destination Fabric - Monitoring, Source Switches Not Managable and Destination Switches Not Managable (not present)
+ cisco.dcnm.dcnm_links: &links_create2
+ state: merged # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_4 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_4 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-test-sw100" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ profile:
+ ipv4_subnet: 193.168.3.1/24 # IP address of interface in src fabric with mask
+ neighbor_ip: 193.168.3.2 # IP address of the interface in dst fabric
+ src_asn: "{{ ansible_num_asn }}" # BGP ASN in source fabric
+ dst_asn: "{{ ansible_svi_asn }}" # BGP ASN in destination fabric
+ peer1_description: "Description of source" # optional, default is ""
+ peer2_description: "Description of dest" # optional, default is ""
+ register: result
+ ignore_errors: yes
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 1'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_svi_fabric }}" ] | length) == 0'
+
+ - name: Merge Links - Destination Fabric - Monitoring, Source Switches Not Managable and Destination Switches Not Managable (not present)
+ cisco.dcnm.dcnm_links:
+ state: merged # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_4 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_4 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-test-sw100" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ profile:
+ ipv4_subnet: 193.168.20.1/24 # IP address of interface in src fabric with mask
+ neighbor_ip: 193.168.20.2 # IP address of the interface in dst fabric
+ src_asn: "{{ ansible_num_asn }}" # BGP ASN in source fabric
+ dst_asn: "{{ ansible_svi_asn }}" # BGP ASN in destination fabric
+ peer1_description: "Description of source - REP" # optional, default is ""
+ peer2_description: "Description of dest - REP" # optional, default is ""
+ register: result
+ ignore_errors: yes
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 0'
+ - '(result["diff"][0]["modified"] | length) == 1'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_svi_fabric }}" ] | length) == 0'
+
+ - name: Merge Links - Destination Fabric - Monitoring, Source Switches Not Managable and Destination Switches Not Managable (not present)
+ cisco.dcnm.dcnm_links:
+ state: replaced # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_4 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_4 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-test-sw100" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ profile:
+ ipv4_subnet: 193.168.20.1/24 # IP address of interface in src fabric with mask
+ neighbor_ip: 193.168.20.2 # IP address of the interface in dst fabric
+ src_asn: "{{ ansible_num_asn }}" # BGP ASN in source fabric
+ dst_asn: "{{ ansible_svi_asn }}" # BGP ASN in destination fabric
+ peer1_description: "Description of source - REP" # optional, default is ""
+ peer2_description: "Description of dest - REP" # optional, default is ""
+ register: result
+ ignore_errors: yes
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 0'
+ - '(result["diff"][0]["modified"] | length) == 1'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_svi_fabric }}" ] | length) == 0'
+
+#############################################
+# IDEMPOTENCE ##
+#############################################
+
+ - name: Create Links - Idempotence
+ cisco.dcnm.dcnm_links: *links_create2
+ register: result
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 0'
+ - '(result["diff"][0]["modified"] | length) == 1'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_svi_fabric }}" ] | length) == 0'
+
+###############################################
+### QUERY ##
+###############################################
+
+ - name: Query Links
+ cisco.dcnm.dcnm_links:
+ state: query # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_4 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_4 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-test-sw100" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ register: result
+
+ - assert:
+ that:
+ '(result["response"] | length) >= 1'
+
+#############################################
+# MERGE ##
+#############################################
+
+ - name: Create Links - Destination Fabric - Monitoring, Source Switches Not Managable and Destination Switches Managable
+ cisco.dcnm.dcnm_links: &links_create3
+ state: merged # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_5 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_5 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-svi1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ profile:
+ ipv4_subnet: 193.168.4.1/24 # IP address of interface in src fabric with mask
+ neighbor_ip: 193.168.4.2 # IP address of the interface in dst fabric
+ src_asn: "{{ ansible_num_asn }}" # BGP ASN in source fabric
+ dst_asn: "{{ ansible_svi_asn }}" # BGP ASN in destination fabric
+ register: result
+ ignore_errors: yes
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 1'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_svi_fabric }}" ] | length) == 0'
+
+#############################################
+# IDEMPOTENCE ##
+#############################################
+
+ - name: Create Links - Idempotence
+ cisco.dcnm.dcnm_links: *links_create3
+ register: result
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 0'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_svi_fabric }}" ] | length) == 0'
+
+###############################################
+### QUERY ##
+###############################################
+
+ - name: Query Links
+ cisco.dcnm.dcnm_links:
+ state: query # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_5 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_5 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-svi1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ register: result
+
+ - assert:
+ that:
+ '(result["response"] | length) >= 1'
+
+#############################################
+# MERGE ##
+#############################################
+
+ - name: Create Links - Destination Fabric - Monitoring, Source Switches Managable and Destination Switches Not Managable
+ cisco.dcnm.dcnm_links: &links_create4
+ state: merged # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_6 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_6 }}" # Interface on the Destination fabric
+ src_device: "n9kv-num-1" # Device on the Source fabric
+ dst_device: "n9kv-test-sw3" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ profile:
+ ipv4_subnet: 193.168.5.1/24 # IP address of interface in src fabric with mask
+ neighbor_ip: 193.168.5.2 # IP address of the interface in dst fabric
+ src_asn: "{{ ansible_num_asn }}" # BGP ASN in source fabric
+ dst_asn: "{{ ansible_svi_asn }}" # BGP ASN in destination fabric
+ register: result
+ ignore_errors: yes
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 1'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 1'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_svi_fabric }}" ] | length) == 0'
+
+#############################################
+# IDEMPOTENCE ##
+#############################################
+
+ - name: Create Links - Idempotence
+ cisco.dcnm.dcnm_links: *links_create4
+ register: result
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 0'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 1'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_svi_fabric }}" ] | length) == 0'
+
+###############################################
+### QUERY ##
+###############################################
+
+ - name: Query Links
+ cisco.dcnm.dcnm_links:
+ state: query # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_6 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_6 }}" # Interface on the Destination fabric
+ src_device: "n9kv-num-1" # Device on the Source fabric
+ dst_device: "n9kv-test-sw3" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ register: result
+
+ - assert:
+ that:
+ '(result["response"] | length) >= 1'
+
+#############################################
+# MERGE ##
+#############################################
+
+ - name: Create Links - Destination Fabric - Monitoring, Source Switches Managable and Destination Switches Managable
+ cisco.dcnm.dcnm_links: &links_create5
+ state: merged # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_7 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_7 }}" # Interface on the Destination fabric
+ src_device: "n9kv-num-1" # Device on the Source fabric
+ dst_device: "n9kv-svi1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ profile:
+ ipv4_subnet: 193.168.6.1/24 # IP address of interface in src fabric with mask
+ neighbor_ip: 193.168.6.2 # IP address of the interface in dst fabric
+ src_asn: "{{ ansible_num_asn }}" # BGP ASN in source fabric
+ dst_asn: "{{ ansible_svi_asn }}" # BGP ASN in destination fabric
+ register: result
+ ignore_errors: yes
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 1'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 1'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_svi_fabric }}" ] | length) == 0'
+
+#############################################
+# IDEMPOTENCE ##
+#############################################
+
+ - name: Create Links - Idempotence
+ cisco.dcnm.dcnm_links: *links_create5
+ register: result
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 0'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 1'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_svi_fabric }}" ] | length) == 0'
+
+###############################################
+### QUERY ##
+###############################################
+
+ - name: Query Links
+ cisco.dcnm.dcnm_links:
+ state: query # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_svi_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_7 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_7 }}" # Interface on the Destination fabric
+ src_device: "n9kv-num-1" # Device on the Source fabric
+ dst_device: "n9kv-svi1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ register: result
+
+ - assert:
+ that:
+ '(result["response"] | length) >= 1'
+
+#############################################
+# MERGE ##
+#############################################
+
+ - name: Create Links - Source Switches Not Managable and Destination Switches Not Managable
+ cisco.dcnm.dcnm_links: &links_create6
+ state: merged # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_ext_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_8 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_8 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-test-sw4" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ profile:
+ ipv4_subnet: 193.168.7.1/24 # IP address of interface in src fabric with mask
+ neighbor_ip: 193.168.7.2 # IP address of the interface in dst fabric
+ src_asn: "{{ ansible_num_asn }}" # BGP ASN in source fabric
+ dst_asn: "{{ ansible_ext_asn }}" # BGP ASN in destination fabric
+ register: result
+ ignore_errors: yes
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 1'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_ext_fabric }}" ] | length) == 0'
+
+#############################################
+# IDEMPOTENCE ##
+#############################################
+
+ - name: Create Links - Idempotence
+ cisco.dcnm.dcnm_links: *links_create6
+ register: result
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 0'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_ext_fabric }}" ] | length) == 0'
+
+###############################################
+### QUERY ##
+###############################################
+
+ - name: Query Links
+ cisco.dcnm.dcnm_links:
+ state: query # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_ext_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_8 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_8 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-test-sw4" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ register: result
+
+ - assert:
+ that:
+ '(result["response"] | length) >= 1'
+
+#############################################
+# MERGE ##
+#############################################
+
+ - name: Create Links - Source Switches Not Managable and Destination Switches Managable
+ cisco.dcnm.dcnm_links: &links_create7
+ state: merged # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_unnum_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_9 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_9 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-unnum-1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ profile:
+ ipv4_subnet: 193.168.8.1/24 # IP address of interface in src fabric with mask
+ neighbor_ip: 193.168.8.2 # IP address of the interface in dst fabric
+ src_asn: "{{ ansible_num_asn }}" # BGP ASN in source fabric
+ dst_asn: "{{ ansible_unnum_asn }}" # BGP ASN in destination fabric
+ register: result
+ ignore_errors: yes
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 1'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_unnum_fabric }}" ] | length) == 0'
+
+#############################################
+# IDEMPOTENCE ##
+#############################################
+
+ - name: Create Links - Idempotence
+ cisco.dcnm.dcnm_links: *links_create7
+ register: result
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 0'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_unnum_fabric }}" ] | length) == 0'
+
+###############################################
+### QUERY ##
+###############################################
+
+ - name: Query Links
+ cisco.dcnm.dcnm_links:
+ state: query # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_unnum_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_9 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_9 }}" # Interface on the Destination fabric
+ src_device: "n9kv-test-sw1" # Device on the Source fabric
+ dst_device: "n9kv-unnum-1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ register: result
+
+ - assert:
+ that:
+ '(result["response"] | length) >= 1'
+
+#############################################
+# MERGE ##
+#############################################
+
+ - name: Create Links - Source Switches Managable and Destination Switches Not Managable (not present in Fabric)
+ cisco.dcnm.dcnm_links: &links_create8
+ state: merged # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_ext_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_10 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_10 }}" # Interface on the Destination fabric
+ src_device: "n9kv-num-1" # Device on the Source fabric
+ dst_device: "n9kv-ext-sw1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ profile:
+ ipv4_subnet: 193.168.9.1/24 # IP address of interface in src fabric with mask
+ neighbor_ip: 193.168.9.2 # IP address of the interface in dst fabric
+ src_asn: "{{ ansible_num_asn }}" # BGP ASN in source fabric
+ dst_asn: "{{ ansible_ext_asn }}" # BGP ASN in destination fabric
+ register: result
+ ignore_errors: yes
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 1'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 1'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_ext_fabric }}" ] | length) == 0'
+
+#############################################
+# IDEMPOTENCE ##
+#############################################
+
+ - name: Create Links - Idempotence
+ cisco.dcnm.dcnm_links: *links_create8
+ register: result
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 0'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 1'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_ext_fabric }}" ] | length) == 0'
+
+###############################################
+### QUERY ##
+###############################################
+
+ - name: Query Links
+ cisco.dcnm.dcnm_links:
+ state: query # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_ext_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_10 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_10 }}" # Interface on the Destination fabric
+ src_device: "n9kv-num-1" # Device on the Source fabric
+ dst_device: "n9kv-ext-sw1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ register: result
+
+ - assert:
+ that:
+ '(result["response"] | length) >= 1'
+
+#############################################
+# MERGE ##
+#############################################
+
+ - name: Create Links - Source Switches Managable and Destination Switches Managable
+ cisco.dcnm.dcnm_links: &links_create9
+ state: merged # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_unnum_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_11 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_11 }}" # Interface on the Destination fabric
+ src_device: "n9kv-num-1" # Device on the Source fabric
+ dst_device: "n9kv-unnum-1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ profile:
+ ipv4_subnet: 193.168.10.1/24 # IP address of interface in src fabric with mask
+ neighbor_ip: 193.168.10.2 # IP address of the interface in dst fabric
+ src_asn: "{{ ansible_num_asn }}" # BGP ASN in source fabric
+ dst_asn: "{{ ansible_unnum_asn }}" # BGP ASN in destination fabric
+ register: result
+ ignore_errors: yes
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 1'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 1'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_unnum_fabric }}" ] | length) == 1'
+
+#############################################
+# IDEMPOTENCE ##
+#############################################
+
+ - name: Create Links - Idempotence
+ cisco.dcnm.dcnm_links: *links_create9
+ register: result
+
+ - assert:
+ that:
+ - 'result.changed == true'
+ - '(result["diff"][0]["merged"] | length) == 0'
+ - '(result["diff"][0]["modified"] | length) == 0'
+ - '(result["diff"][0]["deleted"] | length) == 0'
+ - '(result["diff"][0]["query"] | length) == 0'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_num_fabric }}" ] | length) == 1'
+ - '(result["diff"][0]["deploy"][0][ "{{ ansible_unnum_fabric }}" ] | length) == 1'
+
+###############################################
+### QUERY ##
+###############################################
+
+ - name: Query Links
+ cisco.dcnm.dcnm_links:
+ state: query # choose from [merged, replaced, deleted, query]
+ src_fabric: "{{ ansible_num_fabric }}"
+ config:
+ - dst_fabric: "{{ ansible_unnum_fabric }}" # Destination fabric
+ src_interface: "{{ intf_1_11 }}" # Interface on the Source fabric
+ dst_interface: "{{ intf_1_11 }}" # Interface on the Destination fabric
+ src_device: "n9kv-num-1" # Device on the Source fabric
+ dst_device: "n9kv-unnum-1" # Device on the Destination fabric
+ template: ext_fabric_setup # template to be applied, choose from
+ # [ ext_fabric_setup, ext_multisite_underlay_setup,
+ # ext_evpn_multisite_overlay_setup ]
+ register: result
+
+ - assert:
+ that:
+ '(result["response"] | length) >= 1'
+
+#############################################
+# CLEANUP ##
+#############################################
+
+ always:
+
+ - name: Cleanup - Delete Links
+ cisco.dcnm.dcnm_links: *links_delete
+ register: result
+ when: IT_CONTEXT is not defined
+
+ - assert:
+ that:
+ - 'item["RETURN_CODE"] == 200'
+ loop: '{{ result.response }}'
+ when: IT_CONTEXT is not defined
diff --git a/tests/unit/modules/dcnm/fixtures/dcnm_links_configs.json b/tests/unit/modules/dcnm/fixtures/dcnm_links_configs.json
index e2e4d3143..93d55c289 100644
--- a/tests/unit/modules/dcnm/fixtures/dcnm_links_configs.json
+++ b/tests/unit/modules/dcnm/fixtures/dcnm_links_configs.json
@@ -2199,5 +2199,149 @@
"src_interface": "Ethernet1/1",
"template": "ext_evpn_multisite_overlay_setup"
}
- ]
+ ],
+
+ "inter_src_fab_ro_config": [
+ {
+ "dst_device": "10.64.78.231",
+ "dst_fabric": "mmudigon-dst-fab-ro",
+ "dst_interface": "Ethernet1/1",
+ "profile": {
+ "dst_asn": 1001,
+ "ipv4_subnet": "193.168.1.1/24",
+ "neighbor_ip": "193.168.1.2",
+ "src_asn": 1000
+ },
+ "src_device": "10.64.78.227",
+ "src_interface": "Ethernet1/1",
+ "template": "ext_fabric_setup"
+ }],
+
+ "inter_dst_fab_ro_dst_sw_non_mgbl_config": [
+ {
+ "dst_device": "n9kv-1",
+ "dst_fabric": "mmudigon-dst-fab-ro",
+ "dst_interface": "Ethernet1/1",
+ "profile": {
+ "dst_asn": 1001,
+ "ipv4_subnet": "193.168.1.1/24",
+ "neighbor_ip": "193.168.1.2",
+ "src_asn": 1000
+ },
+ "src_device": "n9kv-num-1",
+ "src_interface": "Ethernet1/1",
+ "template": "ext_fabric_setup"
+ }],
+
+ "inter_dst_fab_ro_src_sw_non_mgbl_config": [
+ {
+ "dst_device": "n9kv-num-1",
+ "dst_fabric": "mmudigon-dst-fab-ro",
+ "dst_interface": "Ethernet1/1",
+ "profile": {
+ "dst_asn": 1001,
+ "ipv4_subnet": "193.168.1.1/24",
+ "neighbor_ip": "193.168.1.2",
+ "src_asn": 1000
+ },
+ "src_device": "n9kv-2",
+ "src_interface": "Ethernet1/1",
+ "template": "ext_fabric_setup"
+ }],
+
+ "inter_dst_fab_ro_src_dst_sw_non_mgbl_config": [
+ {
+ "dst_device": "n9kv-1",
+ "dst_fabric": "mmudigon-dst-fab-ro",
+ "dst_interface": "Ethernet1/1",
+ "profile": {
+ "dst_asn": 1001,
+ "ipv4_subnet": "193.168.1.1/24",
+ "neighbor_ip": "193.168.1.2",
+ "src_asn": 1000
+ },
+ "src_device": "n9kv-2",
+ "src_interface": "Ethernet1/1",
+ "template": "ext_fabric_setup"
+ }],
+
+ "inter_dst_fab_ro_src_dst_sw_mgbl_config": [
+ {
+ "dst_device": "n9kv-num-1",
+ "dst_fabric": "mmudigon-dst-fab-ro",
+ "dst_interface": "Ethernet1/1",
+ "profile": {
+ "dst_asn": 1001,
+ "ipv4_subnet": "193.168.1.1/24",
+ "neighbor_ip": "193.168.1.2",
+ "src_asn": 1000
+ },
+ "src_device": "n9kv-unnum-1",
+ "src_interface": "Ethernet1/1",
+ "template": "ext_fabric_setup"
+ }],
+
+ "inter_dst_fab_rw_dst_sw_non_mgbl_config": [
+ {
+ "dst_device": "n9kv-1",
+ "dst_fabric": "mmudigon-dst-fab-rw",
+ "dst_interface": "Ethernet1/1",
+ "profile": {
+ "dst_asn": 1001,
+ "ipv4_subnet": "193.168.1.1/24",
+ "neighbor_ip": "193.168.1.2",
+ "src_asn": 1000
+ },
+ "src_device": "n9kv-num-1",
+ "src_interface": "Ethernet1/1",
+ "template": "ext_fabric_setup"
+ }],
+
+ "inter_dst_fab_rw_src_sw_non_mgbl_config": [
+ {
+ "dst_device": "n9kv-num-1",
+ "dst_fabric": "mmudigon-dst-fab-rw",
+ "dst_interface": "Ethernet1/1",
+ "profile": {
+ "dst_asn": 1001,
+ "ipv4_subnet": "193.168.1.1/24",
+ "neighbor_ip": "193.168.1.2",
+ "src_asn": 1000
+ },
+ "src_device": "n9kv-2",
+ "src_interface": "Ethernet1/1",
+ "template": "ext_fabric_setup"
+ }],
+
+ "inter_dst_fab_rw_src_dst_sw_non_mgbl_config": [
+ {
+ "dst_device": "n9kv-1",
+ "dst_fabric": "mmudigon-dst-fab-rw",
+ "dst_interface": "Ethernet1/1",
+ "profile": {
+ "dst_asn": 1001,
+ "ipv4_subnet": "193.168.1.1/24",
+ "neighbor_ip": "193.168.1.2",
+ "src_asn": 1000
+ },
+ "src_device": "n9kv-2",
+ "src_interface": "Ethernet1/1",
+ "template": "ext_fabric_setup"
+ }],
+
+ "inter_dst_fab_rw_src_dst_sw_mgbl_config": [
+ {
+ "dst_device": "n9kv-num-1",
+ "dst_fabric": "mmudigon-dst-fab-rw",
+ "dst_interface": "Ethernet1/1",
+ "profile": {
+ "dst_asn": 1001,
+ "ipv4_subnet": "193.168.1.1/24",
+ "neighbor_ip": "193.168.1.2",
+ "src_asn": 1000
+ },
+ "src_device": "n9kv-unnum-1",
+ "src_interface": "Ethernet1/1",
+ "template": "ext_fabric_setup"
+ }]
}
diff --git a/tests/unit/modules/dcnm/fixtures/dcnm_links_payloads.json b/tests/unit/modules/dcnm/fixtures/dcnm_links_payloads.json
index 9c1c343c4..cfe8d748f 100644
--- a/tests/unit/modules/dcnm/fixtures/dcnm_links_payloads.json
+++ b/tests/unit/modules/dcnm/fixtures/dcnm_links_payloads.json
@@ -19,60 +19,178 @@
"mock_fab_inv_data": {
"192.168.123.150": {
+ "logicalName": "n9kv-100",
+ "serialNumber": "9M99N34RDED",
"isVpcConfigured": "True",
- "vpcDomain": 1
+ "vpcDomain": 1,
+ "switchRoleEnum": "Leaf",
+ "managable": "True"
},
"192.168.123.151": {
+ "logicalName": "n9kv-200",
+ "serialNumber": "9NXHSNTEO6C",
"isVpcConfigured": "True",
- "vpcDomain": 1
+ "vpcDomain": 1,
+ "switchRoleEnum": "Leaf",
+ "managable": "True"
},
"192.168.123.156": {
+ "logicalName": "n9kv-ipv6-1",
+ "serialNumber": "9BH0813WFWT",
"isVpcConfigured": "True",
- "vpcDomain": 1
+ "vpcDomain": 1,
+ "switchRoleEnum": "Leaf",
+ "managable": "True"
},
"192.168.123.157": {
+ "logicalName": "n9kv-ipv6-2",
+ "serialNumber": "9ITWBH9OIAH",
"isVpcConfigured": "True",
- "vpcDomain": 1
+ "vpcDomain": 1,
+ "switchRoleEnum": "Leaf",
+ "managable": "True"
},
"192.168.123.160": {
+ "logicalName": "n9kv-num-1",
+ "serialNumber": "9IF87L089SZ",
"isVpcConfigured": "True",
- "vpcDomain": 1
+ "vpcDomain": 1,
+ "switchRoleEnum": "Leaf",
+ "managable": "True"
},
"192.168.123.161": {
+ "logicalName": "n9kv-num-2",
+ "serialNumber": "9FX7O3TU2QM",
"isVpcConfigured": "True",
- "vpcDomain": 1
+ "vpcDomain": 1,
+ "switchRoleEnum": "Leaf",
+ "managable": "True"
},
"192.168.123.170": {
+ "logicalName": "n9kv-unnum-1",
+ "serialNumber": "9EFX823RUL3",
"isVpcConfigured": "True",
- "vpcDomain": 1
+ "vpcDomain": 1,
+ "switchRoleEnum": "Leaf",
+ "managable": "True"
},
"192.168.123.171": {
+ "logicalName": "n9kv-unnum-2",
+ "serialNumber": "9AF3VNZYAKS",
"isVpcConfigured": "True",
- "vpcDomain": 1
+ "vpcDomain": 1,
+ "switchRoleEnum": "Leaf",
+ "managable": "True"
},
"10.64.78.225": {
+ "logicalName": "n9kv-test1",
+ "serialNumber": "98YWRN9WCSC",
"isVpcConfigured": "True",
- "vpcDomain": 1
+ "vpcDomain": 1,
+ "switchRoleEnum": "Leaf",
+ "managable": "True"
},
"10.64.78.226": {
+ "logicalName": "n9kv-test2",
+ "serialNumber": "94UTIRVSX58",
"isVpcConfigured": "True",
- "vpcDomain": 1
+ "vpcDomain": 1,
+ "switchRoleEnum": "Leaf",
+ "managable": "True"
},
"10.64.78.227": {
+ "logicalName": "n9kv-227",
+ "serialNumber": "953E68OKK1L",
"isVpcConfigured": "True",
- "vpcDomain": 1
+ "vpcDomain": 1,
+ "switchRoleEnum": "Leaf",
+ "managable": "True"
},
"10.64.78.228": {
+ "logicalName": "n9kv-228",
+ "serialNumber": "9WCPR0JUV6M",
"isVpcConfigured": "True",
- "vpcDomain": 1
+ "vpcDomain": 1,
+ "switchRoleEnum": "Leaf",
+ "managable": "True"
},
"10.64.78.230": {
+ "logicalName": "test11",
+ "serialNumber": "9XLP8I4TPPM",
"isVpcConfigured": "True",
- "vpcDomain": 1
+ "vpcDomain": 1,
+ "switchRoleEnum": "Leaf",
+ "managable": "True"
},
"10.64.78.231": {
+ "logicalName": "test22",
+ "serialNumber": "9E15XSEM5MS",
"isVpcConfigured": "True",
- "vpcDomain": 1
+ "vpcDomain": 1,
+ "switchRoleEnum": "Leaf",
+ "managable": "True"
+ },
+ "10.69.69.1": {
+ "logicalName": "n9kv-1",
+ "serialNumber": "TEST-SNO-1",
+ "isVpcConfigured": "True",
+ "vpcDomain": 1,
+ "switchRoleEnum": "None",
+ "managable": "False"
+ },
+ "10.69.69.2": {
+ "logicalName": "n9kv-2",
+ "serialNumber": "TEST-SNO-2",
+ "isVpcConfigured": "True",
+ "vpcDomain": 1,
+ "switchRoleEnum": "None",
+ "managable": "False"
+ },
+ "10.69.69.3": {
+ "logicalName": "n9kv-3",
+ "serialNumber": "TEST-SNO-3",
+ "isVpcConfigured": "True",
+ "vpcDomain": 1,
+ "switchRoleEnum": "None",
+ "managable": "False"
+ },
+ "10.69.69.4": {
+ "logicalName": "n9kv-4",
+ "serialNumber": "TEST-SNO-4",
+ "isVpcConfigured": "True",
+ "vpcDomain": 1,
+ "switchRoleEnum": "None",
+ "managable": "False"
+ },
+ "10.69.69.5": {
+ "logicalName": "n9kv-5",
+ "serialNumber": "TEST-SNO-5",
+ "isVpcConfigured": "True",
+ "vpcDomain": 1,
+ "switchRoleEnum": "None",
+ "managable": "False"
+ },
+ "10.69.69.6": {
+ "logicalName": "n9kv-6",
+ "serialNumber": "TEST-SNO-6",
+ "isVpcConfigured": "True",
+ "vpcDomain": 1,
+ "switchRoleEnum": "None",
+ "managable": "False"
+ }
+ },
+
+ "mock_monitor_true_resp": {
+ "RETURN_CODE": 200,
+ "DATA":{
+ "readonly": "True"
+ }
+ },
+
+ "mock_monitor_false_resp": {
+ "RETURN_CODE": 200,
+ "DATA":{
+ "readonly": "False"
}
},
@@ -211,6 +329,7 @@
"sw2-info": {
"fabric-name": "mmudigon-numbered",
"if-name": "Ethernet1/1",
+ "sw-sys-name": "n9kv-num-2",
"sw-serial-number": "9FX7O3TU2QM"
},
"link-dbid": 1856090,
@@ -241,6 +360,7 @@
"sw1-info": {
"fabric-name": "mmudigon-numbered",
"if-name": "Ethernet1/1",
+ "sw-sys-name": "n9kv-num-1",
"sw-serial-number": "9IF87L089SZ"
},
"fabricName": "mmudigon-numbered"
@@ -258,6 +378,7 @@
"sw2-info": {
"fabric-name": "mmudigon-numbered",
"if-name": "Ethernet1/2",
+ "sw-sys-name": "n9kv-num-2",
"sw-serial-number": "9FX7O3TU2QM"
},
"link-dbid": 1856250,
@@ -268,6 +389,7 @@
"sw1-info": {
"fabric-name": "mmudigon-numbered",
"if-name": "Ethernet1/2",
+ "sw-sys-name": "n9kv-num-1",
"sw-serial-number": "9IF87L089SZ"
},
"fabricName": "mmudigon-numbered"
@@ -285,6 +407,7 @@
"sw2-info": {
"fabric-name": "mmudigon-numbered",
"if-name": "Ethernet1/3",
+ "sw-sys-name": "n9kv-num-2",
"sw-serial-number": "9FX7O3TU2QM"
},
"nvPairs": {
@@ -309,6 +432,7 @@
"sw1-info": {
"fabric-name": "mmudigon-numbered",
"if-name": "Ethernet1/3",
+ "sw-sys-name": "n9kv-num-1",
"sw-serial-number": "9IF87L089SZ"
},
"fabricName": "mmudigon-numbered"
@@ -326,6 +450,7 @@
"sw2-info": {
"fabric-name": "mmudigon-unnumbered",
"if-name": "Ethernet1/1",
+ "sw-sys-name": "n9kv-unnum-2",
"sw-serial-number": "9AF3VNZYAKS"
},
"nvPairs": {
@@ -351,6 +476,7 @@
"sw1-info": {
"fabric-name": "mmudigon-unnumbered",
"if-name": "Ethernet1/1",
+ "sw-sys-name": "n9kv-unnum-1",
"sw-serial-number": "9EFX823RUL3"
},
"fabricName": "mmudigon-unnumbered"
@@ -368,6 +494,7 @@
"sw2-info": {
"fabric-name": "mmudigon-unnumbered",
"if-name": "Ethernet1/2",
+ "sw-sys-name": "n9kv-unnum-2",
"sw-serial-number": "9AF3VNZYAKS"
},
"nvPairs": {
@@ -376,6 +503,7 @@
"sw1-info": {
"fabric-name": "mmudigon-unnumbered",
"if-name": "Ethernet1/2",
+ "sw-sys-name": "n9kv-unnum-1",
"sw-serial-number": "9EFX823RUL3"
},
"fabricName": "mmudigon-unnumbered"
@@ -393,6 +521,7 @@
"sw2-info": {
"fabric-name": "mmudigon-ipv6-underlay",
"if-name": "Ethernet1/1",
+ "sw-sys-name": "n9kv-ipv6-2",
"sw-serial-number": "9ITWBH9OIAH"
},
"nvPairs": {
@@ -418,6 +547,7 @@
"sw1-info": {
"fabric-name": "mmudigon-ipv6-underlay",
"if-name": "Ethernet1/1",
+ "sw-sys-name": "n9kv-ipv6-1",
"sw-serial-number": "9BH0813WFWT"
},
"fabricName": "mmudigon-ipv6-underlay"
@@ -435,6 +565,7 @@
"sw2-info": {
"fabric-name": "mmudigon-ipv6-underlay",
"if-name": "Ethernet1/2",
+ "sw-sys-name": "n9kv-ipv6-2",
"sw-serial-number": "9ITWBH9OIAH"
},
"link-dbid": 1859550,
@@ -444,6 +575,7 @@
"sw1-info": {
"fabric-name": "mmudigon-ipv6-underlay",
"if-name": "Ethernet1/2",
+ "sw-sys-name": "n9kv-ipv6-1",
"sw-serial-number": "9BH0813WFWT"
},
"fabricName": "mmudigon-ipv6-underlay"
@@ -461,6 +593,7 @@
"sw2-info": {
"fabric-name": "mmudigon-ipv6-underlay",
"if-name": "Ethernet1/3",
+ "sw-sys-name": "n9kv-ipv6-2",
"sw-serial-number": "9ITWBH9OIAH"
},
"nvPairs": {
@@ -491,6 +624,7 @@
"sw1-info": {
"fabric-name": "mmudigon-ipv6-underlay",
"if-name": "Ethernet1/3",
+ "sw-sys-name": "n9kv-ipv6-1",
"sw-serial-number": "9BH0813WFWT"
},
"fabricName": "mmudigon-ipv6-underlay"
@@ -508,6 +642,7 @@
"sw2-info": {
"fabric-name": "mmudigon",
"if-name": "Ethernet1/4",
+ "sw-sys-name": "n9kv-200",
"sw-serial-number": "9NXHSNTEO6C"
},
"link-dbid": 1862750,
@@ -535,6 +670,7 @@
"sw1-info": {
"fabric-name": "mmudigon",
"if-name": "Ethernet1/4",
+ "sw-sys-name": "n9kv-100",
"sw-serial-number": "9M99N34RDED"
},
"fabricName": "mmudigon"
@@ -552,12 +688,14 @@
"templateName": "ext_fabric_setup",
"sw2-info": {
"if-name": "Ethernet1/3",
+ "sw-sys-name": "test22",
"sw-serial-number": "9E15XSEM5MS",
"fabric-name": "test_net"
},
"sw1-info": {
"fabric-name": "mmudigon-numbered",
"if-name": "Ethernet1/3",
+ "sw-sys-name": "n9kv-227",
"sw-serial-number": "953E68OKK1L"
},
"nvPairs": {
diff --git a/tests/unit/modules/dcnm/test_dcnm_links.py b/tests/unit/modules/dcnm/test_dcnm_links.py
index 1d3cd2bf5..46099b20e 100644
--- a/tests/unit/modules/dcnm/test_dcnm_links.py
+++ b/tests/unit/modules/dcnm/test_dcnm_links.py
@@ -111,6 +111,134 @@ def load_links_fixtures(self):
):
self.run_dcnm_fabric_info.side_effect = [self.mock_ipv6_fab_info]
+ # -------------------------- INTER-MISC --------------------------------------
+
+ if "test_dcnm_inter_links_src_fab_ro" in self._testMethodName:
+ self.run_dcnm_send.side_effect = [self.mock_monitor_true_resp, self.mock_monitor_true_resp]
+
+ if "test_dcnm_inter_links_dst_fab_ro_dst_sw_non_mgbl" in self._testMethodName:
+
+ merge_links_resp = self.payloads_data.get(
+ "merge_links_fabric_response"
+ )
+ deploy_resp = self.payloads_data.get("deploy_resp")
+ config_preview_resp = self.payloads_data.get("config_preview_resp")
+
+ self.run_dcnm_send.side_effect = [self.mock_monitor_false_resp,
+ self.mock_monitor_true_resp,
+ [],
+ merge_links_resp,
+ deploy_resp,
+ config_preview_resp]
+
+ if "test_dcnm_inter_links_dst_fab_ro_src_sw_non_mgbl" in self._testMethodName:
+
+ merge_links_resp = self.payloads_data.get(
+ "merge_links_fabric_response"
+ )
+ deploy_resp = self.payloads_data.get("deploy_resp")
+ config_preview_resp = self.payloads_data.get("config_preview_resp")
+
+ self.run_dcnm_send.side_effect = [self.mock_monitor_false_resp,
+ self.mock_monitor_true_resp,
+ [],
+ merge_links_resp,
+ deploy_resp,
+ config_preview_resp]
+
+ if "test_dcnm_inter_links_dst_fab_ro_src_dst_sw_non_mgbl" in self._testMethodName:
+
+ merge_links_resp = self.payloads_data.get(
+ "merge_links_fabric_response"
+ )
+ deploy_resp = self.payloads_data.get("deploy_resp")
+ config_preview_resp = self.payloads_data.get("config_preview_resp")
+
+ self.run_dcnm_send.side_effect = [self.mock_monitor_false_resp,
+ self.mock_monitor_true_resp,
+ [],
+ merge_links_resp,
+ deploy_resp,
+ config_preview_resp]
+
+ if "test_dcnm_inter_links_dst_fab_ro_src_dst_sw_mgbl" in self._testMethodName:
+
+ merge_links_resp = self.payloads_data.get(
+ "merge_links_fabric_response"
+ )
+ deploy_resp = self.payloads_data.get("deploy_resp")
+ config_preview_resp = self.payloads_data.get("config_preview_resp")
+
+ self.run_dcnm_send.side_effect = [self.mock_monitor_false_resp,
+ self.mock_monitor_true_resp,
+ [],
+ merge_links_resp,
+ deploy_resp,
+ config_preview_resp]
+
+ if "test_dcnm_inter_links_dst_fab_rw_dst_sw_non_mgbl" in self._testMethodName:
+
+ merge_links_resp = self.payloads_data.get(
+ "merge_links_fabric_response"
+ )
+ deploy_resp = self.payloads_data.get("deploy_resp")
+ config_preview_resp = self.payloads_data.get("config_preview_resp")
+
+ self.run_dcnm_send.side_effect = [self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ [],
+ merge_links_resp,
+ deploy_resp,
+ config_preview_resp]
+
+ if "test_dcnm_inter_links_dst_fab_rw_src_sw_non_mgbl" in self._testMethodName:
+
+ merge_links_resp = self.payloads_data.get(
+ "merge_links_fabric_response"
+ )
+ deploy_resp = self.payloads_data.get("deploy_resp")
+ config_preview_resp = self.payloads_data.get("config_preview_resp")
+
+ self.run_dcnm_send.side_effect = [self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ [],
+ merge_links_resp,
+ deploy_resp,
+ config_preview_resp]
+
+ if "test_dcnm_inter_links_dst_fab_rw_src_dst_sw_non_mgbl" in self._testMethodName:
+
+ merge_links_resp = self.payloads_data.get(
+ "merge_links_fabric_response"
+ )
+ deploy_resp = self.payloads_data.get("deploy_resp")
+ config_preview_resp = self.payloads_data.get("config_preview_resp")
+
+ self.run_dcnm_send.side_effect = [self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ [],
+ merge_links_resp,
+ deploy_resp,
+ config_preview_resp]
+
+ if "test_dcnm_inter_links_dst_fab_rw_src_dst_sw_mgbl" in self._testMethodName:
+
+ merge_links_resp = self.payloads_data.get(
+ "merge_links_fabric_response"
+ )
+ deploy_resp = self.payloads_data.get("deploy_resp")
+ config_preview_resp = self.payloads_data.get("config_preview_resp")
+
+ self.run_dcnm_send.side_effect = [self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ [],
+ merge_links_resp,
+ deploy_resp,
+ deploy_resp,
+ config_preview_resp,
+ config_preview_resp,
+ config_preview_resp]
+
# -------------------------- INTRA-FABRIC-UNNUMBERED --------------------------
if (
@@ -125,6 +253,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
[],
[],
merge_links_resp,
@@ -145,6 +274,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
[],
[],
merge_links_resp,
@@ -163,6 +293,7 @@ def load_links_fixtures(self):
)
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
[],
[],
merge_links_resp,
@@ -187,6 +318,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
deploy_resp,
@@ -205,6 +337,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
[],
[],
merge_links_resp,
@@ -235,6 +368,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
merge_links_resp,
@@ -260,6 +394,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
merge_links_resp,
@@ -285,6 +420,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
merge_links_resp,
@@ -310,6 +446,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
[],
@@ -336,6 +473,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
[],
[],
@@ -351,7 +489,9 @@ def load_links_fixtures(self):
== self._testMethodName
):
- self.run_dcnm_send.side_effect = [[], [], [], [], []]
+ self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ [], [], [], [], []]
if (
"test_dcnm_intra_links_unnumbered_template_change"
@@ -368,6 +508,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
merge_links_resp,
deploy_resp,
@@ -379,7 +520,9 @@ def load_links_fixtures(self):
query_links_resp = self.payloads_data.get(
"intra_query_links_unnum_fabric_response"
)
- self.run_dcnm_send.side_effect = [query_links_resp]
+ self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ query_links_resp]
# -------------------------- INTRA-FABRIC-IPV6 ----------------------------------
@@ -395,6 +538,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
[],
[],
[],
@@ -414,6 +558,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
[],
[],
[],
@@ -445,6 +590,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -464,6 +610,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
[],
[],
[],
@@ -494,6 +641,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -523,6 +671,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -553,6 +702,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -583,6 +733,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -614,6 +765,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -630,14 +782,18 @@ def load_links_fixtures(self):
== self._testMethodName
):
- self.run_dcnm_send.side_effect = [[], [], [], [], []]
+ self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ [], [], [], [], []]
if "test_dcnm_intra_links_ipv6_query" in self._testMethodName:
query_links_resp = self.payloads_data.get(
"intra_query_links_ipv6_fabric_response"
)
- self.run_dcnm_send.side_effect = [query_links_resp]
+ self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ query_links_resp]
# -------------------------- INTRA-FABRIC-NUMBERED --------------------------
@@ -653,6 +809,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
[],
[],
[],
@@ -672,6 +829,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
[],
[],
[],
@@ -703,6 +861,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -722,6 +881,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
[],
[],
[],
@@ -751,6 +911,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -780,6 +941,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -810,6 +972,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -840,6 +1003,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -871,6 +1035,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -887,7 +1052,9 @@ def load_links_fixtures(self):
== self._testMethodName
):
- self.run_dcnm_send.side_effect = [[], [], [], [], []]
+ self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ [], [], [], [], []]
if (
"test_dcnm_intra_links_numbered_template_change"
@@ -904,6 +1071,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
merge_links_resp,
deploy_resp,
@@ -915,7 +1083,9 @@ def load_links_fixtures(self):
query_links_resp = self.payloads_data.get(
"intra_query_links_num_fabric_response"
)
- self.run_dcnm_send.side_effect = [query_links_resp]
+ self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ query_links_resp]
# ------------------------------ INTRA-FABRIC-VPC ---------------------------
@@ -931,6 +1101,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
[],
merge_links_resp,
deploy_resp,
@@ -946,6 +1117,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
[],
merge_links_resp,
deploy_resp,
@@ -964,6 +1136,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
deploy_resp,
config_preview_resp,
@@ -981,6 +1154,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
[],
merge_links_resp,
deploy_resp,
@@ -1001,6 +1175,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
merge_links_resp,
deploy_resp,
@@ -1019,6 +1194,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
merge_links_resp,
deploy_resp,
@@ -1040,6 +1216,7 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
have_links_resp1,
merge_links_resp,
deploy_resp,
@@ -1058,10 +1235,11 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
- have_links_resp1,
+ self.mock_monitor_false_resp,
[],
[],
[],
+ have_links_resp1,
[],
delete_links_resp,
deploy_resp,
@@ -1083,10 +1261,11 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
- have_links_resp1,
+ self.mock_monitor_false_resp,
[],
[],
[],
+ have_links_resp1,
[],
delete_links_resp,
deploy_resp,
@@ -1098,14 +1277,18 @@ def load_links_fixtures(self):
== self._testMethodName
):
- self.run_dcnm_send.side_effect = [[], [], [], [], []]
+ self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ [], [], [], [], []]
if "test_dcnm_intra_links_vpc_query" in self._testMethodName:
query_links_resp = self.payloads_data.get(
"intra_query_links_vpc_response"
)
- self.run_dcnm_send.side_effect = [query_links_resp]
+ self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ query_links_resp]
# -------------------------- INTER-FABRIC-NUMBERED --------------------------
@@ -1121,6 +1304,9 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
[],
[],
[],
@@ -1150,6 +1336,9 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
[],
[],
[],
@@ -1200,6 +1389,9 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -1226,6 +1418,9 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
[],
[],
[],
@@ -1271,6 +1466,9 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -1318,6 +1516,9 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -1368,6 +1569,9 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -1418,6 +1622,9 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -1464,6 +1671,9 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
have_links_resp1,
have_links_resp2,
have_links_resp3,
@@ -1487,7 +1697,11 @@ def load_links_fixtures(self):
== self._testMethodName
):
- self.run_dcnm_send.side_effect = [[], [], [], [], [], []]
+ self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ [], [], [], [], [], []]
if (
"test_dcnm_inter_links_numbered_template_change"
@@ -1504,6 +1718,8 @@ def load_links_fixtures(self):
config_preview_resp = self.payloads_data.get("config_preview_resp")
self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
have_links_resp1,
merge_links_resp,
deploy_resp,
@@ -1512,12 +1728,23 @@ def load_links_fixtures(self):
config_preview_resp,
]
- if "test_dcnm_inter_links_numbered_query" in self._testMethodName:
+ if "test_dcnm_inter_links_numbered_query_no_config" in self._testMethodName:
query_links_resp = self.payloads_data.get(
"inter_query_links_num_fabric_response"
)
- self.run_dcnm_send.side_effect = [query_links_resp]
+ self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ query_links_resp]
+ elif "test_dcnm_inter_links_numbered_query" in self._testMethodName:
+
+ query_links_resp = self.payloads_data.get(
+ "inter_query_links_num_fabric_response"
+ )
+ self.run_dcnm_send.side_effect = [
+ self.mock_monitor_false_resp,
+ self.mock_monitor_false_resp,
+ query_links_resp]
def load_fixtures(self, response=None, device=""):
@@ -1549,6 +1776,8 @@ def test_dcnm_intra_links_numbered_merged_new_no_opts(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -1583,6 +1812,8 @@ def test_dcnm_intra_links_numbered_merged_new(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -1617,6 +1848,8 @@ def test_dcnm_intra_links_numbered_merged_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -1651,6 +1884,8 @@ def test_dcnm_intra_links_numbered_merged_new_no_state(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -1685,6 +1920,8 @@ def test_dcnm_intra_links_numbered_merged_new_check_mode(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -1722,6 +1959,8 @@ def test_dcnm_intra_links_numbered_merged_new_existing_and_non_existing(
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -1757,6 +1996,8 @@ def test_dcnm_intra_links_numbered_modify_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -1792,6 +2033,8 @@ def test_dcnm_intra_links_numbered_replace_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -1827,6 +2070,8 @@ def test_dcnm_intra_links_numbered_delete_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -1862,6 +2107,8 @@ def test_dcnm_intra_links_numbered_delete_existing_and_non_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -1897,6 +2144,8 @@ def test_dcnm_intra_links_numbered_delete_non_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -1932,6 +2181,8 @@ def test_dcnm_intra_links_numbered_template_change(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -1967,6 +2218,8 @@ def test_dcnm_intra_links_numbered_query_no_config(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -1998,6 +2251,8 @@ def test_dcnm_intra_links_numbered_query_with_dst_fabric(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2029,6 +2284,8 @@ def test_dcnm_intra_links_numbered_query_with_src_device(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2060,6 +2317,8 @@ def test_dcnm_intra_links_numbered_query_with_dst_device(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2091,6 +2350,8 @@ def test_dcnm_intra_links_numbered_query_with_src_interface(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2122,6 +2383,8 @@ def test_dcnm_intra_links_numbered_query_with_dst_interface(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2151,6 +2414,8 @@ def test_dcnm_intra_links_numbered_query(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2186,6 +2451,8 @@ def test_dcnm_intra_links_unnumbered_merged_new_no_opts(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_umnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2222,6 +2489,8 @@ def test_dcnm_intra_links_unnumbered_merged_new(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2258,6 +2527,8 @@ def test_dcnm_intra_links_unnumbered_merged_new_no_deploy(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2293,6 +2564,8 @@ def test_dcnm_intra_links_unnumbered_merged_existing(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2329,6 +2602,8 @@ def test_dcnm_intra_links_unnumbered_merged_new_no_state(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2365,6 +2640,8 @@ def test_dcnm_intra_links_unnumbered_merged_new_check_mode(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2404,6 +2681,8 @@ def test_dcnm_intra_links_unnumbered_merged_new_existing_and_non_existing(
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2443,6 +2722,8 @@ def test_dcnm_intra_links_unnumbered_modify_existing(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2482,6 +2763,8 @@ def test_dcnm_intra_links_unnumbered_replace_existing(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2521,6 +2804,8 @@ def test_dcnm_intra_links_unnumbered_delete_existing(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2562,6 +2847,8 @@ def test_dcnm_intra_links_unnumbered_delete_existing_and_non_existing(
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2601,6 +2888,8 @@ def test_dcnm_intra_links_unnumbered_delete_non_existing(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2638,6 +2927,8 @@ def test_dcnm_intra_links_unnumbered_template_change(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2677,6 +2968,8 @@ def test_dcnm_intra_links_unnumbered_query_not_exist(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2708,6 +3001,8 @@ def test_dcnm_intra_links_unnumbered_query_no_config(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2741,6 +3036,8 @@ def test_dcnm_intra_links_unnumbered_query_with_dst_fabric(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2774,6 +3071,8 @@ def test_dcnm_intra_links_unnumbered_query_with_src_device(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2807,6 +3106,8 @@ def test_dcnm_intra_links_unnumbered_query_with_dst_device(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2840,6 +3141,8 @@ def test_dcnm_intra_links_unnumbered_query_with_src_interface(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2873,6 +3176,8 @@ def test_dcnm_intra_links_unnumbered_query_with_dst_interface(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2904,6 +3209,8 @@ def test_dcnm_intra_links_unnumbered_query(self):
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2937,6 +3244,8 @@ def test_dcnm_intra_links_ipv6_merged_new_no_opts(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -2971,6 +3280,8 @@ def test_dcnm_intra_links_ipv6_merged_new(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3005,6 +3316,8 @@ def test_dcnm_intra_links_ipv6_merged_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3039,6 +3352,8 @@ def test_dcnm_intra_links_ipv6_merged_new_no_state(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3073,6 +3388,8 @@ def test_dcnm_intra_links_ipv6_merged_new_check_mode(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3108,6 +3425,8 @@ def test_dcnm_intra_links_ipv6_merged_new_existing_and_non_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3143,6 +3462,8 @@ def test_dcnm_intra_links_ipv6_modify_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3180,6 +3501,8 @@ def test_dcnm_intra_links_ipv6_replace_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3215,6 +3538,8 @@ def test_dcnm_intra_links_ipv6_delete_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3250,6 +3575,8 @@ def test_dcnm_intra_links_ipv6_delete_existing_and_non_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3285,6 +3612,8 @@ def test_dcnm_intra_links_ipv6_delete_non_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3318,6 +3647,8 @@ def test_dcnm_intra_links_ipv6_query_no_config(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3349,6 +3680,8 @@ def test_dcnm_intra_links_ipv6_query_with_dst_fabric(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3380,6 +3713,8 @@ def test_dcnm_intra_links_ipv6_query_with_src_device(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3411,6 +3746,8 @@ def test_dcnm_intra_links_ipv6_query_with_dst_device(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3442,6 +3779,8 @@ def test_dcnm_intra_links_ipv6_query_with_src_interface(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3473,6 +3812,8 @@ def test_dcnm_intra_links_ipv6_query_with_dst_interface(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3502,6 +3843,8 @@ def test_dcnm_intra_links_ipv6_query(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3533,6 +3876,8 @@ def test_dcnm_intra_links_ipv6_query_not_exist(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3566,6 +3911,8 @@ def test_dcnm_intra_links_vpc_merged_new_no_opts(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3598,6 +3945,8 @@ def test_dcnm_intra_links_vpc_merged_new(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3630,6 +3979,8 @@ def test_dcnm_intra_links_vpc_merged_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3662,6 +4013,8 @@ def test_dcnm_intra_links_vpc_merged_new_no_state(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3694,6 +4047,8 @@ def test_dcnm_intra_links_vpc_merged_new_check_mode(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3727,6 +4082,8 @@ def test_dcnm_intra_links_vpc_merged_new_existing_and_non_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3760,6 +4117,8 @@ def test_dcnm_intra_links_vpc_modify_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3793,6 +4152,8 @@ def test_dcnm_intra_links_vpc_replace_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3826,6 +4187,8 @@ def test_dcnm_intra_links_vpc_delete_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3859,6 +4222,8 @@ def test_dcnm_intra_links_vpc_delete_existing_and_non_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3892,6 +4257,8 @@ def test_dcnm_intra_links_vpc_delete_non_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3925,6 +4292,8 @@ def test_dcnm_intra_links_vpc_query_no_config(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3956,6 +4325,8 @@ def test_dcnm_intra_links_vpc_query_with_dst_fabric(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -3987,6 +4358,8 @@ def test_dcnm_intra_links_vpc_query_with_src_device(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -4018,6 +4391,8 @@ def test_dcnm_intra_links_vpc_query_with_dst_device(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -4049,6 +4424,8 @@ def test_dcnm_intra_links_vpc_query_with_src_interface(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -4080,6 +4457,8 @@ def test_dcnm_intra_links_vpc_query_with_dst_interface(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -4109,6 +4488,8 @@ def test_dcnm_intra_links_vpc_query(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -4146,6 +4527,8 @@ def test_dcnm_inter_links_numbered_merged_new_no_opts(self):
"mock_unnum_fab_data"
)
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -4182,6 +4565,8 @@ def test_dcnm_inter_links_numbered_merged_new(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4222,6 +4607,8 @@ def test_dcnm_inter_links_numbered_merged_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4262,6 +4649,8 @@ def test_dcnm_inter_links_numbered_merged_new_no_state(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4302,6 +4691,8 @@ def test_dcnm_inter_links_numbered_merged_new_check_mode(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4345,6 +4736,8 @@ def test_dcnm_inter_links_numbered_merged_new_existing_and_non_existing(
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4386,6 +4779,8 @@ def test_dcnm_inter_links_numbered_modify_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4427,6 +4822,8 @@ def test_dcnm_inter_links_numbered_replace_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4468,6 +4865,8 @@ def test_dcnm_inter_links_numbered_delete_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4509,6 +4908,8 @@ def test_dcnm_inter_links_numbered_delete_existing_and_non_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4550,6 +4951,8 @@ def test_dcnm_inter_links_numbered_delete_non_existing(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4589,6 +4992,8 @@ def test_dcnm_inter_links_numbered_template_change(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4629,6 +5034,8 @@ def test_dcnm_inter_links_numbered_query_no_config(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4664,6 +5071,8 @@ def test_dcnm_inter_links_numbered_query_with_dst_fabric(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4699,6 +5108,8 @@ def test_dcnm_inter_links_numbered_query_with_src_device(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4734,6 +5145,8 @@ def test_dcnm_inter_links_numbered_query_with_dst_device(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4769,6 +5182,8 @@ def test_dcnm_inter_links_numbered_query_with_src_interface(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4804,6 +5219,8 @@ def test_dcnm_inter_links_numbered_query_with_dst_interface(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4837,6 +5254,8 @@ def test_dcnm_inter_links_numbered_query(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4872,6 +5291,8 @@ def test_dcnm_inter_links_numbered_query_not_exist(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_unnum_fab_info = self.payloads_data.get(
"mock_unnum_fab_data"
)
@@ -4909,6 +5330,8 @@ def test_dcnm_intra_links_invalid_template(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -4940,6 +5363,8 @@ def test_dcnm_intra_links_missing_src_fabric(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(dict(state="merged", config=self.playbook_config))
@@ -4967,6 +5392,8 @@ def test_dcnm_intra_links_missing_dst_fabric(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5000,6 +5427,8 @@ def test_dcnm_intra_links_missing_src_intf(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5034,6 +5463,8 @@ def test_dcnm_intra_links_missing_dst_intf(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5068,6 +5499,8 @@ def test_dcnm_intra_links_missing_src_device(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5101,6 +5534,8 @@ def test_dcnm_intra_links_missing_dst_device(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5134,6 +5569,8 @@ def test_dcnm_intra_links_missing_template(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5167,6 +5604,8 @@ def test_dcnm_intra_links_missing_peer1_ipv6(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
set_module_args(
@@ -5202,6 +5641,8 @@ def test_dcnm_intra_links_missing_peer2_ipv6(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
set_module_args(
@@ -5237,6 +5678,8 @@ def test_dcnm_intra_links_missing_peer1_ipv4(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5271,6 +5714,8 @@ def test_dcnm_intra_links_missing_peer2_ipv4(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5303,6 +5748,8 @@ def test_dcnm_intra_links_missing_mtu(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5336,6 +5783,8 @@ def test_dcnm_intra_links_missing_admin_state(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5371,6 +5820,8 @@ def test_dcnm_inter_links_invalid_template(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5402,6 +5853,8 @@ def test_dcnm_inter_links_missing_src_fabric(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(dict(state="merged", config=self.playbook_config))
@@ -5429,6 +5882,8 @@ def test_dcnm_inter_links_missing_dst_fabric(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5462,6 +5917,8 @@ def test_dcnm_inter_links_missing_src_intf(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5496,6 +5953,8 @@ def test_dcnm_inter_links_missing_dst_intf(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5530,6 +5989,8 @@ def test_dcnm_inter_links_missing_src_device(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5563,6 +6024,8 @@ def test_dcnm_inter_links_missing_dst_device(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5596,6 +6059,8 @@ def test_dcnm_inter_links_missing_template(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5629,6 +6094,8 @@ def test_dcnm_inter_links_missing_ipv4_subnet(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
set_module_args(
@@ -5663,6 +6130,8 @@ def test_dcnm_inter_links_missing_neighbor_ip(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
self.mock_ipv6_fab_info = self.payloads_data.get("mock_ipv6_fab_data")
set_module_args(
@@ -5697,6 +6166,8 @@ def test_dcnm_inter_links_missing_src_asn(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5730,6 +6201,8 @@ def test_dcnm_inter_links_missing_dst_asn(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5763,6 +6236,8 @@ def test_dcnm_inter_links_missing_ipv4_addr(self):
self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
set_module_args(
dict(
@@ -5781,3 +6256,307 @@ def test_dcnm_inter_links_missing_ipv4_addr(self):
self.assertEqual(
("ipv4_addr : Required parameter not found" in str(e)), True
)
+
+ # ---------------------- INTER-FABRIC MISC ----------------------------
+
+ def test_dcnm_inter_links_src_fab_ro(self):
+
+ # load the json from playbooks
+ self.config_data = loadPlaybookData("dcnm_links_configs")
+ self.payloads_data = loadPlaybookData("dcnm_links_payloads")
+
+ # load required config data
+ self.playbook_config = self.config_data.get(
+ "inter_src_fab_ro_config"
+ )
+ self.mock_ip_sn = self.payloads_data.get("mock_ip_sn")
+ self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
+ self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
+ self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
+
+ set_module_args(
+ dict(
+ state="merged",
+ src_fabric="mmudigon-src-fab-ro",
+ config=self.playbook_config,
+ )
+ )
+
+ result = None
+
+ try:
+ result = self.execute_module(changed=False, failed=False)
+ except Exception as e:
+ self.assertEqual(result, None)
+ self.assertEqual(
+ ("is in Monitoring mode" in str(e)), True
+ )
+ self.assertEqual(
+ ("No changes are allowed on the fabric" in str(e)), True
+ )
+
+ def test_dcnm_inter_links_dst_fab_ro_dst_sw_non_mgbl(self):
+
+ # load the json from playbooks
+ self.config_data = loadPlaybookData("dcnm_links_configs")
+ self.payloads_data = loadPlaybookData("dcnm_links_payloads")
+
+ # load required config data
+ self.playbook_config = self.config_data.get(
+ "inter_dst_fab_ro_dst_sw_non_mgbl_config"
+ )
+ self.mock_ip_sn = self.payloads_data.get("mock_ip_sn")
+ self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
+ self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
+ self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
+
+ set_module_args(
+ dict(
+ state="merged",
+ src_fabric="mmudigon-numbered",
+ config=self.playbook_config,
+ )
+ )
+
+ result = self.execute_module(changed=True, failed=False)
+
+ self.assertEqual(len(result["diff"][0]["merged"]), 1)
+ self.assertEqual(len(result["diff"][0]["modified"]), 0)
+ self.assertEqual(len(result["diff"][0]["deleted"]), 0)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-numbered"]), 1)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-dst-fab-ro"]), 0)
+
+ def test_dcnm_inter_links_dst_fab_ro_src_sw_non_mgbl(self):
+
+ # load the json from playbooks
+ self.config_data = loadPlaybookData("dcnm_links_configs")
+ self.payloads_data = loadPlaybookData("dcnm_links_payloads")
+
+ # load required config data
+ self.playbook_config = self.config_data.get(
+ "inter_dst_fab_ro_src_sw_non_mgbl_config"
+ )
+ self.mock_ip_sn = self.payloads_data.get("mock_ip_sn")
+ self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
+ self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
+ self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
+
+ set_module_args(
+ dict(
+ state="merged",
+ src_fabric="mmudigon-numbered",
+ config=self.playbook_config,
+ )
+ )
+
+ result = self.execute_module(changed=True, failed=False)
+
+ self.assertEqual(len(result["diff"][0]["merged"]), 1)
+ self.assertEqual(len(result["diff"][0]["modified"]), 0)
+ self.assertEqual(len(result["diff"][0]["deleted"]), 0)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-numbered"]), 0)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-dst-fab-ro"]), 0)
+
+ def test_dcnm_inter_links_dst_fab_ro_src_dst_sw_non_mgbl(self):
+
+ # load the json from playbooks
+ self.config_data = loadPlaybookData("dcnm_links_configs")
+ self.payloads_data = loadPlaybookData("dcnm_links_payloads")
+
+ # load required config data
+ self.playbook_config = self.config_data.get(
+ "inter_dst_fab_ro_src_dst_sw_non_mgbl_config"
+ )
+ self.mock_ip_sn = self.payloads_data.get("mock_ip_sn")
+ self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
+ self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
+ self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
+
+ set_module_args(
+ dict(
+ state="merged",
+ src_fabric="mmudigon-numbered",
+ config=self.playbook_config,
+ )
+ )
+
+ result = self.execute_module(changed=True, failed=False)
+
+ self.assertEqual(len(result["diff"][0]["merged"]), 1)
+ self.assertEqual(len(result["diff"][0]["modified"]), 0)
+ self.assertEqual(len(result["diff"][0]["deleted"]), 0)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-numbered"]), 0)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-dst-fab-ro"]), 0)
+
+ def test_dcnm_inter_links_dst_fab_ro_src_dst_sw_mgbl(self):
+
+ # load the json from playbooks
+ self.config_data = loadPlaybookData("dcnm_links_configs")
+ self.payloads_data = loadPlaybookData("dcnm_links_payloads")
+
+ # load required config data
+ self.playbook_config = self.config_data.get(
+ "inter_dst_fab_ro_src_dst_sw_mgbl_config"
+ )
+ self.mock_ip_sn = self.payloads_data.get("mock_ip_sn")
+ self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
+ self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
+ self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
+
+ set_module_args(
+ dict(
+ state="merged",
+ src_fabric="mmudigon-numbered",
+ config=self.playbook_config,
+ )
+ )
+
+ result = self.execute_module(changed=True, failed=False)
+
+ self.assertEqual(len(result["diff"][0]["merged"]), 1)
+ self.assertEqual(len(result["diff"][0]["modified"]), 0)
+ self.assertEqual(len(result["diff"][0]["deleted"]), 0)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-numbered"]), 1)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-dst-fab-ro"]), 0)
+
+ def test_dcnm_inter_links_dst_fab_rw_dst_sw_non_mgbl(self):
+
+ # load the json from playbooks
+ self.config_data = loadPlaybookData("dcnm_links_configs")
+ self.payloads_data = loadPlaybookData("dcnm_links_payloads")
+
+ # load required config data
+ self.playbook_config = self.config_data.get(
+ "inter_dst_fab_rw_dst_sw_non_mgbl_config"
+ )
+ self.mock_ip_sn = self.payloads_data.get("mock_ip_sn")
+ self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
+ self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
+ self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
+
+ set_module_args(
+ dict(
+ state="merged",
+ src_fabric="mmudigon-numbered",
+ config=self.playbook_config,
+ )
+ )
+
+ result = self.execute_module(changed=True, failed=False)
+
+ self.assertEqual(len(result["diff"][0]["merged"]), 1)
+ self.assertEqual(len(result["diff"][0]["modified"]), 0)
+ self.assertEqual(len(result["diff"][0]["deleted"]), 0)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-numbered"]), 1)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-dst-fab-rw"]), 0)
+
+ def test_dcnm_inter_links_dst_fab_rw_src_sw_non_mgbl(self):
+
+ # load the json from playbooks
+ self.config_data = loadPlaybookData("dcnm_links_configs")
+ self.payloads_data = loadPlaybookData("dcnm_links_payloads")
+
+ # load required config data
+ self.playbook_config = self.config_data.get(
+ "inter_dst_fab_rw_src_sw_non_mgbl_config"
+ )
+ self.mock_ip_sn = self.payloads_data.get("mock_ip_sn")
+ self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
+ self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
+ self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
+
+ set_module_args(
+ dict(
+ state="merged",
+ src_fabric="mmudigon-numbered",
+ config=self.playbook_config,
+ )
+ )
+
+ result = self.execute_module(changed=True, failed=False)
+
+ self.assertEqual(len(result["diff"][0]["merged"]), 1)
+ self.assertEqual(len(result["diff"][0]["modified"]), 0)
+ self.assertEqual(len(result["diff"][0]["deleted"]), 0)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-numbered"]), 0)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-dst-fab-rw"]), 0)
+
+ def test_dcnm_inter_links_dst_fab_rw_src_dst_sw_non_mgbl(self):
+
+ # load the json from playbooks
+ self.config_data = loadPlaybookData("dcnm_links_configs")
+ self.payloads_data = loadPlaybookData("dcnm_links_payloads")
+
+ # load required config data
+ self.playbook_config = self.config_data.get(
+ "inter_dst_fab_rw_src_dst_sw_non_mgbl_config"
+ )
+ self.mock_ip_sn = self.payloads_data.get("mock_ip_sn")
+ self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
+ self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
+ self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
+
+ set_module_args(
+ dict(
+ state="merged",
+ src_fabric="mmudigon-numbered",
+ config=self.playbook_config,
+ )
+ )
+
+ result = self.execute_module(changed=True, failed=False)
+
+ self.assertEqual(len(result["diff"][0]["merged"]), 1)
+ self.assertEqual(len(result["diff"][0]["modified"]), 0)
+ self.assertEqual(len(result["diff"][0]["deleted"]), 0)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-numbered"]), 0)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-dst-fab-rw"]), 0)
+
+ def test_dcnm_inter_links_dst_fab_rw_src_dst_sw_mgbl(self):
+
+ # load the json from playbooks
+ self.config_data = loadPlaybookData("dcnm_links_configs")
+ self.payloads_data = loadPlaybookData("dcnm_links_payloads")
+
+ # load required config data
+ self.playbook_config = self.config_data.get(
+ "inter_dst_fab_rw_src_dst_sw_mgbl_config"
+ )
+ self.mock_ip_sn = self.payloads_data.get("mock_ip_sn")
+ self.mock_hn_sn = self.payloads_data.get("mock_hn_sn")
+ self.mock_fab_inv = self.payloads_data.get("mock_fab_inv_data")
+ self.mock_num_fab_info = self.payloads_data.get("mock_num_fab_data")
+ self.mock_monitor_true_resp = self.payloads_data.get("mock_monitor_true_resp")
+ self.mock_monitor_false_resp = self.payloads_data.get("mock_monitor_false_resp")
+
+ set_module_args(
+ dict(
+ state="merged",
+ src_fabric="mmudigon-numbered",
+ config=self.playbook_config,
+ )
+ )
+
+ result = self.execute_module(changed=True, failed=False)
+
+ self.assertEqual(len(result["diff"][0]["merged"]), 1)
+ self.assertEqual(len(result["diff"][0]["modified"]), 0)
+ self.assertEqual(len(result["diff"][0]["deleted"]), 0)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-numbered"]), 1)
+ self.assertEqual(len(result["diff"][0]["deploy"][0]["mmudigon-dst-fab-rw"]), 1)
From 8b9bde18694e236fbd6b3af20f87934216f0c6af Mon Sep 17 00:00:00 2001
From: praveenramoorthy <62758226+praveenramoorthy@users.noreply.github.com>
Date: Thu, 18 May 2023 18:58:58 +0530
Subject: [PATCH 3/8] vrf lite changes (#221)
* vrf lite changes
* vrf lite changes
* Addressed review comments
---
docs/cisco.dcnm.dcnm_vrf_module.rst | 8 +-
plugins/action/dcnm_vrf.py | 13 +-
plugins/modules/dcnm_vrf.py | 325 +++++++++---------
.../targets/dcnm_vrf/tests/dcnm/deleted.yaml | 6 +-
.../targets/dcnm_vrf/tests/dcnm/merged.yaml | 19 +-
.../dcnm_vrf/tests/dcnm/overridden.yaml | 6 +-
.../targets/dcnm_vrf/tests/dcnm/query.yaml | 4 +-
.../targets/dcnm_vrf/tests/dcnm/replaced.yaml | 18 +-
.../dcnm/self-contained-tests/vrf_lite.yaml | 30 +-
9 files changed, 210 insertions(+), 219 deletions(-)
diff --git a/docs/cisco.dcnm.dcnm_vrf_module.rst b/docs/cisco.dcnm.dcnm_vrf_module.rst
index 48db1acb6..97ef5928c 100644
--- a/docs/cisco.dcnm.dcnm_vrf_module.rst
+++ b/docs/cisco.dcnm.dcnm_vrf_module.rst
@@ -197,6 +197,7 @@ Parameters
string
+ / required
|
@@ -1098,18 +1099,15 @@ Examples
- ip_address: 192.168.1.224
- ip_address: 192.168.1.225
vrf_lite:
- # All parameters under vrf_lite are optional
- # For best results in VRF LITE idempotence checks and
- # configurations specify all possible vrf_lite parameters
- peer_vrf: test_vrf_1 # optional
- interface: Ethernet1/16 # optional
+ interface: Ethernet1/16 # mandatory
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
neighbor_ipv6: 2010::10:34:0:3 # optional
dot1q: 2 # dot1q can be got from dcnm/optional
- peer_vrf: test_vrf_2 # optional
- interface: Ethernet1/17 # optional
+ interface: Ethernet1/17 # mandatory
ipv4_addr: 20.33.0.2/30 # optional
neighbor_ipv4: 20.33.0.1 # optional
ipv6_addr: 3010::10:34:0:7/64 # optional
diff --git a/plugins/action/dcnm_vrf.py b/plugins/action/dcnm_vrf.py
index 4c0ade744..a8a473049 100644
--- a/plugins/action/dcnm_vrf.py
+++ b/plugins/action/dcnm_vrf.py
@@ -41,18 +41,9 @@ def run(self, tmp=None, task_vars=None):
if "vrf_lite" in at:
try:
for vl in at["vrf_lite"]:
- if (
- not vl.get("interface")
- ):
- msg = (
- "'interface' parameter is not specified in playbook under 'vrf_lite' config. "
- "Idempotence check will happen based on first available best match. "
- "While attaching, first available extension will be attached for VRF LITE. "
- "For best results specify all possible vrf_lite parameters."
- )
- display.warning(msg)
+ continue
except TypeError:
- msg = "Please specifiy at least one VRF LITE parameter in attach"
+ msg = "Please specify interface parameter under vrf_lite section in the playbook"
return {"failed": True, "msg": msg}
self.result = super(ActionModule, self).run(task_vars=task_vars)
diff --git a/plugins/modules/dcnm_vrf.py b/plugins/modules/dcnm_vrf.py
index 744a87acd..3198a593c 100644
--- a/plugins/modules/dcnm_vrf.py
+++ b/plugins/modules/dcnm_vrf.py
@@ -314,7 +314,7 @@
description:
- Interface of the switch which is connected to the edge router
type: str
- required: false
+ required: true
ipv4_addr:
description:
- IP address of the interface which is connected to the edge router
@@ -448,18 +448,15 @@
- ip_address: 192.168.1.224
- ip_address: 192.168.1.225
vrf_lite:
- # All parameters under vrf_lite are optional
- # For best results in VRF LITE idempotence checks and
- # configurations specify all possible vrf_lite parameters
- peer_vrf: test_vrf_1 # optional
- interface: Ethernet1/16 # optional
+ interface: Ethernet1/16 # mandatory
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
neighbor_ipv6: 2010::10:34:0:3 # optional
dot1q: 2 # dot1q can be got from dcnm/optional
- peer_vrf: test_vrf_2 # optional
- interface: Ethernet1/17 # optional
+ interface: Ethernet1/17 # mandatory
ipv4_addr: 20.33.0.2/30 # optional
neighbor_ipv4: 20.33.0.1 # optional
ipv6_addr: 3010::10:34:0:7/64 # optional
@@ -605,9 +602,6 @@ def __init__(self, module):
self.fabric = module.params["fabric"]
self.config = copy.deepcopy(module.params.get("config"))
self.check_mode = False
- self.vrf_ext = False
- self.role = ""
- self.serial = ""
self.have_create = []
self.want_create = []
self.diff_create = []
@@ -632,7 +626,6 @@ def __init__(self, module):
self.diff_deploy = {}
self.diff_undeploy = {}
self.diff_delete = {}
- self.vrflitevalues = {}
self.diff_input_format = []
self.query = []
self.dcnm_version = dcnm_version_supported(self.module)
@@ -661,6 +654,7 @@ def diff_for_attach_deploy(self, want_a, have_a, replace=False):
dep_vrf = False
for want in want_a:
found = False
+ interface_match = False
if have_a:
for have in have_a:
if want["serialNumber"] == have["serialNumber"]:
@@ -676,77 +670,75 @@ def diff_for_attach_deploy(self, want_a, have_a, replace=False):
want_e = ast.literal_eval(want_ext_values["VRF_LITE_CONN"])
have_e = ast.literal_eval(have_ext_values["VRF_LITE_CONN"])
+ if replace and (len(want_e["VRF_LITE_CONN"]) != len(have_e["VRF_LITE_CONN"])):
+ # In case of replace/override if the length of want and have lite attach of a switch
+ # is not same then we have to push the want to NDFC. No further check is required for
+ # this switch
+ break
+
for wlite in want_e["VRF_LITE_CONN"]:
for hlite in have_e["VRF_LITE_CONN"]:
- if wlite["IF_NAME"]:
- if (
- wlite["IF_NAME"]
- == hlite["IF_NAME"]
- ):
- found = True
- else:
- found = False
- continue
-
- if wlite["DOT1Q_ID"]:
- if (
- wlite["DOT1Q_ID"]
- == hlite["DOT1Q_ID"]
- ):
- found = True
- else:
- found = False
- continue
-
- if wlite["IP_MASK"]:
- if (
- wlite["IP_MASK"]
- == hlite["IP_MASK"]
- ):
- found = True
- else:
- found = False
- continue
-
- if wlite["NEIGHBOR_IP"]:
- if (
- wlite["NEIGHBOR_IP"]
- == hlite["NEIGHBOR_IP"]
- ):
- found = True
- else:
- found = False
- continue
-
- if wlite["IPV6_MASK"]:
- if (
- wlite["IPV6_MASK"]
- == hlite["IPV6_MASK"]
- ):
- found = True
- else:
- found = False
- continue
-
- if wlite["IPV6_NEIGHBOR"]:
- if (
- wlite["IPV6_NEIGHBOR"]
- == hlite["IPV6_NEIGHBOR"]
- ):
- found = True
- else:
- found = False
- continue
-
- if wlite["PEER_VRF_NAME"]:
- if (
- wlite["PEER_VRF_NAME"]
- == hlite["PEER_VRF_NAME"]
- ):
- found = True
- else:
- found = False
- continue
+ found = False
+ interface_match = False
+ if wlite["IF_NAME"] == hlite["IF_NAME"]:
+ found = True
+ interface_match = True
+ if wlite["DOT1Q_ID"]:
+ if (
+ wlite["DOT1Q_ID"]
+ != hlite["DOT1Q_ID"]
+ ):
+ found = False
+ break
+
+ if wlite["IP_MASK"]:
+ if (
+ wlite["IP_MASK"]
+ != hlite["IP_MASK"]
+ ):
+ found = False
+ break
+
+ if wlite["NEIGHBOR_IP"]:
+ if (
+ wlite["NEIGHBOR_IP"]
+ != hlite["NEIGHBOR_IP"]
+ ):
+ found = False
+ break
+
+ if wlite["IPV6_MASK"]:
+ if (
+ wlite["IPV6_MASK"]
+ != hlite["IPV6_MASK"]
+ ):
+ found = False
+ break
+
+ if wlite["IPV6_NEIGHBOR"]:
+ if (
+ wlite["IPV6_NEIGHBOR"]
+ != hlite["IPV6_NEIGHBOR"]
+ ):
+ found = False
+ break
+
+ if wlite["PEER_VRF_NAME"]:
+ if (
+ wlite["PEER_VRF_NAME"]
+ != hlite["PEER_VRF_NAME"]
+ ):
+ found = False
+ break
+
+ if found:
+ break
+
+ if interface_match and not found:
+ break
+
+ if interface_match and not found:
+ break
elif (
want["extensionValues"] != ""
@@ -780,6 +772,9 @@ def diff_for_attach_deploy(self, want_a, have_a, replace=False):
if found:
break
+ if interface_match and not found:
+ break
+
if not found:
if bool(want["isAttached"]):
del want["isAttached"]
@@ -789,6 +784,8 @@ def diff_for_attach_deploy(self, want_a, have_a, replace=False):
def update_attach_params(self, attach, vrf_name, deploy, vlanId):
+ vrf_ext = False
+
if not attach:
return {}
@@ -799,7 +796,6 @@ def update_attach_params(self, attach, vrf_name, deploy, vlanId):
for ip, ser in self.ip_sn.items():
if ip == attach["ip_address"]:
serial = ser
- self.serial = ser
if not serial:
self.module.fail_json(
@@ -809,7 +805,6 @@ def update_attach_params(self, attach, vrf_name, deploy, vlanId):
)
role = self.inventory_data[attach["ip_address"]].get("switchRole")
- self.role = role
if role.lower() == "spine" or role.lower() == "super spine":
msg = "VRFs cannot be attached to switch {0} with role {1}".format(
@@ -898,8 +893,7 @@ def update_attach_params(self, attach, vrf_name, deploy, vlanId):
ext_values["VRF_LITE_CONN"] = json.dumps(ext_values["VRF_LITE_CONN"])
- self.vrflitevalues = ext_values
- self.vrf_ext = True
+ vrf_ext = True
attach.update({"fabric": self.fabric})
attach.update({"vrfName": vrf_name})
@@ -907,7 +901,7 @@ def update_attach_params(self, attach, vrf_name, deploy, vlanId):
attach.update({"deployment": deploy})
attach.update({"isAttached": True})
attach.update({"serialNumber": serial})
- if self.vrf_ext:
+ if vrf_ext:
attach.update({"extensionValues": json.dumps(ext_values).replace(" ", "")})
attach.update(
{
@@ -2260,15 +2254,16 @@ def push_to_remote(self, is_rollback=False):
for v_a in d_a["lanAttachList"]:
v_a.update(vlan=0)
if v_a.get("vrf_lite"):
- """Before apply the vrf_lite config, need double check if the switch role is started wth Border"""
- r = re.search(r"\bborder\b", self.role.lower())
- if not r:
- for ip, ser in self.ip_sn.items():
- if ser == v_a["serialNumber"]:
+ for ip, ser in self.ip_sn.items():
+ if ser == v_a["serialNumber"]:
+ """Before apply the vrf_lite config, need double check if the switch role is started wth Border"""
+ role = self.inventory_data[ip].get("switchRole")
+ r = re.search(r"\bborder\b", role.lower())
+ if not r:
msg = "VRF LITE cannot be attached to switch {0} with role {1}".format(
- ip, self.role
+ ip, role
)
- self.module.fail_json(msg=msg)
+ self.module.fail_json(msg=msg)
"""Get the IP/Interface that is connected to edge router can be get from below query"""
method = "GET"
@@ -2294,95 +2289,91 @@ def push_to_remote(self, is_rollback=False):
ext_values = ext_l["extensionValues"]
ext_values = ast.literal_eval(ext_values)
for ad_l in v_a.get("vrf_lite"):
- vrflite_con = {}
- vrflite_con["VRF_LITE_CONN"] = []
- vrflite_con["VRF_LITE_CONN"].append({})
- if ad_l["interface"]:
+ if ad_l["interface"] == ext_values["IF_NAME"]:
+ vrflite_con = {}
+ vrflite_con["VRF_LITE_CONN"] = []
+ vrflite_con["VRF_LITE_CONN"].append({})
vrflite_con["VRF_LITE_CONN"][0][
"IF_NAME"
] = ad_l["interface"]
- else:
- vrflite_con["VRF_LITE_CONN"][0][
- "IF_NAME"
- ] = ext_values["IF_NAME"]
- if ad_l["dot1q"]:
- vrflite_con["VRF_LITE_CONN"][0][
- "DOT1Q_ID"
- ] = str(ad_l["dot1q"])
- else:
- vrflite_con["VRF_LITE_CONN"][0][
- "DOT1Q_ID"
- ] = str(ext_values["DOT1Q_ID"])
-
- if ad_l["ipv4_addr"]:
- vrflite_con["VRF_LITE_CONN"][0][
- "IP_MASK"
- ] = ad_l["ipv4_addr"]
- else:
- vrflite_con["VRF_LITE_CONN"][0][
- "IP_MASK"
- ] = ext_values["IP_MASK"]
+ if ad_l["dot1q"]:
+ vrflite_con["VRF_LITE_CONN"][0][
+ "DOT1Q_ID"
+ ] = str(ad_l["dot1q"])
+ else:
+ vrflite_con["VRF_LITE_CONN"][0][
+ "DOT1Q_ID"
+ ] = str(ext_values["DOT1Q_ID"])
+
+ if ad_l["ipv4_addr"]:
+ vrflite_con["VRF_LITE_CONN"][0][
+ "IP_MASK"
+ ] = ad_l["ipv4_addr"]
+ else:
+ vrflite_con["VRF_LITE_CONN"][0][
+ "IP_MASK"
+ ] = ext_values["IP_MASK"]
+
+ if ad_l["neighbor_ipv4"]:
+ vrflite_con["VRF_LITE_CONN"][0][
+ "NEIGHBOR_IP"
+ ] = ad_l["neighbor_ipv4"]
+ else:
+ vrflite_con["VRF_LITE_CONN"][0][
+ "NEIGHBOR_IP"
+ ] = ext_values["NEIGHBOR_IP"]
- if ad_l["neighbor_ipv4"]:
- vrflite_con["VRF_LITE_CONN"][0][
- "NEIGHBOR_IP"
- ] = ad_l["neighbor_ipv4"]
- else:
vrflite_con["VRF_LITE_CONN"][0][
- "NEIGHBOR_IP"
- ] = ext_values["NEIGHBOR_IP"]
-
- vrflite_con["VRF_LITE_CONN"][0][
- "NEIGHBOR_ASN"
- ] = ext_values["NEIGHBOR_ASN"]
+ "NEIGHBOR_ASN"
+ ] = ext_values["NEIGHBOR_ASN"]
- if ad_l["ipv6_addr"]:
- vrflite_con["VRF_LITE_CONN"][0][
- "IPV6_MASK"
- ] = ad_l["ipv6_addr"]
- else:
- vrflite_con["VRF_LITE_CONN"][0][
- "IPV6_MASK"
- ] = ext_values["IPV6_MASK"]
+ if ad_l["ipv6_addr"]:
+ vrflite_con["VRF_LITE_CONN"][0][
+ "IPV6_MASK"
+ ] = ad_l["ipv6_addr"]
+ else:
+ vrflite_con["VRF_LITE_CONN"][0][
+ "IPV6_MASK"
+ ] = ext_values["IPV6_MASK"]
+
+ if ad_l["neighbor_ipv6"]:
+ vrflite_con["VRF_LITE_CONN"][0][
+ "IPV6_NEIGHBOR"
+ ] = ad_l["neighbor_ipv6"]
+ else:
+ vrflite_con["VRF_LITE_CONN"][0][
+ "IPV6_NEIGHBOR"
+ ] = ext_values["IPV6_NEIGHBOR"]
- if ad_l["neighbor_ipv6"]:
vrflite_con["VRF_LITE_CONN"][0][
- "IPV6_NEIGHBOR"
- ] = ad_l["neighbor_ipv6"]
- else:
- vrflite_con["VRF_LITE_CONN"][0][
- "IPV6_NEIGHBOR"
- ] = ext_values["IPV6_NEIGHBOR"]
+ "AUTO_VRF_LITE_FLAG"
+ ] = ext_values["AUTO_VRF_LITE_FLAG"]
- vrflite_con["VRF_LITE_CONN"][0][
- "AUTO_VRF_LITE_FLAG"
- ] = ext_values["AUTO_VRF_LITE_FLAG"]
+ if ad_l["peer_vrf"]:
+ vrflite_con["VRF_LITE_CONN"][0][
+ "PEER_VRF_NAME"
+ ] = ad_l["peer_vrf"]
+ else:
+ vrflite_con["VRF_LITE_CONN"][0][
+ "PEER_VRF_NAME"
+ ] = ext_values["PEER_VRF_NAME"]
- if ad_l["peer_vrf"]:
- vrflite_con["VRF_LITE_CONN"][0][
- "PEER_VRF_NAME"
- ] = ad_l["peer_vrf"]
- else:
vrflite_con["VRF_LITE_CONN"][0][
- "PEER_VRF_NAME"
- ] = ext_values["PEER_VRF_NAME"]
-
- vrflite_con["VRF_LITE_CONN"][0][
- "VRF_LITE_JYTHON_TEMPLATE"
- ] = "Ext_VRF_Lite_Jython"
- if (extension_values["VRF_LITE_CONN"]):
- extension_values["VRF_LITE_CONN"]["VRF_LITE_CONN"].extend(vrflite_con["VRF_LITE_CONN"])
- else:
- extension_values["VRF_LITE_CONN"] = vrflite_con
+ "VRF_LITE_JYTHON_TEMPLATE"
+ ] = "Ext_VRF_Lite_Jython"
+ if (extension_values["VRF_LITE_CONN"]):
+ extension_values["VRF_LITE_CONN"]["VRF_LITE_CONN"].extend(vrflite_con["VRF_LITE_CONN"])
+ else:
+ extension_values["VRF_LITE_CONN"] = vrflite_con
- ms_con = {}
- ms_con["MULTISITE_CONN"] = []
- extension_values["MULTISITE_CONN"] = json.dumps(
- ms_con
- )
+ ms_con = {}
+ ms_con["MULTISITE_CONN"] = []
+ extension_values["MULTISITE_CONN"] = json.dumps(
+ ms_con
+ )
- del v_a["vrf_lite"][0]
+ del ad_l
if ext_values is None:
for ip, ser in self.ip_sn.items():
@@ -2528,7 +2519,7 @@ def validate_input(self):
vrf_lite=dict(type="list"),
)
lite_spec = dict(
- interface=dict(type="str"),
+ interface=dict(required=True, type="str"),
peer_vrf=dict(type="str"),
ipv4_addr=dict(type="ipv4_subnet"),
neighbor_ipv4=dict(type="ipv4"),
diff --git a/tests/integration/targets/dcnm_vrf/tests/dcnm/deleted.yaml b/tests/integration/targets/dcnm_vrf/tests/dcnm/deleted.yaml
index 8c120bbc4..489b94c8c 100644
--- a/tests/integration/targets/dcnm_vrf/tests/dcnm/deleted.yaml
+++ b/tests/integration/targets/dcnm_vrf/tests/dcnm/deleted.yaml
@@ -119,7 +119,7 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
@@ -167,7 +167,7 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
@@ -222,7 +222,7 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
diff --git a/tests/integration/targets/dcnm_vrf/tests/dcnm/merged.yaml b/tests/integration/targets/dcnm_vrf/tests/dcnm/merged.yaml
index 5cc6de3e0..f2d7afbc8 100644
--- a/tests/integration/targets/dcnm_vrf/tests/dcnm/merged.yaml
+++ b/tests/integration/targets/dcnm_vrf/tests/dcnm/merged.yaml
@@ -151,7 +151,7 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
@@ -198,7 +198,7 @@
fabric: "{{ test_fabric }}"
state: deleted
-- name: QUERY - sleep for 40 seconds for DCNM to completely remove lite profile
+- name: MERGED - sleep for 40 seconds for DCNM to completely remove lite profile
# The vrf lite profile removal returns ok for deployment, but the switch takes time to remove
# the profile so wait for some time before creating a new vrf, else the switch goes into
# OUT-OF-SYNC state
@@ -216,10 +216,10 @@
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
attach:
- - ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- - peer_vrf: ansible-vrf-int1 # optional
+ - interface: "{{ ansible_int1 }}" # mandatory
+ - ip_address: "{{ ansible_switch1 }}"
deploy: true
register: result
@@ -243,8 +243,8 @@
- '(result.response[1].DATA|dict2items)[1].value == "SUCCESS"'
- 'result.diff[0].attach[0].deploy == true'
- 'result.diff[0].attach[1].deploy == true'
- - '"{{ ansible_switch1 }}" in result.diff[0].attach[0].ip_address'
- - '"{{ ansible_switch2 }}" in result.diff[0].attach[1].ip_address'
+ - '"{{ ansible_switch2 }}" in result.diff[0].attach[0].ip_address'
+ - '"{{ ansible_switch1 }}" in result.diff[0].attach[1].ip_address'
- 'result.diff[0].vrf_name == "ansible-vrf-int1"'
- name: MERGED - Create, Attach and Deploy new VRF - Update with incorrect VRF ID.
@@ -289,7 +289,7 @@
- 'result.changed == false'
- '"The item exceeds the allowed range of max" in result.msg'
-- name: MERGED - Create, Attach and Deploy new VRF - Try configuring VRF LITE without any parameter
+- name: MERGED - Create, Attach and Deploy new VRF - Try configuring VRF LITE without required parameter
cisco.dcnm.dcnm_vrf:
fabric: "{{ test_fabric }}"
state: merged
@@ -303,6 +303,7 @@
- ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
+ - peer_vrf: ansible-vrf-int1 # optional
deploy: true
register: result
ignore_errors: yes
@@ -310,7 +311,7 @@
- assert:
that:
- 'result.changed == false'
- - '"Please specifiy at least one VRF LITE parameter in attach" in result.msg'
+ - '"Invalid parameters in playbook: interface : Required parameter not found" in result.msg'
- name: MERGED - Create, Attach and Deploy new VRF - Try configuring VRF LITE to a non border switch
cisco.dcnm.dcnm_vrf:
@@ -326,7 +327,7 @@
- ip_address: "{{ ansible_switch1 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
diff --git a/tests/integration/targets/dcnm_vrf/tests/dcnm/overridden.yaml b/tests/integration/targets/dcnm_vrf/tests/dcnm/overridden.yaml
index aae1432fb..1cee0dca7 100644
--- a/tests/integration/targets/dcnm_vrf/tests/dcnm/overridden.yaml
+++ b/tests/integration/targets/dcnm_vrf/tests/dcnm/overridden.yaml
@@ -144,7 +144,7 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int2 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/24 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
@@ -192,7 +192,7 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int2 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.6/24 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:10/64 # optional
@@ -244,7 +244,7 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.3/24 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:1/64 # optional
diff --git a/tests/integration/targets/dcnm_vrf/tests/dcnm/query.yaml b/tests/integration/targets/dcnm_vrf/tests/dcnm/query.yaml
index f14cf6075..76115d8d5 100644
--- a/tests/integration/targets/dcnm_vrf/tests/dcnm/query.yaml
+++ b/tests/integration/targets/dcnm_vrf/tests/dcnm/query.yaml
@@ -133,7 +133,7 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int2 # peer_vrf is mandatory
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
@@ -181,7 +181,7 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int2 # peer_vrf is mandatory
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
diff --git a/tests/integration/targets/dcnm_vrf/tests/dcnm/replaced.yaml b/tests/integration/targets/dcnm_vrf/tests/dcnm/replaced.yaml
index ca01c4df9..0a555609c 100644
--- a/tests/integration/targets/dcnm_vrf/tests/dcnm/replaced.yaml
+++ b/tests/integration/targets/dcnm_vrf/tests/dcnm/replaced.yaml
@@ -175,7 +175,7 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
@@ -208,13 +208,6 @@
- '"{{ ansible_switch2 }}" in result.diff[0].attach[1].ip_address'
- 'result.diff[0].vrf_name == "ansible-vrf-int1"'
-- name: QUERY - sleep for 40 seconds for DCNM to completely update the state
- # The vrf lite profile removal returns ok for deployment, but the switch takes time to remove
- # the profile so wait for some time before creating a new vrf, else the switch goes into
- # OUT-OF-SYNC state
- wait_for:
- timeout: 40
-
- name: REPLACED - Update existing VRF LITE extensions using Replace - Delete VRF LITE Attachment Only
cisco.dcnm.dcnm_vrf: &conf3
fabric: "{{ test_fabric }}"
@@ -257,6 +250,13 @@
that:
- 'result.changed == false'
+- name: QUERY - sleep for 40 seconds for DCNM to completely update the state
+ # The vrf lite profile removal returns ok for deployment, but the switch takes time to remove
+ # the profile so wait for some time before creating a new vrf, else the switch goes into
+ # OUT-OF-SYNC state
+ wait_for:
+ timeout: 40
+
- name: REPLACED - Update existing VRF LITE extensions using Replace - Create VRF LITE Attachment Only
cisco.dcnm.dcnm_vrf: &conf4
fabric: "{{ test_fabric }}"
@@ -272,7 +272,7 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/30 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
diff --git a/tests/integration/targets/dcnm_vrf/tests/dcnm/self-contained-tests/vrf_lite.yaml b/tests/integration/targets/dcnm_vrf/tests/dcnm/self-contained-tests/vrf_lite.yaml
index fd198af3e..6ad41f906 100644
--- a/tests/integration/targets/dcnm_vrf/tests/dcnm/self-contained-tests/vrf_lite.yaml
+++ b/tests/integration/targets/dcnm_vrf/tests/dcnm/self-contained-tests/vrf_lite.yaml
@@ -26,6 +26,9 @@
state: deleted
- name: VRF LITE - sleep for 40 seconds for DCNM to completely update the state
+ # The vrf lite profile removal returns ok for deployment, but the switch takes time to remove
+ # the profile so wait for some time before creating a new vrf, else the switch goes into
+ # OUT-OF-SYNC state
wait_for:
timeout: 40
@@ -48,7 +51,7 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/24 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
@@ -104,23 +107,23 @@
vrf_extension_template: Default_VRF_Extension_Universal
vlan_id: 500
attach:
- - ip_address: "{{ ansible_switch1 }}"
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/24 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
neighbor_ipv6: 2010::10:34:0:3 # optional
dot1q: 2 # dot1q can be got from dcnm
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int2 }}" # optional
+ interface: "{{ ansible_int2 }}" # mandatory
ipv4_addr: 20.33.0.2/24 # optional
neighbor_ipv4: 20.33.0.1 # optional
ipv6_addr: 3010::10:34:0:7/64 # optional
neighbor_ipv6: 3010::10:34:0:3 # optional
dot1q: 21 # dot1q can be got from dcnm
+ - ip_address: "{{ ansible_switch1 }}"
deploy: true
register: result
@@ -173,7 +176,7 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/24 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
@@ -228,14 +231,14 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/24 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
neighbor_ipv6: 2010::10:34:0:3 # optional
dot1q: 2 # dot1q can be got from dcnm
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int2 }}" # optional
+ interface: "{{ ansible_int2 }}" # mandatory
ipv4_addr: 20.33.0.2/24 # optional
neighbor_ipv4: 20.33.0.1 # optional
ipv6_addr: 3010::10:34:0:7/64 # optional
@@ -293,6 +296,13 @@
fabric: "{{ test_fabric }}"
state: deleted
+- name: VRF LITE - sleep for 40 seconds for DCNM to completely update the state
+ # The vrf lite profile removal returns ok for deployment, but the switch takes time to remove
+ # the profile so wait for some time before creating a new vrf, else the switch goes into
+ # OUT-OF-SYNC state
+ wait_for:
+ timeout: 40
+
- name: VRF LITE- Create, Attach and Deploy new VRF - VLAN/VRF LITE EXTENSION Provided by the User in multiple switch
cisco.dcnm.dcnm_vrf: &conf5
fabric: "{{ test_fabric }}"
@@ -307,14 +317,14 @@
- ip_address: "{{ ansible_switch2 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int1 }}" # optional
+ interface: "{{ ansible_int1 }}" # mandatory
ipv4_addr: 10.33.0.2/24 # optional
neighbor_ipv4: 10.33.0.1 # optional
ipv6_addr: 2010::10:34:0:7/64 # optional
neighbor_ipv6: 2010::10:34:0:3 # optional
dot1q: 2 # dot1q can be got from dcnm
- peer_vrf: ansible-vrf-int1 # optional
- interface: "{{ ansible_int2 }}" # optional
+ interface: "{{ ansible_int2 }}" # mandatory
ipv4_addr: 20.33.0.2/24 # optional
neighbor_ipv4: 20.33.0.1 # optional
ipv6_addr: 3010::10:34:0:7/64 # optional
@@ -323,7 +333,7 @@
- ip_address: "{{ ansible_switch3 }}"
vrf_lite:
- peer_vrf: ansible-vrf-int3 # optional
- interface: "{{ ansible_int3 }}" # optional
+ interface: "{{ ansible_int3 }}" # mandatory
ipv4_addr: 40.33.0.2/24 # optional
neighbor_ipv4: 40.33.0.1 # optional
ipv6_addr: 5010::10:34:0:7/64 # optional
From e3a7943dced3f9392a0e9dea5bff05139318549e Mon Sep 17 00:00:00 2001
From: praveenramoorthy <62758226+praveenramoorthy@users.noreply.github.com>
Date: Sun, 21 May 2023 15:40:15 +0530
Subject: [PATCH 4/8] Support for new roles in Inventory module (#222)
---
docs/cisco.dcnm.dcnm_inventory_module.rst | 5 +++++
galaxy.yml | 2 +-
plugins/modules/dcnm_inventory.py | 13 ++++++++++++-
3 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/docs/cisco.dcnm.dcnm_inventory_module.rst b/docs/cisco.dcnm.dcnm_inventory_module.rst
index 0aabc184d..9420708eb 100644
--- a/docs/cisco.dcnm.dcnm_inventory_module.rst
+++ b/docs/cisco.dcnm.dcnm_inventory_module.rst
@@ -428,6 +428,11 @@ Parameters
super_spine
border_super_spine
border_gateway_super_spine
+ access
+ aggregation
+ edge_router
+ core_router
+ tor
|
diff --git a/galaxy.yml b/galaxy.yml
index 9bca57617..ade40d2ac 100644
--- a/galaxy.yml
+++ b/galaxy.yml
@@ -13,5 +13,5 @@ description: Ansible collection for the Cisco Nexus® Dashboard Fabric Controlle
license: Apache-2.0
tags: [cisco, ndfc, dcnm, nxos, networking, vxlan]
dependencies:
- "ansible.netcommon": ">=2.6.1,<=4.1.0"
+ "ansible.netcommon": ">=2.6.1"
repository: https://github.com/CiscoDevNet/ansible-dcnm
diff --git a/plugins/modules/dcnm_inventory.py b/plugins/modules/dcnm_inventory.py
index f7a576ea7..d691f9d09 100644
--- a/plugins/modules/dcnm_inventory.py
+++ b/plugins/modules/dcnm_inventory.py
@@ -85,7 +85,8 @@
description:
- Role which needs to be assigned to the switch
choices: ['leaf', 'spine', 'border', 'border_spine', 'border_gateway', 'border_gateway_spine',
- 'super_spine', 'border_super_spine', 'border_gateway_super_spine']
+ 'super_spine', 'border_super_spine', 'border_gateway_super_spine', 'access', 'aggregation',
+ 'edge_router', 'core_router', 'tor']
type: str
required: false
default: leaf
@@ -947,6 +948,11 @@ def validate_input(self):
"super_spine",
"border_super_spine",
"border_gateway_super_spine",
+ "access",
+ "aggregation",
+ "edge_router",
+ "core_router",
+ "tor"
],
default="leaf",
),
@@ -1091,6 +1097,11 @@ def validate_input(self):
"super_spine",
"border_super_spine",
"border_gateway_super_spine",
+ "access",
+ "aggregation",
+ "edge_router",
+ "core_router",
+ "tor",
"None",
],
default="None",
From d645123b416b87b40fe9b668ec61745dfb13e5f7 Mon Sep 17 00:00:00 2001
From: praveenramoorthy <62758226+praveenramoorthy@users.noreply.github.com>
Date: Tue, 23 May 2023 11:13:36 +0530
Subject: [PATCH 5/8] Update CHANGELOG.md
---
CHANGELOG.md | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b8a5901b2..d7b4c57c5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,20 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## Unreleased
+## [3.3.0] - 2023-05-23
+
+### Added
+
+* Support to configure muliple interfaces for vrf_lite on a vrf
+* Added support for more switch roles in inventory module.
+
+### Fixed
+
+* https://github.com/CiscoDevNet/ansible-dcnm/issues/204
+* https://github.com/CiscoDevNet/ansible-dcnm/issues/205
+* https://github.com/CiscoDevNet/ansible-dcnm/issues/206
+* Removed the restriction on netcommon version supported by DCNM collection. The restriction was introduced as fix for https://github.com/CiscoDevNet/ansible-dcnm/issues/209. Netcommon versions `>=2.6.1` is supported.
+
## [3.2.0] - 2023-04-20
### Added
@@ -250,6 +264,7 @@ The Ansible Cisco Data Center Network Manager (DCNM) collection includes modules
* cisco.dcnm.dcnm_network - Add and remove Networks from a DCNM managed VXLAN fabric.
* cisco.dcnm.dcnm_interface - DCNM Ansible Module for managing interfaces.
+[3.3.0]: https://github.com/CiscoDevNet/ansible-dcnm/compare/3.2.0...3.3.0
[3.2.0]: https://github.com/CiscoDevNet/ansible-dcnm/compare/3.1.1...3.2.0
[3.1.1]: https://github.com/CiscoDevNet/ansible-dcnm/compare/3.1.0...3.1.1
[3.1.0]: https://github.com/CiscoDevNet/ansible-dcnm/compare/3.0.0...3.1.0
From d6d7f85813c5f95999beedd2c251b1c7dde017ee Mon Sep 17 00:00:00 2001
From: praveenramoorthy <62758226+praveenramoorthy@users.noreply.github.com>
Date: Tue, 23 May 2023 11:14:50 +0530
Subject: [PATCH 6/8] Update galaxy.yml
---
galaxy.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/galaxy.yml b/galaxy.yml
index ade40d2ac..dad67956f 100644
--- a/galaxy.yml
+++ b/galaxy.yml
@@ -1,7 +1,7 @@
---
namespace: cisco
name: dcnm
-version: 3.2.0
+version: 3.3.0
readme: README.md
authors:
- Shrishail Kariyappanavar
From 979004b3c04ff32afaecaf3939f2097475418571 Mon Sep 17 00:00:00 2001
From: praveenramoorthy <62758226+praveenramoorthy@users.noreply.github.com>
Date: Tue, 23 May 2023 11:16:37 +0530
Subject: [PATCH 7/8] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index d4f2780c5..a64831ed6 100644
--- a/README.md
+++ b/README.md
@@ -63,7 +63,7 @@ You can also include it in a `requirements.yml` file and install it with `ansibl
---
collections:
- name: cisco.dcnm
- version: 3.2.0
+ version: 3.3.0
```
## Using this collection
From cfddcdd51737a7cdf4fa7c83c0d64866e4a815f9 Mon Sep 17 00:00:00 2001
From: praveenramoorthy <62758226+praveenramoorthy@users.noreply.github.com>
Date: Tue, 23 May 2023 12:16:53 +0530
Subject: [PATCH 8/8] Update CHANGELOG.md
---
CHANGELOG.md | 2 --
1 file changed, 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d7b4c57c5..bc15fc867 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,8 +2,6 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
-## Unreleased
-
## [3.3.0] - 2023-05-23
### Added
|