@@ -495,6 +495,8 @@ class DcnmNetwork:
495495 "GET_NET" : "/rest/top-down/fabrics/{}/networks" ,
496496 "GET_NET_NAME" : "/rest/top-down/fabrics/{}/networks/{}" ,
497497 "GET_VLAN" : "/rest/resource-manager/vlan/{}?vlanUsageType=TOP_DOWN_NETWORK_VLAN" ,
498+ "GET_NET_STATUS" : "/rest/top-down/fabrics/{}/networks/{}/status" ,
499+ "GET_NET_SWITCH_DEPLOY" : "/rest/top-down/fabrics/networks/deploy"
498500 },
499501 12 : {
500502 "GET_VRF" : "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/top-down/fabrics/{}/vrfs" ,
@@ -504,6 +506,8 @@ class DcnmNetwork:
504506 "GET_NET" : "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/top-down/fabrics/{}/networks" ,
505507 "GET_NET_NAME" : "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/top-down/fabrics/{}/networks/{}" ,
506508 "GET_VLAN" : "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/resource-manager/vlan/{}?vlanUsageType=TOP_DOWN_NETWORK_VLAN" ,
509+ "GET_NET_STATUS" : "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/top-down/fabrics/{}/networks/{}/status" ,
510+ "GET_NET_SWITCH_DEPLOY" : "/appcenter/cisco/ndfc/api/v1/lan-fabric/rest/top-down/networks/deploy"
507511 },
508512 }
509513
@@ -593,6 +597,8 @@ def find_dict_in_list_by_key_value(search: list, key: str, value: str):
593597 # -> None
594598 ```
595599 """
600+ if search is None :
601+ return None
596602 match = (d for d in search if d [key ] == value )
597603 return next (match , None )
598604
@@ -1466,10 +1472,10 @@ def get_have(self):
14661472 dep_net = ""
14671473 for attach in attach_list :
14681474 torlist = []
1469- attach_state = False if attach [ "lanAttachState" ] == "NA" else True
1470- deploy = attach [ "isLanAttached" ]
1475+ attach_state = bool ( attach . get ( "isLanAttached" , False ))
1476+ deploy = attach_state
14711477 deployed = False
1472- if bool ( deploy ) and (attach ["lanAttachState" ] == "OUT-OF-SYNC" or attach ["lanAttachState" ] == "PENDING" ):
1478+ if attach_state and (attach ["lanAttachState" ] == "OUT-OF-SYNC" or attach ["lanAttachState" ] == "PENDING" ):
14731479 deployed = False
14741480 else :
14751481 deployed = True
@@ -1799,16 +1805,25 @@ def get_diff_replace(self):
17991805 diff_attach .append (r_net_dict )
18001806 all_nets += have_a ["networkName" ] + ","
18011807
1808+ if all_nets :
1809+ modified_all_nets = copy .deepcopy (all_nets [:- 1 ].split ("," ))
1810+ # If the playbook sets the deploy key to False, then we need to remove the network from the deploy list.
1811+ for net in all_nets [:- 1 ].split ("," ):
1812+ want_net_data = self .find_dict_in_list_by_key_value (search = self .config , key = "net_name" , value = net )
1813+ if (want_net_data is not None ) and (want_net_data .get ("deploy" ) is False ):
1814+ modified_all_nets .remove (net )
1815+ all_nets = "," .join (modified_all_nets )
1816+
18021817 if not all_nets :
18031818 self .diff_create = diff_create
18041819 self .diff_attach = diff_attach
18051820 self .diff_deploy = diff_deploy
18061821 return warn_msg
18071822
18081823 if not self .diff_deploy :
1809- diff_deploy .update ({"networkNames" : all_nets [: - 1 ] })
1824+ diff_deploy .update ({"networkNames" : all_nets })
18101825 else :
1811- nets = self .diff_deploy ["networkNames" ] + "," + all_nets [: - 1 ]
1826+ nets = self .diff_deploy ["networkNames" ] + "," + all_nets
18121827 diff_deploy .update ({"networkNames" : nets })
18131828
18141829 self .diff_create = diff_create
@@ -2311,28 +2326,74 @@ def get_diff_query(self):
23112326
23122327 self .query = query
23132328
2329+ def detach_and_deploy_for_del (self , net ):
2330+ method = "GET"
2331+
2332+ payload_net = {}
2333+ deploy_payload = {}
2334+ payload_net ["networkName" ] = net ["networkName" ]
2335+ payload_net ["lanAttachList" ] = []
2336+ attach_list = net ["switchList" ]
2337+ for atch in attach_list :
2338+ payload_atch = {}
2339+ if atch ["lanAttachedState" ].upper () == "PENDING" :
2340+ payload_atch ["serialNumber" ] = atch ["serialNumber" ]
2341+ payload_atch ["networkName" ] = net ["networkName" ]
2342+ payload_atch ["fabric" ] = net ["fabric" ]
2343+ payload_atch ["deployment" ] = False
2344+ payload_net ["lanAttachList" ].append (payload_atch )
2345+
2346+ deploy_payload [atch ["serialNumber" ]] = net ["networkName" ]
2347+
2348+ if payload_net ["lanAttachList" ]:
2349+ payload = [payload_net ]
2350+ method = "POST"
2351+ path = self .paths ["GET_NET" ].format (self .fabric ) + "/attachments"
2352+ resp = dcnm_send (self .module , method , path , json .dumps (payload ))
2353+ self .result ["response" ].append (resp )
2354+ fail , dummy_changed = self .handle_response (resp , "attach" )
2355+ if fail :
2356+ self .failure (resp )
2357+
2358+ method = "POST"
2359+ path = self .paths ["GET_NET_SWITCH_DEPLOY" ].format (self .fabric )
2360+ resp = dcnm_send (self .module , method , path , json .dumps (deploy_payload ))
2361+ self .result ["response" ].append (resp )
2362+ fail , dummy_changed = self .handle_response (resp , "deploy" )
2363+ if fail :
2364+ self .failure (resp )
2365+
23142366 def wait_for_del_ready (self ):
23152367
23162368 method = "GET"
23172369 if self .diff_delete :
23182370 for net in self .diff_delete :
23192371 state = False
2320- path = self .paths ["GET_NET_ATTACH" ].format (self .fabric , net )
2321- while not state :
2372+ path = self .paths ["GET_NET_STATUS" ].format (self .fabric , net )
2373+ retry = max (100 // self .WAIT_TIME_FOR_DELETE_LOOP , 1 )
2374+ deploy_started = False
2375+ while not state and retry >= 0 :
2376+ retry -= 1
23222377 resp = dcnm_send (self .module , method , path )
23232378 state = True
23242379 if resp ["DATA" ]:
2325- attach_list = resp ["DATA" ][0 ]["lanAttachList" ]
2380+ if resp ["DATA" ]["networkStatus" ].upper () == "PENDING" and not deploy_started :
2381+ self .detach_and_deploy_for_del (resp ["DATA" ])
2382+ deploy_started = True
2383+ attach_list = resp ["DATA" ]["switchList" ]
23262384 for atch in attach_list :
2327- if atch ["lanAttachState" ] == "OUT-OF-SYNC" or atch ["lanAttachState" ] == "FAILED" :
2385+ if atch ["lanAttachedState" ]. upper () == "OUT-OF-SYNC" or atch ["lanAttachedState" ]. upper () == "FAILED" :
23282386 self .diff_delete .update ({net : "OUT-OF-SYNC" })
23292387 break
2330- if atch ["lanAttachState" ] != "NA" :
2388+ if atch ["lanAttachedState" ]. upper () != "NA" :
23312389 self .diff_delete .update ({net : "DEPLOYED" })
23322390 state = False
23332391 time .sleep (self .WAIT_TIME_FOR_DELETE_LOOP )
23342392 break
23352393 self .diff_delete .update ({net : "NA" })
2394+ if retry < 0 :
2395+ self .diff_delete .update ({net : "TIMEOUT" })
2396+ return False
23362397
23372398 return True
23382399
@@ -2376,7 +2437,8 @@ def push_to_remote(self, is_rollback=False):
23762437
23772438 for d_a in self .diff_detach :
23782439 for v_a in d_a ["lanAttachList" ]:
2379- del v_a ["is_deploy" ]
2440+ if v_a .get ("is_deploy" ):
2441+ del v_a ["is_deploy" ]
23802442
23812443 resp = dcnm_send (self .module , method , detach_path , json .dumps (self .diff_detach ))
23822444 self .result ["response" ].append (resp )
@@ -2396,7 +2458,7 @@ def push_to_remote(self, is_rollback=False):
23962458 # the state of the network is "OUT-OF-SYNC"
23972459 self .wait_for_del_ready ()
23982460 for net , state in self .diff_delete .items ():
2399- if state == "OUT-OF-SYNC" :
2461+ if state . upper () == "OUT-OF-SYNC" :
24002462 resp = dcnm_send (self .module , method , deploy_path , json .dumps (self .diff_undeploy ))
24012463
24022464 self .result ["response" ].append (resp )
@@ -2410,9 +2472,14 @@ def push_to_remote(self, is_rollback=False):
24102472 method = "DELETE"
24112473 del_failure = ""
24122474 if self .diff_delete and self .wait_for_del_ready ():
2475+ resp = ""
24132476 for net , state in self .diff_delete .items ():
2414- if state == "OUT-OF-SYNC" :
2477+ if state . upper () == "OUT-OF-SYNC" or state == "TIMEOUT " :
24152478 del_failure += net + ","
2479+ if state == "TIMEOUT" :
2480+ resp = "Timeout waiting for network to be in delete ready state.\n "
2481+ if state == "OUT-OF-SYNC" :
2482+ resp += "Network is out of sync.\n "
24162483 continue
24172484 delete_path = path + "/" + net
24182485 resp = dcnm_send (self .module , method , delete_path )
@@ -2498,7 +2565,8 @@ def push_to_remote(self, is_rollback=False):
24982565
24992566 for d_a in self .diff_attach :
25002567 for v_a in d_a ["lanAttachList" ]:
2501- del v_a ["is_deploy" ]
2568+ if v_a .get ("is_deploy" ):
2569+ del v_a ["is_deploy" ]
25022570
25032571 for attempt in range (0 , 50 ):
25042572 resp = dcnm_send (self .module , method , attach_path , json .dumps (self .diff_attach ))
0 commit comments