Skip to content

dcnm_vrf: now raises an error if networks are attached during deletion #456

New issue

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

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

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 21 additions & 20 deletions plugins/modules/dcnm_vrf.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,13 +583,15 @@
"GET_VRF_SWITCH": "/rest/top-down/fabrics/{}/vrfs/switches?vrf-names={}&serial-numbers={}",
"GET_VRF_ID": "/rest/managed-pool/fabrics/{}/partitions/ids",
"GET_VLAN": "/rest/resource-manager/vlan/{}?vlanUsageType=TOP_DOWN_VRF_VLAN",
"GET_NET_VRF": "/rest/resource-manager/fabrics/{}/networks?vrf-name={}"
},
12: {
"GET_VRF": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/top-down/fabrics/{}/vrfs",
"GET_VRF_ATTACH": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/top-down/fabrics/{}/vrfs/attachments?vrf-names={}",
"GET_VRF_SWITCH": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/top-down/fabrics/{}/vrfs/switches?vrf-names={}&serial-numbers={}",
"GET_VRF_ID": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/top-down/fabrics/{}/vrfinfo",
"GET_VLAN": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/resource-manager/vlan/{}?vlanUsageType=TOP_DOWN_VRF_VLAN",
"GET_NET_VRF": "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/top-down/fabrics/{}/networks?vrf-name={}",
},
}

Expand Down Expand Up @@ -3758,6 +3760,18 @@ def push_to_remote(self, is_rollback=False):
# attachment being deleted is re-used on a new vrf attachment being
# created. This is needed specially for state: overridden

for vrf_name in self.diff_delete:
path = self.paths["GET_NET_VRF"].format(self.fabric, vrf_name)
resp = dcnm_send(self.module, "GET", path)
if resp.get("DATA") is None:
msg = f"Invalid Response from Controller. {resp}"
self.module.fail_json(msg=msg)
elif resp["DATA"] != []:
msg = "VRF has associated network attachments. "
msg += "Please remove the network attachments "
msg += "before deleting the VRF. (maybe using dcnm_network module)"
self.module.fail_json(msg=msg)

self.push_diff_detach(is_rollback)
self.push_diff_undeploy(is_rollback)

Expand Down Expand Up @@ -3791,7 +3805,7 @@ def wait_for_vrf_del_ready(self, vrf_name="not_supplied"):
for vrf in self.diff_delete:
ok_to_delete = False
path = self.paths["GET_VRF_ATTACH"].format(self.fabric, vrf)

retry_count = 20
while not ok_to_delete:
resp = dcnm_send(self.module, "GET", path)
ok_to_delete = True
Expand All @@ -3811,31 +3825,18 @@ def wait_for_vrf_del_ready(self, vrf_name="not_supplied"):
):
self.diff_delete.update({vrf: "OUT-OF-SYNC"})
break
if (
attach["lanAttachState"] == "DEPLOYED"
and attach["isLanAttached"] is True
):
vrf_name = attach.get("vrfName", "unknown")
fabric_name = attach.get("fabricName", "unknown")
switch_ip = attach.get("ipAddress", "unknown")
switch_name = attach.get("switchName", "unknown")
vlan_id = attach.get("vlanId", "unknown")
msg = f"Network attachments associated with vrf {vrf_name} "
msg += "must be removed (e.g. using the dcnm_network module) "
msg += "prior to deleting the vrf. "
msg += f"Details: fabric_name: {fabric_name}, "
msg += f"vrf_name: {vrf_name}. "
msg += "Network attachments found on "
msg += f"switch_ip: {switch_ip}, "
msg += f"switch_name: {switch_name}, "
msg += f"vlan_id: {vlan_id}"
self.module.fail_json(msg=msg)
if attach["lanAttachState"] != "NA":
time.sleep(self.WAIT_TIME_FOR_DELETE_LOOP)
self.diff_delete.update({vrf: "DEPLOYED"})
ok_to_delete = False
break
self.diff_delete.update({vrf: "NA"})
if retry_count <= 0:
msg = "Timeout waiting for VRF to be ready for deletion. "
msg += f"vrf: {vrf}, "
msg += f"resp: {resp}"
self.module.fail_json(msg=msg)
retry_count -= 1

def attach_spec(self):
"""
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/modules/dcnm/fixtures/dcnm_vrf.json
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,12 @@
}
]
},
"mock_net_from_vrf_empty": {
"ERROR": "",
"RETURN_CODE": 200,
"MESSAGE": "OK",
"DATA": []
},
"mock_vrf_attach_object_dcnm_only": {
"MESSAGE": "OK",
"METHOD": "POST",
Expand Down
5 changes: 5 additions & 0 deletions tests/unit/modules/dcnm/test_dcnm_vrf.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class TestDcnmVrfModule(TestDcnmModule):
fabric_details_mfd = test_data.get("fabric_details_mfd")
fabric_details_vxlan = test_data.get("fabric_details_vxlan")

mock_net_from_vrf_empty = test_data.get("mock_net_from_vrf_empty")
mock_vrf_attach_object_del_not_ready = test_data.get(
"mock_vrf_attach_object_del_not_ready"
)
Expand Down Expand Up @@ -451,6 +452,7 @@ def load_fixtures(self, response=None, device=""):
self.mock_vrf_object,
self.mock_vrf_attach_get_ext_object_ov_att1_only,
self.mock_vrf_attach_get_ext_object_ov_att2_only,
self.mock_net_from_vrf_empty,
self.attach_success_resp,
self.deploy_success_resp,
self.mock_vrf_attach_object_del_not_ready,
Expand Down Expand Up @@ -488,6 +490,7 @@ def load_fixtures(self, response=None, device=""):
self.mock_vrf_object,
self.mock_vrf_attach_get_ext_object_dcnm_att1_only,
self.mock_vrf_attach_get_ext_object_dcnm_att2_only,
self.mock_net_from_vrf_empty,
self.attach_success_resp,
self.deploy_success_resp,
self.mock_vrf_attach_object_del_not_ready,
Expand Down Expand Up @@ -519,6 +522,7 @@ def load_fixtures(self, response=None, device=""):
self.mock_vrf_object,
self.mock_vrf_attach_get_ext_object_dcnm_att1_only,
self.mock_vrf_attach_get_ext_object_dcnm_att2_only,
self.mock_net_from_vrf_empty,
self.attach_success_resp,
self.deploy_success_resp,
self.mock_vrf_attach_object_del_not_ready,
Expand All @@ -539,6 +543,7 @@ def load_fixtures(self, response=None, device=""):
self.mock_vrf_object_dcnm_only,
self.mock_vrf_attach_get_ext_object_dcnm_att1_only,
self.mock_vrf_attach_get_ext_object_dcnm_att2_only,
self.mock_net_from_vrf_empty,
self.attach_success_resp,
self.deploy_success_resp,
obj1,
Expand Down