From 1ae9597b2553c7cb4c8eea4a8c20f760c4e64402 Mon Sep 17 00:00:00 2001 From: Claus Holbech Date: Wed, 13 Nov 2024 17:37:02 +0100 Subject: [PATCH] Various fixes to address review comments --- .../intended/configs/host1.cfg | 6 ++ .../intended/structured_configs/host1.yml | 7 ++ .../inventory/host_vars/host1/node_type.yml | 1 + .../connected_endpoints.yml | 9 --- .../tables/node-type-uplink-configuration.md | 16 ++--- pyproject.toml | 20 +----- .../_eos_designs/eos_designs_facts/uplinks.py | 2 +- .../pyavd/_eos_designs/schema/__init__.py | 64 ++++++++++++------- .../schema/eos_designs.schema.yml | 1 + .../defs_node_type.schema.yml | 1 + .../shared_utils/filtered_tenants.py | 4 +- .../shared_utils/inband_management.py | 3 +- .../pyavd/_eos_designs/shared_utils/misc.py | 10 +-- .../pyavd/_eos_designs/shared_utils/mlag.py | 40 ++++++++---- .../_eos_designs/shared_utils/node_config.py | 14 +++- .../pyavd/_eos_designs/shared_utils/wan.py | 12 ++-- .../structured_config/base/__init__.py | 2 +- .../connected_endpoints/utils.py | 2 +- python-avd/pyavd/_schema/models/avd_model.py | 6 +- python-avd/pyavd/_utils/default.py | 2 +- .../pyavd/api/ip_addressing/__init__.py | 2 +- python-avd/pyavd/api/ip_addressing/utils.py | 2 +- 22 files changed, 124 insertions(+), 102 deletions(-) diff --git a/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/intended/configs/host1.cfg b/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/intended/configs/host1.cfg index 0dd7c2e17ef..63411758be5 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/intended/configs/host1.cfg +++ b/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/intended/configs/host1.cfg @@ -29,6 +29,12 @@ interface Loopback1 no shutdown ip address 192.168.254.101/32 ! +interface Management1 + description OOB_MANAGEMENT + no shutdown + vrf MGMT + ip address 192.168.0.103/24 +! interface Vxlan1 description host1_VTEP vxlan source-interface Loopback1 diff --git a/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/intended/structured_configs/host1.yml b/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/intended/structured_configs/host1.yml index 224187d1a48..0e8dc9ceee6 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/intended/structured_configs/host1.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/intended/structured_configs/host1.yml @@ -53,6 +53,13 @@ transceiver_qsfp_default_mode_4x10: true vrfs: - name: MGMT ip_routing: false +management_interfaces: +- name: Management1 + description: OOB_MANAGEMENT + shutdown: false + vrf: MGMT + ip_address: 192.168.0.103/24 + type: oob management_api_http: enable_vrfs: - name: MGMT diff --git a/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/inventory/host_vars/host1/node_type.yml b/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/inventory/host_vars/host1/node_type.yml index a94f72a7332..17572cae5f9 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/inventory/host_vars/host1/node_type.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_deprecated_vars/inventory/host_vars/host1/node_type.yml @@ -17,3 +17,4 @@ l3leaf: nodes: - name: host1 id: 5 + mgmt_ip: 192.168.0.103/24 diff --git a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/connected_endpoints.yml b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/connected_endpoints.yml index fd529816716..e638e740c8a 100644 --- a/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/connected_endpoints.yml +++ b/ansible_collections/arista/avd/molecule/eos_designs_unit_tests/intended/structured_configs/connected_endpoints.yml @@ -31,7 +31,6 @@ ethernet_interfaces: peer_type: server description: Interface description server_OLD_SW-1/2_ENDPOINT_PORT1 shutdown: false - poe: {} channel_group: id: 1 mode: active @@ -41,7 +40,6 @@ ethernet_interfaces: peer_type: server description: Interface description server_OLD_SW-1/2_ENDPOINT_PORT2 shutdown: false - poe: {} channel_group: id: 1 mode: active @@ -51,7 +49,6 @@ ethernet_interfaces: peer_type: server description: SERVER_OLD_SW-1/3_ENDPOINT_PORT shutdown: false - poe: {} channel_group: id: 3 mode: active @@ -67,7 +64,6 @@ ethernet_interfaces: peer_type: server description: SERVER_OLD_SW-1/5 shutdown: false - poe: {} channel_group: id: 5 mode: active @@ -76,7 +72,6 @@ ethernet_interfaces: peer_type: server description: SERVER_OLD_SW-1/5 shutdown: false - poe: {} channel_group: id: 5 mode: active @@ -85,7 +80,6 @@ ethernet_interfaces: peer_type: server description: PHYSICAL_PORT_DESCRIPTION shutdown: false - poe: {} channel_group: id: 7 mode: active @@ -94,7 +88,6 @@ ethernet_interfaces: peer_type: server description: PHYSICAL_PORT_DESCRIPTION shutdown: false - poe: {} channel_group: id: 7 mode: active @@ -110,7 +103,6 @@ ethernet_interfaces: peer_type: server description: PHYSICAL_PORT_DESCRIPTION_1 shutdown: false - poe: {} channel_group: id: 10 mode: active @@ -119,7 +111,6 @@ ethernet_interfaces: peer_type: server description: PHYSICAL_PORT_DESCRIPTION_2 shutdown: false - poe: {} channel_group: id: 10 mode: active diff --git a/ansible_collections/arista/avd/roles/eos_designs/docs/tables/node-type-uplink-configuration.md b/ansible_collections/arista/avd/roles/eos_designs/docs/tables/node-type-uplink-configuration.md index da5f450011b..a6666e7b511 100644 --- a/ansible_collections/arista/avd/roles/eos_designs/docs/tables/node-type-uplink-configuration.md +++ b/ansible_collections/arista/avd/roles/eos_designs/docs/tables/node-type-uplink-configuration.md @@ -27,7 +27,7 @@ | [    uplink_switch_interface_speed](## ".defaults.uplink_switch_interface_speed") | String | | | | Set point-to-Point interface speed for the uplink switch interface only.
Speed should be set in the format `` or `forced ` or `auto `.
| | [    uplink_mtu](## ".defaults.uplink_mtu") | Integer | | | Min: 68
Max: 65535 | Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting. | | [    max_uplink_switches](## ".defaults.max_uplink_switches") | Integer | | | | Maximum number of uplink switches.
Changing this value may change IP Addressing on uplinks.
Can be used to reserve IP space for future expansions.
| - | [    max_parallel_uplinks](## ".defaults.max_parallel_uplinks") | Integer | | | | Number of parallel links towards uplink switches.
Changing this value may change interface naming on uplinks (and corresponding downlinks).
Can be used to reserve interfaces for future parallel uplinks.
| + | [    max_parallel_uplinks](## ".defaults.max_parallel_uplinks") | Integer | | `1` | | Number of parallel links towards uplink switches.
Changing this value may change interface naming on uplinks (and corresponding downlinks).
Can be used to reserve interfaces for future parallel uplinks.
| | [    uplink_bfd](## ".defaults.uplink_bfd") | Boolean | | `False` | | Enable bfd on uplink interfaces. | | [    uplink_native_vlan](## ".defaults.uplink_native_vlan") | Integer | | | Min: 1
Max: 4094 | Only applicable to switches with layer-2 port-channel uplinks.
A suspended (disabled) vlan will be created in both ends of the link unless the vlan is defined under network services.
By default the uplink will not have a native_vlan configured, so EOS defaults to vlan 1.
| | [    uplink_ptp](## ".defaults.uplink_ptp") | Dictionary | | | | Enable PTP on all infrastructure links. | @@ -64,7 +64,7 @@ | [          uplink_switch_interface_speed](## ".node_groups.[].nodes.[].uplink_switch_interface_speed") | String | | | | Set point-to-Point interface speed for the uplink switch interface only.
Speed should be set in the format `` or `forced ` or `auto `.
| | [          uplink_mtu](## ".node_groups.[].nodes.[].uplink_mtu") | Integer | | | Min: 68
Max: 65535 | Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting. | | [          max_uplink_switches](## ".node_groups.[].nodes.[].max_uplink_switches") | Integer | | | | Maximum number of uplink switches.
Changing this value may change IP Addressing on uplinks.
Can be used to reserve IP space for future expansions.
| - | [          max_parallel_uplinks](## ".node_groups.[].nodes.[].max_parallel_uplinks") | Integer | | | | Number of parallel links towards uplink switches.
Changing this value may change interface naming on uplinks (and corresponding downlinks).
Can be used to reserve interfaces for future parallel uplinks.
| + | [          max_parallel_uplinks](## ".node_groups.[].nodes.[].max_parallel_uplinks") | Integer | | `1` | | Number of parallel links towards uplink switches.
Changing this value may change interface naming on uplinks (and corresponding downlinks).
Can be used to reserve interfaces for future parallel uplinks.
| | [          uplink_bfd](## ".node_groups.[].nodes.[].uplink_bfd") | Boolean | | `False` | | Enable bfd on uplink interfaces. | | [          uplink_native_vlan](## ".node_groups.[].nodes.[].uplink_native_vlan") | Integer | | | Min: 1
Max: 4094 | Only applicable to switches with layer-2 port-channel uplinks.
A suspended (disabled) vlan will be created in both ends of the link unless the vlan is defined under network services.
By default the uplink will not have a native_vlan configured, so EOS defaults to vlan 1.
| | [          uplink_ptp](## ".node_groups.[].nodes.[].uplink_ptp") | Dictionary | | | | Enable PTP on all infrastructure links. | @@ -93,7 +93,7 @@ | [      uplink_switch_interface_speed](## ".node_groups.[].uplink_switch_interface_speed") | String | | | | Set point-to-Point interface speed for the uplink switch interface only.
Speed should be set in the format `` or `forced ` or `auto `.
| | [      uplink_mtu](## ".node_groups.[].uplink_mtu") | Integer | | | Min: 68
Max: 65535 | Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting. | | [      max_uplink_switches](## ".node_groups.[].max_uplink_switches") | Integer | | | | Maximum number of uplink switches.
Changing this value may change IP Addressing on uplinks.
Can be used to reserve IP space for future expansions.
| - | [      max_parallel_uplinks](## ".node_groups.[].max_parallel_uplinks") | Integer | | | | Number of parallel links towards uplink switches.
Changing this value may change interface naming on uplinks (and corresponding downlinks).
Can be used to reserve interfaces for future parallel uplinks.
| + | [      max_parallel_uplinks](## ".node_groups.[].max_parallel_uplinks") | Integer | | `1` | | Number of parallel links towards uplink switches.
Changing this value may change interface naming on uplinks (and corresponding downlinks).
Can be used to reserve interfaces for future parallel uplinks.
| | [      uplink_bfd](## ".node_groups.[].uplink_bfd") | Boolean | | `False` | | Enable bfd on uplink interfaces. | | [      uplink_native_vlan](## ".node_groups.[].uplink_native_vlan") | Integer | | | Min: 1
Max: 4094 | Only applicable to switches with layer-2 port-channel uplinks.
A suspended (disabled) vlan will be created in both ends of the link unless the vlan is defined under network services.
By default the uplink will not have a native_vlan configured, so EOS defaults to vlan 1.
| | [      uplink_ptp](## ".node_groups.[].uplink_ptp") | Dictionary | | | | Enable PTP on all infrastructure links. | @@ -128,7 +128,7 @@ | [      uplink_switch_interface_speed](## ".nodes.[].uplink_switch_interface_speed") | String | | | | Set point-to-Point interface speed for the uplink switch interface only.
Speed should be set in the format `` or `forced ` or `auto `.
| | [      uplink_mtu](## ".nodes.[].uplink_mtu") | Integer | | | Min: 68
Max: 65535 | Point-to-Point uplinks MTU in bytes. This setting overrides the `p2p_uplinks_mtu` setting. | | [      max_uplink_switches](## ".nodes.[].max_uplink_switches") | Integer | | | | Maximum number of uplink switches.
Changing this value may change IP Addressing on uplinks.
Can be used to reserve IP space for future expansions.
| - | [      max_parallel_uplinks](## ".nodes.[].max_parallel_uplinks") | Integer | | | | Number of parallel links towards uplink switches.
Changing this value may change interface naming on uplinks (and corresponding downlinks).
Can be used to reserve interfaces for future parallel uplinks.
| + | [      max_parallel_uplinks](## ".nodes.[].max_parallel_uplinks") | Integer | | `1` | | Number of parallel links towards uplink switches.
Changing this value may change interface naming on uplinks (and corresponding downlinks).
Can be used to reserve interfaces for future parallel uplinks.
| | [      uplink_bfd](## ".nodes.[].uplink_bfd") | Boolean | | `False` | | Enable bfd on uplink interfaces. | | [      uplink_native_vlan](## ".nodes.[].uplink_native_vlan") | Integer | | | Min: 1
Max: 4094 | Only applicable to switches with layer-2 port-channel uplinks.
A suspended (disabled) vlan will be created in both ends of the link unless the vlan is defined under network services.
By default the uplink will not have a native_vlan configured, so EOS defaults to vlan 1.
| | [      uplink_ptp](## ".nodes.[].uplink_ptp") | Dictionary | | | | Enable PTP on all infrastructure links. | @@ -209,7 +209,7 @@ # Number of parallel links towards uplink switches. # Changing this value may change interface naming on uplinks (and corresponding downlinks). # Can be used to reserve interfaces for future parallel uplinks. - max_parallel_uplinks: + max_parallel_uplinks: # Enable bfd on uplink interfaces. uplink_bfd: @@ -345,7 +345,7 @@ # Number of parallel links towards uplink switches. # Changing this value may change interface naming on uplinks (and corresponding downlinks). # Can be used to reserve interfaces for future parallel uplinks. - max_parallel_uplinks: + max_parallel_uplinks: # Enable bfd on uplink interfaces. uplink_bfd: @@ -458,7 +458,7 @@ # Number of parallel links towards uplink switches. # Changing this value may change interface naming on uplinks (and corresponding downlinks). # Can be used to reserve interfaces for future parallel uplinks. - max_parallel_uplinks: + max_parallel_uplinks: # Enable bfd on uplink interfaces. uplink_bfd: @@ -587,7 +587,7 @@ # Number of parallel links towards uplink switches. # Changing this value may change interface naming on uplinks (and corresponding downlinks). # Can be used to reserve interfaces for future parallel uplinks. - max_parallel_uplinks: + max_parallel_uplinks: # Enable bfd on uplink interfaces. uplink_bfd: diff --git a/pyproject.toml b/pyproject.toml index a59389b413a..a0b5e06d243 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,26 +1,12 @@ [tool.black] # Black has been replaced with Ruff. -# This section should be removed later, but kept here to avoid IDE extensions from messing up the code. -line-length = 160 - -force-exclude = ''' -/( -python-avd/pyavd/_cv/api/\.\* -| python-avd/pyavd/_eos_designs/_schema/__init__\.py -| python-avd/pyavd/_eos_cli_config_gen/_schema/__init__\.py -)/ -''' +force-exclude = '''.*''' [tool.isort] # Isort has been replaced with Ruff. -# This section should be removed later, but kept here to avoid IDE extensions from messing up the code. -extend_skip_glob = [ - "python-avd/pyavd/_cv/api/**/*" +skip_glob = [ + "**/*" ] -profile = "black" -skip_gitignore = true -line_length = 160 -known_first_party = ["pyavd", "schema_tools"] [tool.ruff] line-length = 160 diff --git a/python-avd/pyavd/_eos_designs/eos_designs_facts/uplinks.py b/python-avd/pyavd/_eos_designs/eos_designs_facts/uplinks.py index 82a0a875cf9..e7c779df8e8 100644 --- a/python-avd/pyavd/_eos_designs/eos_designs_facts/uplinks.py +++ b/python-avd/pyavd/_eos_designs/eos_designs_facts/uplinks.py @@ -26,7 +26,7 @@ class UplinksMixin: @cached_property def max_parallel_uplinks(self: EosDesignsFacts) -> int: """Exposed in avd_switch_facts.""" - return self.shared_utils.max_parallel_uplinks + return self.shared_utils.node_config.max_parallel_uplinks @cached_property def max_uplink_switches(self: EosDesignsFacts) -> int: diff --git a/python-avd/pyavd/_eos_designs/schema/__init__.py b/python-avd/pyavd/_eos_designs/schema/__init__.py index b78b06c79ec..588b465fd03 100644 --- a/python-avd/pyavd/_eos_designs/schema/__init__.py +++ b/python-avd/pyavd/_eos_designs/schema/__init__.py @@ -18807,7 +18807,7 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): "uplink_switch_interface_speed": {"type": str}, "uplink_mtu": {"type": int}, "max_uplink_switches": {"type": int}, - "max_parallel_uplinks": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, "uplink_bfd": {"type": bool, "default": False}, "uplink_native_vlan": {"type": int}, "uplink_ptp": {"type": UplinkPtp}, @@ -19007,13 +19007,15 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): Can be used to reserve IP space for future expansions. """ - max_parallel_uplinks: int | None + max_parallel_uplinks: int """ Number of parallel links towards uplink switches. Changing this value may change interface naming on uplinks (and corresponding downlinks). Can be used to reserve interfaces for future parallel uplinks. + + Default value: `1` """ uplink_bfd: bool """ @@ -19614,7 +19616,7 @@ def __init__( uplink_switch_interface_speed: str | None | UndefinedType = Undefined, uplink_mtu: int | None | UndefinedType = Undefined, max_uplink_switches: int | None | UndefinedType = Undefined, - max_parallel_uplinks: int | None | UndefinedType = Undefined, + max_parallel_uplinks: int | UndefinedType = Undefined, uplink_bfd: bool | UndefinedType = Undefined, uplink_native_vlan: int | None | UndefinedType = Undefined, uplink_ptp: UplinkPtp | UndefinedType = Undefined, @@ -21916,7 +21918,7 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): "uplink_switch_interface_speed": {"type": str}, "uplink_mtu": {"type": int}, "max_uplink_switches": {"type": int}, - "max_parallel_uplinks": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, "uplink_bfd": {"type": bool, "default": False}, "uplink_native_vlan": {"type": int}, "uplink_ptp": {"type": UplinkPtp}, @@ -22123,13 +22125,15 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): Can be used to reserve IP space for future expansions. """ - max_parallel_uplinks: int | None + max_parallel_uplinks: int """ Number of parallel links towards uplink switches. Changing this value may change interface naming on uplinks (and corresponding downlinks). Can be used to reserve interfaces for future parallel uplinks. + + Default value: `1` """ uplink_bfd: bool """ @@ -22732,7 +22736,7 @@ def __init__( uplink_switch_interface_speed: str | None | UndefinedType = Undefined, uplink_mtu: int | None | UndefinedType = Undefined, max_uplink_switches: int | None | UndefinedType = Undefined, - max_parallel_uplinks: int | None | UndefinedType = Undefined, + max_parallel_uplinks: int | UndefinedType = Undefined, uplink_bfd: bool | UndefinedType = Undefined, uplink_native_vlan: int | None | UndefinedType = Undefined, uplink_ptp: UplinkPtp | UndefinedType = Undefined, @@ -24996,7 +25000,7 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): "uplink_switch_interface_speed": {"type": str}, "uplink_mtu": {"type": int}, "max_uplink_switches": {"type": int}, - "max_parallel_uplinks": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, "uplink_bfd": {"type": bool, "default": False}, "uplink_native_vlan": {"type": int}, "uplink_ptp": {"type": UplinkPtp}, @@ -25204,13 +25208,15 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): Can be used to reserve IP space for future expansions. """ - max_parallel_uplinks: int | None + max_parallel_uplinks: int """ Number of parallel links towards uplink switches. Changing this value may change interface naming on uplinks (and corresponding downlinks). Can be used to reserve interfaces for future parallel uplinks. + + Default value: `1` """ uplink_bfd: bool """ @@ -25813,7 +25819,7 @@ def __init__( uplink_switch_interface_speed: str | None | UndefinedType = Undefined, uplink_mtu: int | None | UndefinedType = Undefined, max_uplink_switches: int | None | UndefinedType = Undefined, - max_parallel_uplinks: int | None | UndefinedType = Undefined, + max_parallel_uplinks: int | UndefinedType = Undefined, uplink_bfd: bool | UndefinedType = Undefined, uplink_native_vlan: int | None | UndefinedType = Undefined, uplink_ptp: UplinkPtp | UndefinedType = Undefined, @@ -28120,7 +28126,7 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): "uplink_switch_interface_speed": {"type": str}, "uplink_mtu": {"type": int}, "max_uplink_switches": {"type": int}, - "max_parallel_uplinks": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, "uplink_bfd": {"type": bool, "default": False}, "uplink_native_vlan": {"type": int}, "uplink_ptp": {"type": UplinkPtp}, @@ -28327,13 +28333,15 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): Can be used to reserve IP space for future expansions. """ - max_parallel_uplinks: int | None + max_parallel_uplinks: int """ Number of parallel links towards uplink switches. Changing this value may change interface naming on uplinks (and corresponding downlinks). Can be used to reserve interfaces for future parallel uplinks. + + Default value: `1` """ uplink_bfd: bool """ @@ -28936,7 +28944,7 @@ def __init__( uplink_switch_interface_speed: str | None | UndefinedType = Undefined, uplink_mtu: int | None | UndefinedType = Undefined, max_uplink_switches: int | None | UndefinedType = Undefined, - max_parallel_uplinks: int | None | UndefinedType = Undefined, + max_parallel_uplinks: int | UndefinedType = Undefined, uplink_bfd: bool | UndefinedType = Undefined, uplink_native_vlan: int | None | UndefinedType = Undefined, uplink_ptp: UplinkPtp | UndefinedType = Undefined, @@ -37036,7 +37044,7 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): "uplink_switch_interface_speed": {"type": str}, "uplink_mtu": {"type": int}, "max_uplink_switches": {"type": int}, - "max_parallel_uplinks": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, "uplink_bfd": {"type": bool, "default": False}, "uplink_native_vlan": {"type": int}, "uplink_ptp": {"type": UplinkPtp}, @@ -37236,13 +37244,15 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): Can be used to reserve IP space for future expansions. """ - max_parallel_uplinks: int | None + max_parallel_uplinks: int """ Number of parallel links towards uplink switches. Changing this value may change interface naming on uplinks (and corresponding downlinks). Can be used to reserve interfaces for future parallel uplinks. + + Default value: `1` """ uplink_bfd: bool """ @@ -37843,7 +37853,7 @@ def __init__( uplink_switch_interface_speed: str | None | UndefinedType = Undefined, uplink_mtu: int | None | UndefinedType = Undefined, max_uplink_switches: int | None | UndefinedType = Undefined, - max_parallel_uplinks: int | None | UndefinedType = Undefined, + max_parallel_uplinks: int | UndefinedType = Undefined, uplink_bfd: bool | UndefinedType = Undefined, uplink_native_vlan: int | None | UndefinedType = Undefined, uplink_ptp: UplinkPtp | UndefinedType = Undefined, @@ -40145,7 +40155,7 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): "uplink_switch_interface_speed": {"type": str}, "uplink_mtu": {"type": int}, "max_uplink_switches": {"type": int}, - "max_parallel_uplinks": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, "uplink_bfd": {"type": bool, "default": False}, "uplink_native_vlan": {"type": int}, "uplink_ptp": {"type": UplinkPtp}, @@ -40352,13 +40362,15 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): Can be used to reserve IP space for future expansions. """ - max_parallel_uplinks: int | None + max_parallel_uplinks: int """ Number of parallel links towards uplink switches. Changing this value may change interface naming on uplinks (and corresponding downlinks). Can be used to reserve interfaces for future parallel uplinks. + + Default value: `1` """ uplink_bfd: bool """ @@ -40961,7 +40973,7 @@ def __init__( uplink_switch_interface_speed: str | None | UndefinedType = Undefined, uplink_mtu: int | None | UndefinedType = Undefined, max_uplink_switches: int | None | UndefinedType = Undefined, - max_parallel_uplinks: int | None | UndefinedType = Undefined, + max_parallel_uplinks: int | UndefinedType = Undefined, uplink_bfd: bool | UndefinedType = Undefined, uplink_native_vlan: int | None | UndefinedType = Undefined, uplink_ptp: UplinkPtp | UndefinedType = Undefined, @@ -43225,7 +43237,7 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): "uplink_switch_interface_speed": {"type": str}, "uplink_mtu": {"type": int}, "max_uplink_switches": {"type": int}, - "max_parallel_uplinks": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, "uplink_bfd": {"type": bool, "default": False}, "uplink_native_vlan": {"type": int}, "uplink_ptp": {"type": UplinkPtp}, @@ -43433,13 +43445,15 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): Can be used to reserve IP space for future expansions. """ - max_parallel_uplinks: int | None + max_parallel_uplinks: int """ Number of parallel links towards uplink switches. Changing this value may change interface naming on uplinks (and corresponding downlinks). Can be used to reserve interfaces for future parallel uplinks. + + Default value: `1` """ uplink_bfd: bool """ @@ -44042,7 +44056,7 @@ def __init__( uplink_switch_interface_speed: str | None | UndefinedType = Undefined, uplink_mtu: int | None | UndefinedType = Undefined, max_uplink_switches: int | None | UndefinedType = Undefined, - max_parallel_uplinks: int | None | UndefinedType = Undefined, + max_parallel_uplinks: int | UndefinedType = Undefined, uplink_bfd: bool | UndefinedType = Undefined, uplink_native_vlan: int | None | UndefinedType = Undefined, uplink_ptp: UplinkPtp | UndefinedType = Undefined, @@ -46349,7 +46363,7 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): "uplink_switch_interface_speed": {"type": str}, "uplink_mtu": {"type": int}, "max_uplink_switches": {"type": int}, - "max_parallel_uplinks": {"type": int}, + "max_parallel_uplinks": {"type": int, "default": 1}, "uplink_bfd": {"type": bool, "default": False}, "uplink_native_vlan": {"type": int}, "uplink_ptp": {"type": UplinkPtp}, @@ -46556,13 +46570,15 @@ class L3Interfaces(AvdIndexedList[str, L3InterfacesItem]): Can be used to reserve IP space for future expansions. """ - max_parallel_uplinks: int | None + max_parallel_uplinks: int """ Number of parallel links towards uplink switches. Changing this value may change interface naming on uplinks (and corresponding downlinks). Can be used to reserve interfaces for future parallel uplinks. + + Default value: `1` """ uplink_bfd: bool """ @@ -47165,7 +47181,7 @@ def __init__( uplink_switch_interface_speed: str | None | UndefinedType = Undefined, uplink_mtu: int | None | UndefinedType = Undefined, max_uplink_switches: int | None | UndefinedType = Undefined, - max_parallel_uplinks: int | None | UndefinedType = Undefined, + max_parallel_uplinks: int | UndefinedType = Undefined, uplink_bfd: bool | UndefinedType = Undefined, uplink_native_vlan: int | None | UndefinedType = Undefined, uplink_ptp: UplinkPtp | UndefinedType = Undefined, diff --git a/python-avd/pyavd/_eos_designs/schema/eos_designs.schema.yml b/python-avd/pyavd/_eos_designs/schema/eos_designs.schema.yml index 11d2dfe4a2b..900218badfa 100644 --- a/python-avd/pyavd/_eos_designs/schema/eos_designs.schema.yml +++ b/python-avd/pyavd/_eos_designs/schema/eos_designs.schema.yml @@ -7826,6 +7826,7 @@ $defs: documentation_options: table: node-type-uplink-configuration type: int + default: 1 convert_types: - str description: 'Number of parallel links towards uplink switches. diff --git a/python-avd/pyavd/_eos_designs/schema/schema_fragments/defs_node_type.schema.yml b/python-avd/pyavd/_eos_designs/schema/schema_fragments/defs_node_type.schema.yml index b0fcba344c5..5115459bd0e 100644 --- a/python-avd/pyavd/_eos_designs/schema/schema_fragments/defs_node_type.schema.yml +++ b/python-avd/pyavd/_eos_designs/schema/schema_fragments/defs_node_type.schema.yml @@ -252,6 +252,7 @@ $defs: documentation_options: table: node-type-uplink-configuration type: int + default: 1 convert_types: - str description: | diff --git a/python-avd/pyavd/_eos_designs/shared_utils/filtered_tenants.py b/python-avd/pyavd/_eos_designs/shared_utils/filtered_tenants.py index 222d4eead4f..abf27acf0ef 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/filtered_tenants.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/filtered_tenants.py @@ -352,7 +352,7 @@ def endpoint_vlans(self: SharedUtils) -> list: def get_vrf_id(vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem, required: bool = True) -> int | None: vrf_id = default(vrf.vrf_id, vrf.vrf_vni) if vrf_id is None and required: - msg = f"'vrf_id' or 'vrf_vni' for VRF '{vrf.name} must be set." + msg = f"'vrf_id' or 'vrf_vni' for VRF '{vrf.name}' must be set." raise AristaAvdInvalidInputsError(msg) return vrf_id @@ -360,7 +360,7 @@ def get_vrf_id(vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkSe def get_vrf_vni(vrf: EosDesigns._DynamicKeys.DynamicNetworkServicesItem.NetworkServicesItem.VrfsItem) -> int: vrf_vni = default(vrf.vrf_vni, vrf.vrf_id) if vrf_vni is None: - msg = f"'vrf_vni' or 'vrf_id' for VRF '{vrf.name} must be set." + msg = f"'vrf_vni' or 'vrf_id' for VRF '{vrf.name}' must be set." raise AristaAvdInvalidInputsError(msg) return vrf_vni diff --git a/python-avd/pyavd/_eos_designs/shared_utils/inband_management.py b/python-avd/pyavd/_eos_designs/shared_utils/inband_management.py index 6374c9bb52c..d0bd7956cff 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/inband_management.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/inband_management.py @@ -165,8 +165,7 @@ def inband_mgmt_interface(self: SharedUtils) -> str | None: @cached_property def inband_ztp(self: SharedUtils) -> bool: - inband_ztp = self.node_config.inband_ztp - if inband_ztp and self.uplink_type != "port-channel": + if (inband_ztp := self.node_config.inband_ztp) and self.uplink_type != "port-channel": msg = "'inband_ztp' is currently only supported for L2 switches ('uplink_type: port-channel')." raise AristaAvdError(msg) return inband_ztp diff --git a/python-avd/pyavd/_eos_designs/shared_utils/misc.py b/python-avd/pyavd/_eos_designs/shared_utils/misc.py index edb838f3a99..aac25363315 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/misc.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/misc.py @@ -49,8 +49,7 @@ def filter_tags(self: SharedUtils) -> list: @cached_property def igmp_snooping_enabled(self: SharedUtils) -> bool: - default_igmp_snooping_enabled = self.inputs.default_igmp_snooping_enabled - return default(self.node_config.igmp_snooping_enabled, default_igmp_snooping_enabled) + return default(self.node_config.igmp_snooping_enabled, self.inputs.default_igmp_snooping_enabled) @cached_property def only_local_vlan_trunk_groups(self: SharedUtils) -> bool: @@ -102,7 +101,7 @@ def uplink_switch_interfaces(self: SharedUtils) -> list: # Add uplink_switch_interface based on this switch's ID (-1 for 0-based) * max_parallel_uplinks + index_of_parallel_uplinks. # For max_parallel_uplinks: 2 this would assign downlink interfaces like this: # spine1 downlink-interface mapping: [ leaf-id1, leaf-id1, leaf-id2, leaf-id2, leaf-id3, leaf-id3, ... ] - downlink_index = (self.id - 1) * self.max_parallel_uplinks + index_of_parallel_uplinks + downlink_index = (self.id - 1) * self.node_config.max_parallel_uplinks + index_of_parallel_uplinks if len(uplink_switch_facts._default_downlink_interfaces) > downlink_index: uplink_switch_interfaces.append(uplink_switch_facts._default_downlink_interfaces[downlink_index]) else: @@ -127,11 +126,6 @@ def serial_number(self: SharedUtils) -> str | None: """ return default(self.node_config.serial_number, self.inputs.serial_number) - @cached_property - def max_parallel_uplinks(self: SharedUtils) -> int: - """Exposed in avd_switch_facts.""" - return default(self.node_config.max_parallel_uplinks, 1) - @cached_property def max_uplink_switches(self: SharedUtils) -> int: """max_uplink_switches will default to the length of uplink_switches.""" diff --git a/python-avd/pyavd/_eos_designs/shared_utils/mlag.py b/python-avd/pyavd/_eos_designs/shared_utils/mlag.py index e2351c35565..38696c41cde 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/mlag.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/mlag.py @@ -29,17 +29,14 @@ class MlagMixin: @cached_property def mlag(self: SharedUtils) -> bool: - return self.node_type_key_data.mlag_support and self.node_config.mlag and len(self.node_group_config.nodes) == 2 + return self.node_type_key_data.mlag_support and self.node_config.mlag and self.node_group_is_primary_and_peer_hostname is not None @cached_property def group(self: SharedUtils) -> str | None: - """ - Group set to "node_group" name or None. - - Note that since we cheat in node_group_config and return an empty class if there is no group, - we cannot trust the type hint suggesting that group is always set. - """ - return self.node_group_config.group or None + """Group set to "node_group" name or None.""" + if self.node_group_config is not None: + return self.node_group_config.group + return None @cached_property def mlag_interfaces(self: SharedUtils) -> list: @@ -68,17 +65,32 @@ def mlag_peer_l3_ipv4_pool(self: SharedUtils) -> str: @cached_property def mlag_role(self: SharedUtils) -> Literal["primary", "secondary"] | None: - if self.mlag: - return "secondary" if bool(list(self.node_group_config.nodes.keys()).index(self.hostname)) else "primary" + if self.mlag and self.node_group_is_primary_and_peer_hostname is not None: + return "primary" if self.node_group_is_primary_and_peer_hostname[0] else "secondary" return None + @cached_property + def node_group_is_primary_and_peer_hostname(self: SharedUtils) -> tuple[bool, str] | None: + """ + Node group position and peer used for MLAG and WAN HA. + + Returns None if the device is not in a node_group with exactly two devices. + Returns True, if this device is the first one in the node_group. + Returns False, if this device is the second one in the node_group. + """ + if self.node_group_config is None or len(self.node_group_config.nodes) != 2: + return None + + nodes = list(self.node_group_config.nodes.keys()) + index = nodes.index(self.hostname) + peer_index = not index # (0->1 and 1>0) + return index == 0, nodes[peer_index] + @cached_property def mlag_peer(self: SharedUtils) -> str: - if self.mlag_role == "primary": - return list(self.node_group_config.nodes.keys())[1] - if self.mlag_role == "secondary": - return list(self.node_group_config.nodes.keys())[0] # noqa: RUF015 + if self.node_group_is_primary_and_peer_hostname is not None: + return self.node_group_is_primary_and_peer_hostname[1] msg = "Unable to find MLAG peer within same node group" raise AristaAvdError(msg) diff --git a/python-avd/pyavd/_eos_designs/shared_utils/node_config.py b/python-avd/pyavd/_eos_designs/shared_utils/node_config.py index 9f49cfd512f..25aa5a510b4 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/node_config.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/node_config.py @@ -25,6 +25,11 @@ class NodeConfigMixin: def node_type_config( self: SharedUtils, ) -> EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes: + """ + The object representing the `:` containing the `defaults`, `nodes`, `node_groups` etc. + + The relevant dynamic key is found in self.inputs._dynamic_keys which is populated by the _from_dict() loader on the EosDesigns class. + """ node_type_key = self.node_type_key_data.key if node_type_key in self.inputs._dynamic_keys.custom_node_types: @@ -39,12 +44,17 @@ def node_type_config( @cached_property def node_group_config( self: SharedUtils, - ) -> EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodeGroupsItem: + ) -> EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodeGroupsItem | None: + """ + The object representing the `.node_groups[]` where this node is found. + + Used by MLAG and WAN HA logic to find out who our MLAG / WAN HA peer is. + """ for node_group in self.node_type_config.node_groups: if self.hostname in node_group.nodes: return node_group - return EosDesigns._DynamicKeys.DynamicNodeTypesItem.NodeTypes.NodeGroupsItem() + return None @cached_property def node_config( diff --git a/python-avd/pyavd/_eos_designs/shared_utils/wan.py b/python-avd/pyavd/_eos_designs/shared_utils/wan.py index 28e3adb9b31..62e28cd966a 100644 --- a/python-avd/pyavd/_eos_designs/shared_utils/wan.py +++ b/python-avd/pyavd/_eos_designs/shared_utils/wan.py @@ -412,7 +412,7 @@ def cv_pathfinder_role(self: SharedUtils) -> str | None: @cached_property def wan_ha(self: SharedUtils) -> bool: """Only trigger HA if 2 cv_pathfinder clients are in the same group and wan_ha.enabled is true.""" - if not (self.is_cv_pathfinder_client and len(self.node_group_config.nodes) == 2): + if not self.is_cv_pathfinder_client or self.node_group_is_primary_and_peer_hostname is None: return False if self.node_config.wan_ha.enabled is None: @@ -436,7 +436,7 @@ def is_first_ha_peer(self: SharedUtils) -> bool: This should be called only from functions which have checked that HA is enabled. """ - return next(iter(self.node_group_config.nodes.keys())) == self.hostname + return self.node_group_is_primary_and_peer_hostname is not None and self.node_group_is_primary_and_peer_hostname[0] @cached_property def wan_ha_peer(self: SharedUtils) -> str | None: @@ -444,11 +444,9 @@ def wan_ha_peer(self: SharedUtils) -> str | None: if not self.wan_ha: return None - keys = list(self.node_group_config.nodes.keys()) - if self.is_first_ha_peer: - return keys[1] - if keys.index(self.hostname) == 1: - return keys[0] + if self.node_group_is_primary_and_peer_hostname is not None: + return self.node_group_is_primary_and_peer_hostname[1] + msg = "Unable to find WAN HA peer within same node group" raise AristaAvdError(msg) diff --git a/python-avd/pyavd/_eos_designs/structured_config/base/__init__.py b/python-avd/pyavd/_eos_designs/structured_config/base/__init__.py index 94ddc48189b..b73e2631f1e 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/base/__init__.py +++ b/python-avd/pyavd/_eos_designs/structured_config/base/__init__.py @@ -582,7 +582,7 @@ def lacp(self) -> dict | None: msg = f"'id' is not set on '{self.shared_utils.hostname}' to set LACP port ID ranges" raise AristaAvdInvalidInputsError(msg) - node_group_length = max(len(self.shared_utils.node_group_config.nodes), 1) + node_group_length = max(len(self.shared_utils.node_group_config.nodes), 1) if self.shared_utils.node_group_config is not None else 1 begin = 1 + (((switch_id - 1) % node_group_length) * lacp_port_id_range.size) + lacp_port_id_range.offset end = (((switch_id - 1) % node_group_length + 1) * lacp_port_id_range.size) + lacp_port_id_range.offset diff --git a/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/utils.py b/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/utils.py index cada468c44d..686f43e46dc 100644 --- a/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/utils.py +++ b/python-avd/pyavd/_eos_designs/structured_config/connected_endpoints/utils.py @@ -237,7 +237,7 @@ def _get_adapter_poe( ) -> dict | None: """Return poe settings for one adapter.""" if self.shared_utils.platform_settings.feature_support.poe: - return adapter.poe._as_dict() + return adapter.poe._as_dict() or None return None diff --git a/python-avd/pyavd/_schema/models/avd_model.py b/python-avd/pyavd/_schema/models/avd_model.py index 6456a35f392..b3e31c63f39 100644 --- a/python-avd/pyavd/_schema/models/avd_model.py +++ b/python-avd/pyavd/_schema/models/avd_model.py @@ -118,9 +118,9 @@ def __getattr__(self, name: str) -> Any: if name not in self._fields: raise AttributeError("'" + self.__class__.__name__ + "' object has no attribute '" + name + "'") - new_default_value = self._get_field_default_value(name) - setattr(self, name, new_default_value) - return new_default_value + default_value = self._get_field_default_value(name) + setattr(self, name, default_value) + return default_value def _get_defined_attr(self, name: str) -> Any | Undefined: """ diff --git a/python-avd/pyavd/_utils/default.py b/python-avd/pyavd/_utils/default.py index 7d98eb283f9..4774600283b 100644 --- a/python-avd/pyavd/_utils/default.py +++ b/python-avd/pyavd/_utils/default.py @@ -14,7 +14,7 @@ T = TypeVar("T") -def default(*values: Unpack[tuple[Unpack[tuple[T | None]], T]]) -> T: +def default(*values: Unpack[tuple[Unpack[tuple[T | None, ...]], T]]) -> T: """ Accepts any number of arguments. Return the first value which is not None. diff --git a/python-avd/pyavd/api/ip_addressing/__init__.py b/python-avd/pyavd/api/ip_addressing/__init__.py index 59461a8079b..e300458354b 100644 --- a/python-avd/pyavd/api/ip_addressing/__init__.py +++ b/python-avd/pyavd/api/ip_addressing/__init__.py @@ -313,7 +313,7 @@ def vrf_loopback_ipv6(self, pool: str) -> str: Used for "vtep_diagnostic.loopback". """ - offset = self.shared_utils.id + self.shared_utils.loopback_ipv6_offset + offset = self.shared_utils.id + self.shared_utils.node_config.loopback_ipv6_offset return get_ip_from_pool(pool, 128, offset, 0) def evpn_underlay_l3_multicast_group( diff --git a/python-avd/pyavd/api/ip_addressing/utils.py b/python-avd/pyavd/api/ip_addressing/utils.py index 27a1d307c87..f3b61f528ef 100644 --- a/python-avd/pyavd/api/ip_addressing/utils.py +++ b/python-avd/pyavd/api/ip_addressing/utils.py @@ -67,7 +67,7 @@ def _max_uplink_switches(self: AvdIpAddressing) -> int: @cached_property def _max_parallel_uplinks(self: AvdIpAddressing) -> int: - return self.shared_utils.max_parallel_uplinks + return self.shared_utils.node_config.max_parallel_uplinks @cached_property def _loopback_ipv4_address(self: AvdIpAddressing) -> str | None: