318318 default: false
319319requirements:
320320 - catalystcentersdk >= 3.1.6.0.2
321- - python >= 3.9
321+ - python >= 3.12
322322notes:
323323 - SDK Methods used are sites.Sites.get_site,
324324 devices.Devices.get_network_device_by_ip,
@@ -688,7 +688,20 @@ def validate_input(self, state=None):
688688 "elements" : "dict" ,
689689 },
690690 "skip_ap_provision" : {"type" : "bool" , "required" : False },
691- "rolling_ap_upgrade" : {"type" : "dict" , "required" : False },
691+ "rolling_ap_upgrade" : {
692+ "type" : "dict" ,
693+ "required" : False ,
694+ "options" : {
695+ "enable_rolling_ap_upgrade" : {
696+ "type" : "bool" ,
697+ "required" : False ,
698+ },
699+ "ap_reboot_percentage" : {
700+ "type" : "int" ,
701+ "required" : False ,
702+ },
703+ },
704+ },
692705 "ap_authorization_list_name" : {"type" : "str" , "required" : False },
693706 "authorize_mesh_and_non_mesh_aps" : {"type" : "bool" , "required" : False , "default" : False },
694707 "provisioning" : {"type" : "bool" , "required" : False , "default" : True },
@@ -735,11 +748,11 @@ def validate_input(self, state=None):
735748
736749 for config_item in self .config :
737750 telemetry_list = config_item .get ("application_telemetry" , [])
738- for index , config_item in enumerate (self .config ):
751+ for index , config_item in enumerate (self .config , start = 1 ):
739752 telemetry_list = config_item .get ("application_telemetry" , [])
740753
741754 # Validate each telemetry entry
742- for entry_index , telemetry_entry in enumerate (telemetry_list ):
755+ for entry_index , telemetry_entry in enumerate (telemetry_list , start = 1 ):
743756
744757 if (
745758 "device_ips" not in telemetry_entry
@@ -782,7 +795,7 @@ def validate_input(self, state=None):
782795 "type" : "str" ,
783796 "required" : True ,
784797 }
785- for index , config_item in enumerate (self .config ):
798+ for index , config_item in enumerate (self .config , start = 1 ):
786799 if (
787800 "site_name_hierarchy" not in config_item
788801 or not config_item ["site_name_hierarchy" ]
@@ -818,6 +831,36 @@ def validate_input(self, state=None):
818831 )
819832 self .set_operation_result ("failed" , False , self .msg , "ERROR" ).check_return_status ()
820833
834+ rolling_ap_upgrade = config_item .get ("rolling_ap_upgrade" )
835+ if rolling_ap_upgrade is not None :
836+ self .log (
837+ "Validating 'rolling_ap_upgrade' in config item at index {0}." .format (index ),
838+ "DEBUG" ,
839+ )
840+
841+ ap_reboot_percentage = rolling_ap_upgrade .get ("ap_reboot_percentage" )
842+ if ap_reboot_percentage is not None :
843+ allowed_ap_reboot_percentages = frozenset ({5 , 15 , 25 })
844+ if not str (ap_reboot_percentage ).isdigit ():
845+ self .msg = (
846+ "Invalid 'ap_reboot_percentage' value '{0}'. Must be an integer. "
847+ "Supported values are 5, 15, and 25." .format (ap_reboot_percentage )
848+ )
849+ self .set_operation_result ("failed" , False , self .msg , "ERROR" ).check_return_status ()
850+ elif int (ap_reboot_percentage ) not in allowed_ap_reboot_percentages :
851+ self .msg = (
852+ "Invalid 'ap_reboot_percentage' value '{0}'. "
853+ "Supported values are 5, 15, and 25." .format (ap_reboot_percentage )
854+ )
855+ self .set_operation_result ("failed" , False , self .msg , "ERROR" ).check_return_status ()
856+ else :
857+ self .log (
858+ "Validated 'ap_reboot_percentage' with supported value '{0}' in config item at index {1}." .format (
859+ ap_reboot_percentage , index
860+ ),
861+ "DEBUG" ,
862+ )
863+
821864 if missing_params :
822865 self .msg = "Missing or invalid required parameter(s): {0}" .format (
823866 ", " .join (set (missing_params ))
@@ -2612,11 +2655,12 @@ def get_device_type(self):
26122655 )
26132656
26142657 except Exception as e :
2615- error_message = "The Device - {0} is already deleted from the Inventory or not present in the Cisco Catalyst Center." .format (
2616- device [ "management_ip_address" ]
2658+ self . msg = "Device with IP {0} not found in Cisco Catalyst Center." .format (
2659+ ip_address
26172660 )
2618- self .log (error_message , "WARNING" )
2619- continue
2661+ self .set_operation_result (
2662+ "failed" , False , self .msg , "ERROR"
2663+ ).check_return_status ()
26202664
26212665 if not dev_response or "response" not in dev_response :
26222666 self .log (
@@ -3446,44 +3490,14 @@ def provision_wireless_device(self):
34463490 self .log ("'skip_ap_provision' is not specified" , "DEBUG" )
34473491
34483492 self .log ("Processing rolling AP upgrade settings" , "INFO" )
3449- allowed_ap_reboot_percentages = {5 , 10 , 25 }
34503493
34513494 if "rolling_ap_upgrade" in prov_params :
34523495 self .log ("Found 'rolling_ap_upgrade' in provisioning parameters" , "DEBUG" )
34533496
34543497 rolling_upgrade_config = {}
34553498 rolling_upgrade_data = prov_params ["rolling_ap_upgrade" ]
34563499
3457- if "ap_reboot_percentage" in rolling_upgrade_data :
3458- reboot_percentage_value = rolling_upgrade_data ["ap_reboot_percentage" ]
3459-
3460- if reboot_percentage_value is None or not str (reboot_percentage_value ).isdigit ():
3461- self .msg = (
3462- "Error: Invalid percentage value '{0}'. Must be an integer. "
3463- "Supported values are 5, 10, and 25." .format (reboot_percentage_value )
3464- )
3465- self .set_operation_result ("failed" , False , self .msg , "ERROR" ).check_return_status ()
3466-
3467- reboot_percentage_value = int (reboot_percentage_value )
3468- if reboot_percentage_value not in allowed_ap_reboot_percentages :
3469- self .msg = (
3470- "Error: Invalid percentage value '{0}'. "
3471- "Supported values are 5, 10, and 25." .format (reboot_percentage_value )
3472- )
3473- self .set_operation_result ("failed" , False , self .msg , "ERROR" ).check_return_status ()
3474-
3475- rolling_upgrade_config ["ap_reboot_percentage" ] = reboot_percentage_value
3476- self .log (
3477- "Processed 'ap_reboot_percentage': {0}" .format (reboot_percentage_value ),
3478- "DEBUG" ,
3479- )
3480-
3481- # Process remaining keys in 'rolling_ap¿_upgrade'
34823500 for key , value in rolling_upgrade_data .items ():
3483- if key == "ap_reboot_percentage" :
3484- self .log ("Skipping already processed key 'ap_reboot_percentage'" , "DEBUG" )
3485- continue
3486-
34873501 if value is not None :
34883502 rolling_upgrade_config [key ] = value
34893503 self .log (
@@ -3496,6 +3510,18 @@ def provision_wireless_device(self):
34963510 "DEBUG" ,
34973511 )
34983512
3513+ # Normalize validated percentage to int for SDK payload schema.
3514+ if rolling_upgrade_config .get ("ap_reboot_percentage" ) is not None :
3515+ rolling_upgrade_config ["ap_reboot_percentage" ] = int (
3516+ rolling_upgrade_config ["ap_reboot_percentage" ]
3517+ )
3518+ self .log (
3519+ "Normalized 'ap_reboot_percentage' to int: {0}" .format (
3520+ rolling_upgrade_config ["ap_reboot_percentage" ]
3521+ ),
3522+ "DEBUG" ,
3523+ )
3524+
34993525 payload ["rollingApUpgrade" ] = rolling_upgrade_config
35003526
35013527 # Process AP authorization list configuration if provided
0 commit comments