66from __future__ import absolute_import , division , print_function
77
88__metaclass__ = type
9- __author__ = "Rugvedi Kapse, Madhan Sankaranarayanan"
9+ __author__ = "Rugvedi Kapse, Madhan Sankaranarayanan, Abhishek Maheshwari "
1010DOCUMENTATION = r"""
1111---
1212module: sda_host_port_onboarding_workflow_manager
3939extends_documentation_fragment:
4040 - cisco.dnac.workflow_manager_params
4141author: Rugvedi Kapse (@rukapse) Madhan Sankaranarayanan
42- (@madhansansel)
42+ (@madhansansel) Abhishek Maheshwari (@abmahesh)
4343options:
4444 config_verify:
4545 description: Set to True to verify the Cisco Catalyst
5353 type: str
5454 choices: [merged, deleted]
5555 default: merged
56+ sda_fabric_port_channel_limit:
57+ description: >
58+ Number of port channels to be processed in a single batch
59+ when performing add/update/delete operations. If the number
60+ of port channels in the request exceeds this limit, the module
61+ will process them in sequential batches of this size.
62+ This helps manage large configurations without overwhelming
63+ the system.
64+ type: int
65+ default: 20
5666 config:
5767 description:
5868 - A list containing detailed configurations for
@@ -4233,7 +4243,6 @@ def get_vlans_and_ssids_mapped_to_vlans(self, fabric_id):
42334243 return vlans_and_ssids_mapped_to_vlans
42344244
42354245 except Exception as e :
4236- # Log an error message and fail if an exception occurs
42374246 self .msg = (
42384247 "An error occurred while retrieving VLANs and SSIDs mapped to VLANs "
42394248 "Details using SDA - 'retrieve_the_vlans_and_ssids_mapped_to_the_vlan_within_a_fabric_site' "
@@ -4742,17 +4751,88 @@ def add_port_channels(self, add_port_channels_params):
47424751 dict: The task ID from the API call.
47434752 Description:
47444753 This method initiates the task to add port channels using the provided parameters and returns the task ID.
4754+ The method processes port channels in batches of 20 sequentially, waiting for each batch to complete.
47454755 """
4756+ payload = add_port_channels_params .get ("payload" , [])
4757+ batch_size = self .params .get ("sda_fabric_port_channel_limit" , 20 )
4758+
4759+ # If payload has 20 or fewer items, process normally
4760+ if len (payload ) <= batch_size :
4761+ self .log (
4762+ "Processing {0} port channels in single batch" .format (len (payload )),
4763+ "INFO" ,
4764+ )
4765+ return self .get_taskid_post_api_call (
4766+ "sda" , "add_port_channels" , add_port_channels_params
4767+ )
4768+
4769+ # Process in batches sequentially
47464770 self .log (
4747- "Initiating addition of port channels with parameters: {0} " .format (
4748- add_port_channels_params
4771+ "Processing {0} port channels in batches of {1} sequentially " .format (
4772+ len ( payload ), batch_size
47494773 ),
47504774 "INFO" ,
47514775 )
4752- return self .get_taskid_post_api_call (
4753- "sda" , "add_port_channels" , add_port_channels_params
4776+
4777+ final_task_id = None
4778+ successful_batches = 0
4779+
4780+ self .log ("Starting batch processing for port channel addition." , "DEBUG" )
4781+ for i in range (0 , len (payload ), batch_size ):
4782+ batch = payload [i :i + batch_size ]
4783+ batch_params = {"payload" : batch }
4784+ batch_number = (i // batch_size ) + 1
4785+ self .log (
4786+ "Processing batch {0} with {1} port channels sequentially" .format (
4787+ batch_number , len (batch )
4788+ ),
4789+ "DEBUG" ,
4790+ )
4791+
4792+ task_id = self .get_taskid_post_api_call (
4793+ "sda" , "add_port_channels" , batch_params
4794+ )
4795+
4796+ self .log (
4797+ "Batch {0} API call completed, Task ID: {1}. Waiting for task completion..." .format (
4798+ batch_number , task_id
4799+ ),
4800+ "INFO" ,
4801+ )
4802+
4803+ task_name = "Add Port Channel(s) Task - Batch {0}" .format (batch_number )
4804+ batch_msg = "Batch {0} with {1} port channels has completed successfully." .format (
4805+ batch_number , len (batch )
4806+ )
4807+
4808+ self .log ("Checking task status for batch {0}." .format (batch_number ), "DEBUG" )
4809+ self .get_task_status_from_tasks_by_id (task_id , task_name , batch_msg )
4810+
4811+ if self .status == "success" :
4812+ successful_batches += 1
4813+ final_task_id = task_id
4814+ self .log (
4815+ "Batch {0} completed successfully. Proceeding to next batch..." .format (batch_number ),
4816+ "INFO" ,
4817+ )
4818+ else :
4819+ self .log (
4820+ "Batch {0} failed with status: {1}. Stopping further processing." .format (
4821+ batch_number , self .status
4822+ ),
4823+ "ERROR" ,
4824+ )
4825+ return task_id
4826+
4827+ self .log (
4828+ "Sequential port channel addition completed. Successful batches: {0}" .format (
4829+ successful_batches
4830+ ),
4831+ "INFO" ,
47544832 )
47554833
4834+ return final_task_id
4835+
47564836 def update_port_channels (self , update_port_channels_params ):
47574837 """
47584838 Initiates the task to update port channels.
@@ -4762,17 +4842,89 @@ def update_port_channels(self, update_port_channels_params):
47624842 dict: The task ID from the API call.
47634843 Description:
47644844 This method initiates the task to update port channels using the provided parameters and returns the task ID.
4845+ This method processes port channels in batches of 20 sequentially, waiting for each batch to complete.
47654846 """
4847+ payload = update_port_channels_params .get ("payload" , [])
4848+ batch_size = self .params .get ("sda_fabric_port_channel_limit" , 20 )
4849+
4850+ if len (payload ) <= batch_size :
4851+ self .log (
4852+ "Processing {0} port channels in single batch" .format (len (payload )),
4853+ "INFO" ,
4854+ )
4855+ return self .get_taskid_post_api_call (
4856+ "sda" , "update_port_channels" , update_port_channels_params
4857+ )
4858+
47664859 self .log (
4767- "Initiating update of port channels with parameters: {0} " .format (
4768- update_port_channels_params
4860+ "Processing {0} port channels in batches of {1} sequentially " .format (
4861+ len ( payload ), batch_size
47694862 ),
47704863 "INFO" ,
47714864 )
4772- return self .get_taskid_post_api_call (
4773- "sda" , "update_port_channels" , update_port_channels_params
4865+
4866+ final_task_id = None
4867+ successful_batches = 0
4868+
4869+ self .log ("Starting batch processing for port channel updates." , "DEBUG" )
4870+ for i in range (0 , len (payload ), batch_size ):
4871+ batch = payload [i :i + batch_size ]
4872+ batch_params = {"payload" : batch }
4873+ batch_number = (i // batch_size ) + 1
4874+
4875+ self .log (
4876+ "Processing batch {0} with {1} port channels sequentially" .format (
4877+ batch_number , len (batch )
4878+ ),
4879+ "INFO" ,
4880+ )
4881+
4882+ # Execute the API call for this batch
4883+ task_id = self .get_taskid_post_api_call (
4884+ "sda" , "update_port_channels" , batch_params
4885+ )
4886+
4887+ self .log (
4888+ "Batch {0} API call completed, Task ID: {1}. Waiting for task completion..." .format (
4889+ batch_number , task_id
4890+ ),
4891+ "INFO" ,
4892+ )
4893+
4894+ # Wait for this batch to complete before proceeding
4895+ task_name = "Update Port Channel(s) Task - Batch {0}" .format (batch_number )
4896+ batch_msg = "Batch {0} with {1} port channels has completed successfully." .format (
4897+ batch_number , len (batch )
4898+ )
4899+
4900+ self .log ("Checking task status for batch {0}." .format (batch_number ), "DEBUG" )
4901+ self .get_task_status_from_tasks_by_id (task_id , task_name , batch_msg )
4902+
4903+ if self .status == "success" :
4904+ successful_batches += 1
4905+ final_task_id = task_id # Keep the last successful task ID
4906+ self .log (
4907+ "Batch {0} completed successfully. Proceeding to next batch..." .format (batch_number ),
4908+ "INFO" ,
4909+ )
4910+ else :
4911+ self .log (
4912+ "Batch {0} failed with status: {1}. Stopping further processing." .format (
4913+ batch_number , self .status
4914+ ),
4915+ "ERROR" ,
4916+ )
4917+ return task_id
4918+
4919+ self .log (
4920+ "Sequential port channel update completed. Successful batches: {0}" .format (
4921+ successful_batches
4922+ ),
4923+ "INFO" ,
47744924 )
47754925
4926+ return final_task_id
4927+
47764928 def delete_port_channels (self , delete_port_channel_param ):
47774929 """
47784930 Initiates the task to delete port channels.
@@ -4967,12 +5119,59 @@ def get_add_port_channels_task_status(self, task_id):
49675119 This method constructs a message indicating the successful completion of the add port channels
49685120 operation. It then retrieves the task status using the provided task ID. If the operation is
49695121 successful, it fetches existing port channels and updates the message with the names of the
4970- newly created port channels.
5122+ newly created port channels. Handles both single batch and sequential batch processing.
49715123 """
49725124 task_name = "Add Port Channel(s) Task"
49735125 add_port_channels_params = self .want ["add_port_channels_params" ]
5126+ payload = add_port_channels_params .get ("payload" , [])
5127+ batch_size = self .params .get ("sda_fabric_port_channel_limit" , 20 )
5128+
5129+ if len (payload ) > batch_size :
5130+ self .log (
5131+ "Processing sequential add port channels task status for {0} port channels" .format (
5132+ len (payload )
5133+ ),
5134+ "INFO" ,
5135+ )
5136+
5137+ if self .status == "success" :
5138+ # Fetch existing port channels to get the names
5139+ existing_port_channels = self .get_port_channels (
5140+ self .have .get ("get_port_channels_params" )
5141+ )
5142+
5143+ # Compare interface names and collect created port channel names
5144+ port_channels_names = []
5145+ for port_channel in existing_port_channels :
5146+ for payload_channel in payload :
5147+ if set (payload_channel ["interfaceNames" ]) == set (
5148+ port_channel ["interfaceNames" ]
5149+ ):
5150+ port_channels_names .append (port_channel ["portChannelName" ])
5151+ break
5152+
5153+ self .log (
5154+ "Names of port_channels that were successfully created via sequential processing: {0}" .format (
5155+ port_channels_names
5156+ ),
5157+ "DEBUG" ,
5158+ )
5159+
5160+ updated_msg = {}
5161+ updated_msg [
5162+ "{0} Succeeded for following port channel(s) (Sequential Processing)" .format (task_name )
5163+ ] = {
5164+ "success_count" : len (port_channels_names ),
5165+ "success_port_channels" : port_channels_names ,
5166+ "total_batches" : (len (payload ) + batch_size - 1 ) // batch_size ,
5167+ "sequential_processing" : True ,
5168+ }
5169+ self .msg = updated_msg
5170+
5171+ return self
5172+
49745173 msg = "{0} has completed successfully for params: {1}." .format (
4975- task_name , add_port_channels_params [ " payload" ]
5174+ task_name , payload
49765175 )
49775176
49785177 # Execute the task and get the status
@@ -4996,7 +5195,7 @@ def get_add_port_channels_task_status(self, task_id):
49965195 # Compare interface names and collect created port channel names
49975196 port_channels_names = []
49985197 for port_channel in existing_port_channels :
4999- for payload_channel in add_port_channels_params [ " payload" ] :
5198+ for payload_channel in payload :
50005199 if set (payload_channel ["interfaceNames" ]) == set (
50015200 port_channel ["interfaceNames" ]
50025201 ):
@@ -5033,16 +5232,51 @@ def get_update_port_channels_task_status(self, task_id):
50335232 Description:
50345233 This method constructs a message indicating the successful completion of the update port channels
50355234 operation. It then retrieves the task status using the provided task ID and logs the relevant information.
5235+ Handles both single batch and sequential batch processing.
50365236 """
50375237 task_name = "Update Port Channel(s) Task"
5038- msg = {}
50395238
50405239 # Retrieve the parameters for updating port channels
50415240 update_port_channels_params = self .want .get ("update_port_channels_params" )
5241+ payload = update_port_channels_params .get ("payload" , [])
5242+ batch_size = self .params .get ("sda_fabric_port_channel_limit" , 20 )
50425243 port_channels_list = [
50435244 port .get ("portChannelName" )
5044- for port in update_port_channels_params [ " payload" ]
5245+ for port in payload
50455246 ]
5247+
5248+ # Check if this was sequential processing (more than batch_size port channels)
5249+ if len (payload ) > batch_size :
5250+ # For sequential processing, the task status was already checked during processing
5251+ # We just need to prepare the final message
5252+ self .log (
5253+ "Processing sequential update port channels task status for {0} port channels" .format (
5254+ len (payload )
5255+ ),
5256+ "INFO" ,
5257+ )
5258+
5259+ if self .status == "success" :
5260+ msg = {}
5261+ msg ["{0} Succeeded for following port channel(s) (Sequential Processing)" .format (task_name )] = {
5262+ "success_count" : len (port_channels_list ),
5263+ "success_port_channels" : port_channels_list ,
5264+ "total_batches" : (len (payload ) + batch_size - 1 ) // batch_size ,
5265+ "sequential_processing" : True ,
5266+ }
5267+ self .msg = msg
5268+ return self .get_task_status_from_tasks_by_id (task_id , task_name , msg )
5269+ else :
5270+ msg = {}
5271+ msg ["{0} Failed during sequential processing" .format (task_name )] = {
5272+ "total_port_channels" : len (port_channels_list ),
5273+ "port_channels" : port_channels_list ,
5274+ "sequential_processing" : True ,
5275+ "status" : self .status ,
5276+ }
5277+ return self .get_task_status_from_tasks_by_id (task_id , task_name , msg )
5278+
5279+ msg = {}
50465280 msg ["{0} Succeeded for following port channel(s)" .format (task_name )] = {
50475281 "success_count" : len (port_channels_list ),
50485282 "success_port_channels" : port_channels_list ,
@@ -7000,6 +7234,7 @@ def main():
70007234 "dnac_log" : {"type" : "bool" , "default" : False },
70017235 "validate_response_schema" : {"type" : "bool" , "default" : True },
70027236 "config_verify" : {"type" : "bool" , "default" : False },
7237+ "sda_fabric_port_channel_limit" : {"type" : "int" , "default" : 20 },
70037238 "dnac_api_task_timeout" : {"type" : "int" , "default" : 1200 },
70047239 "dnac_task_poll_interval" : {"type" : "int" , "default" : 2 },
70057240 "config" : {"required" : True , "type" : "list" , "elements" : "dict" },
0 commit comments