@@ -296,6 +296,9 @@ def __init__(self, module):
296296 self .module_schema = self .provision_workflow_manager_mapping ()
297297 self .log ("Initialized ProvisionPlaybookGenerator class instance." , "DEBUG" )
298298 self .site_id_name_dict = self .get_site_id_name_mapping ()
299+ self ._cached_provisioned_devices = None
300+ self ._cached_inventory_devices = None
301+ self ._cached_inventory_by_id = None
299302
300303 def get_site_id_name_mapping (self ):
301304 """
@@ -324,6 +327,30 @@ def get_site_id_name_mapping(self):
324327
325328 return site_id_name_mapping
326329
330+ def get_inventory_devices (self ):
331+ """
332+ Retrieve inventory devices once and reuse them throughout the current run.
333+
334+ Returns:
335+ list: Inventory device records from Catalyst Center.
336+ """
337+ if self ._cached_inventory_devices is not None :
338+ return self ._cached_inventory_devices
339+
340+ all_devices_response = self .catalystcenter ._exec (
341+ family = "devices" ,
342+ function = "get_device_list" ,
343+ op_modifies = False ,
344+ )
345+ self .log ("Received API response: {0}" .format (all_devices_response ), "DEBUG" )
346+ self ._cached_inventory_devices = all_devices_response .get ("response" , [])
347+ self ._cached_inventory_by_id = {
348+ device .get ("id" ): device
349+ for device in self ._cached_inventory_devices
350+ if device .get ("id" )
351+ }
352+ return self ._cached_inventory_devices
353+
327354 def write_dict_to_yaml (self , data_dict , file_path , dumper = OrderedDumper , file_mode = "overwrite" ):
328355 """
329356 Converts a dictionary to YAML format and writes it to a specified file path.
@@ -916,6 +943,10 @@ def get_all_provisioned_devices_internal(self):
916943 list: List of all provisioned devices
917944 """
918945 self .log ("Retrieving all provisioned devices from SDA API" , "INFO" )
946+ if self ._cached_provisioned_devices is not None :
947+ self .log ("Using cached provisioned devices list" , "DEBUG" )
948+ return self ._cached_provisioned_devices
949+
919950 try :
920951 # Get all provisioned devices from SDA API
921952 response = self .catalystcenter ._exec (
@@ -928,63 +959,68 @@ def get_all_provisioned_devices_internal(self):
928959 self .log ("Retrieved {0} devices from SDA provisioned devices API" .format (len (sda_devices )), "INFO" )
929960
930961 # WORKAROUND: Check for missing wireless controllers
931- all_devices_response = self .catalystcenter ._exec (
932- family = "devices" ,
933- function = "get_device_list" ,
934- op_modifies = False ,
935- )
936- self .log ("Received API response: {0}" .format (all_devices_response ), "DEBUG" )
937- all_devices = all_devices_response .get ("response" , [])
962+ all_devices = self .get_inventory_devices ()
963+ inventory_by_id = self ._cached_inventory_by_id or {}
938964
939965 wireless_controllers_found = []
940966 sda_device_ids = {device .get ("networkDeviceId" ) for device in sda_devices }
941967
968+ for sda_device in sda_devices :
969+ inventory_device = inventory_by_id .get (sda_device .get ("networkDeviceId" ))
970+ if inventory_device :
971+ sda_device .update (
972+ {
973+ "id" : inventory_device .get ("id" ),
974+ "managementIpAddress" : inventory_device .get ("managementIpAddress" ),
975+ "family" : inventory_device .get ("family" ),
976+ "type" : inventory_device .get ("type" ),
977+ "hostname" : inventory_device .get ("hostname" ),
978+ "location" : inventory_device .get ("location" ),
979+ "siteId" : sda_device .get ("siteId" ) or inventory_device .get ("siteId" ),
980+ }
981+ )
982+
942983 for device in all_devices :
943984 device_id = device .get ("id" )
944985 management_ip = device .get ("managementIpAddress" )
945986
946987 if device_id in sda_device_ids :
947988 continue
948989
949- try :
950- device_detail_response = self .catalystcenter ._exec (
951- family = "devices" ,
952- function = "get_device_detail" ,
953- op_modifies = False ,
954- params = {"search_by" : device_id , "identifier" : "uuid" },
955- )
956- self .log ("Received API response: {0}" .format (device_detail_response ), "DEBUG" )
957- device_info = device_detail_response .get ("response" , {})
958- device_family = device_info .get ("nwDeviceFamily" )
990+ device_family = device .get ("family" ) or device .get ("nwDeviceFamily" )
959991
960- if device_family == "Wireless Controller" :
961- try :
962- provision_response = self .catalystcenter ._exec (
963- family = "sda" ,
964- function = "get_provisioned_wired_device" ,
965- op_modifies = False ,
966- params = {"device_management_ip_address" : management_ip }
967- )
968- self .log ("Received API response: {0}" .format (provision_response ), "DEBUG" )
969- if provision_response .get ("status" ) == "success" :
970- mock_device = {
971- "networkDeviceId" : device_id ,
972- "siteId" : device .get ("siteId" ),
973- "deviceType" : "WirelessController"
974- }
975- sda_devices .append (mock_device )
976- wireless_controllers_found .append (management_ip )
977- except Exception :
978- self .log ("Wireless controller with IP {0} not provisioned in SDA" .format (management_ip ), "WARNING" )
979- pass
980- except Exception :
981- self .log ("Could not retrieve details for device ID {0}" .format (device_id ), "WARNING" )
982- pass
992+ if device_family == "Wireless Controller" :
993+ try :
994+ provision_response = self .catalystcenter ._exec (
995+ family = "sda" ,
996+ function = "get_provisioned_wired_device" ,
997+ op_modifies = False ,
998+ params = {"device_management_ip_address" : management_ip }
999+ )
1000+ self .log ("Received API response: {0}" .format (provision_response ), "DEBUG" )
1001+ if provision_response .get ("status" ) == "success" :
1002+ mock_device = {
1003+ "networkDeviceId" : device_id ,
1004+ "siteId" : device .get ("siteId" ),
1005+ "deviceType" : "WirelessController" ,
1006+ "id" : device .get ("id" ),
1007+ "managementIpAddress" : management_ip ,
1008+ "family" : device_family ,
1009+ "type" : device .get ("type" ),
1010+ "hostname" : device .get ("hostname" ),
1011+ "location" : device .get ("location" ),
1012+ }
1013+ sda_devices .append (mock_device )
1014+ wireless_controllers_found .append (management_ip )
1015+ except Exception :
1016+ self .log ("Wireless controller with IP {0} not provisioned in SDA" .format (management_ip ), "WARNING" )
1017+ pass
9831018
9841019 self .log ("Found {0} additional provisioned wireless controllers" .format (
9851020 len (wireless_controllers_found )), "INFO" )
9861021
987- return sda_devices
1022+ self ._cached_provisioned_devices = sda_devices
1023+ return self ._cached_provisioned_devices
9881024
9891025 except Exception as e :
9901026 self .log ("Error retrieving provisioned devices: {0}" .format (str (e )), "ERROR" )
@@ -1209,6 +1245,11 @@ def transform_device_site_hierarchy(self, device_details):
12091245 else :
12101246 self .log ("WARNING: Site ID {0} not found in site mapping" .format (site_id ), "WARNING" )
12111247
1248+ cached_location = device_details .get ("location" )
1249+ if cached_location and str (cached_location ).strip ():
1250+ self .log ("Using cached location field for site hierarchy: {0}" .format (cached_location ), "DEBUG" )
1251+ return cached_location
1252+
12121253 # Fallback: If no siteId or mapping failed, get it from device detail API
12131254 if not site_id or not site_name_hierarchy :
12141255 self .log ("Fallback: Getting site hierarchy from device detail API for device {0}" .format (device_id ), "DEBUG" )
@@ -1285,6 +1326,10 @@ def transform_device_family_info(self, device_details):
12851326 Returns:
12861327 str: Device family type (e.g., 'Switches and Hubs', 'Wireless Controller').
12871328 """
1329+ cached_family = device_details .get ("nwDeviceFamily" ) or device_details .get ("family" )
1330+ if cached_family :
1331+ return cached_family
1332+
12881333 device_id = device_details .get ("networkDeviceId" )
12891334 self .log ("Transforming device family info for device ID: {0}" .format (device_id ), "DEBUG" )
12901335
@@ -1329,6 +1374,10 @@ def transform_device_management_ip(self, device_details):
13291374 Returns:
13301375 str: Device management IP address.
13311376 """
1377+ cached_ip = device_details .get ("managementIpAddress" ) or device_details .get ("managementIpAddr" )
1378+ if cached_ip :
1379+ return cached_ip
1380+
13321381 self .log ("Transforming device management IP for device: {0}" .format (device_details .get ("networkDeviceId" )), "DEBUG" )
13331382
13341383 device_id = device_details .get ("networkDeviceId" )
0 commit comments