diff --git a/plugins/modules/sda_fabric_devices_workflow_manager.py b/plugins/modules/sda_fabric_devices_workflow_manager.py index 3e3416300..b6d80b330 100644 --- a/plugins/modules/sda_fabric_devices_workflow_manager.py +++ b/plugins/modules/sda_fabric_devices_workflow_manager.py @@ -130,14 +130,14 @@ is_default_exit: description: - Indicates whether this Border Node serves as the default gateway for traffic exiting the virtual network. - - The `is_default_exit` can be updated. + - The `is_default_exit` cannot be updated. type: bool default: true import_external_routes: description: - Determines whether routes from external networks are imported into the fabric. - Enhances security by limiting route usage to internal routes. - - The 'import_external_routes' can be updated. + - The 'import_external_routes' cannot be updated. type: bool default: true border_priority: @@ -2442,7 +2442,7 @@ def get_device_params(self, fabric_id, network_id, device_details, config_index) network_id (str): The Id of the network device. device_details (dict): Playbook details containing fabric devices details along with the Border Settings, L2 Handoff, L3 SDA Handoff, L3 IP Handoff information. - config_index (int) - Pointer to the device_config elements in the playbook. + config_index (int): Pointer to the device_config elements in the playbook. Returns: device_info (dict): The processed device details from the user playbook. Description: @@ -2523,8 +2523,10 @@ def get_device_params(self, fabric_id, network_id, device_details, config_index) have_border_settings = None # Get the border settings details from the Cisco Catalyst Center, if available - if not borders_settings: + if have_device_details: have_border_settings = have_device_details.get("borderDeviceSettings") + + if not borders_settings: if not have_border_settings: self.msg = ( "The parameter 'border_settings' is mandatory when the 'device_roles' has 'BORDER_NODE' " @@ -2536,7 +2538,10 @@ def get_device_params(self, fabric_id, network_id, device_details, config_index) device_info.update({ "borderDeviceSettings": have_border_settings }) - self.log("Border settings retrieved from existing data: {}".format(have_border_settings), "DEBUG") + self.log( + "Border settings retrieved from existing data: {have_border_settings}" + .format(have_border_settings=have_border_settings), "DEBUG" + ) return device_info self.log("Processing user-provided border settings", "DEBUG") @@ -2581,8 +2586,8 @@ def get_device_params(self, fabric_id, network_id, device_details, config_index) if "LAYER_3" in border_types: if not (layer3_settings or have_layer3_settings): self.msg = ( - "The parameter 'border_settings' is mandatory when the 'device_roles' has 'BORDER_NODE' " - "for the device {ip}.".format(ip=device_ip) + "The parameter 'layer3_settings' is mandatory under 'borders_settings' when the " + "'device_roles' has 'BORDER_NODE' for the device {ip}.".format(ip=device_ip) ) self.status = "failed" return self.check_return_status() @@ -2599,27 +2604,55 @@ def get_device_params(self, fabric_id, network_id, device_details, config_index) ) self.status = "failed" return self.check_return_status() + else: + if have_layer3_settings and (str(local_autonomous_system_number) != str(have_layer3_settings.get("localAutonomousSystemNumber"))): + self.msg = ( + "The parameter 'local_autonomous_system_number' under 'layer3_settings' should not be " + "updated for the device with IP '{ip}'.".format(ip=device_ip) + ) + self.status = "failed" + return self.check_return_status() self.validate_local_autonomous_system_number(local_autonomous_system_number, device_ip) self.log( "Successfully validated 'local_autonomous_system_number': {asn_number}" .format(asn_number=local_autonomous_system_number), "DEBUG" ) - is_default_exit = layer3_settings.get("layer3_settings") - if not is_default_exit: + is_default_exit = layer3_settings.get("is_default_exit") + if is_default_exit is None: if have_layer3_settings: have_is_default_exit = have_layer3_settings.get("isDefaultExit") is_default_exit = have_is_default_exit else: is_default_exit = True + else: + if have_layer3_settings: + have_is_default_exit = have_layer3_settings.get("importExternalRoutes") + if is_default_exit != have_is_default_exit: + self.msg = ( + "The parameter 'is_default_exit' under 'layer3_settings' should not be " + "updated for the device with IP '{ip}'.".format(ip=device_ip) + ) + self.status = "failed" + return self.check_return_status() import_external_routes = layer3_settings.get("import_external_routes") - if not import_external_routes: + if import_external_routes is None: if have_layer3_settings: have_import_external_routes = have_layer3_settings.get("importExternalRoutes") import_external_routes = have_import_external_routes else: import_external_routes = True + else: + if have_layer3_settings: + have_import_external_routes = have_layer3_settings.get("importExternalRoutes") + if import_external_routes != have_import_external_routes: + self.msg = ( + "The parameter 'import_external_routes' under 'layer3_settings' should not be " + "updated for the device with IP '{ip}'.".format(ip=device_ip) + ) + self.status = "failed" + return self.check_return_status() border_priority = layer3_settings.get("border_priority") # Default value of border priority is 10 @@ -3107,7 +3140,7 @@ def get_sda_l3_handoff_params(self, fabric_id, network_id, device_details, devic ) return sda_l3_handoff_info - def validate_layer3_handoff_ip_transit(self, item, device_ip, is_ip_l3_handoff_exists, have_ip_l3_handoff): + def validate_layer3_handoff_ip_transit(self, item, device_ip, is_ip_l3_handoff_exists, have_ip_l3_handoff, l3_ip_handoff_index): """ Validate Layer 3 handoff IP transit parameters. @@ -3116,6 +3149,7 @@ def validate_layer3_handoff_ip_transit(self, item, device_ip, is_ip_l3_handoff_e device_ip (str): The device IP address. is_ip_l3_handoff_exists (int): The existence of the L3 handoff item. have_ip_l3_handoff (dict): Existing L3 handoff details for the device. + l3_ip_handoff_index (int): Index for the current item in the 'have_ip_l3_handoff'. Returns: tuple: A tuple containing transit_id, interface_name, virtual_network_name, vlan_id, tcp_mss_adjustment @@ -3217,9 +3251,9 @@ def validate_layer3_handoff_ip_transit(self, item, device_ip, is_ip_l3_handoff_e self.log(self.msg, "ERROR") return (None, None, None, None, None, False) elif virtual_network_name and (not vlan_id): - vlan_id = have_ip_l3_handoff.get("vlanId") + vlan_id = have_ip_l3_handoff[l3_ip_handoff_index].get("vlanId") elif vlan_id and (not virtual_network_name): - virtual_network_name = have_ip_l3_handoff.get("virtualNetworkName") + virtual_network_name = have_ip_l3_handoff[l3_ip_handoff_index].get("virtualNetworkName") else: if not (virtual_network_name and vlan_id): self.msg = ( @@ -3234,7 +3268,7 @@ def validate_layer3_handoff_ip_transit(self, item, device_ip, is_ip_l3_handoff_e tcp_mss_adjustment = item.get("tcp_mss_adjustment") if not tcp_mss_adjustment: if is_ip_l3_handoff_exists: - have_tcp_mss_adjustment = have_ip_l3_handoff.get("tcpMssAdjustment") + have_tcp_mss_adjustment = have_ip_l3_handoff[l3_ip_handoff_index].get("tcpMssAdjustment") if have_tcp_mss_adjustment: tcp_mss_adjustment = have_tcp_mss_adjustment else: @@ -3322,7 +3356,8 @@ def get_ip_l3_handoff_params(self, fabric_id, network_id, device_details, device (transit_id, interface_name, virtual_network_name, vlan_id, tcp_mss_adjustment, is_valid) = \ self.validate_layer3_handoff_ip_transit( - item, device_details.get("device_ip"), is_ip_l3_handoff_exists, have_ip_l3_handoff + item, device_details.get("device_ip"), is_ip_l3_handoff_exists, + have_ip_l3_handoff, l3_ip_handoff_index ) if not is_valid: